xref: /trunk/main/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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/borderlineprimitive2d.hxx>
32 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
33 #include <basegfx/polygon/b2dpolygon.hxx>
34 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
35 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
36 #include <numeric>
37 
38 //////////////////////////////////////////////////////////////////////////////
39 
40 namespace drawinglayer
41 {
42     namespace primitive2d
43     {
44         Primitive2DSequence BorderLinePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
45         {
46             Primitive2DSequence xRetval;
47 
48             if(!getStart().equal(getEnd()) && (getCreateInside() || getCreateOutside()))
49             {
50                 if(isInsideUsed())
51                 {
52                     // get data and vectors
53                     const double fWidth(getWidth());
54                     basegfx::B2DVector aVector(getEnd() - getStart());
55                     aVector.normalize();
56                     const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector));
57 
58                     if(isOutsideUsed())
59                     {
60                         // both used, double line definition. Create left and right offset
61                         xRetval.realloc(getCreateInside() && getCreateOutside() ? 2 : 1);
62                         sal_uInt32 nInsert(0);
63 
64                         if(getCreateInside())
65                         {
66                             // create geometry for left
67                             const basegfx::B2DVector aLeftOff(aPerpendicular * (0.5 * (getCorrectedLeftWidth() - fWidth)));
68                             const basegfx::B2DPoint aTmpStart(getStart() + aLeftOff - (getExtendInnerStart() * aVector));
69                             const basegfx::B2DPoint aTmpEnd(getEnd() + aLeftOff + (getExtendInnerEnd() * aVector));
70                             basegfx::B2DPolygon aLeft;
71 
72                             if(leftIsHairline())
73                             {
74                                 // create hairline primitive
75                                 aLeft.append(aTmpStart);
76                                 aLeft.append(aTmpEnd);
77 
78                                 xRetval[nInsert++] = Primitive2DReference(new PolygonHairlinePrimitive2D(
79                                     aLeft,
80                                     getRGBColor()));
81                             }
82                             else
83                             {
84                                 // create filled polygon primitive. Already tried to create thick lines
85                                 // with the correct LineWidth, but this leads to problems when no AA
86                                 // is available and fat line special case reductions between 0.5 < x < 2.5 line widths
87                                 // are executed due to the FilledPolygon-do-not-paint-their-bottom-and-right-lines.
88                                 const basegfx::B2DVector aLineWidthOffset((getCorrectedLeftWidth() * 0.5) * aPerpendicular);
89 
90                                 aLeft.append(aTmpStart + aLineWidthOffset);
91                                 aLeft.append(aTmpEnd + aLineWidthOffset);
92                                 aLeft.append(aTmpEnd - aLineWidthOffset);
93                                 aLeft.append(aTmpStart - aLineWidthOffset);
94                                 aLeft.setClosed(true);
95 
96                                 xRetval[nInsert++] = Primitive2DReference(new PolyPolygonColorPrimitive2D(
97                                     basegfx::B2DPolyPolygon(aLeft), getRGBColor()));
98                             }
99                         }
100 
101                         if(getCreateOutside())
102                         {
103                             // create geometry for right
104                             const basegfx::B2DVector aRightOff(aPerpendicular * (0.5 * (fWidth - getCorrectedRightWidth())));
105                             const basegfx::B2DPoint aTmpStart(getStart() + aRightOff - (getExtendOuterStart() * aVector));
106                             const basegfx::B2DPoint aTmpEnd(getEnd() + aRightOff + (getExtendOuterEnd() * aVector));
107                             basegfx::B2DPolygon aRight;
108 
109                             if(rightIsHairline())
110                             {
111                                 // create hairline primitive
112                                 aRight.append(aTmpStart);
113                                 aRight.append(aTmpEnd);
114 
115                                 xRetval[nInsert++] = Primitive2DReference(new PolygonHairlinePrimitive2D(
116                                     aRight,
117                                     getRGBColor()));
118                             }
119                             else
120                             {
121                                 // create filled polygon primitive
122                                 const basegfx::B2DVector aLineWidthOffset((getCorrectedRightWidth() * 0.5) * aPerpendicular);
123 
124                                 aRight.append(aTmpStart + aLineWidthOffset);
125                                 aRight.append(aTmpEnd + aLineWidthOffset);
126                                 aRight.append(aTmpEnd - aLineWidthOffset);
127                                 aRight.append(aTmpStart - aLineWidthOffset);
128                                 aRight.setClosed(true);
129 
130                                 xRetval[nInsert++] = Primitive2DReference(new PolyPolygonColorPrimitive2D(
131                                     basegfx::B2DPolyPolygon(aRight), getRGBColor()));
132                             }
133                         }
134                     }
135                     else
136                     {
137                         // single line, create geometry
138                         basegfx::B2DPolygon aPolygon;
139                         const double fMaxExtStart(::std::max(getExtendInnerStart(), getExtendOuterStart()));
140                         const double fMaxExtEnd(::std::max(getExtendInnerEnd(), getExtendOuterEnd()));
141                         const basegfx::B2DPoint aTmpStart(getStart() - (fMaxExtStart * aVector));
142                         const basegfx::B2DPoint aTmpEnd(getEnd() + (fMaxExtEnd * aVector));
143                         xRetval.realloc(1);
144 
145                         if(leftIsHairline())
146                         {
147                             // create hairline primitive
148                             aPolygon.append(aTmpStart);
149                             aPolygon.append(aTmpEnd);
150 
151                             xRetval[0] = Primitive2DReference(new PolygonHairlinePrimitive2D(
152                                 aPolygon,
153                                 getRGBColor()));
154                         }
155                         else
156                         {
157                             // create filled polygon primitive
158                             const basegfx::B2DVector aLineWidthOffset((getCorrectedLeftWidth() * 0.5) * aPerpendicular);
159 
160                             aPolygon.append(aTmpStart + aLineWidthOffset);
161                             aPolygon.append(aTmpEnd + aLineWidthOffset);
162                             aPolygon.append(aTmpEnd - aLineWidthOffset);
163                             aPolygon.append(aTmpStart - aLineWidthOffset);
164                             aPolygon.setClosed(true);
165 
166                             xRetval[0] = Primitive2DReference(new PolyPolygonColorPrimitive2D(
167                                 basegfx::B2DPolyPolygon(aPolygon), getRGBColor()));
168                         }
169                     }
170                 }
171             }
172 
173             return xRetval;
174         }
175 
176         BorderLinePrimitive2D::BorderLinePrimitive2D(
177             const basegfx::B2DPoint& rStart,
178             const basegfx::B2DPoint& rEnd,
179             double fLeftWidth,
180             double fDistance,
181             double fRightWidth,
182             double fExtendInnerStart,
183             double fExtendInnerEnd,
184             double fExtendOuterStart,
185             double fExtendOuterEnd,
186             bool bCreateInside,
187             bool bCreateOutside,
188             const basegfx::BColor& rRGBColor)
189         :   BufferedDecompositionPrimitive2D(),
190             maStart(rStart),
191             maEnd(rEnd),
192             mfLeftWidth(fLeftWidth),
193             mfDistance(fDistance),
194             mfRightWidth(fRightWidth),
195             mfExtendInnerStart(fExtendInnerStart),
196             mfExtendInnerEnd(fExtendInnerEnd),
197             mfExtendOuterStart(fExtendOuterStart),
198             mfExtendOuterEnd(fExtendOuterEnd),
199             maRGBColor(rRGBColor),
200             mbCreateInside(bCreateInside),
201             mbCreateOutside(bCreateOutside)
202         {
203         }
204 
205         bool BorderLinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
206         {
207             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
208             {
209                 const BorderLinePrimitive2D& rCompare = (BorderLinePrimitive2D&)rPrimitive;
210 
211                 return (getStart() == rCompare.getStart()
212                     && getEnd() == rCompare.getEnd()
213                     && getLeftWidth() == rCompare.getLeftWidth()
214                     && getDistance() == rCompare.getDistance()
215                     && getRightWidth() == rCompare.getRightWidth()
216                     && getExtendInnerStart() == rCompare.getExtendInnerStart()
217                     && getExtendInnerEnd() == rCompare.getExtendInnerEnd()
218                     && getExtendOuterStart() == rCompare.getExtendOuterStart()
219                     && getExtendOuterEnd() == rCompare.getExtendOuterEnd()
220                     && getCreateInside() == rCompare.getCreateInside()
221                     && getCreateOutside() == rCompare.getCreateOutside()
222                     && getRGBColor() == rCompare.getRGBColor());
223             }
224 
225             return false;
226         }
227 
228         // provide unique ID
229         ImplPrimitrive2DIDBlock(BorderLinePrimitive2D, PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D)
230 
231     } // end of namespace primitive2d
232 } // end of namespace drawinglayer
233 
234 //////////////////////////////////////////////////////////////////////////////
235 // eof
236