Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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>
26 :
27 :
28 :
29 : namespace drawinglayer
30 : {
31 : namespace primitive2d
32 : {
33 : static double fDiscreteSize(1.1);
34 :
35 918 : Primitive2DSequence TextEffectPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
36 : {
37 918 : Primitive2DSequence aRetval;
38 :
39 : // get the distance of one discrete units from target display. Use between 1.0 and sqrt(2) to
40 : // have good results on rotated objects, too
41 918 : const basegfx::B2DVector aDistance(rViewInformation.getInverseObjectToViewTransformation() *
42 2754 : basegfx::B2DVector(fDiscreteSize, fDiscreteSize));
43 1836 : const basegfx::B2DVector aDiagonalDistance(aDistance * (1.0 / 1.44));
44 :
45 918 : switch(getTextEffectStyle2D())
46 : {
47 : case TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED:
48 : case TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED:
49 : case TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT:
50 : case TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT:
51 : {
52 : // prepare transform of sub-group back to (0,0) and align to X-Axis
53 : basegfx::B2DHomMatrix aBackTransform(basegfx::tools::createTranslateB2DHomMatrix(
54 823 : -getRotationCenter().getX(), -getRotationCenter().getY()));
55 823 : aBackTransform.rotate(-getDirection());
56 :
57 : // prepare transform of sub-group back to it's position and rotation
58 1646 : basegfx::B2DHomMatrix aForwardTransform(basegfx::tools::createRotateB2DHomMatrix(getDirection()));
59 823 : aForwardTransform.translate(getRotationCenter().getX(), getRotationCenter().getY());
60 :
61 : // create transformation for one discrete unit
62 : const bool bEmbossed(
63 823 : TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED == getTextEffectStyle2D()
64 823 : || TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT == getTextEffectStyle2D());
65 : const bool bDefaultTextColor(
66 823 : TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT == getTextEffectStyle2D()
67 823 : || TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT == getTextEffectStyle2D());
68 1646 : basegfx::B2DHomMatrix aTransform(aBackTransform);
69 823 : aRetval.realloc(2);
70 :
71 823 : if(bEmbossed)
72 : {
73 : // to bottom-right
74 823 : aTransform.translate(aDiagonalDistance.getX(), aDiagonalDistance.getY());
75 : }
76 : else
77 : {
78 : // to top-left
79 0 : aTransform.translate(-aDiagonalDistance.getX(), -aDiagonalDistance.getY());
80 : }
81 :
82 823 : aTransform *= aForwardTransform;
83 :
84 823 : if(bDefaultTextColor)
85 : {
86 : // emboss/engrave in black, original forced to white
87 : const basegfx::BColorModifierSharedPtr aBColorModifierToGray(
88 : new basegfx::BColorModifier_replace(
89 0 : basegfx::BColor(0.0)));
90 : const Primitive2DReference xModifiedColor(
91 : new ModifiedColorPrimitive2D(
92 : getTextContent(),
93 0 : aBColorModifierToGray));
94 :
95 0 : aRetval[0] = Primitive2DReference(
96 : new TransformPrimitive2D(
97 : aTransform,
98 0 : Primitive2DSequence(&xModifiedColor, 1)));
99 :
100 : // add original, too
101 : const basegfx::BColorModifierSharedPtr aBColorModifierToWhite(
102 : new basegfx::BColorModifier_replace(
103 0 : basegfx::BColor(1.0)));
104 :
105 0 : aRetval[1] = Primitive2DReference(
106 : new ModifiedColorPrimitive2D(
107 : getTextContent(),
108 0 : aBColorModifierToWhite));
109 : }
110 : else
111 : {
112 : // emboss/engrave in gray, keep original's color
113 : const basegfx::BColorModifierSharedPtr aBColorModifierToGray(
114 : new basegfx::BColorModifier_replace(
115 823 : basegfx::BColor(0.75))); // 192
116 : const Primitive2DReference xModifiedColor(
117 : new ModifiedColorPrimitive2D(
118 : getTextContent(),
119 1646 : aBColorModifierToGray));
120 :
121 1646 : aRetval[0] = Primitive2DReference(
122 : new TransformPrimitive2D(
123 : aTransform,
124 2469 : Primitive2DSequence(&xModifiedColor, 1)));
125 :
126 : // add original, too
127 1646 : aRetval[1] = Primitive2DReference(new GroupPrimitive2D(getTextContent()));
128 : }
129 :
130 1646 : break;
131 : }
132 : case TEXTEFFECTSTYLE2D_OUTLINE:
133 : {
134 : // create transform primitives in all directions
135 95 : basegfx::B2DHomMatrix aTransform;
136 95 : aRetval.realloc(9);
137 :
138 95 : aTransform.set(0, 2, aDistance.getX());
139 95 : aTransform.set(1, 2, 0.0);
140 95 : aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
141 :
142 95 : aTransform.set(0, 2, aDiagonalDistance.getX());
143 95 : aTransform.set(1, 2, aDiagonalDistance.getY());
144 95 : aRetval[1] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
145 :
146 95 : aTransform.set(0, 2, 0.0);
147 95 : aTransform.set(1, 2, aDistance.getY());
148 95 : aRetval[2] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
149 :
150 95 : aTransform.set(0, 2, -aDiagonalDistance.getX());
151 95 : aTransform.set(1, 2, aDiagonalDistance.getY());
152 95 : aRetval[3] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
153 :
154 95 : aTransform.set(0, 2, -aDistance.getX());
155 95 : aTransform.set(1, 2, 0.0);
156 95 : aRetval[4] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
157 :
158 95 : aTransform.set(0, 2, -aDiagonalDistance.getX());
159 95 : aTransform.set(1, 2, -aDiagonalDistance.getY());
160 95 : aRetval[5] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
161 :
162 95 : aTransform.set(0, 2, 0.0);
163 95 : aTransform.set(1, 2, -aDistance.getY());
164 95 : aRetval[6] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
165 :
166 95 : aTransform.set(0, 2, aDiagonalDistance.getX());
167 95 : aTransform.set(1, 2, -aDiagonalDistance.getY());
168 95 : aRetval[7] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
169 :
170 : // at last, place original over it, but force to white
171 : const basegfx::BColorModifierSharedPtr aBColorModifierToWhite(
172 : new basegfx::BColorModifier_replace(
173 190 : basegfx::BColor(1.0, 1.0, 1.0)));
174 190 : aRetval[8] = Primitive2DReference(
175 : new ModifiedColorPrimitive2D(
176 : getTextContent(),
177 190 : aBColorModifierToWhite));
178 :
179 190 : break;
180 : }
181 : }
182 :
183 1836 : return aRetval;
184 : }
185 :
186 2009 : TextEffectPrimitive2D::TextEffectPrimitive2D(
187 : const Primitive2DSequence& rTextContent,
188 : const basegfx::B2DPoint& rRotationCenter,
189 : double fDirection,
190 : TextEffectStyle2D eTextEffectStyle2D)
191 : : BufferedDecompositionPrimitive2D(),
192 : maTextContent(rTextContent),
193 : maRotationCenter(rRotationCenter),
194 : mfDirection(fDirection),
195 2009 : meTextEffectStyle2D(eTextEffectStyle2D)
196 : {
197 2009 : }
198 :
199 0 : bool TextEffectPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
200 : {
201 0 : if(BasePrimitive2D::operator==(rPrimitive))
202 : {
203 0 : const TextEffectPrimitive2D& rCompare = static_cast<const TextEffectPrimitive2D&>(rPrimitive);
204 :
205 0 : return (getTextContent() == rCompare.getTextContent()
206 0 : && getRotationCenter() == rCompare.getRotationCenter()
207 0 : && getDirection() == rCompare.getDirection()
208 0 : && getTextEffectStyle2D() == rCompare.getTextEffectStyle2D());
209 : }
210 :
211 0 : return false;
212 : }
213 :
214 18124 : basegfx::B2DRange TextEffectPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
215 : {
216 : // get range of content and grow by used fDiscreteSize. That way it is not necessary to ask
217 : // the whole decomposition for its ranges (which may be expensive with outline mode which
218 : // then will ask 9 times at nearly the same content. This may even be refined here using the
219 : // TextEffectStyle information, e.g. for TEXTEFFECTSTYLE2D_RELIEF the grow needs only to
220 : // be in two directions
221 18124 : basegfx::B2DRange aRetval(getB2DRangeFromPrimitive2DSequence(getTextContent(), rViewInformation));
222 18124 : aRetval.grow(fDiscreteSize);
223 :
224 18124 : return aRetval;
225 : }
226 :
227 931 : Primitive2DSequence TextEffectPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
228 : {
229 931 : ::osl::MutexGuard aGuard( m_aMutex );
230 :
231 931 : if(getBuffered2DDecomposition().hasElements())
232 : {
233 60 : if(maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation())
234 : {
235 : // conditions of last local decomposition have changed, delete
236 47 : const_cast< TextEffectPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence());
237 : }
238 : }
239 :
240 931 : if(!getBuffered2DDecomposition().hasElements())
241 : {
242 : // remember ViewRange and ViewTransformation
243 918 : const_cast< TextEffectPrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation();
244 : }
245 :
246 : // use parent implementation
247 931 : return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
248 : }
249 :
250 : // provide unique ID
251 931 : ImplPrimitive2DIDBlock(TextEffectPrimitive2D, PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D)
252 :
253 : } // end of namespace primitive2d
254 : } // end of namespace drawinglayer
255 :
256 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|