Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / drawinglayer / source / primitive2d / texteffectprimitive2d.cxx
blobdb0cfeef49e153326910e6a88e74f953bc7ab942
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 <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
30 namespace primitive2d
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
59 const bool bEmbossed(
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);
67 if(bEmbossed)
69 // to bottom-right
70 aTransform.translate(aDiagonalDistance.getX(), aDiagonalDistance.getY());
72 else
74 // to top-left
75 aTransform.translate(-aDiagonalDistance.getX(), -aDiagonalDistance.getY());
78 aTransform *= aForwardTransform;
80 if(bDefaultTextColor)
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(
88 getTextContent(),
89 aBColorModifierToGray));
91 rContainer.push_back(
92 new TransformPrimitive2D(
93 aTransform,
94 Primitive2DContainer { xModifiedColor }));
96 // add original, too
97 const basegfx::BColorModifierSharedPtr aBColorModifierToWhite(
98 new basegfx::BColorModifier_replace(
99 basegfx::BColor(1.0)));
101 rContainer.push_back(
102 new ModifiedColorPrimitive2D(
103 getTextContent(),
104 aBColorModifierToWhite));
106 else
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(
114 getTextContent(),
115 aBColorModifierToGray));
117 rContainer.push_back(
118 new TransformPrimitive2D(
119 aTransform,
120 Primitive2DContainer { xModifiedColor }));
122 // add original, too
123 rContainer.push_back(new GroupPrimitive2D(getTextContent()));
126 break;
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(
171 getTextContent(),
172 aBColorModifierToWhite));
174 break;
179 TextEffectPrimitive2D::TextEffectPrimitive2D(
180 const Primitive2DContainer& rTextContent,
181 const basegfx::B2DPoint& rRotationCenter,
182 double fDirection,
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());
204 return false;
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);
217 return aRetval;
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);
243 // provide unique ID
244 ImplPrimitive2DIDBlock(TextEffectPrimitive2D, PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D)
246 } // end of namespace primitive2d
247 } // end of namespace drawinglayer
249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */