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/textlineprimitive2d.hxx>
32 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
33 #include <drawinglayer/attribute/strokeattribute.hxx>
34 #include <drawinglayer/attribute/lineattribute.hxx>
35 #include <basegfx/matrix/b2dhommatrixtools.hxx>
36 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
37 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
38 
39 //////////////////////////////////////////////////////////////////////////////
40 
41 namespace drawinglayer
42 {
43 	namespace primitive2d
44 	{
45 		Primitive2DSequence TextLinePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
46         {
47             Primitive2DSequence xRetval;
48 
49             if(TEXT_LINE_NONE != getTextLine())
50             {
51                 bool bDoubleLine(false);
52                 bool bWaveLine(false);
53                 bool bBoldLine(false);
54                 const int* pDotDashArray(0);
55                 basegfx::B2DLineJoin eLineJoin(basegfx::B2DLINEJOIN_NONE);
56                 double fOffset(getOffset());
57                 double fHeight(getHeight());
58 
59                 static const int aDottedArray[]     = { 1, 1, 0};               // DOTTED LINE
60                 static const int aDotDashArray[]    = { 1, 1, 4, 1, 0};         // DASHDOT
61                 static const int aDashDotDotArray[] = { 1, 1, 1, 1, 4, 1, 0};   // DASHDOTDOT
62                 static const int aDashedArray[]     = { 5, 2, 0};               // DASHED LINE
63                 static const int aLongDashArray[]   = { 7, 2, 0};               // LONGDASH
64 
65 				// get decomposition
66 				basegfx::B2DVector aScale, aTranslate;
67 				double fRotate, fShearX;
68 				getObjectTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
69 
70                 switch(getTextLine())
71                 {
72                     default: // case TEXT_LINE_SINGLE:
73                     {
74                         break;
75                     }
76                     case TEXT_LINE_DOUBLE:
77                     {
78                         bDoubleLine = true;
79                         break;
80                     }
81                     case TEXT_LINE_DOTTED:
82                     {
83                         pDotDashArray = aDottedArray;
84                         break;
85                     }
86                     case TEXT_LINE_DASH:
87                     {
88                         pDotDashArray = aDashedArray;
89                         break;
90                     }
91                     case TEXT_LINE_LONGDASH:
92                     {
93                         pDotDashArray = aLongDashArray;
94                         break;
95                     }
96                     case TEXT_LINE_DASHDOT:
97                     {
98                         pDotDashArray = aDotDashArray;
99                         break;
100                     }
101                     case TEXT_LINE_DASHDOTDOT:
102                     {
103                         pDotDashArray = aDashDotDotArray;
104                         break;
105                     }
106                     case TEXT_LINE_SMALLWAVE:
107                     {
108                         bWaveLine = true;
109                         break;
110                     }
111                     case TEXT_LINE_WAVE:
112                     {
113                         bWaveLine = true;
114                         break;
115                     }
116                     case TEXT_LINE_DOUBLEWAVE:
117                     {
118                         bDoubleLine = true;
119                         bWaveLine = true;
120                         break;
121                     }
122                     case TEXT_LINE_BOLD:
123                     {
124                         bBoldLine = true;
125                         break;
126                     }
127                     case TEXT_LINE_BOLDDOTTED:
128                     {
129                         bBoldLine = true;
130                         pDotDashArray = aDottedArray;
131                         break;
132                     }
133                     case TEXT_LINE_BOLDDASH:
134                     {
135                         bBoldLine = true;
136                         pDotDashArray = aDashedArray;
137                         break;
138                     }
139                     case TEXT_LINE_BOLDLONGDASH:
140                     {
141                         bBoldLine = true;
142                         pDotDashArray = aLongDashArray;
143                         break;
144                     }
145                     case TEXT_LINE_BOLDDASHDOT:
146                     {
147                         bBoldLine = true;
148                         pDotDashArray = aDotDashArray;
149                         break;
150                     }
151                     case TEXT_LINE_BOLDDASHDOTDOT:
152                     {
153                         bBoldLine = true;
154                         pDotDashArray = aDashDotDotArray;
155                         break;
156                     }
157                     case TEXT_LINE_BOLDWAVE:
158                     {
159                         bWaveLine = true;
160                         bBoldLine = true;
161                         break;
162                     }
163                 }
164 
165                 if(bBoldLine)
166                 {
167                     fHeight *= 2.0;
168                 }
169 
170                 if(bDoubleLine)
171                 {
172                     fOffset -= 0.50 * fHeight;
173                     fHeight *= 0.64;
174                 }
175 
176                 if(bWaveLine)
177                 {
178                     eLineJoin = basegfx::B2DLINEJOIN_ROUND;
179                     fHeight *= 0.25;
180                 }
181 
182                 // prepare Line and Stroke Attributes
183                 const attribute::LineAttribute aLineAttribute(getLineColor(), fHeight, eLineJoin);
184                 attribute::StrokeAttribute aStrokeAttribute;
185 
186                 if(pDotDashArray)
187                 {
188                     ::std::vector< double > aDoubleArray;
189 
190                     for(const int* p = pDotDashArray; *p; ++p)
191                     {
192                         aDoubleArray.push_back((double)(*p) * fHeight);
193                     }
194 
195                     aStrokeAttribute = attribute::StrokeAttribute(aDoubleArray);
196                 }
197 
198                 // create base polygon and new primitive
199                 basegfx::B2DPolygon aLine;
200                 Primitive2DReference aNewPrimitive;
201 
202                 aLine.append(basegfx::B2DPoint(0.0, fOffset));
203                 aLine.append(basegfx::B2DPoint(getWidth(), fOffset));
204 
205                 const basegfx::B2DHomMatrix aUnscaledTransform(
206                     basegfx::tools::createShearXRotateTranslateB2DHomMatrix(
207     					fShearX, fRotate, aTranslate));
208 
209                 aLine.transform(aUnscaledTransform);
210 
211                 if(bWaveLine)
212                 {
213                     double fWaveWidth(10.6 * fHeight);
214 
215                     if(TEXT_LINE_SMALLWAVE == getTextLine())
216                     {
217                         fWaveWidth *= 0.7;
218                     }
219                     else if(TEXT_LINE_WAVE == getTextLine())
220                     {
221                         // extra multiply to get the same WaveWidth as with the bold version
222                         fWaveWidth *= 2.0;
223                     }
224 
225                     aNewPrimitive = Primitive2DReference(new PolygonWavePrimitive2D(aLine, aLineAttribute, aStrokeAttribute, fWaveWidth, fWaveWidth * 0.5));
226                 }
227                 else
228                 {
229                     aNewPrimitive = Primitive2DReference(new PolygonStrokePrimitive2D(aLine, aLineAttribute, aStrokeAttribute));
230                 }
231 
232                 // add primitive
233                 appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, aNewPrimitive);
234 
235                 if(bDoubleLine)
236                 {
237                     // double line, create 2nd primitive with offset using TransformPrimitive based on
238                     // already created NewPrimitive
239                     double fLineDist(2.3 * fHeight);
240 
241                     if(bWaveLine)
242                     {
243                         fLineDist = 6.3 * fHeight;
244                     }
245 
246                     // move base point of text to 0.0 and de-rotate
247                     basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(
248                         -aTranslate.getX(), -aTranslate.getY()));
249                     aTransform.rotate(-fRotate);
250 
251                     // translate in Y by offset
252                     aTransform.translate(0.0, fLineDist);
253 
254                     // move back and rotate
255                     aTransform.rotate(fRotate);
256                     aTransform.translate(aTranslate.getX(), aTranslate.getY());
257 
258                     // add transform primitive
259                     const Primitive2DSequence aContent(&aNewPrimitive, 1);
260                     appendPrimitive2DReferenceToPrimitive2DSequence(xRetval,
261                         Primitive2DReference(new TransformPrimitive2D(aTransform, aContent)));
262                 }
263             }
264 
265             return xRetval;
266         }
267 
268         TextLinePrimitive2D::TextLinePrimitive2D(
269             const basegfx::B2DHomMatrix& rObjectTransformation,
270             double fWidth,
271             double fOffset,
272             double fHeight,
273             TextLine eTextLine,
274             const basegfx::BColor& rLineColor)
275         :   BufferedDecompositionPrimitive2D(),
276             maObjectTransformation(rObjectTransformation),
277             mfWidth(fWidth),
278             mfOffset(fOffset),
279             mfHeight(fHeight),
280             meTextLine(eTextLine),
281             maLineColor(rLineColor)
282         {
283         }
284 
285 		bool TextLinePrimitive2D::operator==( const BasePrimitive2D& rPrimitive ) const
286         {
287 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
288 			{
289 				const TextLinePrimitive2D& rCompare = (TextLinePrimitive2D&)rPrimitive;
290 
291 				return (getObjectTransformation() == rCompare.getObjectTransformation()
292                     && getWidth() == rCompare.getWidth()
293                     && getOffset() == rCompare.getOffset()
294                     && getHeight() == rCompare.getHeight()
295                     && getTextLine() == rCompare.getTextLine()
296                     && getLineColor() == rCompare.getLineColor());
297 			}
298 
299 			return false;
300         }
301 
302 		// provide unique ID
303 		ImplPrimitrive2DIDBlock(TextLinePrimitive2D, PRIMITIVE2D_ID_TEXTLINEPRIMITIVE2D)
304 
305     } // end of namespace primitive2d
306 } // end of namespace drawinglayer
307 
308 //////////////////////////////////////////////////////////////////////////////
309 // eof
310