LibreOffice Module svx (master)  1
sdrdecompositiontools.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
40 #include <svx/svdotext.hxx>
52 #include <osl/diagnose.h>
53 
54 
55 using namespace com::sun::star;
56 
57 
59 {
60 namespace
61 {
62 // See also: SdrTextObj::AdjustRectToTextDistance
63 basegfx::B2DRange getTextAnchorRange(const attribute::SdrTextAttribute& rText,
64  const basegfx::B2DRange& rSnapRange)
65 {
66  // Take vertical text orientation into account when deciding
67  // which dimension is its width, and which is its height
68  const OutlinerParaObject& rOutlinerParaObj = rText.getOutlinerParaObject();
69  const bool bVerticalWriting(rOutlinerParaObj.IsEffectivelyVertical());
70  const double fWidthForText = bVerticalWriting ? rSnapRange.getHeight() : rSnapRange.getWidth();
71  // create a range describing the wanted text position and size (aTextAnchorRange). This
72  // means to use the text distance values here
73  // If the margin is larger than the entire width of the text area, then limit the
74  // margin.
75  const double fTextLeftDistance
76  = std::min(static_cast<double>(rText.getTextLeftDistance()), fWidthForText);
77  const double nTextRightDistance
78  = std::min(static_cast<double>(rText.getTextRightDistance()), fWidthForText);
79  double fDistanceForTextL, fDistanceForTextT, fDistanceForTextR, fDistanceForTextB;
80  if (!bVerticalWriting)
81  {
82  fDistanceForTextL = fTextLeftDistance;
83  fDistanceForTextT = rText.getTextUpperDistance();
84  fDistanceForTextR = nTextRightDistance;
85  fDistanceForTextB = rText.getTextLowerDistance();
86  }
87  else if (rOutlinerParaObj.IsTopToBottom())
88  {
89  fDistanceForTextL = rText.getTextLowerDistance();
90  fDistanceForTextT = fTextLeftDistance;
91  fDistanceForTextR = rText.getTextUpperDistance();
92  fDistanceForTextB = nTextRightDistance;
93  }
94  else
95  {
96  fDistanceForTextL = rText.getTextUpperDistance();
97  fDistanceForTextT = nTextRightDistance;
98  fDistanceForTextR = rText.getTextLowerDistance();
99  fDistanceForTextB = fTextLeftDistance;
100  }
101  const basegfx::B2DPoint aTopLeft(rSnapRange.getMinX() + fDistanceForTextL,
102  rSnapRange.getMinY() + fDistanceForTextT);
103  const basegfx::B2DPoint aBottomRight(rSnapRange.getMaxX() - fDistanceForTextR,
104  rSnapRange.getMaxY() - fDistanceForTextB);
105  basegfx::B2DRange aAnchorRange;
106  aAnchorRange.expand(aTopLeft);
107  aAnchorRange.expand(aBottomRight);
108 
109  // If the shape has no width, then don't attempt to break the text into multiple
110  // lines, not a single character would satisfy a zero width requirement.
111  // SdrTextObj::impDecomposeBlockTextPrimitive() uses the same constant to
112  // effectively set no limits.
113  if (!bVerticalWriting && aAnchorRange.getWidth() == 0)
114  {
115  aAnchorRange.expand(basegfx::B2DPoint(aTopLeft.getX() - 1000000, aTopLeft.getY()));
116  aAnchorRange.expand(basegfx::B2DPoint(aBottomRight.getX() + 1000000, aBottomRight.getY()));
117  }
118  else if (bVerticalWriting && aAnchorRange.getHeight() == 0)
119  {
120  aAnchorRange.expand(basegfx::B2DPoint(aTopLeft.getX(), aTopLeft.getY() - 1000000));
121  aAnchorRange.expand(basegfx::B2DPoint(aBottomRight.getX(), aBottomRight.getY() + 1000000));
122  }
123  return aAnchorRange;
124 }
125 };
126 
127  class TransparencePrimitive2D;
128 
130  const basegfx::B2DPolyPolygon& rPolyPolygon,
131  const attribute::SdrFillAttribute& rFill,
132  const attribute::FillGradientAttribute& rFillGradient)
133  {
134  // when we have no given definition range, use the range of the given geometry
135  // also for definition (simplest case)
136  const basegfx::B2DRange aRange(basegfx::utils::getRange(rPolyPolygon));
137 
139  rPolyPolygon,
140  aRange,
141  rFill,
142  rFillGradient);
143  }
144 
146  const basegfx::B2DPolyPolygon& rPolyPolygon,
147  const basegfx::B2DRange& rDefinitionRange,
148  const attribute::SdrFillAttribute& rFill,
149  const attribute::FillGradientAttribute& rFillGradient)
150  {
152  {
153  return Primitive2DReference();
154  }
155 
156  // prepare fully scaled polygon
157  rtl::Reference<BasePrimitive2D> pNewFillPrimitive;
158 
159  if(!rFill.getGradient().isDefault())
160  {
161  pNewFillPrimitive = new PolyPolygonGradientPrimitive2D(
162  rPolyPolygon,
163  rDefinitionRange,
164  rFill.getGradient());
165  }
166  else if(!rFill.getHatch().isDefault())
167  {
168  pNewFillPrimitive = new PolyPolygonHatchPrimitive2D(
169  rPolyPolygon,
170  rDefinitionRange,
171  rFill.getColor(),
172  rFill.getHatch());
173  }
174  else if(!rFill.getFillGraphic().isDefault())
175  {
176  pNewFillPrimitive = new PolyPolygonGraphicPrimitive2D(
177  rPolyPolygon,
178  rDefinitionRange,
179  rFill.getFillGraphic().createFillGraphicAttribute(rDefinitionRange));
180  }
181  else
182  {
183  pNewFillPrimitive = new PolyPolygonColorPrimitive2D(
184  rPolyPolygon,
185  rFill.getColor());
186  }
187 
188  if(0.0 != rFill.getTransparence())
189  {
190  // create simpleTransparencePrimitive, add created fill primitive
191  Primitive2DContainer aContent { pNewFillPrimitive };
192  return Primitive2DReference(new UnifiedTransparencePrimitive2D(std::move(aContent), rFill.getTransparence()));
193  }
194  else if(!rFillGradient.isDefault())
195  {
196  // create sequence with created fill primitive
197  Primitive2DContainer aContent { pNewFillPrimitive };
198 
199  // create FillGradientPrimitive2D for transparence and add to new sequence
200  // fillGradientPrimitive is enough here (compared to PolyPolygonGradientPrimitive2D) since float transparence will be masked anyways
201  const basegfx::B2DRange aRange(basegfx::utils::getRange(rPolyPolygon));
202  Primitive2DReference xRefB(
204  aRange,
205  rDefinitionRange,
206  rFillGradient));
207  Primitive2DContainer aAlpha { xRefB };
208 
209  // create TransparencePrimitive2D using alpha and content
210  return Primitive2DReference(new TransparencePrimitive2D(std::move(aContent), std::move(aAlpha)));
211  }
212  else
213  {
214  // add to decomposition
215  return pNewFillPrimitive;
216  }
217  }
218 
220  const basegfx::B2DPolygon& rPolygon,
221  const attribute::SdrLineAttribute& rLine,
223  {
224  // create line and stroke attribute
225  const attribute::LineAttribute aLineAttribute(rLine.getColor(), rLine.getWidth(), rLine.getJoin(), rLine.getCap());
226  const attribute::StrokeAttribute aStrokeAttribute(std::vector(rLine.getDotDashArray()), rLine.getFullDotDashLen());
227  rtl::Reference<BasePrimitive2D> pNewLinePrimitive;
228 
229  if(!rPolygon.isClosed() && !rStroke.isDefault())
230  {
232  attribute::LineStartEndAttribute aEnd(rStroke.getEndWidth(), rStroke.getEndPolyPolygon(), rStroke.isEndCentered());
233 
234  // create data
235  pNewLinePrimitive = new PolygonStrokeArrowPrimitive2D(rPolygon, aLineAttribute, aStrokeAttribute, aStart, aEnd);
236  }
237  else
238  {
239  // create data
240  pNewLinePrimitive = new PolygonStrokePrimitive2D(rPolygon, aLineAttribute, aStrokeAttribute);
241  }
242 
243  if(0.0 != rLine.getTransparence())
244  {
245  // create simpleTransparencePrimitive, add created fill primitive
246  Primitive2DContainer aContent { pNewLinePrimitive };
247  return Primitive2DReference(new UnifiedTransparencePrimitive2D(std::move(aContent), rLine.getTransparence()));
248  }
249  else
250  {
251  // add to decomposition
252  return pNewLinePrimitive;
253  }
254  }
255 
257  const basegfx::B2DPolyPolygon& rUnitPolyPolygon,
258  const basegfx::B2DHomMatrix& rObjectTransform,
259  const attribute::SdrTextAttribute& rText,
260  const attribute::SdrLineAttribute& rStroke,
261  bool bCellText,
262  bool bWordWrap)
263  {
264  basegfx::B2DHomMatrix aAnchorTransform(rObjectTransform);
266 
267  if(rText.isContour())
268  {
269  // contour text
270  if(!rStroke.isDefault() && 0.0 != rStroke.getWidth())
271  {
272  // take line width into account and shrink contour polygon accordingly
273  // decompose to get scale
274  basegfx::B2DVector aScale, aTranslate;
275  double fRotate, fShearX;
276  rObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX);
277 
278  // scale outline to object's size to allow growing with value relative to that size
279  // and also to keep aspect ratio
280  basegfx::B2DPolyPolygon aScaledUnitPolyPolygon(rUnitPolyPolygon);
281  aScaledUnitPolyPolygon.transform(basegfx::utils::createScaleB2DHomMatrix(
282  fabs(aScale.getX()), fabs(aScale.getY())));
283 
284  // grow the polygon. To shrink, use negative value (half width)
285  aScaledUnitPolyPolygon = basegfx::utils::growInNormalDirection(aScaledUnitPolyPolygon, -(rStroke.getWidth() * 0.5));
286 
287  // scale back to unit polygon
288  aScaledUnitPolyPolygon.transform(basegfx::utils::createScaleB2DHomMatrix(
289  0.0 != aScale.getX() ? 1.0 / aScale.getX() : 1.0,
290  0.0 != aScale.getY() ? 1.0 / aScale.getY() : 1.0));
291 
292  // create with unit polygon
293  pNew = new SdrContourTextPrimitive2D(
294  &rText.getSdrText(),
295  rText.getOutlinerParaObject(),
296  aScaledUnitPolyPolygon,
297  rObjectTransform);
298  }
299  else
300  {
301  // create with unit polygon
302  pNew = new SdrContourTextPrimitive2D(
303  &rText.getSdrText(),
304  rText.getOutlinerParaObject(),
305  rUnitPolyPolygon,
306  rObjectTransform);
307  }
308  }
309  else if(!rText.getSdrFormTextAttribute().isDefault())
310  {
311  // text on path, use scaled polygon
312  basegfx::B2DPolyPolygon aScaledPolyPolygon(rUnitPolyPolygon);
313  aScaledPolyPolygon.transform(rObjectTransform);
314  pNew = new SdrPathTextPrimitive2D(
315  &rText.getSdrText(),
316  rText.getOutlinerParaObject(),
317  aScaledPolyPolygon,
318  rText.getSdrFormTextAttribute());
319  }
320  else
321  {
322  // rObjectTransform is the whole SdrObject transformation from unit rectangle
323  // to its size and position. Decompose to allow working with single values.
324  basegfx::B2DVector aScale, aTranslate;
325  double fRotate, fShearX;
326  rObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX);
327 
328  // extract mirroring
329  const bool bMirrorX(basegfx::fTools::less(aScale.getX(), 0.0));
330  const bool bMirrorY(basegfx::fTools::less(aScale.getY(), 0.0));
331  aScale = basegfx::absolute(aScale);
332 
333  // Get the real size, since polygon outline and scale
334  // from the object transformation may vary (e.g. ellipse segments)
335  basegfx::B2DHomMatrix aJustScaleTransform;
336  aJustScaleTransform.set(0, 0, aScale.getX());
337  aJustScaleTransform.set(1, 1, aScale.getY());
338  basegfx::B2DPolyPolygon aScaledUnitPolyPolygon(rUnitPolyPolygon);
339  aScaledUnitPolyPolygon.transform(aJustScaleTransform);
340  const basegfx::B2DRange aTextAnchorRange
341  = getTextAnchorRange(rText, basegfx::utils::getRange(aScaledUnitPolyPolygon));
342 
343  // now create a transformation from this basic range (aTextAnchorRange)
344  // #i121494# if we have no scale use at least 1.0 to have a carrier e.g. for
345  // mirror values, else these will get lost
347  basegfx::fTools::equalZero(aTextAnchorRange.getWidth()) ? 1.0 : aTextAnchorRange.getWidth(),
348  basegfx::fTools::equalZero(aTextAnchorRange.getHeight()) ? 1.0 : aTextAnchorRange.getHeight(),
349  aTextAnchorRange.getMinX(), aTextAnchorRange.getMinY());
350 
351  // apply mirroring
352  aAnchorTransform.scale(bMirrorX ? -1.0 : 1.0, bMirrorY ? -1.0 : 1.0);
353 
354  // apply object's other transforms
355  aAnchorTransform = basegfx::utils::createShearXRotateTranslateB2DHomMatrix(fShearX, fRotate, aTranslate)
356  * aAnchorTransform;
357 
358  if(rText.isFitToSize())
359  {
360  // stretched text in range
361  pNew = new SdrStretchTextPrimitive2D(
362  &rText.getSdrText(),
363  rText.getOutlinerParaObject(),
364  aAnchorTransform,
365  rText.isFixedCellHeight());
366  }
367  else if(rText.isAutoFit())
368  {
369  // isotropically scaled text in range
370  pNew = new SdrAutoFitTextPrimitive2D(
371  &rText.getSdrText(),
372  rText.getOutlinerParaObject(),
373  aAnchorTransform,
374  bWordWrap);
375  }
376  else if( rText.isChainable() && !rText.isInEditMode() )
377  {
378  pNew = new SdrChainedTextPrimitive2D(
379  &rText.getSdrText(),
380  rText.getOutlinerParaObject(),
381  aAnchorTransform );
382  }
383  else // text in range
384  {
385  // build new primitive
386  pNew = new SdrBlockTextPrimitive2D(
387  &rText.getSdrText(),
388  rText.getOutlinerParaObject(),
389  aAnchorTransform,
390  rText.getSdrTextHorzAdjust(),
391  rText.getSdrTextVertAdjust(),
392  rText.isFixedCellHeight(),
393  rText.isScroll(),
394  bCellText,
395  bWordWrap);
396  }
397  }
398 
399  OSL_ENSURE(pNew != nullptr, "createTextPrimitive: no text primitive created (!)");
400 
401  if(rText.isBlink())
402  {
403  // prepare animation and primitive list
405  rText.getBlinkTextTiming(aAnimationList);
406 
407  if(0.0 != aAnimationList.getDuration())
408  {
409  // create content sequence
410  Primitive2DReference xRefA(pNew);
411  Primitive2DContainer aContent { xRefA };
412 
413  // create and add animated switch primitive
414  return Primitive2DReference(new AnimatedBlinkPrimitive2D(aAnimationList, std::move(aContent)));
415  }
416  else
417  {
418  // add to decomposition
419  return Primitive2DReference(pNew);
420  }
421  }
422 
423  if(rText.isScroll())
424  {
425  // suppress scroll when FontWork
426  if(rText.getSdrFormTextAttribute().isDefault())
427  {
428  // get scroll direction
429  const SdrTextAniDirection eDirection(rText.getSdrText().GetObject().GetTextAniDirection());
430  const bool bHorizontal(SdrTextAniDirection::Left == eDirection || SdrTextAniDirection::Right == eDirection);
431 
432  // decompose to get separated values for the scroll box
433  basegfx::B2DVector aScale, aTranslate;
434  double fRotate, fShearX;
435  aAnchorTransform.decompose(aScale, aTranslate, fRotate, fShearX);
436 
437  // build transform from scaled only to full AnchorTransform and inverse
439  fShearX, fRotate, aTranslate));
440  basegfx::B2DHomMatrix aISRT(aSRT);
441  aISRT.invert();
442 
443  // bring the primitive back to scaled only and get scaled range, create new clone for this
444  rtl::Reference<SdrTextPrimitive2D> pNew2 = pNew->createTransformedClone(aISRT);
445  OSL_ENSURE(pNew2, "createTextPrimitive: Could not create transformed clone of text primitive (!)");
446  pNew = pNew2.get();
447 
448  // create neutral geometry::ViewInformation2D for local range and decompose calls. This is okay
449  // since the decompose is view-independent
450  geometry::ViewInformation2D aViewInformation2D;
451 
452  // get range
453  const basegfx::B2DRange aScaledRange(pNew->getB2DRange(aViewInformation2D));
454 
455  // create left outside and right outside transformations. Also take care
456  // of the clip rectangle
457  basegfx::B2DHomMatrix aLeft, aRight;
458  basegfx::B2DPoint aClipTopLeft(0.0, 0.0);
459  basegfx::B2DPoint aClipBottomRight(aScale.getX(), aScale.getY());
460 
461  if(bHorizontal)
462  {
463  aClipTopLeft.setY(aScaledRange.getMinY());
464  aClipBottomRight.setY(aScaledRange.getMaxY());
465  aLeft.translate(-aScaledRange.getMaxX(), 0.0);
466  aRight.translate(aScale.getX() - aScaledRange.getMinX(), 0.0);
467  }
468  else
469  {
470  aClipTopLeft.setX(aScaledRange.getMinX());
471  aClipBottomRight.setX(aScaledRange.getMaxX());
472  aLeft.translate(0.0, -aScaledRange.getMaxY());
473  aRight.translate(0.0, aScale.getY() - aScaledRange.getMinY());
474  }
475 
476  aLeft *= aSRT;
477  aRight *= aSRT;
478 
479  // prepare animation list
481 
482  if(bHorizontal)
483  {
484  rText.getScrollTextTiming(aAnimationList, aScale.getX(), aScaledRange.getWidth());
485  }
486  else
487  {
488  rText.getScrollTextTiming(aAnimationList, aScale.getY(), aScaledRange.getHeight());
489  }
490 
491  if(0.0 != aAnimationList.getDuration())
492  {
493  // create a new Primitive2DContainer containing the animated text in its scaled only state.
494  // use the decomposition to force to simple text primitives, those will no longer
495  // need the outliner for formatting (alternatively it is also possible to just add
496  // pNew to aNewPrimitiveSequence)
497  Primitive2DContainer aAnimSequence;
498  pNew->get2DDecomposition(aAnimSequence, aViewInformation2D);
499  pNew.clear();
500 
501  // create a new animatedInterpolatePrimitive and add it
502  Primitive2DReference xRefA(new AnimatedInterpolatePrimitive2D({ aLeft, aRight }, aAnimationList, std::move(aAnimSequence)));
503  Primitive2DContainer aContent { xRefA };
504 
505  // scrolling needs an encapsulating clipping primitive
506  const basegfx::B2DRange aClipRange(aClipTopLeft, aClipBottomRight);
508  aClipPolygon.transform(aSRT);
509  return Primitive2DReference(new MaskPrimitive2D(basegfx::B2DPolyPolygon(aClipPolygon), std::move(aContent)));
510  }
511  else
512  {
513  // add to decomposition
514  return Primitive2DReference(pNew);
515  }
516  }
517  }
518 
519  if(rText.isInEditMode())
520  {
521  // #i97628#
522  // encapsulate with TextHierarchyEditPrimitive2D to allow renderers
523  // to suppress actively edited content if needed
524  Primitive2DReference xRefA(pNew);
525  Primitive2DContainer aContent { xRefA };
526 
527  // create and add TextHierarchyEditPrimitive2D primitive
528  return Primitive2DReference(new TextHierarchyEditPrimitive2D(std::move(aContent)));
529  }
530  else
531  {
532  // add to decomposition
533  return pNew;
534  }
535  }
536 
538  Primitive2DContainer&& rContent,
539  const attribute::SdrShadowAttribute& rShadow,
540  const basegfx::B2DHomMatrix& rObjectMatrix,
541  const Primitive2DContainer* pContentForShadow)
542  {
543  if(rContent.empty())
544  return std::move(rContent);
545 
546  basegfx::B2DHomMatrix aShadowOffset;
547 
548  if(rShadow.getSize().getX() != 100000)
549  {
550  basegfx::B2DTuple aScale;
551  basegfx::B2DTuple aTranslate;
552  double fRotate = 0;
553  double fShearX = 0;
554  rObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
555  // Scale the shadow
556  double nTranslateX = aTranslate.getX();
557  double nTranslateY = aTranslate.getY();
558 
559  // The origin for scaling is the top left corner by default. A negative
560  // shadow offset changes the origin.
561  if (rShadow.getOffset().getX() < 0)
562  nTranslateX += aScale.getX();
563  if (rShadow.getOffset().getY() < 0)
564  nTranslateY += aScale.getY();
565 
566  aShadowOffset.translate(-nTranslateX, -nTranslateY);
567  aShadowOffset.scale(rShadow.getSize().getX() * 0.00001, rShadow.getSize().getY() * 0.00001);
568  aShadowOffset.translate(nTranslateX, nTranslateY);
569  }
570 
571  aShadowOffset.translate(rShadow.getOffset().getX(), rShadow.getOffset().getY());
572 
573  // create shadow primitive and add content
574  const Primitive2DContainer& rContentForShadow
575  = pContentForShadow ? *pContentForShadow : rContent;
576  int nContentWithTransparence = std::count_if(
577  rContentForShadow.begin(), rContentForShadow.end(),
578  [](const Primitive2DReference& xChild) {
579  auto pChild = dynamic_cast<BufferedDecompositionPrimitive2D*>(xChild.get());
580  return pChild && pChild->getTransparenceForShadow() != 0;
581  });
582  if (nContentWithTransparence == 0)
583  {
584  Primitive2DContainer aRetval(2);
585  aRetval[0] = Primitive2DReference(
586  new ShadowPrimitive2D(
587  aShadowOffset,
588  rShadow.getColor(),
589  rShadow.getBlur(),
590  Primitive2DContainer(pContentForShadow ? *pContentForShadow : rContent)));
591 
592  if (0.0 != rShadow.getTransparence())
593  {
594  // create SimpleTransparencePrimitive2D
595  Primitive2DContainer aTempContent{ aRetval[0] };
596 
597  aRetval[0] = Primitive2DReference(
599  std::move(aTempContent),
600  rShadow.getTransparence()));
601  }
602 
603  aRetval[1] = Primitive2DReference(new GroupPrimitive2D(std::move(rContent)));
604  return aRetval;
605  }
606 
607  Primitive2DContainer aRetval;
608  for (const auto& xChild : rContentForShadow)
609  {
610  double fChildTransparence = 0.0;
611  auto pChild = dynamic_cast<BufferedDecompositionPrimitive2D*>(xChild.get());
612  if (pChild)
613  {
614  fChildTransparence = pChild->getTransparenceForShadow();
615  fChildTransparence /= 100;
616  }
617  aRetval.push_back(Primitive2DReference(
618  new ShadowPrimitive2D(aShadowOffset, rShadow.getColor(), rShadow.getBlur(),
619  Primitive2DContainer({ xChild }))));
620  if (rShadow.getTransparence() != 0.0 || fChildTransparence != 0.0)
621  {
622  Primitive2DContainer aTempContent{ aRetval.back() };
623 
624  double fChildAlpha = 1.0 - fChildTransparence;
625  double fShadowAlpha = 1.0 - rShadow.getTransparence();
626  double fTransparence = 1.0 - fChildAlpha * fShadowAlpha;
628  std::move(aTempContent), fTransparence));
629  }
630  }
631 
632  aRetval.push_back(
633  Primitive2DReference(new GroupPrimitive2D(std::move(rContent))));
634  return aRetval;
635  }
636 
638  Primitive2DContainer&& rContent,
639  const attribute::SdrGlowAttribute& rGlow)
640  {
641  if(rContent.empty())
642  return std::move(rContent);
643  Primitive2DContainer aRetval(2);
644  aRetval[0] = Primitive2DReference(
645  new GlowPrimitive2D(rGlow.getColor(), rGlow.getRadius(), Primitive2DContainer(rContent)));
646  aRetval[1] = Primitive2DReference(new GroupPrimitive2D(Primitive2DContainer(rContent)));
647  return aRetval;
648  }
649 
651  sal_Int32 nRadius)
652  {
653  if (aContent.empty() || !nRadius)
654  return std::move(aContent);
655  Primitive2DContainer aRetval(1);
656  aRetval[0] = Primitive2DReference(new SoftEdgePrimitive2D(nRadius, std::move(aContent)));
657  return aRetval;
658  }
659 
660 } // end of namespace
661 
662 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double getY() const
B2DPolygon growInNormalDirection(const B2DPolygon &rCandidate, double fValue)
const FillGradientAttribute & getGradient() const
void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
css::drawing::LineCap getCap() const
bool moreOrEqual(const T &rfValA, const T &rfValB)
B2DTuple absolute(const B2DTuple &rTup)
bool equalZero(const T &rfVal)
const basegfx::BColor & getColor() const
const basegfx::BColor & getColor() const
bool IsTopToBottom() const
void setX(double fX)
const basegfx::B2DPolyPolygon & getStartPolyPolygon() const
Primitive2DContainer createEmbeddedGlowPrimitive(Primitive2DContainer &&rContent, const attribute::SdrGlowAttribute &rGlow)
Primitive2DContainer createEmbeddedShadowPrimitive(Primitive2DContainer &&rContent, const attribute::SdrShadowAttribute &rShadow, const basegfx::B2DHomMatrix &rObjectMatrix, const Primitive2DContainer *pContentForShadow)
B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY)
basegfx::B2DLineJoin getJoin() const
B2DHomMatrix createScaleTranslateB2DHomMatrix(double fScaleX, double fScaleY, double fTranslateX, double fTranslateY)
const FillHatchAttribute & getHatch() const
Primitive2DReference createPolyPolygonFillPrimitive(const basegfx::B2DPolyPolygon &rPolyPolygon, const basegfx::B2DRange &rDefinitionRange, const attribute::SdrFillAttribute &rFill, const attribute::FillGradientAttribute &rFillGradient)
SdrTextHorzAdjust getSdrTextHorzAdjust() const
bool isClosed() const
const OutlinerParaObject & getOutlinerParaObject() const
FillGraphicAttribute createFillGraphicAttribute(const basegfx::B2DRange &rRange) const
const basegfx::B2DPolyPolygon & getEndPolyPolygon() const
void getScrollTextTiming(drawinglayer::animation::AnimationEntryList &rAnimList, double fFrameLength, double fTextLength) const
virtual double getDuration() const override
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
SdrTextObj & GetObject() const
Definition: svdtext.hxx:64
B2DPolygon createPolygonFromRect(const B2DRectangle &rRect, double fRadiusX, double fRadiusY)
const basegfx::B2DVector & getOffset() const
const ::std::vector< double > & getDotDashArray() const
const basegfx::BColor & getColor() const
void scale(double fX, double fY)
void transform(const basegfx::B2DHomMatrix &rMatrix)
Primitive2DReference createTextPrimitive(const basegfx::B2DPolyPolygon &rUnitPolyPolygon, const basegfx::B2DHomMatrix &rObjectTransform, const attribute::SdrTextAttribute &rText, const attribute::SdrLineAttribute &rStroke, bool bCellText, bool bWordWrap)
B2DRange getRange(const B2DPolygon &rCandidate)
void transform(const basegfx::B2DHomMatrix &rMatrix)
void setY(double fY)
bool IsEffectivelyVertical() const
void getBlinkTextTiming(drawinglayer::animation::AnimationEntryList &rAnimList) const
bool less(const T &rfValA, const T &rfValB)
Primitive2DContainer createEmbeddedSoftEdgePrimitive(Primitive2DContainer &&aContent, sal_Int32 nRadius)
SdrTextAniDirection GetTextAniDirection() const
Definition: svdotext.cxx:1762
void translate(double fX, double fY)
SdrTextAniDirection
Definition: sdtaditm.hxx:29
const SdrFormTextAttribute & getSdrFormTextAttribute() const
double getX() const
const SdrFillGraphicAttribute & getFillGraphic() const
SdrTextVertAdjust getSdrTextVertAdjust() const
const basegfx::B2DVector & getSize() const
B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(double fShearX, double fRadiant, double fTranslateX, double fTranslateY)
Primitive2DReference createPolygonLinePrimitive(const basegfx::B2DPolygon &rPolygon, const attribute::SdrLineAttribute &rLine, const attribute::SdrLineStartEndAttribute &rStroke)
void expand(const Tuple2D< double > &rTuple)