LibreOffice Module svx (master)  1
viewcontactofgraphic.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 
22 #include <svx/svdograf.hxx>
23 #include <sdgtritm.hxx>
24 #include <svx/sdgluitm.hxx>
25 #include <sdgcoitm.hxx>
26 #include <svx/sdggaitm.hxx>
27 #include <sdginitm.hxx>
28 #include <svx/sdgmoitm.hxx>
30 #include <svl/itemset.hxx>
31 #include <tools/debug.hxx>
32 
33 #include <svx/sdgcpitm.hxx>
38 #include <vcl/canvastools.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/settings.hxx>
45 #include <editeng/eeitem.hxx>
46 #include <editeng/colritem.hxx>
50 
51 #include <bitmaps.hlst>
52 
53 namespace sdr::contact
54 {
55  // Create an Object-Specific ViewObjectContact, set ViewContact and
56  // ObjectContact. Always needs to return something.
58  {
59  ViewObjectContact* pRetval = new ViewObjectContactOfGraphic(rObjectContact, *this);
60  DBG_ASSERT(pRetval, "ViewContact::CreateObjectSpecificViewObjectContact() failed (!)");
61 
62  return *pRetval;
63  }
64 
66  : ViewContactOfTextObj(rGrafObj)
67  {
68  }
69 
71  {
72  }
73 
75  const basegfx::B2DHomMatrix& rObjectMatrix,
77  {
79  GraphicObject aEmptyGraphicObject;
80  GraphicAttr aEmptyGraphicAttr;
81 
82  // SdrGrafPrimitive2D without content in original size which carries all eventual attributes and texts
84  rObjectMatrix,
85  rAttribute,
86  aEmptyGraphicObject,
87  aEmptyGraphicAttr));
88  xRetval = drawinglayer::primitive2d::Primitive2DContainer { xReferenceA };
89 
90  // SdrGrafPrimitive2D with content (which is the preview graphic) scaled to smaller size and
91  // without attributes
92  basegfx::B2DHomMatrix aSmallerMatrix;
93 
94  // #i94431# for some reason, i forgot to take the PrefMapMode of the graphic
95  // into account. Since EmptyPresObj's are only used in Draw/Impress, it is
96  // safe to assume 100th mm as target.
97  Size aPrefSize(GetGrafObject().GetGrafPrefSize());
98 
99  if(MapUnit::MapPixel == GetGrafObject().GetGrafPrefMapMode().GetMapUnit())
100  {
101  aPrefSize = Application::GetDefaultDevice()->PixelToLogic(aPrefSize, MapMode(MapUnit::Map100thMM));
102  }
103  else
104  {
105  aPrefSize = OutputDevice::LogicToLogic(aPrefSize, GetGrafObject().GetGrafPrefMapMode(), MapMode(MapUnit::Map100thMM));
106  }
107 
108  // decompose object matrix to get single values
109  basegfx::B2DVector aScale, aTranslate;
110  double fRotate, fShearX;
111  rObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
112 
113  const double fOffsetX((aScale.getX() - aPrefSize.getWidth()) / 2.0);
114  const double fOffsetY((aScale.getY() - aPrefSize.getHeight()) / 2.0);
115 
116  if(basegfx::fTools::moreOrEqual(fOffsetX, 0.0) && basegfx::fTools::moreOrEqual(fOffsetY, 0.0))
117  {
118  // create the EmptyPresObj fallback visualisation. The fallback graphic
119  // is already provided in rGraphicObject in this case, use it
120  aSmallerMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(aPrefSize.getWidth(), aPrefSize.getHeight(), fOffsetX, fOffsetY);
121  aSmallerMatrix = basegfx::utils::createShearXRotateTranslateB2DHomMatrix(fShearX, fRotate, aTranslate)
122  * aSmallerMatrix;
123 
124  const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject();
125  const GraphicAttr aLocalGrafInfo;
127  aSmallerMatrix,
129  rGraphicObject,
130  aLocalGrafInfo));
131 
132  xRetval.push_back(xReferenceB);
133  }
134 
135  return xRetval;
136  }
137 
139  const basegfx::B2DHomMatrix& rObjectMatrix,
141  {
143  GraphicObject aEmptyGraphicObject;
144  GraphicAttr aEmptyGraphicAttr;
145 
146  // SdrGrafPrimitive2D without content in original size which carries all eventual attributes and texts
148  rObjectMatrix,
149  rAttribute,
150  aEmptyGraphicObject,
151  aEmptyGraphicAttr));
152  xRetval = drawinglayer::primitive2d::Primitive2DContainer { xReferenceA };
153 
154  if(rAttribute.getLine().isDefault())
155  {
156  // create a surrounding frame when no linestyle given
157  const Color aColor(Application::GetSettings().GetStyleSettings().GetShadowColor());
158  const basegfx::BColor aBColor(aColor.getBColor());
160  aOutline.transform(rObjectMatrix);
161 
162  xRetval.push_back(
165  aOutline,
166  aBColor)));
167  }
168 
169  // decompose object matrix to get single values
170  basegfx::B2DVector aScale, aTranslate;
171  double fRotate, fShearX;
172  rObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
173 
174  // define a distance value, used for distance from bitmap to borders and from bitmap
175  // to text, too (2 mm)
176  const double fDistance(200.0);
177 
178  // consume borders from values
179  aScale.setX(std::max(0.0, aScale.getX() - (2.0 * fDistance)));
180  aScale.setY(std::max(0.0, aScale.getY() - (2.0 * fDistance)));
181  aTranslate.setX(aTranslate.getX() + fDistance);
182  aTranslate.setY(aTranslate.getY() + fDistance);
183 
184  // draw a draft bitmap
185  const BitmapEx aDraftBitmap(BMAP_GrafikEi);
186 
187  if(!aDraftBitmap.IsEmpty())
188  {
189  Size aPrefSize(aDraftBitmap.GetPrefSize());
190 
191  if(MapUnit::MapPixel == aDraftBitmap.GetPrefMapMode().GetMapUnit())
192  {
193  aPrefSize = Application::GetDefaultDevice()->PixelToLogic(aDraftBitmap.GetSizePixel(), MapMode(MapUnit::Map100thMM));
194  }
195  else
196  {
197  aPrefSize = OutputDevice::LogicToLogic(aPrefSize, aDraftBitmap.GetPrefMapMode(), MapMode(MapUnit::Map100thMM));
198  }
199 
200  const double fBitmapScaling(2.0);
201  const double fWidth(aPrefSize.getWidth() * fBitmapScaling);
202  const double fHeight(aPrefSize.getHeight() * fBitmapScaling);
203 
204  if(basegfx::fTools::more(fWidth, 1.0)
205  && basegfx::fTools::more(fHeight, 1.0)
206  && basegfx::fTools::lessOrEqual(fWidth, aScale.getX())
207  && basegfx::fTools::lessOrEqual(fHeight, aScale.getY()))
208  {
210  fWidth, fHeight, fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
211 
212  xRetval.push_back(
215  VCLUnoHelper::CreateVCLXBitmap(aDraftBitmap),
216  aBitmapMatrix)));
217 
218  // consume bitmap size in X
219  aScale.setX(std::max(0.0, aScale.getX() - (fWidth + fDistance)));
220  aTranslate.setX(aTranslate.getX() + fWidth + fDistance);
221  }
222  }
223 
224  // Build the text for the draft object
225  OUString aDraftText = GetGrafObject().GetFileName();
226 
227  if (aDraftText.isEmpty())
228  {
229  aDraftText = GetGrafObject().GetName() + " ...";
230  }
231 
232  if (!aDraftText.isEmpty())
233  {
234  // #i103255# Goal is to produce TextPrimitives which hold the given text as
235  // BlockText in the available space. It would be very tricky to do
236  // an own word wrap/line layout here.
237  // Using SdrBlockTextPrimitive2D OTOH is critical since it internally
238  // uses the SdrObject it references. To solve this, create a temp
239  // SdrObject with Attributes and Text, generate a SdrBlockTextPrimitive2D
240  // directly and immediately decompose it. After that, it is no longer
241  // needed and can be deleted.
242 
243  // create temp RectObj as TextObj and set needed attributes
244  SdrRectObj* pRectObj(new SdrRectObj(GetGrafObject().getSdrModelFromSdrObject(), OBJ_TEXT));
245  pRectObj->NbcSetText(aDraftText);
247 
248  // get SdrText and OPO
249  SdrText* pSdrText(pRectObj->getText(0));
250  OutlinerParaObject* pOPO(pRectObj->GetOutlinerParaObject());
251 
252  if(pSdrText && pOPO)
253  {
254  // directly use the remaining space as TextRangeTransform
256  aScale, fShearX, fRotate, aTranslate));
257 
258  // directly create temp SdrBlockTextPrimitive2D
260  pSdrText,
261  *pOPO,
262  aTextRangeTransform,
265  false,
266  false,
267  false,
268  false));
269 
270  // decompose immediately with neutral ViewInformation. This will
271  // layout the text to more simple TextPrimitives from drawinglayer
272  const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
273  xBlockTextPrimitive->get2DDecomposition(xRetval, aViewInformation2D);
274  }
275 
276  // always use SdrObject::Free(...) for SdrObjects (!)
277  SdrObject* pTemp(pRectObj);
278  SdrObject::Free(pTemp);
279  }
280 
281  return xRetval;
282  }
283 
285  {
287  const SfxItemSet& rItemSet = GetGrafObject().GetMergedItemSet();
288 
289  // create and fill GraphicAttr
290  GraphicAttr aLocalGrafInfo;
291  const sal_uInt16 nTrans(rItemSet.Get(SDRATTR_GRAFTRANSPARENCE).GetValue());
292  const SdrGrafCropItem& rCrop(rItemSet.Get(SDRATTR_GRAFCROP));
293  aLocalGrafInfo.SetLuminance(rItemSet.Get(SDRATTR_GRAFLUMINANCE).GetValue());
294  aLocalGrafInfo.SetContrast(rItemSet.Get(SDRATTR_GRAFCONTRAST).GetValue());
295  aLocalGrafInfo.SetChannelR(rItemSet.Get(SDRATTR_GRAFRED).GetValue());
296  aLocalGrafInfo.SetChannelG(rItemSet.Get(SDRATTR_GRAFGREEN).GetValue());
297  aLocalGrafInfo.SetChannelB(rItemSet.Get(SDRATTR_GRAFBLUE).GetValue());
298  aLocalGrafInfo.SetGamma(rItemSet.Get(SDRATTR_GRAFGAMMA).GetValue() * 0.01);
299  aLocalGrafInfo.SetTransparency(static_cast<sal_uInt8>(::basegfx::fround(std::min(nTrans, sal_uInt16(100)) * 2.55)));
300  aLocalGrafInfo.SetInvert(rItemSet.Get(SDRATTR_GRAFINVERT).GetValue());
301  aLocalGrafInfo.SetDrawMode(rItemSet.Get(SDRATTR_GRAFMODE).GetValue());
302  aLocalGrafInfo.SetCrop(rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom());
303 
304  // we have content if graphic is not completely transparent
305  const bool bHasContent(255L != aLocalGrafInfo.GetTransparency());
308  rItemSet,
309  GetGrafObject().getText(0),
310  bHasContent));
311 
312  // take unrotated snap rect for position and size. Directly use model data, not getBoundRect() or getSnapRect()
313  // which will use the primitive data we just create in the near future
314  const ::basegfx::B2DRange aObjectRange = vcl::unotools::b2DRectangleFromRectangle(GetGrafObject().GetGeoRect());
315 
316  // look for mirroring
317  const GeoStat& rGeoStat(GetGrafObject().GetGeoStat());
318  const sal_Int32 nRotationAngle(rGeoStat.nRotationAngle);
319  const bool bRota180(18000 == nRotationAngle);
320  const bool bMirrored(GetGrafObject().IsMirrored());
321  const sal_uInt16 nMirrorCase(bRota180 ? (bMirrored ? 3 : 4) : (bMirrored ? 2 : 1));
322  bool bHMirr((2 == nMirrorCase ) || (4 == nMirrorCase));
323  bool bVMirr((3 == nMirrorCase ) || (4 == nMirrorCase));
324 
325  // set mirror flags at LocalGrafInfo. Take into account that the geometry in
326  // aObjectRange is already changed and rotated when bRota180 is used. To rebuild
327  // that old behaviour (as long as part of the model data), correct the H/V flags
328  // accordingly. The created bitmapPrimitive WILL use the rotation, too.
329  if(bRota180)
330  {
331  // if bRota180 which is used for vertical mirroring, the graphic will already be rotated
332  // by 180 degrees. To correct, switch off VMirror and invert HMirroring.
333  bHMirr = !bHMirr;
334  bVMirr = false;
335  }
336 
337  if(bHMirr || bVMirr)
338  {
339  aLocalGrafInfo.SetMirrorFlags((bHMirr ? BmpMirrorFlags::Horizontal : BmpMirrorFlags::NONE)|(bVMirr ? BmpMirrorFlags::Vertical : BmpMirrorFlags::NONE));
340  }
341 
342  // fill object matrix
343  const double fShearX(rGeoStat.nShearAngle ? tan((36000 - rGeoStat.nShearAngle) * F_PI18000) : 0.0);
344  const double fRotate(nRotationAngle ? (36000 - nRotationAngle) * F_PI18000 : 0.0);
346  aObjectRange.getWidth(), aObjectRange.getHeight(),
347  fShearX, fRotate,
348  aObjectRange.getMinX(), aObjectRange.getMinY()));
349 
350  // get the current, unchanged graphic object from SdrGrafObj
351  const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject();
352 
354  {
355  // it's an EmptyPresObj, create the SdrGrafPrimitive2D without content and another scaled one
356  // with the content which is the placeholder graphic
357  xRetval = createVIP2DSForPresObj(aObjectMatrix, aAttribute);
358  }
359 #ifndef IOS // Enforce swap-in for tiled rendering for now, while we have no delayed updating mechanism
360  else if(visualisationUsesDraft())
361  {
362  // #i102380# The graphic is swapped out. To not force a swap-in here, there is a mechanism
363  // which shows a swapped-out-visualisation (which gets created here now) and an asynchronous
364  // visual update mechanism for swapped-out graphics when they were loaded (see AsynchGraphicLoadingEvent
365  // and ViewObjectContactOfGraphic implementation). Not forcing the swap-in here allows faster
366  // (non-blocking) processing here and thus in the effect e.g. fast scrolling through pages
367  xRetval = createVIP2DSForDraft(aObjectMatrix, aAttribute);
368  }
369 #endif
370  else
371  {
372  // create primitive. Info: Calling the copy-constructor of GraphicObject in this
373  // SdrGrafPrimitive2D constructor will force a full swap-in of the graphic
376  aObjectMatrix,
377  aAttribute,
378  rGraphicObject,
379  aLocalGrafInfo));
380 
381  xRetval = drawinglayer::primitive2d::Primitive2DContainer { xReference };
382  }
383 
384  // always append an invisible outline for the cases where no visible content exists
385  xRetval.push_back(
387  aObjectMatrix));
388 
389  return xRetval;
390  }
391 
393  {
394  return GetGrafObject().IsEmptyPresObj();
395  }
396 
398  {
399  // no draft when already PresObj
401  return false;
402 
403  // draft when swapped out
404  const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject();
405 
406  // draft when no graphic
407  return GraphicType::NONE == rGraphicObject.GetType() || GraphicType::Default == rGraphicObject.GetType();
408  }
409 
410 } // end of namespace
411 
412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool lessOrEqual(const double &rfValA, const double &rfValB)
void SetTransparency(sal_uInt8 cTransparency)
void SetGamma(double fGamma)
static bool moreOrEqual(const double &rfValA, const double &rfValB)
constexpr TypedWhichId< SdrGrafGamma100Item > SDRATTR_GRAFGAMMA(SDRATTR_GRAF_FIRST+5)
void setX(double fX)
const OUString & GetFileName() const
Definition: svdograf.hxx:169
B2DPolygon const & createUnitPolygon()
const MapMode & GetPrefMapMode() const
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
static bool more(const double &rfValA, const double &rfValB)
virtual SdrText * getText(sal_Int32 nIndex) const override
returns the nth available text.
Definition: svdotext.cxx:2057
tools::Long getWidth() const
void SetInvert(bool bInvert)
tools::Long nRotationAngle
Definition: svdtrans.hxx:216
static const AllSettings & GetSettings()
double getX() const
void SetMirrorFlags(BmpMirrorFlags nMirrFlags)
virtual ViewObjectContact & CreateObjectSpecificViewObjectContact(ObjectContact &rObjectContact) override
constexpr TypedWhichId< SdrGrafRedItem > SDRATTR_GRAFRED(SDRATTR_GRAF_FIRST+0)
double getY() const
const GraphicObject & GetGraphicObject(bool bForceSwapIn=false) const
Definition: svdograf.cxx:275
static void Free(SdrObject *&_rpObject)
Definition: svdobj.cxx:396
void SetDrawMode(GraphicDrawMode eDrawMode)
Rectangle objects (rectangle, circle, ...)
Definition: svdorect.hxx:39
static OutputDevice * GetDefaultDevice()
B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(double fScaleX, double fScaleY, double fShearX, double fRadiant, double fTranslateX, double fTranslateY)
const Size & GetPrefSize() const
The transformation of a rectangle into a polygon, by using angle parameters from GeoStat.
Definition: svdtrans.hxx:214
const SdrGrafObj & GetGrafObject() const
B2DHomMatrix createScaleTranslateB2DHomMatrix(double fScaleX, double fScaleY, double fTranslateX, double fTranslateY)
virtual drawinglayer::primitive2d::Primitive2DContainer createViewIndependentPrimitive2DSequence() const override
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTRED
B2IRange fround(const B2DRange &rRange)
tools::Long getHeight() const
bool IsEmpty() const
constexpr TypedWhichId< SdrGrafTransparenceItem > SDRATTR_GRAFTRANSPARENCE(SDRATTR_GRAF_FIRST+6)
drawinglayer::primitive2d::Primitive2DContainer createVIP2DSForPresObj(const basegfx::B2DHomMatrix &rObjectMatrix, const drawinglayer::attribute::SdrLineFillEffectsTextAttribute &rAttribute) const
#define DBG_ASSERT(sCon, aError)
constexpr TypedWhichId< SdrGrafLuminanceItem > SDRATTR_GRAFLUMINANCE(SDRATTR_GRAF_FIRST+3)
void SetContrast(short nContrastPercent)
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
constexpr TypedWhichId< SdrGrafBlueItem > SDRATTR_GRAFBLUE(SDRATTR_GRAF_FIRST+2)
void SetChannelG(short nChannelGPercent)
constexpr TypedWhichId< SdrGrafModeItem > SDRATTR_GRAFMODE(SDRATTR_GRAF_FIRST+8)
void SetMergedItem(const SfxPoolItem &rItem)
Definition: svdobj.cxx:1900
MapUnit GetMapUnit() const
bool IsMirrored(const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin, const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored)
void SetChannelR(short nChannelRPercent)
This class represents an embedded or linked bitmap graphic object.
Definition: svdograf.hxx:77
Abstract DrawObject.
Definition: svdobj.hxx:260
constexpr TypedWhichId< SdrGrafCropItem > SDRATTR_GRAFCROP(SDRATTR_GRAF_FIRST+9)
OUString GetName() const
Definition: svdobj.cxx:698
GraphicType GetType() const
void SetChannelB(short nChannelBPercent)
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
constexpr TypedWhichId< SdrGrafGreenItem > SDRATTR_GRAFGREEN(SDRATTR_GRAF_FIRST+1)
Point PixelToLogic(const Point &rDevicePt) const
css::uno::Reference< css::graphic::XPrimitive2D > Primitive2DReference
void setY(double fY)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
virtual OutlinerParaObject * GetOutlinerParaObject() const override
Definition: svdotext.cxx:1362
void SetLuminance(short nLuminancePercent)
const SfxItemSet & GetMergedItemSet() const
Definition: svdobj.cxx:1890
constexpr TypedWhichId< SvxColorItem > EE_CHAR_COLOR(EE_CHAR_START+0)
void NbcSetText(const OUString &rStr)
Definition: svdotext.cxx:190
Primitive2DReference createHiddenGeometryPrimitives2D(const basegfx::B2DHomMatrix &rMatrix)
#define F_PI18000
basegfx::BColor getBColor() const
constexpr TypedWhichId< SdrGrafContrastItem > SDRATTR_GRAFCONTRAST(SDRATTR_GRAF_FIRST+4)
constexpr TypedWhichId< SdrGrafInvertItem > SDRATTR_GRAFINVERT(SDRATTR_GRAF_FIRST+7)
void SetCrop(tools::Long nLeft_100TH_MM, tools::Long nTop_100TH_MM, tools::Long nRight_100TH_MM, tools::Long nBottom_100TH_MM)
tools::Long nShearAngle
Definition: svdtrans.hxx:217
B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(double fShearX, double fRadiant, double fTranslateX, double fTranslateY)
static css::uno::Reference< css::awt::XBitmap > CreateVCLXBitmap(const BitmapEx &rBitmap)
const Size & GetSizePixel() const
periodic cubic Spline (ni)
Definition: svdobjkind.hxx:42
attribute::SdrLineFillEffectsTextAttribute createNewSdrLineFillEffectsTextAttribute(const SfxItemSet &rSet, const SdrText *pText, bool bHasContent)
sal_uInt8 GetTransparency() const
drawinglayer::primitive2d::Primitive2DContainer createVIP2DSForDraft(const basegfx::B2DHomMatrix &rObjectMatrix, const drawinglayer::attribute::SdrLineFillEffectsTextAttribute &rAttribute) const
bool IsEmptyPresObj() const
Definition: svdobj.hxx:829