1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
39 void GraphicPrimitive2D::create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& ) const
41 if(255 == getGraphicAttr().GetTransparency())
43 // content is invisible, done
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(
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
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(
118 // content is invisible, done
122 if(isAdjusted
|| isDrawMode
)
124 // embed to needed ModifiedColorPrimitive2D's if necessary. Do this for
125 // adjustments and draw mode specials
126 aRetval
= create2DColorModifierEmbeddingsAsNeeded(
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());
139 // content is invisible, done
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(
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(
170 getGraphicAttr().GetLeftCrop(),
171 getGraphicAttr().GetTopCrop(),
172 getGraphicAttr().GetRightCrop(),
173 getGraphicAttr().GetBottomCrop()));
175 // embed content in cropPrimitive
176 Primitive2DReference
xPrimitive(
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
),
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());
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());
234 ImplPrimitive2DIDBlock(GraphicPrimitive2D
, PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D
)
236 } // end of namespace primitive2d
237 } // end of namespace drawinglayer
239 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */