Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / drawinglayer / source / primitive2d / graphicprimitive2d.cxx
blobf684227ba1c8c1227877659d12d5f85fb58e809b
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 <sal/config.h>
22 #include <algorithm>
24 #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
25 #include <drawinglayer/primitive2d/cropprimitive2d.hxx>
26 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
27 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
28 #include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx>
29 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
30 #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
31 #include <basegfx/matrix/b2dhommatrixtools.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/outdev.hxx>
35 namespace drawinglayer
37 namespace primitive2d
39 void GraphicPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& ) const
41 if(255 == getGraphicAttr().GetTransparency())
43 // content is invisible, done
44 return;
47 // do not apply mirroring from GraphicAttr to the Metafile by calling
48 // GetTransformedGraphic, this will try to mirror the Metafile using Scale()
49 // at the Metafile. This again calls Scale at the single MetaFile actions,
50 // but this implementation never worked. I reworked that implementations,
51 // but for security reasons i will try not to use it.
52 basegfx::B2DHomMatrix aTransform(getTransform());
54 if(getGraphicAttr().IsMirrored())
56 // content needs mirroring
57 const bool bHMirr(getGraphicAttr().GetMirrorFlags() & BmpMirrorFlags::Horizontal);
58 const bool bVMirr(getGraphicAttr().GetMirrorFlags() & BmpMirrorFlags::Vertical);
60 // mirror by applying negative scale to the unit primitive and
61 // applying the object transformation on it.
62 aTransform = basegfx::utils::createScaleB2DHomMatrix(
63 bHMirr ? -1.0 : 1.0,
64 bVMirr ? -1.0 : 1.0);
65 aTransform.translate(
66 bHMirr ? 1.0 : 0.0,
67 bVMirr ? 1.0 : 0.0);
68 aTransform = getTransform() * aTransform;
71 // Get transformed graphic. Suppress rotation and cropping, only filtering is needed
72 // here (and may be replaced later on). Cropping is handled below as mask primitive (if set).
73 // Also need to suppress mirroring, it is part of the transformation now (see above).
74 // Also move transparency handling to embedding to a UnifiedTransparencePrimitive2D; do
75 // that by remembering original transparency and applying that later if needed
76 GraphicAttr aSuppressGraphicAttr(getGraphicAttr());
78 aSuppressGraphicAttr.SetCrop(0, 0, 0, 0);
79 aSuppressGraphicAttr.SetRotation(0);
80 aSuppressGraphicAttr.SetMirrorFlags(BmpMirrorFlags::NONE);
81 aSuppressGraphicAttr.SetTransparency(0);
83 const GraphicObject& rGraphicObject = getGraphicObject();
84 Graphic aTransformedGraphic(rGraphicObject.GetGraphic());
85 const bool isBitmap(GraphicType::Bitmap == aTransformedGraphic.GetType() && !aTransformedGraphic.getVectorGraphicData().get());
86 const bool isAdjusted(getGraphicAttr().IsAdjusted());
87 const bool isDrawMode(GraphicDrawMode::Standard != getGraphicAttr().GetDrawMode());
89 if(isBitmap && (isAdjusted || isDrawMode))
91 // the pure primitive solution with the color modifiers works well, too, but when
92 // it is a bitmap graphic the old modification currently is faster; so use it here
93 // instead of creating all as in create2DColorModifierEmbeddingsAsNeeded (see below).
94 // Still, crop, rotation, mirroring and transparency is handled by primitives already
95 // (see above).
96 // This could even be done when vector graphic, but we explicitly want to have the
97 // pure primitive solution for this; this will allow vector graphics to stay vector
98 // graphics, independent from the color filtering stuff. This will enhance e.g.
99 // SVG and print quality while reducing data size at the same time.
100 // The other way around the old modifications when only used on already bitmap objects
101 // will not lose any quality.
102 aTransformedGraphic = rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr);
104 // reset GraphicAttr after use to not apply double
105 aSuppressGraphicAttr = GraphicAttr();
108 // create sub-content; helper takes care of correct handling of
109 // bitmap, svg or metafile content
110 Primitive2DContainer aRetval;
111 create2DDecompositionOfGraphic(
112 aRetval,
113 aTransformedGraphic,
114 aTransform);
116 if(aRetval.empty())
118 // content is invisible, done
119 return;
122 if(isAdjusted || isDrawMode)
124 // embed to needed ModifiedColorPrimitive2D's if necessary. Do this for
125 // adjustments and draw mode specials
126 aRetval = create2DColorModifierEmbeddingsAsNeeded(
127 aRetval,
128 aSuppressGraphicAttr.GetDrawMode(),
129 std::clamp(aSuppressGraphicAttr.GetLuminance() * 0.01, -1.0, 1.0),
130 std::clamp(aSuppressGraphicAttr.GetContrast() * 0.01, -1.0, 1.0),
131 std::clamp(aSuppressGraphicAttr.GetChannelR() * 0.01, -1.0, 1.0),
132 std::clamp(aSuppressGraphicAttr.GetChannelG() * 0.01, -1.0, 1.0),
133 std::clamp(aSuppressGraphicAttr.GetChannelB() * 0.01, -1.0, 1.0),
134 std::clamp(aSuppressGraphicAttr.GetGamma(), 0.0, 10.0),
135 aSuppressGraphicAttr.IsInvert());
137 if(aRetval.empty())
139 // content is invisible, done
140 return;
144 if(getGraphicAttr().IsTransparent())
146 // check for transparency
147 const double fTransparency(std::clamp(getGraphicAttr().GetTransparency() * (1.0 / 255.0), 0.0, 1.0));
149 if(!basegfx::fTools::equalZero(fTransparency))
151 const Primitive2DReference aUnifiedTransparence(
152 new UnifiedTransparencePrimitive2D(
153 aRetval,
154 fTransparency));
156 aRetval = Primitive2DContainer { aUnifiedTransparence };
160 if(getGraphicAttr().IsCropped())
162 // check for cropping
163 // calculate scalings between real image size and logic object size. This
164 // is necessary since the crop values are relative to original bitmap size
165 const basegfx::B2DVector aObjectScale(aTransform * basegfx::B2DVector(1.0, 1.0));
166 const basegfx::B2DVector aCropScaleFactor(
167 rGraphicObject.calculateCropScaling(
168 aObjectScale.getX(),
169 aObjectScale.getY(),
170 getGraphicAttr().GetLeftCrop(),
171 getGraphicAttr().GetTopCrop(),
172 getGraphicAttr().GetRightCrop(),
173 getGraphicAttr().GetBottomCrop()));
175 // embed content in cropPrimitive
176 Primitive2DReference xPrimitive(
177 new CropPrimitive2D(
178 aRetval,
179 aTransform,
180 getGraphicAttr().GetLeftCrop() * aCropScaleFactor.getX(),
181 getGraphicAttr().GetTopCrop() * aCropScaleFactor.getY(),
182 getGraphicAttr().GetRightCrop() * aCropScaleFactor.getX(),
183 getGraphicAttr().GetBottomCrop() * aCropScaleFactor.getY()));
185 aRetval = Primitive2DContainer { xPrimitive };
188 rContainer.insert(rContainer.end(), aRetval.begin(), aRetval.end());
191 GraphicPrimitive2D::GraphicPrimitive2D(
192 const basegfx::B2DHomMatrix& rTransform,
193 const GraphicObject& rGraphicObject,
194 const GraphicAttr& rGraphicAttr)
195 : BufferedDecompositionPrimitive2D(),
196 maTransform(rTransform),
197 maGraphicObject(rGraphicObject),
198 maGraphicAttr(rGraphicAttr)
202 GraphicPrimitive2D::GraphicPrimitive2D(
203 const basegfx::B2DHomMatrix& rTransform,
204 const GraphicObject& rGraphicObject)
205 : BufferedDecompositionPrimitive2D(),
206 maTransform(rTransform),
207 maGraphicObject(rGraphicObject),
208 maGraphicAttr()
212 bool GraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
214 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
216 const GraphicPrimitive2D& rCompare = static_cast<const GraphicPrimitive2D&>(rPrimitive);
218 return (getTransform() == rCompare.getTransform()
219 && getGraphicObject() == rCompare.getGraphicObject()
220 && getGraphicAttr() == rCompare.getGraphicAttr());
223 return false;
226 basegfx::B2DRange GraphicPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
228 basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
229 aRetval.transform(getTransform());
230 return aRetval;
233 // provide unique ID
234 ImplPrimitive2DIDBlock(GraphicPrimitive2D, PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D)
236 } // end of namespace primitive2d
237 } // end of namespace drawinglayer
239 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */