fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svx / source / sdr / contact / viewcontactofgraphic.cxx
blob05e709db15baf4d4de196714175fd4b32f345eee
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svx/sdr/contact/viewcontactofgraphic.hxx>
21 #include <svx/sdr/contact/viewobjectcontactofgraphic.hxx>
22 #include <svx/svdograf.hxx>
23 #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
24 #include <svl/itemset.hxx>
26 #include <svx/sdgcpitm.hxx>
27 #include <svx/sdr/contact/displayinfo.hxx>
28 #include <svx/sdr/contact/viewobjectcontact.hxx>
29 #include <svx/sdr/contact/objectcontact.hxx>
30 #include <svx/sdr/event/eventhandler.hxx>
31 #include <basegfx/matrix/b2dhommatrix.hxx>
32 #include <svx/sdr/primitive2d/sdrgrafprimitive2d.hxx>
33 #include "svx/svdstr.hrc"
34 #include <svx/svdglob.hxx>
35 #include <vcl/svapp.hxx>
36 #include <basegfx/polygon/b2dpolygontools.hxx>
37 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
38 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
39 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
40 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
41 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
42 #include <svx/sdr/primitive2d/sdrtextprimitive2d.hxx>
43 #include <editeng/eeitem.hxx>
44 #include <editeng/colritem.hxx>
45 #include <basegfx/matrix/b2dhommatrixtools.hxx>
46 #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
48 //////////////////////////////////////////////////////////////////////////////
50 namespace sdr
52 namespace contact
54 // Create a Object-Specific ViewObjectContact, set ViewContact and
55 // ObjectContact. Always needs to return something.
56 ViewObjectContact& ViewContactOfGraphic::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact)
58 ViewObjectContact* pRetval = new ViewObjectContactOfGraphic(rObjectContact, *this);
59 DBG_ASSERT(pRetval, "ViewContact::CreateObjectSpecificViewObjectContact() failed (!)");
61 return *pRetval;
64 ViewContactOfGraphic::ViewContactOfGraphic(SdrGrafObj& rGrafObj)
65 : ViewContactOfTextObj(rGrafObj)
69 ViewContactOfGraphic::~ViewContactOfGraphic()
73 void ViewContactOfGraphic::flushGraphicObjects()
75 // #i102380# The graphic is swapped out. To let that have an effect ist is necessary to
76 // delete copies of the GraphicObject which are not swapped out and have no SwapHandler set
77 // (this is what happnes when the GraphicObject gets copied to a SdrGrafPrimitive2D). This
78 // is best achieved for the VC by clearing the local decomposition cache. It would be possible
79 // to also do this for the VOC cache, but that VOCs exist exactly expresss that the object
80 // gets visualised, so this would be wrong.
81 flushViewIndependentPrimitive2DSequence();
84 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createVIP2DSForPresObj(
85 const basegfx::B2DHomMatrix& rObjectMatrix,
86 const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute,
87 const GraphicAttr& rLocalGrafInfo) const
89 drawinglayer::primitive2d::Primitive2DSequence xRetval;
90 GraphicObject aEmptyGraphicObject;
91 GraphicAttr aEmptyGraphicAttr;
93 // SdrGrafPrimitive2D without content in original size which carries all eventual attributes and texts
94 const drawinglayer::primitive2d::Primitive2DReference xReferenceA(new drawinglayer::primitive2d::SdrGrafPrimitive2D(
95 rObjectMatrix,
96 rAttribute,
97 aEmptyGraphicObject,
98 aEmptyGraphicAttr));
99 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReferenceA, 1);
101 // SdrGrafPrimitive2D with content (which is the preview graphic) scaled to smaller size and
102 // without attributes
103 basegfx::B2DHomMatrix aSmallerMatrix;
105 // #i94431# for some reason, i forgot to take the PrefMapMode of the graphic
106 // into account. Since EmptyPresObj's are only used in Draw/Impress, it is
107 // safe to assume 100th mm as target.
108 Size aPrefSize(GetGrafObject().GetGrafPrefSize());
110 if(MAP_PIXEL == GetGrafObject().GetGrafPrefMapMode().GetMapUnit())
112 aPrefSize = Application::GetDefaultDevice()->PixelToLogic(aPrefSize, MAP_100TH_MM);
114 else
116 aPrefSize = Application::GetDefaultDevice()->LogicToLogic(aPrefSize, GetGrafObject().GetGrafPrefMapMode(), MAP_100TH_MM);
119 // decompose object matrix to get single values
120 basegfx::B2DVector aScale, aTranslate;
121 double fRotate, fShearX;
122 rObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
124 const double fOffsetX((aScale.getX() - aPrefSize.getWidth()) / 2.0);
125 const double fOffsetY((aScale.getY() - aPrefSize.getHeight()) / 2.0);
127 if(basegfx::fTools::moreOrEqual(fOffsetX, 0.0) && basegfx::fTools::moreOrEqual(fOffsetY, 0.0))
129 // create the EmptyPresObj fallback visualisation. The fallback graphic
130 // is already provided in rGraphicObject in this case, use it
131 aSmallerMatrix = basegfx::tools::createScaleTranslateB2DHomMatrix(aPrefSize.getWidth(), aPrefSize.getHeight(), fOffsetX, fOffsetY);
132 aSmallerMatrix = basegfx::tools::createShearXRotateTranslateB2DHomMatrix(fShearX, fRotate, aTranslate)
133 * aSmallerMatrix;
135 const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false);
136 const drawinglayer::primitive2d::Primitive2DReference xReferenceB(new drawinglayer::primitive2d::SdrGrafPrimitive2D(
137 aSmallerMatrix,
138 drawinglayer::attribute::SdrLineFillShadowTextAttribute(),
139 rGraphicObject,
140 rLocalGrafInfo));
142 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xReferenceB);
145 return xRetval;
148 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createVIP2DSForDraft(
149 const basegfx::B2DHomMatrix& rObjectMatrix,
150 const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute) const
152 drawinglayer::primitive2d::Primitive2DSequence xRetval;
153 GraphicObject aEmptyGraphicObject;
154 GraphicAttr aEmptyGraphicAttr;
156 // SdrGrafPrimitive2D without content in original size which carries all eventual attributes and texts
157 const drawinglayer::primitive2d::Primitive2DReference xReferenceA(new drawinglayer::primitive2d::SdrGrafPrimitive2D(
158 rObjectMatrix,
159 rAttribute,
160 aEmptyGraphicObject,
161 aEmptyGraphicAttr));
162 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReferenceA, 1);
164 if(rAttribute.getLine().isDefault())
166 // create a surrounding frame when no linestyle given
167 const Color aColor(Application::GetSettings().GetStyleSettings().GetShadowColor());
168 const basegfx::BColor aBColor(aColor.getBColor());
169 basegfx::B2DPolygon aOutline(basegfx::tools::createUnitPolygon());
170 aOutline.transform(rObjectMatrix);
172 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval,
173 drawinglayer::primitive2d::Primitive2DReference(
174 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
175 aOutline,
176 aBColor)));
179 // decompose object matrix to get single values
180 basegfx::B2DVector aScale, aTranslate;
181 double fRotate, fShearX;
182 rObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
184 // define a distance value, used for distance from bitmap to borders and from bitmap
185 // to text, too (2 mm)
186 const double fDistance(200.0);
188 // consume borders from values
189 aScale.setX(std::max(0.0, aScale.getX() - (2.0 * fDistance)));
190 aScale.setY(std::max(0.0, aScale.getY() - (2.0 * fDistance)));
191 aTranslate.setX(aTranslate.getX() + fDistance);
192 aTranslate.setY(aTranslate.getY() + fDistance);
194 // draw a draft bitmap
195 const Bitmap aDraftBitmap(ResId(BMAP_GrafikEi, *ImpGetResMgr()));
197 if(!aDraftBitmap.IsEmpty())
199 Size aPrefSize(aDraftBitmap.GetPrefSize());
201 if(MAP_PIXEL == aDraftBitmap.GetPrefMapMode().GetMapUnit())
203 aPrefSize = Application::GetDefaultDevice()->PixelToLogic(aDraftBitmap.GetSizePixel(), MAP_100TH_MM);
205 else
207 aPrefSize = Application::GetDefaultDevice()->LogicToLogic(aPrefSize, aDraftBitmap.GetPrefMapMode(), MAP_100TH_MM);
210 const double fBitmapScaling(2.0);
211 const double fWidth(aPrefSize.getWidth() * fBitmapScaling);
212 const double fHeight(aPrefSize.getHeight() * fBitmapScaling);
214 if(basegfx::fTools::more(fWidth, 1.0)
215 && basegfx::fTools::more(fHeight, 1.0)
216 && basegfx::fTools::lessOrEqual(fWidth, aScale.getX())
217 && basegfx::fTools::lessOrEqual(fHeight, aScale.getY()))
219 const basegfx::B2DHomMatrix aBitmapMatrix(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
220 fWidth, fHeight, fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
222 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval,
223 drawinglayer::primitive2d::Primitive2DReference(
224 new drawinglayer::primitive2d::BitmapPrimitive2D(
225 BitmapEx(aDraftBitmap),
226 aBitmapMatrix)));
228 // consume bitmap size in X
229 aScale.setX(std::max(0.0, aScale.getX() - (fWidth + fDistance)));
230 aTranslate.setX(aTranslate.getX() + fWidth + fDistance);
234 // Build the text for the draft object
235 XubString aDraftText = GetGrafObject().GetFileName();
237 if(!aDraftText.Len())
239 aDraftText = GetGrafObject().GetName();
240 aDraftText.AppendAscii(" ...");
243 if(aDraftText.Len() && GetGrafObject().GetModel())
245 // #i103255# Goal is to produce TextPrimitives which hold the given text as
246 // BlockText in the available space. It would be very tricky to do
247 // an own word wrap/line layout here.
248 // Using SdrBlockTextPrimitive2D OTOH is critical since it internally
249 // uses the SdrObject it references. To solve this, create a temp
250 // SdrObject with Attributes and Text, generate a SdrBlockTextPrimitive2D
251 // directly and immediately decompose it. After that, it is no longer
252 // needed and can be deleted.
254 // create temp RectObj as TextObj and set needed attributes
255 SdrRectObj aRectObj(OBJ_TEXT);
256 aRectObj.SetModel(GetGrafObject().GetModel());
257 aRectObj.NbcSetText(aDraftText);
258 aRectObj.SetMergedItem(SvxColorItem(Color(COL_LIGHTRED), EE_CHAR_COLOR));
260 // get SdrText and OPO
261 SdrText* pSdrText = aRectObj.getText(0);
262 OutlinerParaObject* pOPO = aRectObj.GetOutlinerParaObject();
264 if(pSdrText && pOPO)
266 // directly use the remaining space as TextRangeTransform
267 const basegfx::B2DHomMatrix aTextRangeTransform(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
268 aScale, fShearX, fRotate, aTranslate));
270 // directly create temp SdrBlockTextPrimitive2D
271 drawinglayer::primitive2d::SdrBlockTextPrimitive2D aBlockTextPrimitive(
272 pSdrText,
273 *pOPO,
274 aTextRangeTransform,
275 SDRTEXTHORZADJUST_LEFT,
276 SDRTEXTVERTADJUST_TOP,
277 false,
278 false,
279 false,
280 false,
281 false);
283 // decompose immediately with neutral ViewInformation. This will
284 // layout the text to more simple TextPrimitives from drawinglayer
285 const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
287 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(
288 xRetval,
289 aBlockTextPrimitive.get2DDecomposition(aViewInformation2D));
293 return xRetval;
296 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createViewIndependentPrimitive2DSequence() const
298 drawinglayer::primitive2d::Primitive2DSequence xRetval;
299 const SfxItemSet& rItemSet = GetGrafObject().GetMergedItemSet();
301 // create and fill GraphicAttr
302 GraphicAttr aLocalGrafInfo;
303 const sal_uInt16 nTrans(((SdrGrafTransparenceItem&)rItemSet.Get(SDRATTR_GRAFTRANSPARENCE)).GetValue());
304 const SdrGrafCropItem& rCrop((const SdrGrafCropItem&)rItemSet.Get(SDRATTR_GRAFCROP));
305 aLocalGrafInfo.SetLuminance(((SdrGrafLuminanceItem&)rItemSet.Get(SDRATTR_GRAFLUMINANCE)).GetValue());
306 aLocalGrafInfo.SetContrast(((SdrGrafContrastItem&)rItemSet.Get(SDRATTR_GRAFCONTRAST)).GetValue());
307 aLocalGrafInfo.SetChannelR(((SdrGrafRedItem&)rItemSet.Get(SDRATTR_GRAFRED)).GetValue());
308 aLocalGrafInfo.SetChannelG(((SdrGrafGreenItem&)rItemSet.Get(SDRATTR_GRAFGREEN)).GetValue());
309 aLocalGrafInfo.SetChannelB(((SdrGrafBlueItem&)rItemSet.Get(SDRATTR_GRAFBLUE)).GetValue());
310 aLocalGrafInfo.SetGamma(((SdrGrafGamma100Item&)rItemSet.Get(SDRATTR_GRAFGAMMA)).GetValue() * 0.01);
311 aLocalGrafInfo.SetTransparency((sal_uInt8)::basegfx::fround(std::min(nTrans, (sal_uInt16)100) * 2.55));
312 aLocalGrafInfo.SetInvert(((SdrGrafInvertItem&)rItemSet.Get(SDRATTR_GRAFINVERT)).GetValue());
313 aLocalGrafInfo.SetDrawMode(((SdrGrafModeItem&)rItemSet.Get(SDRATTR_GRAFMODE)).GetValue());
314 aLocalGrafInfo.SetCrop(rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom());
316 // we have content if graphic is not completely transparent
317 const bool bHasContent(255L != aLocalGrafInfo.GetTransparency());
318 drawinglayer::attribute::SdrLineFillShadowTextAttribute aAttribute(
319 drawinglayer::primitive2d::createNewSdrLineFillShadowTextAttribute(
320 rItemSet,
321 GetGrafObject().getText(0),
322 bHasContent));
324 // take unrotated snap rect for position and size. Directly use model data, not getBoundRect() or getSnapRect()
325 // which will use the primitive data we just create in the near future
326 Rectangle rRectangle = GetGrafObject().GetGeoRect();
327 // Hack for calc, transform position of object according
328 // to current zoom so as objects relative position to grid
329 // appears stable
330 rRectangle += GetGrafObject().GetGridOffset();
331 const ::basegfx::B2DRange aObjectRange(
332 rRectangle.Left(), rRectangle.Top(),
333 rRectangle.Right(), rRectangle.Bottom());
335 // look for mirroring
336 const GeoStat& rGeoStat(GetGrafObject().GetGeoStat());
337 const sal_Int32 nDrehWink(rGeoStat.nDrehWink);
338 const bool bRota180(18000 == nDrehWink);
339 const bool bMirrored(GetGrafObject().IsMirrored());
340 const sal_uInt16 nMirrorCase(bRota180 ? (bMirrored ? 3 : 4) : (bMirrored ? 2 : 1));
341 bool bHMirr((2 == nMirrorCase ) || (4 == nMirrorCase));
342 bool bVMirr((3 == nMirrorCase ) || (4 == nMirrorCase));
344 // set mirror flags at LocalGrafInfo. Take into account that the geometry in
345 // aObjectRange is already changed and rotated when bRota180 is used. To rebuild
346 // that old behaviour (as long as part of the model data), correct the H/V flags
347 // accordingly. The created bitmapPrimitive WILL use the rotation, too.
348 if(bRota180)
350 // if bRota180 which is used for vertical mirroring, the graphic will already be rotated
351 // by 180 degrees. To correct, switch off VMirror and invert HMirroring.
352 bHMirr = !bHMirr;
353 bVMirr = false;
356 if(bHMirr || bVMirr)
358 aLocalGrafInfo.SetMirrorFlags((bHMirr ? BMP_MIRROR_HORZ : 0)|(bVMirr ? BMP_MIRROR_VERT : 0));
361 // fill object matrix
362 const double fShearX(rGeoStat.nShearWink ? tan((36000 - rGeoStat.nShearWink) * F_PI18000) : 0.0);
363 const double fRotate(nDrehWink ? (36000 - nDrehWink) * F_PI18000 : 0.0);
364 const basegfx::B2DHomMatrix aObjectMatrix(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
365 aObjectRange.getWidth(), aObjectRange.getHeight(),
366 fShearX, fRotate,
367 aObjectRange.getMinX(), aObjectRange.getMinY()));
369 // get the current, unchenged graphic obect from SdrGrafObj
370 const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false);
372 if(visualisationUsesPresObj())
374 // it's an EmptyPresObj, create the SdrGrafPrimitive2D without content and another scaled one
375 // with the content which is the placeholder graphic
376 xRetval = createVIP2DSForPresObj(aObjectMatrix, aAttribute, aLocalGrafInfo);
378 else if(visualisationUsesDraft())
380 // #i102380# The graphic is swapped out. To not force a swap-in here, there is a mechanism
381 // which shows a swapped-out-visualisation (which gets created here now) and an asynchronious
382 // visual update mechanism for swapped-out grapgics when they were loaded (see AsynchGraphicLoadingEvent
383 // and ViewObjectContactOfGraphic implementation). Not forcing the swap-in here allows faster
384 // (non-blocking) processing here and thus in the effect e.g. fast scrolling through pages
385 xRetval = createVIP2DSForDraft(aObjectMatrix, aAttribute);
387 else
389 // create primitive. Info: Calling the copy-constructor of GraphicObject in this
390 // SdrGrafPrimitive2D constructor will force a full swap-in of the graphic
391 const drawinglayer::primitive2d::Primitive2DReference xReference(
392 new drawinglayer::primitive2d::SdrGrafPrimitive2D(
393 aObjectMatrix,
394 aAttribute,
395 rGraphicObject,
396 aLocalGrafInfo));
398 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
401 // always append an invisible outline for the cases where no visible content exists
402 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval,
403 drawinglayer::primitive2d::createHiddenGeometryPrimitives2D(
404 false, aObjectMatrix));
406 return xRetval;
409 bool ViewContactOfGraphic::visualisationUsesPresObj() const
411 return GetGrafObject().IsEmptyPresObj();
414 bool ViewContactOfGraphic::visualisationUsesDraft() const
416 // no draft when already PresObj
417 if(visualisationUsesPresObj())
418 return false;
420 // draft when swapped out
421 const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false);
422 static bool bAllowReplacements(true);
424 if(rGraphicObject.IsSwappedOut() && bAllowReplacements)
425 return true;
427 // draft when no graphic
428 if(GRAPHIC_NONE == rGraphicObject.GetType() || GRAPHIC_DEFAULT == rGraphicObject.GetType())
429 return true;
431 return false;
434 } // end of namespace contact
435 } // end of namespace sdr
437 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */