xref: /AOO41X/main/drawinglayer/source/primitive2d/graphicprimitive2d.cxx (revision 5be78d22e6c042fbf34ae49f26275dc40c5231d1)
1464702f4SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3464702f4SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4464702f4SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5464702f4SAndrew Rist  * distributed with this work for additional information
6464702f4SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7464702f4SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8464702f4SAndrew Rist  * "License"); you may not use this file except in compliance
9464702f4SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11464702f4SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13464702f4SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14464702f4SAndrew Rist  * software distributed under the License is distributed on an
15464702f4SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16464702f4SAndrew Rist  * KIND, either express or implied.  See the License for the
17464702f4SAndrew Rist  * specific language governing permissions and limitations
18464702f4SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20464702f4SAndrew Rist  *************************************************************/
21464702f4SAndrew Rist 
22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
23cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx"
24cdf0e10cSrcweir 
25cdf0e10cSrcweir #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
26ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/cropprimitive2d.hxx>
27cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
28ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
29035a2f44SArmin Le Grand #include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx>
30*49c58f9bSArmin Le Grand #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
31*49c58f9bSArmin Le Grand #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
32035a2f44SArmin Le Grand #include <basegfx/matrix/b2dhommatrixtools.hxx>
33cdf0e10cSrcweir #include <vcl/svapp.hxx>
34035a2f44SArmin Le Grand #include <vcl/outdev.hxx>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
37cdf0e10cSrcweir 
38cdf0e10cSrcweir namespace drawinglayer
39cdf0e10cSrcweir {
40cdf0e10cSrcweir     namespace primitive2d
41cdf0e10cSrcweir     {
create2DDecomposition(const geometry::ViewInformation2D & rViewInformation) const42cdf0e10cSrcweir         Primitive2DSequence GraphicPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D&
43cdf0e10cSrcweir #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
44cdf0e10cSrcweir             rViewInformation
45cdf0e10cSrcweir #else
46cdf0e10cSrcweir             /*rViewInformation*/
47cdf0e10cSrcweir #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
48cdf0e10cSrcweir             ) const
49cdf0e10cSrcweir         {
50cdf0e10cSrcweir             Primitive2DSequence aRetval;
51cdf0e10cSrcweir 
52*49c58f9bSArmin Le Grand             if(255L == getGraphicAttr().GetTransparency())
53cdf0e10cSrcweir             {
54*49c58f9bSArmin Le Grand                 // content is invisible, done
55*49c58f9bSArmin Le Grand                 return aRetval;
56*49c58f9bSArmin Le Grand             }
57*49c58f9bSArmin Le Grand 
58cdf0e10cSrcweir             // do not apply mirroring from GraphicAttr to the Metafile by calling
59cdf0e10cSrcweir             // GetTransformedGraphic, this will try to mirror the Metafile using Scale()
60cdf0e10cSrcweir             // at the Metafile. This again calls Scale at the single MetaFile actions,
61cdf0e10cSrcweir             // but this implementation never worked. I reworked that implementations,
62cdf0e10cSrcweir             // but for security reasons i will try not to use it.
63cdf0e10cSrcweir             basegfx::B2DHomMatrix aTransform(getTransform());
64cdf0e10cSrcweir 
65cdf0e10cSrcweir             if(getGraphicAttr().IsMirrored())
66cdf0e10cSrcweir             {
67cdf0e10cSrcweir                 // content needs mirroring
68cdf0e10cSrcweir                 const bool bHMirr(getGraphicAttr().GetMirrorFlags() & BMP_MIRROR_HORZ);
69cdf0e10cSrcweir                 const bool bVMirr(getGraphicAttr().GetMirrorFlags() & BMP_MIRROR_VERT);
70cdf0e10cSrcweir 
71cdf0e10cSrcweir                 // mirror by applying negative scale to the unit primitive and
72cdf0e10cSrcweir                 // applying the object transformation on it.
73cdf0e10cSrcweir                 aTransform = basegfx::tools::createScaleB2DHomMatrix(
74cdf0e10cSrcweir                     bHMirr ? -1.0 : 1.0,
75cdf0e10cSrcweir                     bVMirr ? -1.0 : 1.0);
76cdf0e10cSrcweir                 aTransform.translate(
77cdf0e10cSrcweir                     bHMirr ? 1.0 : 0.0,
78cdf0e10cSrcweir                     bVMirr ? 1.0 : 0.0);
79cdf0e10cSrcweir                 aTransform = getTransform() * aTransform;
80cdf0e10cSrcweir             }
81cdf0e10cSrcweir 
82cdf0e10cSrcweir             // Get transformed graphic. Suppress rotation and cropping, only filtering is needed
83cdf0e10cSrcweir             // here (and may be replaced later on). Cropping is handled below as mask primitive (if set).
84cdf0e10cSrcweir             // Also need to suppress mirroring, it is part of the transformation now (see above).
85*49c58f9bSArmin Le Grand             // Also move transparency handling to embedding to a UnifiedTransparencePrimitive2D; do
86*49c58f9bSArmin Le Grand             // that by remembering original transparency and applying that later if needed
87cdf0e10cSrcweir             GraphicAttr aSuppressGraphicAttr(getGraphicAttr());
88*49c58f9bSArmin Le Grand 
89cdf0e10cSrcweir             aSuppressGraphicAttr.SetCrop(0, 0, 0, 0);
90cdf0e10cSrcweir             aSuppressGraphicAttr.SetRotation(0);
91cdf0e10cSrcweir             aSuppressGraphicAttr.SetMirrorFlags(0);
92*49c58f9bSArmin Le Grand             aSuppressGraphicAttr.SetTransparency(0);
93cdf0e10cSrcweir 
94cdf0e10cSrcweir             const GraphicObject& rGraphicObject = getGraphicObject();
95*49c58f9bSArmin Le Grand             Graphic aTransformedGraphic(rGraphicObject.GetGraphic());
96*49c58f9bSArmin Le Grand             const bool isBitmap(GRAPHIC_BITMAP == aTransformedGraphic.GetType() && !aTransformedGraphic.getSvgData().get());
97*49c58f9bSArmin Le Grand             const bool isAdjusted(getGraphicAttr().IsAdjusted());
98*49c58f9bSArmin Le Grand             const bool isDrawMode(GRAPHICDRAWMODE_STANDARD != getGraphicAttr().GetDrawMode());
99cdf0e10cSrcweir 
100*49c58f9bSArmin Le Grand             if(isBitmap && (isAdjusted || isDrawMode))
101*49c58f9bSArmin Le Grand             {
102*49c58f9bSArmin Le Grand                 // the pure primitive solution with the color modifiers works well, too, but when
103*49c58f9bSArmin Le Grand                 // it is a bitmap graphic the old modification currently is faster; so use it here
104*49c58f9bSArmin Le Grand                 // instead of creating all as in create2DColorModifierEmbeddingsAsNeeded (see below).
105*49c58f9bSArmin Le Grand                 // Still, crop, rotation, mirroring and transparency is handled by primitives already
106*49c58f9bSArmin Le Grand                 // (see above).
107*49c58f9bSArmin Le Grand                 // This could even be done when vector graphic, but we explicitely want to have the
108*49c58f9bSArmin Le Grand                 // pure primitive solution for this; this will allow vector graphics to stay vector
109*49c58f9bSArmin Le Grand                 // geraphics, independent from the color filtering stuff. This will enhance e.g.
110*49c58f9bSArmin Le Grand                 // SVG and print quality while reducing data size at the same time.
111*49c58f9bSArmin Le Grand                 // The other way around the old modifications when only used on already bitmap objects
112*49c58f9bSArmin Le Grand                 // will not loose any quality.
113*49c58f9bSArmin Le Grand                 aTransformedGraphic = rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr);
114*49c58f9bSArmin Le Grand 
115*49c58f9bSArmin Le Grand                 // reset GraphicAttr after use to not apply double
116*49c58f9bSArmin Le Grand                 aSuppressGraphicAttr = GraphicAttr();
117*49c58f9bSArmin Le Grand             }
118*49c58f9bSArmin Le Grand 
119*49c58f9bSArmin Le Grand             // create sub-content; helper takes care of correct handling of
120*49c58f9bSArmin Le Grand             // bitmap, svg or metafile content
121035a2f44SArmin Le Grand             aRetval = create2DDecompositionOfGraphic(
122035a2f44SArmin Le Grand                 aTransformedGraphic,
123035a2f44SArmin Le Grand                 aTransform);
124cdf0e10cSrcweir 
125*49c58f9bSArmin Le Grand             if(!aRetval.getLength())
126cdf0e10cSrcweir             {
127*49c58f9bSArmin Le Grand                 // content is invisible, done
128*49c58f9bSArmin Le Grand                 return aRetval;
129*49c58f9bSArmin Le Grand             }
130*49c58f9bSArmin Le Grand 
131*49c58f9bSArmin Le Grand             if(isAdjusted || isDrawMode)
132*49c58f9bSArmin Le Grand             {
133*49c58f9bSArmin Le Grand                 // embed to needed ModifiedColorPrimitive2D's if necessary. Do this for
134*49c58f9bSArmin Le Grand                 // adjustments and draw mode specials
135*49c58f9bSArmin Le Grand                 aRetval = create2DColorModifierEmbeddingsAsNeeded(
136*49c58f9bSArmin Le Grand                     aRetval,
137*49c58f9bSArmin Le Grand                     aSuppressGraphicAttr.GetDrawMode(),
138*49c58f9bSArmin Le Grand                     basegfx::clamp(aSuppressGraphicAttr.GetLuminance() * 0.01, -1.0, 1.0),
139*49c58f9bSArmin Le Grand                     basegfx::clamp(aSuppressGraphicAttr.GetContrast() * 0.01, -1.0, 1.0),
140*49c58f9bSArmin Le Grand                     basegfx::clamp(aSuppressGraphicAttr.GetChannelR() * 0.01, -1.0, 1.0),
141*49c58f9bSArmin Le Grand                     basegfx::clamp(aSuppressGraphicAttr.GetChannelG() * 0.01, -1.0, 1.0),
142*49c58f9bSArmin Le Grand                     basegfx::clamp(aSuppressGraphicAttr.GetChannelB() * 0.01, -1.0, 1.0),
143*49c58f9bSArmin Le Grand                     basegfx::clamp(aSuppressGraphicAttr.GetGamma(), 0.0, 10.0),
144*49c58f9bSArmin Le Grand                     aSuppressGraphicAttr.IsInvert());
145*49c58f9bSArmin Le Grand 
146*49c58f9bSArmin Le Grand                 if(!aRetval.getLength())
147*49c58f9bSArmin Le Grand                 {
148*49c58f9bSArmin Le Grand                     // content is invisible, done
149*49c58f9bSArmin Le Grand                     return aRetval;
150*49c58f9bSArmin Le Grand                 }
151*49c58f9bSArmin Le Grand             }
152*49c58f9bSArmin Le Grand 
153*49c58f9bSArmin Le Grand             if(getGraphicAttr().IsTransparent())
154*49c58f9bSArmin Le Grand             {
155*49c58f9bSArmin Le Grand                 // check for transparency
156*49c58f9bSArmin Le Grand                 const double fTransparency(basegfx::clamp(getGraphicAttr().GetTransparency() * (1.0 / 255.0), 0.0, 1.0));
157*49c58f9bSArmin Le Grand 
158*49c58f9bSArmin Le Grand                 if(!basegfx::fTools::equalZero(fTransparency))
159*49c58f9bSArmin Le Grand                 {
160*49c58f9bSArmin Le Grand                     const Primitive2DReference aUnifiedTransparence(
161*49c58f9bSArmin Le Grand                         new UnifiedTransparencePrimitive2D(
162*49c58f9bSArmin Le Grand                             aRetval,
163*49c58f9bSArmin Le Grand                             fTransparency));
164*49c58f9bSArmin Le Grand 
165*49c58f9bSArmin Le Grand                     aRetval = Primitive2DSequence(&aUnifiedTransparence, 1);
166*49c58f9bSArmin Le Grand                 }
167*49c58f9bSArmin Le Grand             }
168*49c58f9bSArmin Le Grand 
169cdf0e10cSrcweir             if(getGraphicAttr().IsCropped())
170cdf0e10cSrcweir             {
171*49c58f9bSArmin Le Grand                 // check for cropping
172cdf0e10cSrcweir                 // calculate scalings between real image size and logic object size. This
173cdf0e10cSrcweir                 // is necessary since the crop values are relative to original bitmap size
1742376739dSArmin Le Grand                 const basegfx::B2DVector aObjectScale(aTransform * basegfx::B2DVector(1.0, 1.0));
1752376739dSArmin Le Grand                 const basegfx::B2DVector aCropScaleFactor(
1762376739dSArmin Le Grand                     rGraphicObject.calculateCropScaling(
1772376739dSArmin Le Grand                         aObjectScale.getX(),
1782376739dSArmin Le Grand                         aObjectScale.getY(),
1792376739dSArmin Le Grand                         getGraphicAttr().GetLeftCrop(),
1802376739dSArmin Le Grand                         getGraphicAttr().GetTopCrop(),
1812376739dSArmin Le Grand                         getGraphicAttr().GetRightCrop(),
1822376739dSArmin Le Grand                         getGraphicAttr().GetBottomCrop()));
183cdf0e10cSrcweir 
184ddde725dSArmin Le Grand                 // embed content in cropPrimitive
185035a2f44SArmin Le Grand                 Primitive2DReference xPrimitive(
186035a2f44SArmin Le Grand                     new CropPrimitive2D(
187035a2f44SArmin Le Grand                         aRetval,
188ddde725dSArmin Le Grand                         aTransform,
1892376739dSArmin Le Grand                         getGraphicAttr().GetLeftCrop() * aCropScaleFactor.getX(),
1902376739dSArmin Le Grand                         getGraphicAttr().GetTopCrop() * aCropScaleFactor.getY(),
1912376739dSArmin Le Grand                         getGraphicAttr().GetRightCrop() * aCropScaleFactor.getX(),
1922376739dSArmin Le Grand                         getGraphicAttr().GetBottomCrop() * aCropScaleFactor.getY()));
193cdf0e10cSrcweir 
194035a2f44SArmin Le Grand                 aRetval = Primitive2DSequence(&xPrimitive, 1);
195035a2f44SArmin Le Grand             }
196cdf0e10cSrcweir 
197cdf0e10cSrcweir             return aRetval;
198cdf0e10cSrcweir         }
199cdf0e10cSrcweir 
GraphicPrimitive2D(const basegfx::B2DHomMatrix & rTransform,const GraphicObject & rGraphicObject,const GraphicAttr & rGraphicAttr)200cdf0e10cSrcweir         GraphicPrimitive2D::GraphicPrimitive2D(
201cdf0e10cSrcweir             const basegfx::B2DHomMatrix& rTransform,
202cdf0e10cSrcweir             const GraphicObject& rGraphicObject,
203cdf0e10cSrcweir             const GraphicAttr& rGraphicAttr)
204cdf0e10cSrcweir         :	BufferedDecompositionPrimitive2D(),
205cdf0e10cSrcweir             maTransform(rTransform),
206cdf0e10cSrcweir             maGraphicObject(rGraphicObject),
207cdf0e10cSrcweir             maGraphicAttr(rGraphicAttr)
208cdf0e10cSrcweir         {
209cdf0e10cSrcweir         }
210cdf0e10cSrcweir 
GraphicPrimitive2D(const basegfx::B2DHomMatrix & rTransform,const GraphicObject & rGraphicObject)211cdf0e10cSrcweir         GraphicPrimitive2D::GraphicPrimitive2D(
212cdf0e10cSrcweir             const basegfx::B2DHomMatrix& rTransform,
213cdf0e10cSrcweir             const GraphicObject& rGraphicObject)
214cdf0e10cSrcweir         :	BufferedDecompositionPrimitive2D(),
215cdf0e10cSrcweir             maTransform(rTransform),
216cdf0e10cSrcweir             maGraphicObject(rGraphicObject),
217cdf0e10cSrcweir             maGraphicAttr()
218cdf0e10cSrcweir         {
219cdf0e10cSrcweir         }
220cdf0e10cSrcweir 
operator ==(const BasePrimitive2D & rPrimitive) const221cdf0e10cSrcweir         bool GraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
222cdf0e10cSrcweir         {
223cdf0e10cSrcweir             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
224cdf0e10cSrcweir             {
225cdf0e10cSrcweir                 const GraphicPrimitive2D& rCompare = (GraphicPrimitive2D&)rPrimitive;
226cdf0e10cSrcweir 
227cdf0e10cSrcweir                 return (getTransform() == rCompare.getTransform()
228cdf0e10cSrcweir                     && getGraphicObject() == rCompare.getGraphicObject()
229cdf0e10cSrcweir                     && getGraphicAttr() == rCompare.getGraphicAttr());
230cdf0e10cSrcweir             }
231cdf0e10cSrcweir 
232cdf0e10cSrcweir             return false;
233cdf0e10cSrcweir         }
234cdf0e10cSrcweir 
getB2DRange(const geometry::ViewInformation2D &) const235cdf0e10cSrcweir         basegfx::B2DRange GraphicPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
236cdf0e10cSrcweir         {
237cdf0e10cSrcweir             basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
238cdf0e10cSrcweir             aRetval.transform(getTransform());
239cdf0e10cSrcweir             return aRetval;
240cdf0e10cSrcweir         }
241cdf0e10cSrcweir 
242cdf0e10cSrcweir         // provide unique ID
243cdf0e10cSrcweir         ImplPrimitrive2DIDBlock(GraphicPrimitive2D, PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D)
244cdf0e10cSrcweir 
245cdf0e10cSrcweir     } // end of namespace primitive2d
246cdf0e10cSrcweir } // end of namespace drawinglayer
247cdf0e10cSrcweir 
248cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
249cdf0e10cSrcweir // eof
250