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