LibreOffice Module svx (master)  1
svdotxtr.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 
20 
21 #include <svx/svdotext.hxx>
22 #include <svx/svdtrans.hxx>
23 #include <svx/svdogrp.hxx>
24 #include <svx/svdopath.hxx>
25 #include <svx/svdoutl.hxx>
26 #include <svx/svdpage.hxx>
27 #include <svx/svdmodel.hxx>
28 #include <editeng/editdata.hxx>
29 #include <editeng/outliner.hxx>
33 #include <svl/itemset.hxx>
34 #include <svx/svditer.hxx>
37 #include <svx/xfillit0.hxx>
38 #include <svx/xflclit.hxx>
39 #include <svx/xlineit0.hxx>
40 #include <svx/xlnclit.hxx>
41 #include <svx/xlnwtit.hxx>
42 #include <svx/sdshitm.hxx>
43 
44 using namespace com::sun::star;
45 
47 {
48  if (aGeo.nRotationAngle!=0 || aGeo.nShearAngle!=0)
49  {
50  // Either the rotation or shear angle exists.
51  tools::Rectangle aSR0(GetSnapRect());
52  long nWdt0=aSR0.Right()-aSR0.Left();
53  long nHgt0=aSR0.Bottom()-aSR0.Top();
54  long nWdt1=rRect.Right()-rRect.Left();
55  long nHgt1=rRect.Bottom()-rRect.Top();
56  SdrTextObj::NbcResize(maSnapRect.TopLeft(),Fraction(nWdt1,nWdt0),Fraction(nHgt1,nHgt0));
57  SdrTextObj::NbcMove(Size(rRect.Left()-aSR0.Left(),rRect.Top()-aSR0.Top()));
58  }
59  else
60  {
61  // No rotation or shear.
62 
63  maRect = rRect;
64  ImpJustifyRect(maRect);
65 
66  AdaptTextMinSize();
67 
68  ImpCheckShear();
69  SetRectsDirty();
70  }
71 }
72 
74 {
75  return maRect;
76 }
77 
79 {
80  maRect = rRect;
81  ImpJustifyRect(maRect);
82 
83  AdaptTextMinSize();
84 
85  SetRectsDirty();
86 }
87 
89 {
90  return aGeo.nRotationAngle;
91 }
92 
93 long SdrTextObj::GetShearAngle(bool /*bVertical*/) const
94 {
95  return aGeo.nShearAngle;
96 }
97 
98 void SdrTextObj::NbcMove(const Size& rSiz)
99 {
100  maRect.Move(rSiz);
101  aOutRect.Move(rSiz);
102  maSnapRect.Move(rSiz);
103  SetRectsDirty(true);
104 }
105 
106 void SdrTextObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
107 {
108  bool bNotSheared=aGeo.nShearAngle==0;
109  bool bRotate90=bNotSheared && aGeo.nRotationAngle % 9000 ==0;
110  bool bXMirr=(xFact.GetNumerator()<0) != (xFact.GetDenominator()<0);
111  bool bYMirr=(yFact.GetNumerator()<0) != (yFact.GetDenominator()<0);
112  if (bXMirr || bYMirr) {
113  Point aRef1(GetSnapRect().Center());
114  if (bXMirr) {
115  Point aRef2(aRef1);
116  aRef2.AdjustY( 1 );
117  NbcMirrorGluePoints(aRef1,aRef2);
118  }
119  if (bYMirr) {
120  Point aRef2(aRef1);
121  aRef2.AdjustX( 1 );
122  NbcMirrorGluePoints(aRef1,aRef2);
123  }
124  }
125 
126  if (aGeo.nRotationAngle==0 && aGeo.nShearAngle==0) {
127  ResizeRect(maRect,rRef,xFact,yFact);
128  if (bYMirr) {
129  maRect.Justify();
130  maRect.Move(maRect.Right()-maRect.Left(),maRect.Bottom()-maRect.Top());
131  aGeo.nRotationAngle=18000;
132  aGeo.RecalcSinCos();
133  }
134  }
135  else
136  {
137  tools::Polygon aPol(Rect2Poly(maRect,aGeo));
138 
139  for(sal_uInt16 a(0); a < aPol.GetSize(); a++)
140  {
141  ResizePoint(aPol[a], rRef, xFact, yFact);
142  }
143 
144  if(bXMirr != bYMirr)
145  {
146  // turn polygon and move it a little
147  tools::Polygon aPol0(aPol);
148 
149  aPol[0] = aPol0[1];
150  aPol[1] = aPol0[0];
151  aPol[2] = aPol0[3];
152  aPol[3] = aPol0[2];
153  aPol[4] = aPol0[1];
154  }
155 
156  Poly2Rect(aPol, maRect, aGeo);
157  }
158 
159  if (bRotate90) {
160  bool bRota90=aGeo.nRotationAngle % 9000 ==0;
161  if (!bRota90) { // there's seems to be a rounding error occurring: correct it
162  long a=NormAngle36000(aGeo.nRotationAngle);
163  if (a<4500) a=0;
164  else if (a<13500) a=9000;
165  else if (a<22500) a=18000;
166  else if (a<31500) a=27000;
167  else a=0;
168  aGeo.nRotationAngle=a;
169  aGeo.RecalcSinCos();
170  }
171  if (bNotSheared!=(aGeo.nShearAngle==0)) { // correct a rounding error occurring with Shear
172  aGeo.nShearAngle=0;
173  aGeo.RecalcTan();
174  }
175  }
176 
177  ImpJustifyRect(maRect);
178 
179  AdaptTextMinSize();
180 
181  if(bTextFrame && !getSdrModelFromSdrObject().IsPasteResize())
182  {
183  NbcAdjustTextFrameWidthAndHeight();
184  }
185 
186  ImpCheckShear();
187  SetRectsDirty();
188 }
189 
190 void SdrTextObj::NbcRotate(const Point& rRef, long nAngle, double sn, double cs)
191 {
192  SetGlueReallyAbsolute(true);
193  long dx=maRect.Right()-maRect.Left();
194  long dy=maRect.Bottom()-maRect.Top();
195  Point aP(maRect.TopLeft());
196  RotatePoint(aP,rRef,sn,cs);
197  maRect.SetLeft(aP.X() );
198  maRect.SetTop(aP.Y() );
199  maRect.SetRight(maRect.Left()+dx );
200  maRect.SetBottom(maRect.Top()+dy );
201  if (aGeo.nRotationAngle==0) {
202  aGeo.nRotationAngle=NormAngle36000(nAngle);
203  aGeo.nSin=sn;
204  aGeo.nCos=cs;
205  } else {
206  aGeo.nRotationAngle=NormAngle36000(aGeo.nRotationAngle+nAngle);
207  aGeo.RecalcSinCos();
208  }
209  SetRectsDirty();
210  NbcRotateGluePoints(rRef,nAngle,sn,cs);
211  SetGlueReallyAbsolute(false);
212 }
213 
214 void SdrTextObj::NbcShear(const Point& rRef, long /*nAngle*/, double tn, bool bVShear)
215 {
216  SetGlueReallyAbsolute(true);
217 
218  // when this is a SdrPathObj, aRect may be uninitialized
219  tools::Polygon aPol(Rect2Poly(maRect.IsEmpty() ? GetSnapRect() : maRect, aGeo));
220 
221  sal_uInt16 nPointCount=aPol.GetSize();
222  for (sal_uInt16 i=0; i<nPointCount; i++) {
223  ShearPoint(aPol[i],rRef,tn,bVShear);
224  }
225  Poly2Rect(aPol,maRect,aGeo);
226  ImpJustifyRect(maRect);
227  if (bTextFrame) {
228  NbcAdjustTextFrameWidthAndHeight();
229  }
230  ImpCheckShear();
231  SetRectsDirty();
232  NbcShearGluePoints(rRef,tn,bVShear);
233  SetGlueReallyAbsolute(false);
234 }
235 
236 void SdrTextObj::NbcMirror(const Point& rRef1, const Point& rRef2)
237 {
238  SetGlueReallyAbsolute(true);
239  bool bNotSheared=aGeo.nShearAngle==0;
240  bool bRotate90 = false;
241  if (bNotSheared &&
242  (rRef1.X()==rRef2.X() || rRef1.Y()==rRef2.Y() ||
243  std::abs(rRef1.X()-rRef2.X())==std::abs(rRef1.Y()-rRef2.Y()))) {
244  bRotate90=aGeo.nRotationAngle % 9000 ==0;
245  }
246  tools::Polygon aPol(Rect2Poly(maRect,aGeo));
247  sal_uInt16 i;
248  sal_uInt16 nPointCount=aPol.GetSize();
249  for (i=0; i<nPointCount; i++) {
250  MirrorPoint(aPol[i],rRef1,rRef2);
251  }
252  // turn polygon and move it a little
253  tools::Polygon aPol0(aPol);
254  aPol[0]=aPol0[1];
255  aPol[1]=aPol0[0];
256  aPol[2]=aPol0[3];
257  aPol[3]=aPol0[2];
258  aPol[4]=aPol0[1];
259  Poly2Rect(aPol,maRect,aGeo);
260 
261  if (bRotate90) {
262  bool bRota90=aGeo.nRotationAngle % 9000 ==0;
263  if (bRotate90 && !bRota90) { // there's seems to be a rounding error occurring: correct it
264  long a=NormAngle36000(aGeo.nRotationAngle);
265  if (a<4500) a=0;
266  else if (a<13500) a=9000;
267  else if (a<22500) a=18000;
268  else if (a<31500) a=27000;
269  else a=0;
270  aGeo.nRotationAngle=a;
271  aGeo.RecalcSinCos();
272  }
273  }
274  if (bNotSheared!=(aGeo.nShearAngle==0)) { // correct a rounding error occurring with Shear
275  aGeo.nShearAngle=0;
276  aGeo.RecalcTan();
277  }
278 
279  ImpJustifyRect(maRect);
280  if (bTextFrame) {
281  NbcAdjustTextFrameWidthAndHeight();
282  }
283  ImpCheckShear();
284  SetRectsDirty();
285  NbcMirrorGluePoints(rRef1,rRef2);
286  SetGlueReallyAbsolute(false);
287 }
288 
289 
291 {
292  SdrObjectUniquePtr pRetval;
293 
294  if(!ImpCanConvTextToCurve())
295  {
296  // suppress HelpTexts from PresObj's
297  return nullptr;
298  }
299 
300  // get primitives
301  const drawinglayer::primitive2d::Primitive2DContainer & xSequence(GetViewContact().getViewIndependentPrimitive2DContainer());
302 
303  if(!xSequence.empty())
304  {
305  // create an extractor with neutral ViewInformation
306  const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
307  drawinglayer::processor2d::TextAsPolygonExtractor2D aExtractor(aViewInformation2D);
308 
309  // extract text as polygons
310  aExtractor.process(xSequence);
311 
312  // get results
314  const sal_uInt32 nResultCount(rResult.size());
315 
316  if(nResultCount)
317  {
318  // prepare own target
319  SdrObjGroup* pGroup = new SdrObjGroup(getSdrModelFromSdrObject());
320  SdrObjList* pObjectList = pGroup->GetSubList();
321 
322  // process results
323  for(sal_uInt32 a(0); a < nResultCount; a++)
324  {
325  const drawinglayer::processor2d::TextAsPolygonDataNode& rCandidate = rResult[a];
326  basegfx::B2DPolyPolygon aPolyPolygon(rCandidate.getB2DPolyPolygon());
327 
328  if(aPolyPolygon.count())
329  {
330  // take care of wanted polygon type
331  if(bToPoly)
332  {
333  if(aPolyPolygon.areControlPointsUsed())
334  {
335  aPolyPolygon = basegfx::utils::adaptiveSubdivideByAngle(aPolyPolygon);
336  }
337  }
338  else
339  {
340  if(!aPolyPolygon.areControlPointsUsed())
341  {
342  aPolyPolygon = basegfx::utils::expandToCurve(aPolyPolygon);
343  }
344  }
345 
346  // create ItemSet with object attributes
347  SfxItemSet aAttributeSet(GetObjectItemSet());
348  SdrPathObj* pPathObj = nullptr;
349 
350  // always clear objectshadow; this is included in the extraction
351  aAttributeSet.Put(makeSdrShadowItem(false));
352 
353  if(rCandidate.getIsFilled())
354  {
355  // set needed items
356  aAttributeSet.Put(XFillColorItem(OUString(), Color(rCandidate.getBColor())));
357  aAttributeSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
358  aAttributeSet.Put(XFillStyleItem(drawing::FillStyle_SOLID));
359 
360  // create filled SdrPathObj
361  pPathObj = new SdrPathObj(
362  getSdrModelFromSdrObject(),
363  OBJ_PATHFILL,
364  aPolyPolygon);
365  }
366  else
367  {
368  // set needed items
369  aAttributeSet.Put(XLineColorItem(OUString(), Color(rCandidate.getBColor())));
370  aAttributeSet.Put(XLineStyleItem(drawing::LineStyle_SOLID));
371  aAttributeSet.Put(XLineWidthItem(0));
372  aAttributeSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
373 
374  // create line SdrPathObj
375  pPathObj = new SdrPathObj(
376  getSdrModelFromSdrObject(),
377  OBJ_PATHLINE,
378  aPolyPolygon);
379  }
380 
381  // copy basic information from original
382  pPathObj->ImpSetAnchorPos(GetAnchorPos());
383  pPathObj->NbcSetLayer(GetLayer());
384  pPathObj->NbcSetStyleSheet(GetStyleSheet(), true);
385 
386  // apply prepared ItemSet and add to target
387  pPathObj->SetMergedItemSet(aAttributeSet);
388  pObjectList->InsertObject(pPathObj);
389  }
390  }
391 
392  // postprocess; if no result and/or only one object, simplify
393  if(!pObjectList->GetObjCount())
394  {
395  // always use SdrObject::Free(...) for SdrObjects (!)
396  SdrObject* pTemp(pGroup);
397  SdrObject::Free(pTemp);
398  }
399  else if(1 == pObjectList->GetObjCount())
400  {
401  pRetval.reset(pObjectList->RemoveObject(0));
402 
403  // always use SdrObject::Free(...) for SdrObjects (!)
404  SdrObject* pTemp(pGroup);
405  SdrObject::Free(pTemp);
406  }
407  else
408  {
409  pRetval.reset(pGroup);
410  }
411  }
412  }
413 
414  return pRetval;
415 }
416 
417 
418 SdrObjectUniquePtr SdrTextObj::DoConvertToPolyObj(bool bBezier, bool bAddText) const
419 {
420  if(bAddText)
421  {
422  return ImpConvertContainedTextToSdrPathObjs(!bBezier);
423  }
424 
425  return nullptr;
426 }
427 
429 {
430  return !IsOutlText();
431 }
432 
433 SdrPathObjUniquePtr SdrTextObj::ImpConvertMakeObj(const basegfx::B2DPolyPolygon& rPolyPolygon, bool bClosed, bool bBezier) const
434 {
435  SdrObjKind ePathKind = bClosed ? OBJ_PATHFILL : OBJ_PATHLINE;
436  basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPolygon);
437 
438  // #i37011#
439  if(!bBezier)
440  {
441  aB2DPolyPolygon = basegfx::utils::adaptiveSubdivideByAngle(aB2DPolyPolygon);
442  ePathKind = bClosed ? OBJ_POLY : OBJ_PLIN;
443  }
444 
445  SdrPathObjUniquePtr pPathObj(new SdrPathObj(
446  getSdrModelFromSdrObject(),
447  ePathKind,
448  aB2DPolyPolygon));
449 
450  if(bBezier)
451  {
452  // create bezier curves
453  pPathObj->SetPathPoly(basegfx::utils::expandToCurve(pPathObj->GetPathPoly()));
454  }
455 
456  pPathObj->ImpSetAnchorPos(aAnchor);
457  pPathObj->NbcSetLayer(GetLayer());
459  pPathObj->ClearMergedItem();
460  pPathObj->SetMergedItemSet(GetObjectItemSet());
461  pPathObj->GetProperties().BroadcastItemChange(aC);
462  pPathObj->NbcSetStyleSheet(GetStyleSheet(), true);
463 
464  return pPathObj;
465 }
466 
468 {
469  if(!ImpCanConvTextToCurve())
470  {
471  return pObj;
472  }
473 
474  SdrObjectUniquePtr pText = ImpConvertContainedTextToSdrPathObjs(!bBezier);
475 
476  if(!pText)
477  {
478  return pObj;
479  }
480 
481  if(!pObj)
482  {
483  return pText;
484  }
485 
486  if(pText->IsGroupObject())
487  {
488  // is already group object, add partial shape in front
489  SdrObjList* pOL=pText->GetSubList();
490  pOL->InsertObject(pObj.release(),0);
491 
492  return pText;
493  }
494  else
495  {
496  // not yet a group, create one and add partial and new shapes
497  std::unique_ptr<SdrObjGroup, SdrObjectFreeOp> pGrp(new SdrObjGroup(getSdrModelFromSdrObject()));
498  SdrObjList* pOL=pGrp->GetSubList();
499  pOL->InsertObject(pObj.release());
500  pOL->InsertObject(pText.release());
501 
502  return pGrp;
503  }
504 }
505 
506 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::vector< TextAsPolygonDataNode > TextAsPolygonDataNodeVector
virtual void NbcResize(const Point &rRef, const Fraction &xFact, const Fraction &yFact) override
Definition: svdotxtr.cxx:106
void ShearPoint(Point &rPnt, const Point &rRef, double tn, bool bVShear=false)
Definition: svdtrans.hxx:122
long AdjustX(long nHorzMove)
void ResizePoint(Point &rPnt, const Point &rRef, const Fraction &xFract, const Fraction &yFract)
Definition: svdtrans.hxx:106
const TextAsPolygonDataNodeVector & getTarget() const
void Poly2Rect(const tools::Polygon &rPol, tools::Rectangle &rRect, GeoStat &rGeo)
Definition: svdtrans.cxx:486
B2DPolygon expandToCurve(const B2DPolygon &rCandidate)
bool ImpCanConvTextToCurve() const
Definition: svdotxtr.cxx:428
const basegfx::B2DPolyPolygon & getB2DPolyPolygon() const
size_t GetObjCount() const
Definition: svdpage.cxx:767
SdrObjectUniquePtr ImpConvertAddText(SdrObjectUniquePtr pObj, bool bBezier) const
Definition: svdotxtr.cxx:467
circle cut
Definition: svdobj.hxx:125
static void Free(SdrObject *&_rpObject)
Definition: svdobj.cxx:423
virtual void InsertObject(SdrObject *pObj, size_t nPos=SAL_MAX_SIZE)
Definition: svdpage.cxx:358
Center
long NormAngle36000(long a)
Normalize angle to -180.00..179.99.
Definition: svdtrans.cxx:407
std::unique_ptr< SdrPathObj, SdrObjectFreeOp > SdrPathObjUniquePtr
Definition: svdotext.hxx:135
polygon, PolyPolygon
Definition: svdobj.hxx:126
void ImpSetAnchorPos(const Point &rPnt)
Definition: svdobj.cxx:1592
virtual void NbcMirror(const Point &rRef1, const Point &rRef2) override
Definition: svdotxtr.cxx:236
virtual long GetRotateAngle() const override
Definition: svdotxtr.cxx:88
long Right() const
SVX_DLLPRIVATE SdrObjectUniquePtr ImpConvertContainedTextToSdrPathObjs(bool bToPoly) const
Definition: svdotxtr.cxx:290
void SetMergedItemSet(const SfxItemSet &rSet, bool bClearAllItems=false)
Definition: svdobj.cxx:1936
PolyLine.
Definition: svdobj.hxx:127
long Top() const
void ResizeRect(tools::Rectangle &rRect, const Point &rRef, const Fraction &rxFact, const Fraction &ryFact)
Definition: svdtrans.cxx:36
long AdjustY(long nVertMove)
uno_Any a
SdrPathObjUniquePtr ImpConvertMakeObj(const basegfx::B2DPolyPolygon &rPolyPolygon, bool bClosed, bool bBezier) const
Definition: svdotxtr.cxx:433
int i
const basegfx::BColor & getBColor() const
void MirrorPoint(Point &rPnt, const Point &rRef1, const Point &rRef2)
Definition: svdtrans.cxx:103
virtual long GetShearAngle(bool bVertical=false) const override
Definition: svdotxtr.cxx:93
long Bottom() const
void process(const primitive2d::Primitive2DContainer &rSource)
sal_uInt16 GetSize() const
tools::Polygon Rect2Poly(const tools::Rectangle &rRect, const GeoStat &rGeo)
Definition: svdtrans.cxx:473
virtual SdrObjList * GetSubList() const override
Definition: svdogrp.cxx:186
virtual void NbcMove(const Size &rSiz) override
The methods Move, Resize, Rotate, Mirror, Shear, SetSnapRect and SetLogicRect call the corresponding ...
Definition: svdotxtr.cxx:98
Abstract DrawObject.
Definition: svdobj.hxx:312
virtual SdrObject * RemoveObject(size_t nObjNum)
Definition: svdpage.cxx:436
long X() const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
void RotatePoint(Point &rPnt, const Point &rRef, double sn, double cs)
Definition: svdtrans.hxx:114
sal_Int32 GetDenominator() const
B2DPolygon adaptiveSubdivideByAngle(const B2DPolygon &rCandidate, double fAngleBound)
SdrObjKind
Definition: svdobj.hxx:116
sal_Int32 GetNumerator() const
std::unique_ptr< SdrObject, SdrObjectFreeOp > SdrObjectUniquePtr
Definition: svdobj.hxx:114
SdrOnOffItem makeSdrShadowItem(bool bShadow)
Definition: sdshitm.hxx:25
long Left() const
virtual void NbcRotate(const Point &rRef, long nAngle, double sn, double cs) override
Definition: svdotxtr.cxx:190
virtual void NbcSetStyleSheet(SfxStyleSheet *pNewStyleSheet, bool bDontRemoveHardAttr)
Definition: svdobj.cxx:2180
virtual void NbcSetLogicRect(const tools::Rectangle &rRect) override
Definition: svdotxtr.cxx:78
virtual void NbcShear(const Point &rRef, long nAngle, double tn, bool bVShear) override
Definition: svdotxtr.cxx:214
virtual SdrObjectUniquePtr DoConvertToPolyObj(bool bBezier, bool bAddText) const override
Definition: svdotxtr.cxx:418
open Bezier-curve
Definition: svdobj.hxx:128
virtual void NbcSetSnapRect(const tools::Rectangle &rRect) override
Definition: svdotxtr.cxx:46
long Y() const
virtual const tools::Rectangle & GetLogicRect() const override
Definition: svdotxtr.cxx:73
virtual void NbcSetLayer(SdrLayerID nLayer)
Definition: svdobj.cxx:621