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 0 : Primitive2DSequence TextEffectPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
36 : {
37 0 : 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 0 : const basegfx::B2DVector aDistance(rViewInformation.getInverseObjectToViewTransformation() *
42 0 : basegfx::B2DVector(fDiscreteSize, fDiscreteSize));
43 0 : const basegfx::B2DVector aDiagonalDistance(aDistance * (1.0 / 1.44));
44 :
45 0 : 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 0 : -getRotationCenter().getX(), -getRotationCenter().getY()));
55 0 : aBackTransform.rotate(-getDirection());
56 :
57 : // prepare transform of sub-group back to it's position and rotation
58 0 : basegfx::B2DHomMatrix aForwardTransform(basegfx::tools::createRotateB2DHomMatrix(getDirection()));
59 0 : aForwardTransform.translate(getRotationCenter().getX(), getRotationCenter().getY());
60 :
61 : // create transformation for one discrete unit
62 : const bool bEmbossed(
63 0 : TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED == getTextEffectStyle2D()
64 0 : || TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT == getTextEffectStyle2D());
65 : const bool bDefaultTextColor(
66 0 : TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT == getTextEffectStyle2D()
67 0 : || TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT == getTextEffectStyle2D());
68 0 : basegfx::B2DHomMatrix aTransform(aBackTransform);
69 0 : aRetval.realloc(2);
70 :
71 0 : if(bEmbossed)
72 : {
73 : // to bottom-right
74 0 : 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 0 : aTransform *= aForwardTransform;
83 :
84 0 : if(bDefaultTextColor)
85 : {
86 : // emboss/engrave in black, original forced to white
87 0 : const basegfx::BColorModifier aBColorModifierToGray(basegfx::BColor(0.0));
88 0 : const Primitive2DReference xModifiedColor(new ModifiedColorPrimitive2D(getTextContent(), aBColorModifierToGray));
89 0 : aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, Primitive2DSequence(&xModifiedColor, 1)));
90 :
91 : // add original, too
92 0 : const basegfx::BColorModifier aBColorModifierToWhite(basegfx::BColor(1.0));
93 0 : aRetval[1] = Primitive2DReference(new ModifiedColorPrimitive2D(getTextContent(), aBColorModifierToWhite));
94 : }
95 : else
96 : {
97 : // emboss/engrave in gray, keep original's color
98 0 : const basegfx::BColorModifier aBColorModifierToGray(basegfx::BColor(0.75)); // 192
99 0 : const Primitive2DReference xModifiedColor(new ModifiedColorPrimitive2D(getTextContent(), aBColorModifierToGray));
100 0 : aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, Primitive2DSequence(&xModifiedColor, 1)));
101 :
102 : // add original, too
103 0 : aRetval[1] = Primitive2DReference(new GroupPrimitive2D(getTextContent()));
104 : }
105 :
106 0 : break;
107 : }
108 : case TEXTEFFECTSTYLE2D_OUTLINE:
109 : {
110 : // create transform primitives in all directions
111 0 : basegfx::B2DHomMatrix aTransform;
112 0 : aRetval.realloc(9);
113 :
114 0 : aTransform.set(0, 2, aDistance.getX());
115 0 : aTransform.set(1, 2, 0.0);
116 0 : aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
117 :
118 0 : aTransform.set(0, 2, aDiagonalDistance.getX());
119 0 : aTransform.set(1, 2, aDiagonalDistance.getY());
120 0 : aRetval[1] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
121 :
122 0 : aTransform.set(0, 2, 0.0);
123 0 : aTransform.set(1, 2, aDistance.getY());
124 0 : aRetval[2] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
125 :
126 0 : aTransform.set(0, 2, -aDiagonalDistance.getX());
127 0 : aTransform.set(1, 2, aDiagonalDistance.getY());
128 0 : aRetval[3] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
129 :
130 0 : aTransform.set(0, 2, -aDistance.getX());
131 0 : aTransform.set(1, 2, 0.0);
132 0 : aRetval[4] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
133 :
134 0 : aTransform.set(0, 2, -aDiagonalDistance.getX());
135 0 : aTransform.set(1, 2, -aDiagonalDistance.getY());
136 0 : aRetval[5] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
137 :
138 0 : aTransform.set(0, 2, 0.0);
139 0 : aTransform.set(1, 2, -aDistance.getY());
140 0 : aRetval[6] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
141 :
142 0 : aTransform.set(0, 2, aDiagonalDistance.getX());
143 0 : aTransform.set(1, 2, -aDiagonalDistance.getY());
144 0 : aRetval[7] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
145 :
146 : // at last, place original over it, but force to white
147 0 : const basegfx::BColorModifier aBColorModifierToWhite(basegfx::BColor(1.0, 1.0, 1.0));
148 0 : aRetval[8] = Primitive2DReference(new ModifiedColorPrimitive2D(getTextContent(), aBColorModifierToWhite));
149 :
150 0 : break;
151 : }
152 : }
153 :
154 0 : return aRetval;
155 : }
156 :
157 0 : TextEffectPrimitive2D::TextEffectPrimitive2D(
158 : const Primitive2DSequence& rTextContent,
159 : const basegfx::B2DPoint& rRotationCenter,
160 : double fDirection,
161 : TextEffectStyle2D eTextEffectStyle2D)
162 : : BufferedDecompositionPrimitive2D(),
163 : maTextContent(rTextContent),
164 : maRotationCenter(rRotationCenter),
165 : mfDirection(fDirection),
166 0 : meTextEffectStyle2D(eTextEffectStyle2D)
167 : {
168 0 : }
169 :
170 0 : bool TextEffectPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
171 : {
172 0 : if(BasePrimitive2D::operator==(rPrimitive))
173 : {
174 0 : const TextEffectPrimitive2D& rCompare = (TextEffectPrimitive2D&)rPrimitive;
175 :
176 0 : return (getTextContent() == rCompare.getTextContent()
177 0 : && getRotationCenter() == rCompare.getRotationCenter()
178 0 : && getDirection() == rCompare.getDirection()
179 0 : && getTextEffectStyle2D() == rCompare.getTextEffectStyle2D());
180 : }
181 :
182 0 : return false;
183 : }
184 :
185 0 : basegfx::B2DRange TextEffectPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
186 : {
187 : // get range of content and grow by used fDiscreteSize. That way it is not necessary to ask
188 : // the whole decomposition for it's ranges (which may be expensive with outline mode which
189 : // then will ask 9 times at nearly the same content. This may even be refined here using the
190 : // TextEffectStyle information, e.g. for TEXTEFFECTSTYLE2D_RELIEF the grow needs only to
191 : // be in two directions
192 0 : basegfx::B2DRange aRetval(getB2DRangeFromPrimitive2DSequence(getTextContent(), rViewInformation));
193 0 : aRetval.grow(fDiscreteSize);
194 :
195 0 : return aRetval;
196 : }
197 :
198 0 : Primitive2DSequence TextEffectPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
199 : {
200 0 : ::osl::MutexGuard aGuard( m_aMutex );
201 :
202 0 : if(getBuffered2DDecomposition().hasElements())
203 : {
204 0 : if(maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation())
205 : {
206 : // conditions of last local decomposition have changed, delete
207 0 : const_cast< TextEffectPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence());
208 : }
209 : }
210 :
211 0 : if(!getBuffered2DDecomposition().hasElements())
212 : {
213 : // remember ViewRange and ViewTransformation
214 0 : const_cast< TextEffectPrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation();
215 : }
216 :
217 : // use parent implementation
218 0 : return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
219 : }
220 :
221 : // provide unique ID
222 0 : ImplPrimitrive2DIDBlock(TextEffectPrimitive2D, PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D)
223 :
224 : } // end of namespace primitive2d
225 : } // end of namespace drawinglayer
226 :
227 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|