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 <drawinglayer/primitive2d/texteffectprimitive2d.hxx>
21 #include <drawinglayer/geometry/viewinformation2d.hxx>
22 #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
23 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
24 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
25 #include <basegfx/matrix/b2dhommatrixtools.hxx>
28 namespace drawinglayer
32 static const double fDiscreteSize(1.1);
34 void TextEffectPrimitive2D::create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& rViewInformation
) const
36 // get the distance of one discrete units from target display. Use between 1.0 and sqrt(2) to
37 // have good results on rotated objects, too
38 const basegfx::B2DVector
aDistance(rViewInformation
.getInverseObjectToViewTransformation() *
39 basegfx::B2DVector(fDiscreteSize
, fDiscreteSize
));
40 const basegfx::B2DVector
aDiagonalDistance(aDistance
* (1.0 / 1.44));
42 switch(getTextEffectStyle2D())
44 case TextEffectStyle2D::ReliefEmbossed
:
45 case TextEffectStyle2D::ReliefEngraved
:
46 case TextEffectStyle2D::ReliefEmbossedDefault
:
47 case TextEffectStyle2D::ReliefEngravedDefault
:
49 // prepare transform of sub-group back to (0,0) and align to X-Axis
50 basegfx::B2DHomMatrix
aBackTransform(basegfx::utils::createTranslateB2DHomMatrix(
51 -getRotationCenter().getX(), -getRotationCenter().getY()));
52 aBackTransform
.rotate(-getDirection());
54 // prepare transform of sub-group back to its position and rotation
55 basegfx::B2DHomMatrix
aForwardTransform(basegfx::utils::createRotateB2DHomMatrix(getDirection()));
56 aForwardTransform
.translate(getRotationCenter().getX(), getRotationCenter().getY());
58 // create transformation for one discrete unit
60 TextEffectStyle2D::ReliefEmbossed
== getTextEffectStyle2D()
61 || TextEffectStyle2D::ReliefEmbossedDefault
== getTextEffectStyle2D());
62 const bool bDefaultTextColor(
63 TextEffectStyle2D::ReliefEmbossedDefault
== getTextEffectStyle2D()
64 || TextEffectStyle2D::ReliefEngravedDefault
== getTextEffectStyle2D());
65 basegfx::B2DHomMatrix
aTransform(aBackTransform
);
70 aTransform
.translate(aDiagonalDistance
.getX(), aDiagonalDistance
.getY());
75 aTransform
.translate(-aDiagonalDistance
.getX(), -aDiagonalDistance
.getY());
78 aTransform
*= aForwardTransform
;
82 // emboss/engrave in black, original forced to white
83 const basegfx::BColorModifierSharedPtr
aBColorModifierToGray(
84 new basegfx::BColorModifier_replace(
85 basegfx::BColor(0.0)));
86 const Primitive2DReference
xModifiedColor(
87 new ModifiedColorPrimitive2D(
89 aBColorModifierToGray
));
92 new TransformPrimitive2D(
94 Primitive2DContainer
{ xModifiedColor
}));
97 const basegfx::BColorModifierSharedPtr
aBColorModifierToWhite(
98 new basegfx::BColorModifier_replace(
99 basegfx::BColor(1.0)));
101 rContainer
.push_back(
102 new ModifiedColorPrimitive2D(
104 aBColorModifierToWhite
));
108 // emboss/engrave in gray, keep original's color
109 const basegfx::BColorModifierSharedPtr
aBColorModifierToGray(
110 new basegfx::BColorModifier_replace(
111 basegfx::BColor(0.75))); // 192
112 const Primitive2DReference
xModifiedColor(
113 new ModifiedColorPrimitive2D(
115 aBColorModifierToGray
));
117 rContainer
.push_back(
118 new TransformPrimitive2D(
120 Primitive2DContainer
{ xModifiedColor
}));
123 rContainer
.push_back(new GroupPrimitive2D(getTextContent()));
128 case TextEffectStyle2D::Outline
:
130 // create transform primitives in all directions
131 basegfx::B2DHomMatrix aTransform
;
133 aTransform
.set(0, 2, aDistance
.getX());
134 aTransform
.set(1, 2, 0.0);
135 rContainer
.push_back(new TransformPrimitive2D(aTransform
, getTextContent()));
137 aTransform
.set(0, 2, aDiagonalDistance
.getX());
138 aTransform
.set(1, 2, aDiagonalDistance
.getY());
139 rContainer
.push_back(new TransformPrimitive2D(aTransform
, getTextContent()));
141 aTransform
.set(0, 2, 0.0);
142 aTransform
.set(1, 2, aDistance
.getY());
143 rContainer
.push_back(new TransformPrimitive2D(aTransform
, getTextContent()));
145 aTransform
.set(0, 2, -aDiagonalDistance
.getX());
146 aTransform
.set(1, 2, aDiagonalDistance
.getY());
147 rContainer
.push_back(new TransformPrimitive2D(aTransform
, getTextContent()));
149 aTransform
.set(0, 2, -aDistance
.getX());
150 aTransform
.set(1, 2, 0.0);
151 rContainer
.push_back(new TransformPrimitive2D(aTransform
, getTextContent()));
153 aTransform
.set(0, 2, -aDiagonalDistance
.getX());
154 aTransform
.set(1, 2, -aDiagonalDistance
.getY());
155 rContainer
.push_back(new TransformPrimitive2D(aTransform
, getTextContent()));
157 aTransform
.set(0, 2, 0.0);
158 aTransform
.set(1, 2, -aDistance
.getY());
159 rContainer
.push_back(new TransformPrimitive2D(aTransform
, getTextContent()));
161 aTransform
.set(0, 2, aDiagonalDistance
.getX());
162 aTransform
.set(1, 2, -aDiagonalDistance
.getY());
163 rContainer
.push_back(new TransformPrimitive2D(aTransform
, getTextContent()));
165 // at last, place original over it, but force to white
166 const basegfx::BColorModifierSharedPtr
aBColorModifierToWhite(
167 new basegfx::BColorModifier_replace(
168 basegfx::BColor(1.0, 1.0, 1.0)));
169 rContainer
.push_back(
170 new ModifiedColorPrimitive2D(
172 aBColorModifierToWhite
));
179 TextEffectPrimitive2D::TextEffectPrimitive2D(
180 const Primitive2DContainer
& rTextContent
,
181 const basegfx::B2DPoint
& rRotationCenter
,
183 TextEffectStyle2D eTextEffectStyle2D
)
184 : BufferedDecompositionPrimitive2D(),
185 maTextContent(rTextContent
),
186 maRotationCenter(rRotationCenter
),
187 mfDirection(fDirection
),
188 meTextEffectStyle2D(eTextEffectStyle2D
)
192 bool TextEffectPrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
194 if(BasePrimitive2D::operator==(rPrimitive
))
196 const TextEffectPrimitive2D
& rCompare
= static_cast<const TextEffectPrimitive2D
&>(rPrimitive
);
198 return (getTextContent() == rCompare
.getTextContent()
199 && getRotationCenter() == rCompare
.getRotationCenter()
200 && getDirection() == rCompare
.getDirection()
201 && getTextEffectStyle2D() == rCompare
.getTextEffectStyle2D());
207 basegfx::B2DRange
TextEffectPrimitive2D::getB2DRange(const geometry::ViewInformation2D
& rViewInformation
) const
209 // get range of content and grow by used fDiscreteSize. That way it is not necessary to ask
210 // the whole decomposition for its ranges (which may be expensive with outline mode which
211 // then will ask 9 times at nearly the same content. This may even be refined here using the
212 // TextEffectStyle information, e.g. for TEXTEFFECTSTYLE2D_RELIEF the grow needs only to
213 // be in two directions
214 basegfx::B2DRange
aRetval(getTextContent().getB2DRange(rViewInformation
));
215 aRetval
.grow(fDiscreteSize
);
220 void TextEffectPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor
& rVisitor
, const geometry::ViewInformation2D
& rViewInformation
) const
222 ::osl::MutexGuard
aGuard( m_aMutex
);
224 if(!getBuffered2DDecomposition().empty())
226 if(maLastObjectToViewTransformation
!= rViewInformation
.getObjectToViewTransformation())
228 // conditions of last local decomposition have changed, delete
229 const_cast< TextEffectPrimitive2D
* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
233 if(getBuffered2DDecomposition().empty())
235 // remember ViewRange and ViewTransformation
236 const_cast< TextEffectPrimitive2D
* >(this)->maLastObjectToViewTransformation
= rViewInformation
.getObjectToViewTransformation();
239 // use parent implementation
240 BufferedDecompositionPrimitive2D::get2DDecomposition(rVisitor
, rViewInformation
);
244 ImplPrimitive2DIDBlock(TextEffectPrimitive2D
, PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D
)
246 } // end of namespace primitive2d
247 } // end of namespace drawinglayer
249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */