1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_drawinglayer.hxx"
26 
27 #include <drawinglayer/primitive2d/textstrikeoutprimitive2d.hxx>
28 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
29 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
30 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
31 #include <basegfx/polygon/b2dpolygon.hxx>
32 #include <basegfx/matrix/b2dhommatrixtools.hxx>
33 #include <drawinglayer/attribute/lineattribute.hxx>
34 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
35 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
36 
37 //////////////////////////////////////////////////////////////////////////////
38 
39 namespace drawinglayer
40 {
41 	namespace primitive2d
42     {
BaseTextStrikeoutPrimitive2D(const basegfx::B2DHomMatrix & rObjectTransformation,double fWidth,const basegfx::BColor & rFontColor)43         BaseTextStrikeoutPrimitive2D::BaseTextStrikeoutPrimitive2D(
44             const basegfx::B2DHomMatrix& rObjectTransformation,
45             double fWidth,
46             const basegfx::BColor& rFontColor)
47         :   BufferedDecompositionPrimitive2D(),
48             maObjectTransformation(rObjectTransformation),
49             mfWidth(fWidth),
50             maFontColor(rFontColor)
51         {
52         }
53 
operator ==(const BasePrimitive2D & rPrimitive) const54         bool BaseTextStrikeoutPrimitive2D::operator==( const BasePrimitive2D& rPrimitive ) const
55         {
56 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
57 			{
58 				const BaseTextStrikeoutPrimitive2D& rCompare = (BaseTextStrikeoutPrimitive2D&)rPrimitive;
59 
60 				return (getObjectTransformation() == rCompare.getObjectTransformation()
61                     && getWidth() == rCompare.getWidth()
62                     && getFontColor() == rCompare.getFontColor());
63 			}
64 
65 			return false;
66         }
67     } // end of namespace primitive2d
68 } // end of namespace drawinglayer
69 
70 //////////////////////////////////////////////////////////////////////////////
71 
72 namespace drawinglayer
73 {
74 	namespace primitive2d
75 	{
create2DDecomposition(const geometry::ViewInformation2D &) const76         Primitive2DSequence TextCharacterStrikeoutPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
77         {
78             // strikeout with character
79             const String aSingleCharString(getStrikeoutChar());
80 			basegfx::B2DVector aScale, aTranslate;
81 			double fRotate, fShearX;
82 
83             // get decomposition
84 			getObjectTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
85 
86 			// prepare TextLayouter
87 		    TextLayouterDevice aTextLayouter;
88 
89             aTextLayouter.setFontAttribute(
90                 getFontAttribute(),
91                 aScale.getX(),
92                 aScale.getY(),
93                 getLocale());
94 
95             const double fStrikeCharWidth(aTextLayouter.getTextWidth(aSingleCharString, 0, 1));
96             const double fStrikeCharCount(fabs(getWidth()/fStrikeCharWidth));
97             const sal_uInt32 nStrikeCharCount(static_cast< sal_uInt32 >(fStrikeCharCount + 0.5));
98 			std::vector<double> aDXArray(nStrikeCharCount);
99             String aStrikeoutString;
100 
101             for(sal_uInt32 a(0); a < nStrikeCharCount; a++)
102             {
103 	            aStrikeoutString += aSingleCharString;
104 	            aDXArray[a] = (a + 1) * fStrikeCharWidth;
105             }
106 
107             Primitive2DReference xReference(
108                 new TextSimplePortionPrimitive2D(
109                     getObjectTransformation(),
110                     aStrikeoutString,
111 			        0,
112 			        aStrikeoutString.Len(),
113                     aDXArray,
114                     getFontAttribute(),
115                     getLocale(),
116                     getFontColor()));
117 
118             return Primitive2DSequence(&xReference, 1);
119         }
120 
TextCharacterStrikeoutPrimitive2D(const basegfx::B2DHomMatrix & rObjectTransformation,double fWidth,const basegfx::BColor & rFontColor,sal_Unicode aStrikeoutChar,const attribute::FontAttribute & rFontAttribute,const::com::sun::star::lang::Locale & rLocale)121         TextCharacterStrikeoutPrimitive2D::TextCharacterStrikeoutPrimitive2D(
122             const basegfx::B2DHomMatrix& rObjectTransformation,
123             double fWidth,
124             const basegfx::BColor& rFontColor,
125             sal_Unicode aStrikeoutChar,
126             const attribute::FontAttribute& rFontAttribute,
127             const ::com::sun::star::lang::Locale& rLocale)
128         :   BaseTextStrikeoutPrimitive2D(rObjectTransformation, fWidth, rFontColor),
129             maStrikeoutChar(aStrikeoutChar),
130             maFontAttribute(rFontAttribute),
131             maLocale(rLocale)
132         {
133         }
134 
operator ==(const BasePrimitive2D & rPrimitive) const135         bool TextCharacterStrikeoutPrimitive2D::operator==( const BasePrimitive2D& rPrimitive ) const
136         {
137 			if(BaseTextStrikeoutPrimitive2D::operator==(rPrimitive))
138 			{
139 				const TextCharacterStrikeoutPrimitive2D& rCompare = (TextCharacterStrikeoutPrimitive2D&)rPrimitive;
140 
141 				return (getStrikeoutChar() == rCompare.getStrikeoutChar()
142                     && getFontAttribute() == rCompare.getFontAttribute()
143                     && LocalesAreEqual(getLocale(), rCompare.getLocale()));
144 			}
145 
146 			return false;
147         }
148 
149 		// provide unique ID
150 		ImplPrimitrive2DIDBlock(TextCharacterStrikeoutPrimitive2D, PRIMITIVE2D_ID_TEXTCHARACTERSTRIKEOUTPRIMITIVE2D)
151 
152     } // end of namespace primitive2d
153 } // end of namespace drawinglayer
154 
155 //////////////////////////////////////////////////////////////////////////////
156 
157 namespace drawinglayer
158 {
159 	namespace primitive2d
160 	{
create2DDecomposition(const geometry::ViewInformation2D &) const161         Primitive2DSequence TextGeometryStrikeoutPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
162         {
163             OSL_ENSURE(TEXT_STRIKEOUT_SLASH != getTextStrikeout() && TEXT_STRIKEOUT_X != getTextStrikeout(),
164                 "Wrong TEXT_STRIKEOUT type; a TextCharacterStrikeoutPrimitive2D should be used (!)");
165 
166             // strikeout with geometry
167             double fStrikeoutHeight(getHeight());
168             double fStrikeoutOffset(getOffset());
169             bool bDoubleLine(false);
170 
171 			// get decomposition
172 			basegfx::B2DVector aScale, aTranslate;
173 			double fRotate, fShearX;
174 			getObjectTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
175 
176             // set line attribute
177             switch(getTextStrikeout())
178             {
179                 default : // case primitive2d::TEXT_STRIKEOUT_SINGLE:
180                 {
181 		            break;
182                 }
183 	            case primitive2d::TEXT_STRIKEOUT_DOUBLE:
184                 {
185 		            bDoubleLine = true;
186 		            break;
187                 }
188 	            case primitive2d::TEXT_STRIKEOUT_BOLD:
189                 {
190 		            fStrikeoutHeight *= 2.0;
191 		            break;
192                 }
193             }
194 
195             if(bDoubleLine)
196             {
197 	            fStrikeoutOffset -= 0.50 * fStrikeoutHeight;
198 	            fStrikeoutHeight *= 0.64;
199             }
200 
201 		    // create base polygon and new primitive
202             basegfx::B2DPolygon aStrikeoutLine;
203 
204 		    aStrikeoutLine.append(basegfx::B2DPoint(0.0, -fStrikeoutOffset));
205 	        aStrikeoutLine.append(basegfx::B2DPoint(getWidth(), -fStrikeoutOffset));
206 
207             const basegfx::B2DHomMatrix aUnscaledTransform(
208                 basegfx::tools::createShearXRotateTranslateB2DHomMatrix(
209 					fShearX, fRotate, aTranslate));
210 
211             aStrikeoutLine.transform(aUnscaledTransform);
212 
213 			// add primitive
214 	        const attribute::LineAttribute aLineAttribute(getFontColor(), fStrikeoutHeight, basegfx::B2DLINEJOIN_NONE);
215             Primitive2DSequence xRetval(1);
216             xRetval[0] = Primitive2DReference(new PolygonStrokePrimitive2D(aStrikeoutLine, aLineAttribute));
217 
218             if(bDoubleLine)
219 		    {
220 			    // double line, create 2nd primitive with offset using TransformPrimitive based on
221 			    // already created NewPrimitive
222 		        const double fLineDist(2.0 * fStrikeoutHeight);
223 
224 			    // move base point of text to 0.0 and de-rotate
225                 basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(
226                     -aTranslate.getX(), -aTranslate.getY()));
227 			    aTransform.rotate(-fRotate);
228 
229 			    // translate in Y by offset
230 			    aTransform.translate(0.0, -fLineDist);
231 
232 			    // move back and rotate
233 			    aTransform.rotate(fRotate);
234 			    aTransform.translate(aTranslate.getX(), aTranslate.getY());
235 
236 			    // add transform primitive
237                 appendPrimitive2DReferenceToPrimitive2DSequence(xRetval,
238                     Primitive2DReference(
239                         new TransformPrimitive2D(
240                             aTransform,
241                             xRetval)));
242 		    }
243 
244             return xRetval;
245         }
246 
TextGeometryStrikeoutPrimitive2D(const basegfx::B2DHomMatrix & rObjectTransformation,double fWidth,const basegfx::BColor & rFontColor,double fHeight,double fOffset,TextStrikeout eTextStrikeout)247         TextGeometryStrikeoutPrimitive2D::TextGeometryStrikeoutPrimitive2D(
248             const basegfx::B2DHomMatrix& rObjectTransformation,
249             double fWidth,
250             const basegfx::BColor& rFontColor,
251             double fHeight,
252             double fOffset,
253 		    TextStrikeout eTextStrikeout)
254         :   BaseTextStrikeoutPrimitive2D(rObjectTransformation, fWidth, rFontColor),
255             mfHeight(fHeight),
256             mfOffset(fOffset),
257             meTextStrikeout(eTextStrikeout)
258         {
259         }
260 
operator ==(const BasePrimitive2D & rPrimitive) const261 		bool TextGeometryStrikeoutPrimitive2D::operator==( const BasePrimitive2D& rPrimitive ) const
262         {
263 			if(BaseTextStrikeoutPrimitive2D::operator==(rPrimitive))
264 			{
265 				const TextGeometryStrikeoutPrimitive2D& rCompare = (TextGeometryStrikeoutPrimitive2D&)rPrimitive;
266 
267 				return (getHeight() == rCompare.getHeight()
268                     && getOffset() == rCompare.getOffset()
269                     && getTextStrikeout() == rCompare.getTextStrikeout());
270 			}
271 
272 			return false;
273         }
274 
275 		// provide unique ID
276 		ImplPrimitrive2DIDBlock(TextGeometryStrikeoutPrimitive2D, PRIMITIVE2D_ID_TEXTGEOMETRYSTRIKEOUTPRIMITIVE2D)
277 
278     } // end of namespace primitive2d
279 } // end of namespace drawinglayer
280 
281 //////////////////////////////////////////////////////////////////////////////
282 // eof
283