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