1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  */
10 
11 #include <test/outputdevice.hxx>
12 
13 #include <basegfx/matrix/b2dhommatrix.hxx>
14 #include <vcl/BitmapReadAccess.hxx>
15 
16 #include <list>
17 
18 namespace vcl::test {
19 
20 namespace
21 {
22 
drawLineOffset(OutputDevice & rDevice,tools::Rectangle const & rRect,int nOffset)23 void drawLineOffset(OutputDevice& rDevice, tools::Rectangle const & rRect, int nOffset)
24 {
25     Point aLeftTop     (rRect.Left()  + nOffset, rRect.Top()    + nOffset);
26     Point aRightTop    (rRect.Right() - nOffset, rRect.Top()    + nOffset);
27     Point aLeftBottom  (rRect.Left()  + nOffset, rRect.Bottom() - nOffset);
28     Point aRightBottom (rRect.Right() - nOffset, rRect.Bottom() - nOffset);
29 
30     rDevice.DrawLine(aLeftTop,     aRightTop);
31     rDevice.DrawLine(aRightTop,    aRightBottom);
32     rDevice.DrawLine(aRightBottom, aLeftBottom);
33     rDevice.DrawLine(aLeftBottom,  aLeftTop);
34 }
35 
36 } // end anonymous namespace
37 
setupRectangle(bool bEnableAA)38 Bitmap OutputDeviceTestLine::setupRectangle(bool bEnableAA)
39 {
40     initialSetup(13, 13, constBackgroundColor, bEnableAA);
41 
42     mpVirtualDevice->SetLineColor(constLineColor);
43     mpVirtualDevice->SetFillColor();
44 
45     drawLineOffset(*mpVirtualDevice, maVDRectangle, 2);
46     drawLineOffset(*mpVirtualDevice, maVDRectangle, 5);
47 
48     return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
49 }
50 
setupDiamond()51 Bitmap OutputDeviceTestLine::setupDiamond()
52 {
53     initialSetup(11, 11, constBackgroundColor);
54 
55     mpVirtualDevice->SetLineColor(constLineColor);
56     mpVirtualDevice->SetFillColor();
57 
58     Point aPoint1, aPoint2, aPoint3, aPoint4;
59     OutputDeviceTestCommon::createDiamondPoints(maVDRectangle, 4, aPoint1, aPoint2, aPoint3, aPoint4);
60 
61     mpVirtualDevice->DrawLine(aPoint1, aPoint2);
62     mpVirtualDevice->DrawLine(aPoint2, aPoint3);
63     mpVirtualDevice->DrawLine(aPoint3, aPoint4);
64     mpVirtualDevice->DrawLine(aPoint4, aPoint1);
65 
66     return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
67 }
68 
setupLines()69 Bitmap OutputDeviceTestLine::setupLines()
70 {
71     initialSetup(13, 13, constBackgroundColor);
72 
73     mpVirtualDevice->SetLineColor(constLineColor);
74     mpVirtualDevice->SetFillColor();
75 
76     Point aHorizontalLinePoint1, aHorizontalLinePoint2;
77     Point aVerticalLinePoint1, aVerticalLinePoint2;
78     Point aDiagonalLinePoint1, aDiagonalLinePoint2;
79 
80     OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints(
81                           maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2,
82                                          aVerticalLinePoint1,   aVerticalLinePoint2,
83                                          aDiagonalLinePoint1,   aDiagonalLinePoint2);
84 
85     mpVirtualDevice->DrawLine(aHorizontalLinePoint1, aHorizontalLinePoint2);
86     mpVirtualDevice->DrawLine(aVerticalLinePoint1,   aVerticalLinePoint2);
87     mpVirtualDevice->DrawLine(aDiagonalLinePoint1,   aDiagonalLinePoint2);
88 
89     return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
90 }
91 
setupAALines()92 Bitmap OutputDeviceTestLine::setupAALines()
93 {
94     initialSetup(13, 13, constBackgroundColor);
95 
96     mpVirtualDevice->SetAntialiasing(AntialiasingFlags::Enable);
97     mpVirtualDevice->SetLineColor(constLineColor);
98     mpVirtualDevice->SetFillColor();
99 
100     Point aHorizontalLinePoint1, aHorizontalLinePoint2;
101     Point aVerticalLinePoint1, aVerticalLinePoint2;
102     Point aDiagonalLinePoint1, aDiagonalLinePoint2;
103 
104     OutputDeviceTestCommon::createHorizontalVerticalDiagonalLinePoints(
105                           maVDRectangle, aHorizontalLinePoint1, aHorizontalLinePoint2,
106                                          aVerticalLinePoint1,   aVerticalLinePoint2,
107                                          aDiagonalLinePoint1,   aDiagonalLinePoint2);
108 
109     mpVirtualDevice->DrawLine(aHorizontalLinePoint1, aHorizontalLinePoint2);
110     mpVirtualDevice->DrawLine(aVerticalLinePoint1,   aVerticalLinePoint2);
111     mpVirtualDevice->DrawLine(aDiagonalLinePoint1,   aDiagonalLinePoint2);
112 
113     return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
114 }
115 
setupDashedLine()116 Bitmap OutputDeviceTestLine::setupDashedLine()
117 {
118     initialSetup(13, 13, constBackgroundColor);
119 
120     mpVirtualDevice->SetLineColor(constLineColor);
121     mpVirtualDevice->SetFillColor();
122 
123     tools::Rectangle rectangle = maVDRectangle;
124     rectangle.shrink(2);
125 
126     std::vector<double> stroke({ 2.0, 1.0 });
127     mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(),
128         basegfx::B2DPolygon{
129             basegfx::B2DPoint(rectangle.getX(), rectangle.getY()),
130             basegfx::B2DPoint(rectangle.getX(), rectangle.getY() + rectangle.getHeight()),
131             basegfx::B2DPoint(rectangle.getX() + rectangle.getWidth(),
132                               rectangle.getY() + rectangle.getHeight()),
133             basegfx::B2DPoint(rectangle.getX() + rectangle.getWidth(), rectangle.getY()),
134             basegfx::B2DPoint(rectangle.getX(), rectangle.getY())},
135         1, 0, &stroke, basegfx::B2DLineJoin::NONE );
136 
137     return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
138 }
139 
checkDashedLine(Bitmap & rBitmap)140 TestResult OutputDeviceTestLine::checkDashedLine(Bitmap& rBitmap)
141 {
142     TestResult returnValue = TestResult::Passed;
143     for (int i = 0; i < 7; i++)
144     {
145         TestResult eResult = TestResult::Passed;
146         if( i == 2 )
147         {
148             // Build a sequence of pixels for the drawn rectangle border,
149             // check that they alternate appropriately (there should be
150             // normally 2 line, 1 background).
151             std::list< bool > dash; // true - line color, false - background
152             const int width = rBitmap.GetSizePixel().Width();
153             const int height = rBitmap.GetSizePixel().Height();
154             BitmapReadAccess access(rBitmap);
155             for( int x = 2; x < width - 2; ++x )
156                 dash.push_back( access.GetPixel( 2, x ) == constLineColor );
157             for( int y = 3; y < height - 3; ++y )
158                 dash.push_back( access.GetPixel( y, width - 3 ) == constLineColor );
159             for( int x = width - 3; x >= 2; --x )
160                 dash.push_back( access.GetPixel( height - 3, x ) == constLineColor );
161             for( int y = height - 4; y >= 3; --y )
162                 dash.push_back( access.GetPixel( y, 2 ) == constLineColor );
163             for( int x = 2; x < width - 2; ++x ) // repeat, to check also the corner
164                 dash.push_back( access.GetPixel( 2, x ) == constLineColor );
165             bool last = false;
166             int lastCount = 0;
167             while( !dash.empty())
168             {
169                 if( dash.front() == last )
170                 {
171                     ++lastCount;
172                     if( lastCount > ( last ? 4 : 3 ))
173                         eResult = TestResult::Failed;
174                     else if( lastCount > ( last ? 3 : 2 ) && eResult != TestResult::Failed)
175                         eResult = TestResult::PassedWithQuirks;
176                 }
177                 else
178                 {
179                     last = dash.front();
180                     lastCount = 1;
181                 }
182                 dash.pop_front();
183             }
184         }
185         else
186         {
187             eResult = OutputDeviceTestCommon::checkRectangle(rBitmap, i, constBackgroundColor);
188         }
189 
190         if (eResult == TestResult::Failed)
191             returnValue = TestResult::Failed;
192         if (eResult == TestResult::PassedWithQuirks && returnValue != TestResult::Failed)
193             returnValue = TestResult::PassedWithQuirks;
194     }
195     return returnValue;
196 }
197 
198 constexpr int CAPSHRINK = 25;
199 constexpr int CAPWIDTH = 20;
setupLineCap(css::drawing::LineCap lineCap)200 Bitmap OutputDeviceTestLine::setupLineCap( css::drawing::LineCap lineCap )
201 {
202     initialSetup(101, 101, constBackgroundColor);
203 
204     mpVirtualDevice->SetLineColor(constLineColor);
205     mpVirtualDevice->SetFillColor();
206 
207     tools::Rectangle rectangle = maVDRectangle;
208     rectangle.shrink(CAPSHRINK);
209 
210     const basegfx::B2DPolygon poly{
211         basegfx::B2DPoint(rectangle.LeftCenter().getX(), rectangle.LeftCenter().getY()),
212         basegfx::B2DPoint(rectangle.RightCenter().getX(), rectangle.RightCenter().getY())};
213 
214     mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(),poly,
215         CAPWIDTH, 0, nullptr, basegfx::B2DLineJoin::NONE, lineCap );
216 
217     mpVirtualDevice->SetLineColor(constFillColor);
218     mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(), poly,
219         0, 0, nullptr, basegfx::B2DLineJoin::NONE );
220 
221     return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
222 }
223 
setupLineJoin(basegfx::B2DLineJoin lineJoin)224 Bitmap OutputDeviceTestLine::setupLineJoin( basegfx::B2DLineJoin lineJoin )
225 {
226     initialSetup(101, 101, constBackgroundColor);
227 
228     mpVirtualDevice->SetLineColor(constLineColor);
229     mpVirtualDevice->SetFillColor();
230 
231     tools::Rectangle rectangle = maVDRectangle;
232     rectangle.shrink(CAPSHRINK);
233 
234     const basegfx::B2DPolygon poly{
235         basegfx::B2DPoint(rectangle.TopLeft().getX(), rectangle.TopLeft().getY()),
236         basegfx::B2DPoint(rectangle.TopRight().getX(), rectangle.TopRight().getY()),
237         basegfx::B2DPoint(rectangle.BottomRight().getX(), rectangle.BottomRight().getY())};
238 
239     mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(), poly,
240         CAPWIDTH, 0, nullptr, lineJoin );
241 
242     mpVirtualDevice->SetLineColor(constFillColor);
243     mpVirtualDevice->DrawPolyLineDirect( basegfx::B2DHomMatrix(), poly,
244         0, 0, nullptr, lineJoin );
245 
246     return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
247 }
248 
249 } // end namespace vcl::test
250 
251 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
252