merge the formfield patch from ooo-build
[ooovba.git] / svx / source / sdr / contact / viewcontactofgraphic.cxx
blob5781e7bbeb44af8f598def2dd470fb233f0f7feb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: viewcontactofgraphic.cxx,v $
10 * $Revision: 1.14.18.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <svx/sdr/contact/viewcontactofgraphic.hxx>
34 #include <svx/sdr/contact/viewobjectcontactofgraphic.hxx>
35 #include <svx/svdograf.hxx>
36 #include <svx/sdr/attribute/sdrallattribute.hxx>
37 #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
38 #include <svtools/itemset.hxx>
40 #ifndef ITEMID_GRF_CROP
41 #define ITEMID_GRF_CROP 0
42 #endif
44 #include <svx/sdgcpitm.hxx>
45 #include <drawinglayer/attribute/sdrattribute.hxx>
46 #include <svx/sdr/contact/displayinfo.hxx>
47 #include <svx/sdr/contact/viewobjectcontact.hxx>
48 #include <svx/sdr/contact/objectcontact.hxx>
49 #include <svx/sdr/event/eventhandler.hxx>
50 #include <basegfx/matrix/b2dhommatrix.hxx>
51 #include <svx/sdr/primitive2d/sdrgrafprimitive2d.hxx>
52 #include "svdstr.hrc"
53 #include <svdglob.hxx>
54 #include <vcl/svapp.hxx>
56 #include <basegfx/polygon/b2dpolygontools.hxx>
57 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
58 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
59 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
60 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
61 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
63 #include <svx/sdr/primitive2d/sdrtextprimitive2d.hxx>
64 #include <svx/eeitem.hxx>
65 #include <svx/colritem.hxx>
66 //#include <svx/xtable.hxx>
68 //////////////////////////////////////////////////////////////////////////////
70 namespace sdr
72 namespace contact
74 // Create a Object-Specific ViewObjectContact, set ViewContact and
75 // ObjectContact. Always needs to return something.
76 ViewObjectContact& ViewContactOfGraphic::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact)
78 ViewObjectContact* pRetval = new ViewObjectContactOfGraphic(rObjectContact, *this);
79 DBG_ASSERT(pRetval, "ViewContact::CreateObjectSpecificViewObjectContact() failed (!)");
81 return *pRetval;
84 ViewContactOfGraphic::ViewContactOfGraphic(SdrGrafObj& rGrafObj)
85 : ViewContactOfTextObj(rGrafObj)
89 ViewContactOfGraphic::~ViewContactOfGraphic()
93 void ViewContactOfGraphic::flushGraphicObjects()
95 // #i102380# The graphic is swapped out. To let that have an effect ist is necessary to
96 // delete copies of the GraphicObject which are not swapped out and have no SwapHandler set
97 // (this is what happnes when the GraphicObject gets copied to a SdrGrafPrimitive2D). This
98 // is best achieved for the VC by clearing the local decomposition cache. It would be possible
99 // to also do this for the VOC cache, but that VOCs exist exactly expresss that the object
100 // gets visualised, so this would be wrong.
101 flushViewIndependentPrimitive2DSequence();
104 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createVIP2DSForPresObj(
105 const basegfx::B2DHomMatrix& rObjectMatrix,
106 const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute,
107 const GraphicAttr& rLocalGrafInfo) const
109 drawinglayer::primitive2d::Primitive2DSequence xRetval;
110 GraphicObject aEmptyGraphicObject;
111 GraphicAttr aEmptyGraphicAttr;
113 // SdrGrafPrimitive2D without content in original size which carries all eventual attributes and texts
114 const drawinglayer::primitive2d::Primitive2DReference xReferenceA(new drawinglayer::primitive2d::SdrGrafPrimitive2D(
115 rObjectMatrix,
116 rAttribute,
117 aEmptyGraphicObject,
118 aEmptyGraphicAttr));
119 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReferenceA, 1);
121 // SdrGrafPrimitive2D with content (which is the preview graphic) scaled to smaller size and
122 // without attributes
123 basegfx::B2DHomMatrix aSmallerMatrix;
125 // #i94431# for some reason, i forgot to take the PrefMapMode of the graphic
126 // into account. Since EmptyPresObj's are only used in Draw/Impress, it is
127 // safe to assume 100th mm as target.
128 Size aPrefSize(GetGrafObject().GetGrafPrefSize());
130 if(MAP_PIXEL == GetGrafObject().GetGrafPrefMapMode().GetMapUnit())
132 aPrefSize = Application::GetDefaultDevice()->PixelToLogic(aPrefSize, MAP_100TH_MM);
134 else
136 aPrefSize = Application::GetDefaultDevice()->LogicToLogic(aPrefSize, GetGrafObject().GetGrafPrefMapMode(), MAP_100TH_MM);
139 // decompose object matrix to get single values
140 basegfx::B2DVector aScale, aTranslate;
141 double fRotate, fShearX;
142 rObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
144 const double fOffsetX((aScale.getX() - aPrefSize.getWidth()) / 2.0);
145 const double fOffsetY((aScale.getY() - aPrefSize.getHeight()) / 2.0);
147 if(basegfx::fTools::moreOrEqual(fOffsetX, 0.0) && basegfx::fTools::moreOrEqual(fOffsetY, 0.0))
149 // create the EmptyPresObj fallback visualisation. The fallback graphic
150 // is already provided in rGraphicObject in this case, use it
151 aSmallerMatrix.scale(aPrefSize.getWidth(), aPrefSize.getHeight());
152 aSmallerMatrix.translate(fOffsetX, fOffsetY);
153 aSmallerMatrix.shearX(fShearX);
154 aSmallerMatrix.rotate(fRotate);
155 aSmallerMatrix.translate(aTranslate.getX(), aTranslate.getY());
157 const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false);
158 const drawinglayer::attribute::SdrLineFillShadowTextAttribute aEmptyAttributes(0, 0, 0, 0, 0, 0);
159 const drawinglayer::primitive2d::Primitive2DReference xReferenceB(new drawinglayer::primitive2d::SdrGrafPrimitive2D(
160 aSmallerMatrix,
161 aEmptyAttributes,
162 rGraphicObject,
163 rLocalGrafInfo));
165 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xReferenceB);
168 return xRetval;
171 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createVIP2DSForDraft(
172 const basegfx::B2DHomMatrix& rObjectMatrix,
173 const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute) const
175 drawinglayer::primitive2d::Primitive2DSequence xRetval;
176 GraphicObject aEmptyGraphicObject;
177 GraphicAttr aEmptyGraphicAttr;
179 // SdrGrafPrimitive2D without content in original size which carries all eventual attributes and texts
180 const drawinglayer::primitive2d::Primitive2DReference xReferenceA(new drawinglayer::primitive2d::SdrGrafPrimitive2D(
181 rObjectMatrix,
182 rAttribute,
183 aEmptyGraphicObject,
184 aEmptyGraphicAttr));
185 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReferenceA, 1);
187 if(!rAttribute.getLine())
189 // create a surrounding frame when no linestyle given
190 const Color aColor(Application::GetSettings().GetStyleSettings().GetShadowColor());
191 const basegfx::BColor aBColor(aColor.getBColor());
192 const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
194 basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aUnitRange));
195 aOutline.transform(rObjectMatrix);
197 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval,
198 drawinglayer::primitive2d::Primitive2DReference(
199 new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
200 aOutline,
201 aBColor)));
204 // decompose object matrix to get single values
205 basegfx::B2DVector aScale, aTranslate;
206 double fRotate, fShearX;
207 rObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
209 // define a distance value, used for distance from bitmap to borders and from bitmap
210 // to text, too (2 mm)
211 const double fDistance(200.0);
213 // consume borders from values
214 aScale.setX(std::max(0.0, aScale.getX() - (2.0 * fDistance)));
215 aScale.setY(std::max(0.0, aScale.getY() - (2.0 * fDistance)));
216 aTranslate.setX(aTranslate.getX() + fDistance);
217 aTranslate.setY(aTranslate.getY() + fDistance);
219 // draw a draft bitmap
220 const Bitmap aDraftBitmap(ResId(BMAP_GrafikEi, *ImpGetResMgr()));
222 if(!aDraftBitmap.IsEmpty())
224 Size aPrefSize(aDraftBitmap.GetPrefSize());
226 if(MAP_PIXEL == aDraftBitmap.GetPrefMapMode().GetMapUnit())
228 aPrefSize = Application::GetDefaultDevice()->PixelToLogic(aDraftBitmap.GetSizePixel(), MAP_100TH_MM);
230 else
232 aPrefSize = Application::GetDefaultDevice()->LogicToLogic(aPrefSize, aDraftBitmap.GetPrefMapMode(), MAP_100TH_MM);
235 const double fBitmapScaling(2.0);
236 const double fWidth(aPrefSize.getWidth() * fBitmapScaling);
237 const double fHeight(aPrefSize.getHeight() * fBitmapScaling);
239 if(basegfx::fTools::more(fWidth, 1.0)
240 && basegfx::fTools::more(fHeight, 1.0)
241 && basegfx::fTools::lessOrEqual(fWidth, aScale.getX())
242 && basegfx::fTools::lessOrEqual(fHeight, aScale.getY()))
244 basegfx::B2DHomMatrix aBitmapMatrix;
246 aBitmapMatrix.scale(fWidth, fHeight);
247 aBitmapMatrix.shearX(fShearX);
248 aBitmapMatrix.rotate(fRotate);
249 aBitmapMatrix.translate(aTranslate.getX(), aTranslate.getY());
251 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval,
252 drawinglayer::primitive2d::Primitive2DReference(
253 new drawinglayer::primitive2d::BitmapPrimitive2D(
254 BitmapEx(aDraftBitmap),
255 aBitmapMatrix)));
257 // consume bitmap size in X
258 aScale.setX(std::max(0.0, aScale.getX() - (fWidth + fDistance)));
259 aTranslate.setX(aTranslate.getX() + fWidth + fDistance);
263 // Build the text for the draft object
264 XubString aDraftText = GetGrafObject().GetFileName();
266 if(!aDraftText.Len())
268 aDraftText = GetGrafObject().GetName();
269 aDraftText.AppendAscii(" ...");
272 if(aDraftText.Len() && GetGrafObject().GetModel())
274 // #i103255# Goal is to produce TextPrimitives which hold the given text as
275 // BlockText in the available space. It would be very tricky to do
276 // an own word wrap/line layout here.
277 // Using SdrBlockTextPrimitive2D OTOH is critical since it internally
278 // uses the SdrObject it references. To solve this, create a temp
279 // SdrObject with Attributes and Text, generate a SdrBlockTextPrimitive2D
280 // directly and immediately decompose it. After that, it is no longer
281 // needed and can be deleted.
283 // create temp RectObj as TextObj and set needed attributes
284 SdrRectObj aRectObj(OBJ_TEXT);
285 aRectObj.SetModel(GetGrafObject().GetModel());
286 aRectObj.NbcSetText(aDraftText);
287 aRectObj.SetMergedItem(SvxColorItem(Color(COL_LIGHTRED), EE_CHAR_COLOR));
289 // get SdrText and OPO
290 SdrText* pSdrText = aRectObj.getText(0);
291 OutlinerParaObject* pOPO = aRectObj.GetOutlinerParaObject();
293 if(pSdrText && pOPO)
295 // directly use the remaining space as TextRangeTransform
296 basegfx::B2DHomMatrix aTextRangeTransform;
298 aTextRangeTransform.scale(aScale.getX(), aScale.getY());
299 aTextRangeTransform.shearX(fShearX);
300 aTextRangeTransform.rotate(fRotate);
301 aTextRangeTransform.translate(aTranslate.getX(), aTranslate.getY());
303 // directly create temp SdrBlockTextPrimitive2D
304 drawinglayer::primitive2d::SdrBlockTextPrimitive2D aBlockTextPrimitive(
305 pSdrText,
306 *pOPO,
307 aTextRangeTransform,
308 SDRTEXTHORZADJUST_LEFT,
309 SDRTEXTVERTADJUST_TOP,
310 false,
311 false,
312 false,
313 false);
315 // decompose immediately with neutral ViewInformation. This will
316 // layout the text to more simple TextPrimitives from drawinglayer
317 const drawinglayer::geometry::ViewInformation2D aViewInformation2D(0);
319 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(
320 xRetval,
321 aBlockTextPrimitive.get2DDecomposition(aViewInformation2D));
325 return xRetval;
328 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createViewIndependentPrimitive2DSequence() const
330 drawinglayer::primitive2d::Primitive2DSequence xRetval;
331 SdrText* pSdrText = GetGrafObject().getText(0);
333 if(pSdrText)
335 const SfxItemSet& rItemSet = GetGrafObject().GetMergedItemSet();
336 drawinglayer::attribute::SdrLineFillShadowTextAttribute* pAttribute =
337 drawinglayer::primitive2d::createNewSdrLineFillShadowTextAttribute(rItemSet, *pSdrText);
338 bool bVisible(pAttribute && pAttribute->isVisible());
340 // create and fill GraphicAttr
341 GraphicAttr aLocalGrafInfo;
342 const sal_uInt16 nTrans(((SdrGrafTransparenceItem&)rItemSet.Get(SDRATTR_GRAFTRANSPARENCE)).GetValue());
343 const SdrGrafCropItem& rCrop((const SdrGrafCropItem&)rItemSet.Get(SDRATTR_GRAFCROP));
344 aLocalGrafInfo.SetLuminance(((SdrGrafLuminanceItem&)rItemSet.Get(SDRATTR_GRAFLUMINANCE)).GetValue());
345 aLocalGrafInfo.SetContrast(((SdrGrafContrastItem&)rItemSet.Get(SDRATTR_GRAFCONTRAST)).GetValue());
346 aLocalGrafInfo.SetChannelR(((SdrGrafRedItem&)rItemSet.Get(SDRATTR_GRAFRED)).GetValue());
347 aLocalGrafInfo.SetChannelG(((SdrGrafGreenItem&)rItemSet.Get(SDRATTR_GRAFGREEN)).GetValue());
348 aLocalGrafInfo.SetChannelB(((SdrGrafBlueItem&)rItemSet.Get(SDRATTR_GRAFBLUE)).GetValue());
349 aLocalGrafInfo.SetGamma(((SdrGrafGamma100Item&)rItemSet.Get(SDRATTR_GRAFGAMMA)).GetValue() * 0.01);
350 aLocalGrafInfo.SetTransparency((BYTE)::basegfx::fround(Min(nTrans, (USHORT)100) * 2.55));
351 aLocalGrafInfo.SetInvert(((SdrGrafInvertItem&)rItemSet.Get(SDRATTR_GRAFINVERT)).GetValue());
352 aLocalGrafInfo.SetDrawMode(((SdrGrafModeItem&)rItemSet.Get(SDRATTR_GRAFMODE)).GetValue());
353 aLocalGrafInfo.SetCrop(rCrop.GetLeft(), rCrop.GetTop(), rCrop.GetRight(), rCrop.GetBottom());
355 if(!bVisible && 255L != aLocalGrafInfo.GetTransparency())
357 // content is visible, so force some fill stuff
358 delete pAttribute;
359 bVisible = true;
361 // check shadow
362 drawinglayer::attribute::SdrShadowAttribute* pShadow = drawinglayer::primitive2d::createNewSdrShadowAttribute(rItemSet);
364 if(pShadow && !pShadow->isVisible())
366 delete pShadow;
367 pShadow = 0L;
370 // create new attribute set
371 pAttribute = new drawinglayer::attribute::SdrLineFillShadowTextAttribute(0L, 0L, 0L, pShadow, 0L, 0L);
374 if(pAttribute)
376 if(pAttribute->isVisible() || bVisible)
378 // take unrotated snap rect for position and size. Directly use model data, not getBoundRect() or getSnapRect()
379 // which will use the primitive data we just create in the near future
380 const Rectangle& rRectangle = GetGrafObject().GetGeoRect();
381 const ::basegfx::B2DRange aObjectRange(rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom());
382 basegfx::B2DHomMatrix aObjectMatrix;
384 // look for mirroring
385 const GeoStat& rGeoStat(GetGrafObject().GetGeoStat());
386 const sal_Int32 nDrehWink(rGeoStat.nDrehWink);
387 const bool bRota180(18000 == nDrehWink);
388 const bool bMirrored(GetGrafObject().IsMirrored());
389 const sal_uInt16 nMirrorCase(bRota180 ? (bMirrored ? 3 : 4) : (bMirrored ? 2 : 1));
390 bool bHMirr((2 == nMirrorCase ) || (4 == nMirrorCase));
391 bool bVMirr((3 == nMirrorCase ) || (4 == nMirrorCase));
393 // set mirror flags at LocalGrafInfo. Take into account that the geometry in
394 // aObjectRange is already changed and rotated when bRota180 is used. To rebuild
395 // that old behaviour (as long as part of the model data), correct the H/V flags
396 // accordingly. The created bitmapPrimitive WILL use the rotation, too.
397 if(bRota180)
399 // if bRota180 which is used for vertical mirroring, the graphic will already be rotated
400 // by 180 degrees. To correct, switch off VMirror and invert HMirroring.
401 bHMirr = !bHMirr;
402 bVMirr = false;
405 if(bHMirr || bVMirr)
407 aLocalGrafInfo.SetMirrorFlags((bHMirr ? BMP_MIRROR_HORZ : 0)|(bVMirr ? BMP_MIRROR_VERT : 0));
410 // fill object matrix
411 const double fShearX(rGeoStat.nShearWink ? tan((36000 - rGeoStat.nShearWink) * F_PI18000) : 0.0);
412 const double fRotate(nDrehWink ? (36000 - nDrehWink) * F_PI18000 : 0.0);
413 aObjectMatrix.scale(aObjectRange.getWidth(), aObjectRange.getHeight());
414 aObjectMatrix.shearX(fShearX);
415 aObjectMatrix.rotate(fRotate);
416 aObjectMatrix.translate(aObjectRange.getMinX(), aObjectRange.getMinY());
418 // get the current, unchenged graphic obect from SdrGrafObj
419 const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false);
421 if(visualisationUsesPresObj())
423 // it's an EmptyPresObj, create the SdrGrafPrimitive2D without content and another scaled one
424 // with the content which is the placeholder graphic
425 xRetval = createVIP2DSForPresObj(aObjectMatrix, *pAttribute, aLocalGrafInfo);
427 else if(visualisationUsesDraft())
429 // #i102380# The graphic is swapped out. To not force a swap-in here, there is a mechanism
430 // which shows a swapped-out-visualisation (which gets created here now) and an asynchronious
431 // visual update mechanism for swapped-out grapgics when they were loaded (see AsynchGraphicLoadingEvent
432 // and ViewObjectContactOfGraphic implementation). Not forcing the swap-in here allows faster
433 // (non-blocking) processing here and thus in the effect e.g. fast scrolling through pages
434 xRetval = createVIP2DSForDraft(aObjectMatrix, *pAttribute);
436 else
438 // create primitive. Info: Calling the copy-constructor of GraphicObject in this
439 // SdrGrafPrimitive2D constructor will force a full swap-in of the graphic
440 const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::SdrGrafPrimitive2D(
441 aObjectMatrix,
442 *pAttribute,
443 rGraphicObject,
444 aLocalGrafInfo));
446 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
450 delete pAttribute;
454 return xRetval;
457 bool ViewContactOfGraphic::visualisationUsesPresObj() const
459 return GetGrafObject().IsEmptyPresObj();
462 bool ViewContactOfGraphic::visualisationUsesDraft() const
464 // no draft when already PresObj
465 if(visualisationUsesPresObj())
466 return false;
468 // draft when swapped out
469 const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false);
470 static bool bAllowReplacements(true);
472 if(rGraphicObject.IsSwappedOut() && bAllowReplacements)
473 return true;
475 // draft when no graphic
476 if(GRAPHIC_NONE == rGraphicObject.GetType() || GRAPHIC_DEFAULT == rGraphicObject.GetType())
477 return true;
479 return false;
482 } // end of namespace contact
483 } // end of namespace sdr
485 //////////////////////////////////////////////////////////////////////////////
486 // eof