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
53namespace 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));
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 std::move(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 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 rtl::Reference<SdrRectObj> pRectObj(new SdrRectObj(GetGrafObject().getSdrModelFromSdrObject(), SdrObjKind::Text));
245 pRectObj->NbcSetText(aDraftText);
246 pRectObj->SetMergedItem(SvxColorItem(COL_LIGHTRED, EE_CHAR_COLOR));
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
277 return xRetval;
278 }
279
281 {
282 const SfxItemSet& rItemSet = GetGrafObject().GetMergedItemSet();
283
284 // create and fill GraphicAttr
285 GraphicAttr aLocalGrafInfo;
286 const sal_uInt16 nTrans(rItemSet.Get(SDRATTR_GRAFTRANSPARENCE).GetValue());
287 const SdrGrafCropItem& rCrop(rItemSet.Get(SDRATTR_GRAFCROP));
288 aLocalGrafInfo.SetLuminance(rItemSet.Get(SDRATTR_GRAFLUMINANCE).GetValue());
289 aLocalGrafInfo.SetContrast(rItemSet.Get(SDRATTR_GRAFCONTRAST).GetValue());
290 aLocalGrafInfo.SetChannelR(rItemSet.Get(SDRATTR_GRAFRED).GetValue());
291 aLocalGrafInfo.SetChannelG(rItemSet.Get(SDRATTR_GRAFGREEN).GetValue());
292 aLocalGrafInfo.SetChannelB(rItemSet.Get(SDRATTR_GRAFBLUE).GetValue());
293 aLocalGrafInfo.SetGamma(rItemSet.Get(SDRATTR_GRAFGAMMA).GetValue() * 0.01);
294 aLocalGrafInfo.SetAlpha(255 - static_cast<sal_uInt8>(::basegfx::fround(std::min(nTrans, sal_uInt16(100)) * 2.55)));
295 aLocalGrafInfo.SetInvert(rItemSet.Get(SDRATTR_GRAFINVERT).GetValue());
296 aLocalGrafInfo.SetDrawMode(rItemSet.Get(SDRATTR_GRAFMODE).GetValue());
297 aLocalGrafInfo.SetCrop(rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom());
298
299 // we have content if graphic is not completely transparent
300 const bool bHasContent(0 != aLocalGrafInfo.GetAlpha());
303 rItemSet,
304 GetGrafObject().getText(0),
305 bHasContent));
306
307 // take unrotated snap rect for position and size. Directly use model data, not getBoundRect() or getSnapRect()
308 // which will use the primitive data we just create in the near future
309 const ::basegfx::B2DRange aObjectRange = vcl::unotools::b2DRectangleFromRectangle(GetGrafObject().GetGeoRect());
310
311 // look for mirroring
312 const GeoStat& rGeoStat(GetGrafObject().GetGeoStat());
313 const Degree100 nRotationAngle(rGeoStat.m_nRotationAngle);
314 const bool bMirrored(GetGrafObject().IsMirrored());
315
316 if (bMirrored)
317 aLocalGrafInfo.SetMirrorFlags(BmpMirrorFlags::Horizontal);
318
319 // fill object matrix
320 const double fShearX(-rGeoStat.mfTanShearAngle);
321 const double fRotate(nRotationAngle ? toRadians(36000_deg100 - nRotationAngle) : 0.0);
323 aObjectRange.getWidth(), aObjectRange.getHeight(),
324 fShearX, fRotate,
325 aObjectRange.getMinX(), aObjectRange.getMinY()));
326
327 // get the current, unchanged graphic object from SdrGrafObj
328 const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject();
329
331 {
332 // it's an EmptyPresObj, create the SdrGrafPrimitive2D without content and another scaled one
333 // with the content which is the placeholder graphic
334 rVisitor.visit(createVIP2DSForPresObj(aObjectMatrix, aAttribute));
335 }
336#ifndef IOS // Enforce swap-in for tiled rendering for now, while we have no delayed updating mechanism
337 else if(visualisationUsesDraft())
338 {
339 // #i102380# The graphic is swapped out. To not force a swap-in here, there is a mechanism
340 // which shows a swapped-out-visualisation (which gets created here now) and an asynchronous
341 // visual update mechanism for swapped-out graphics when they were loaded (see AsynchGraphicLoadingEvent
342 // and ViewObjectContactOfGraphic implementation). Not forcing the swap-in here allows faster
343 // (non-blocking) processing here and thus in the effect e.g. fast scrolling through pages
344 rVisitor.visit(createVIP2DSForDraft(aObjectMatrix, aAttribute));
345 }
346#endif
347 else
348 {
349 // create primitive. Info: Calling the copy-constructor of GraphicObject in this
350 // SdrGrafPrimitive2D constructor will force a full swap-in of the graphic
353 aObjectMatrix,
354 aAttribute,
355 rGraphicObject,
356 aLocalGrafInfo));
357
358 rVisitor.visit(xReference);
359 }
360
361 // always append an invisible outline for the cases where no visible content exists
362 rVisitor.visit(
364 aObjectMatrix));
365 }
366
368 {
369 return GetGrafObject().IsEmptyPresObj();
370 }
371
373 {
374 // no draft when already PresObj
376 return false;
377
378 // draft when swapped out
379 const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject();
380
381 // draft when no graphic
382 return GraphicType::NONE == rGraphicObject.GetType() || GraphicType::Default == rGraphicObject.GetType();
383 }
384
385} // end of namespace
386
387/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static OutputDevice * GetDefaultDevice()
static const AllSettings & GetSettings()
bool IsEmpty() const
const MapMode & GetPrefMapMode() const
const Size & GetPrefSize() const
const Size & GetSizePixel() const
basegfx::BColor getBColor() const
The transformation of a rectangle into a polygon, by using angle parameters from GeoStat.
Definition: svdtrans.hxx:201
double mfTanShearAngle
Definition: svdtrans.hxx:205
Degree100 m_nRotationAngle
Definition: svdtrans.hxx:203
void SetGamma(double fGamma)
void SetChannelR(short nChannelRPercent)
void SetMirrorFlags(BmpMirrorFlags nMirrFlags)
void SetContrast(short nContrastPercent)
void SetChannelB(short nChannelBPercent)
sal_uInt8 GetAlpha() const
void SetCrop(tools::Long nLeft_100TH_MM, tools::Long nTop_100TH_MM, tools::Long nRight_100TH_MM, tools::Long nBottom_100TH_MM)
void SetInvert(bool bInvert)
void SetDrawMode(GraphicDrawMode eDrawMode)
void SetLuminance(short nLuminancePercent)
void SetAlpha(sal_uInt8 cAlpha)
void SetChannelG(short nChannelGPercent)
GraphicType GetType() const
MapUnit GetMapUnit() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
This class represents an embedded or linked bitmap graphic object.
Definition: svdograf.hxx:68
const OUString & GetFileName() const
Definition: svdograf.hxx:160
const GraphicObject & GetGraphicObject(bool bForceSwapIn=false) const
Definition: svdograf.cxx:327
bool IsEmptyPresObj() const
Definition: svdobj.hxx:833
virtual const OUString & GetName() const
Definition: svdobj.cxx:771
const SfxItemSet & GetMergedItemSet() const
Definition: svdobj.cxx:1974
Rectangle objects (rectangle, circle, ...)
Definition: svdorect.hxx:39
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
constexpr tools::Long getHeight() const
constexpr tools::Long getWidth() const
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
void transform(const basegfx::B2DHomMatrix &rMatrix)
TYPE getX() const
void setY(TYPE fY)
TYPE getY() const
void setX(TYPE fX)
virtual void visit(const Primitive2DReference &)=0
virtual ViewObjectContact & CreateObjectSpecificViewObjectContact(ObjectContact &rObjectContact) override
drawinglayer::primitive2d::Primitive2DContainer createVIP2DSForDraft(const basegfx::B2DHomMatrix &rObjectMatrix, const drawinglayer::attribute::SdrLineFillEffectsTextAttribute &rAttribute) const
virtual void createViewIndependentPrimitive2DSequence(drawinglayer::primitive2d::Primitive2DDecompositionVisitor &rVisitor) const override
drawinglayer::primitive2d::Primitive2DContainer createVIP2DSForPresObj(const basegfx::B2DHomMatrix &rObjectMatrix, const drawinglayer::attribute::SdrLineFillEffectsTextAttribute &rAttribute) const
const SdrGrafObj & GetGrafObject() const
constexpr ::Color COL_LIGHTRED(0xFF, 0x00, 0x00)
#define DBG_ASSERT(sCon, aError)
double toRadians(D x)
constexpr TypedWhichId< SvxColorItem > EE_CHAR_COLOR(EE_CHAR_START+0)
bool lessOrEqual(const T &rfValA, const T &rfValB)
bool more(const T &rfValA, const T &rfValB)
bool moreOrEqual(const T &rfValA, const T &rfValB)
B2DHomMatrix createScaleTranslateB2DHomMatrix(double fScaleX, double fScaleY, double fTranslateX, double fTranslateY)
B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix(double fScaleX, double fScaleY, double fShearX, double fRadiant, double fTranslateX, double fTranslateY)
B2DHomMatrix createShearXRotateTranslateB2DHomMatrix(double fShearX, double fRadiant, double fTranslateX, double fTranslateY)
B2DPolygon const & createUnitPolygon()
Primitive2DReference createHiddenGeometryPrimitives2D(const basegfx::B2DHomMatrix &rMatrix)
attribute::SdrLineFillEffectsTextAttribute createNewSdrLineFillEffectsTextAttribute(const SfxItemSet &rSet, const SdrText *pText, bool bHasContent, bool bSuppressShadow)
bool IsMirrored(const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin, const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored)
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
@ SDRTEXTVERTADJUST_TOP
Definition: sdtaitm.hxx:29
@ SDRTEXTHORZADJUST_LEFT
Definition: sdtaitm.hxx:53
constexpr TypedWhichId< SdrGrafGreenItem > SDRATTR_GRAFGREEN(SDRATTR_GRAF_FIRST+1)
constexpr TypedWhichId< SdrGrafLuminanceItem > SDRATTR_GRAFLUMINANCE(SDRATTR_GRAF_FIRST+3)
constexpr TypedWhichId< SdrGrafRedItem > SDRATTR_GRAFRED(SDRATTR_GRAF_FIRST+0)
constexpr TypedWhichId< SdrGrafInvertItem > SDRATTR_GRAFINVERT(SDRATTR_GRAF_FIRST+7)
constexpr TypedWhichId< SdrGrafModeItem > SDRATTR_GRAFMODE(SDRATTR_GRAF_FIRST+8)
constexpr TypedWhichId< SdrGrafContrastItem > SDRATTR_GRAFCONTRAST(SDRATTR_GRAF_FIRST+4)
constexpr TypedWhichId< SdrGrafGamma100Item > SDRATTR_GRAFGAMMA(SDRATTR_GRAF_FIRST+5)
constexpr TypedWhichId< SdrGrafCropItem > SDRATTR_GRAFCROP(SDRATTR_GRAF_FIRST+9)
constexpr TypedWhichId< SdrGrafTransparenceItem > SDRATTR_GRAFTRANSPARENCE(SDRATTR_GRAF_FIRST+6)
constexpr TypedWhichId< SdrGrafBlueItem > SDRATTR_GRAFBLUE(SDRATTR_GRAF_FIRST+2)
@ Text
closed free-hand line
unsigned char sal_uInt8