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