1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
11 #include <rtl/math.hxx>
13 #include <comphelper/processfactory.hxx>
14 #include <comphelper/random.hxx>
15 #include <cppuhelper/bootstrap.hxx>
16 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
17 #include <com/sun/star/lang/XInitialization.hpp>
18 #include <com/sun/star/registry/XSimpleRegistry.hpp>
19 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
22 #include <vcl/vclmain.hxx>
23 #include <vcl/layout.hxx>
24 #include <salhelper/thread.hxx>
26 #include <tools/urlobj.hxx>
27 #include <tools/stream.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/pngread.hxx>
30 #include <vcl/wrkwin.hxx>
31 #include <vcl/virdev.hxx>
32 #include <vcl/graphicfilter.hxx>
33 #include <vcl/button.hxx>
34 #include <vcl/toolbox.hxx>
35 #include <vcl/pngwrite.hxx>
36 #include <vcl/floatwin.hxx>
37 #include <vcl/salbtype.hxx>
38 #include <vcl/bmpacc.hxx>
39 #include <vcl/help.hxx>
41 #include <basegfx/numeric/ftools.hxx>
42 #include <basegfx/matrix/b2dhommatrix.hxx>
43 #include <vcldemo-debug.hxx>
44 #include <opengl/zone.hxx>
46 // internal headers for OpenGLTests class.
48 #include "salframe.hxx"
49 #include "openglgdiimpl.hxx"
50 #include "opengl/texture.hxx"
51 #include "opengl/framebuffer.hxx"
52 #include <vcl/opengl/OpenGLHelper.hxx>
54 #include <rtl/math.hxx>
56 #define FIXME_SELF_INTERSECTING_WORKING 0
57 #define FIXME_BOUNCE_BUTTON 0
58 #define THUMB_REPEAT_FACTOR 10
60 using namespace com::sun::star
;
66 osl_getSystemTime(&aValue
);
67 return (double)aValue
.Seconds
* 1000 +
68 (double)aValue
.Nanosec
/ (1000*1000);
76 RENDER_THUMB
, // small view <n> to a page
77 RENDER_EXPANDED
, // expanded view of this renderer
88 struct RenderContext
{
91 DemoRenderer
*mpDemoRenderer
;
94 struct RegionRenderer
{
100 virtual ~RegionRenderer() {}
101 virtual OUString
getName() = 0;
102 virtual sal_uInt16
getAccelerator() = 0;
103 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
104 const RenderContext
&rCtx
) = 0;
105 // repeating count for profiling (to exceed the poor time resolution on Windows)
106 virtual sal_uInt16
getTestRepeatCount() = 0;
107 #define RENDER_DETAILS(name,key,repeat) \
108 virtual OUString getName() SAL_OVERRIDE \
109 { return OUString(SAL_STRINGIFY(name)); } \
110 virtual sal_uInt16 getAccelerator() SAL_OVERRIDE \
112 virtual sal_uInt16 getTestRepeatCount() SAL_OVERRIDE \
119 std::vector
< RegionRenderer
* > maRenderers
;
120 sal_Int32 mnSelectedRenderer
;
123 void InitRenderers();
126 DemoRenderer() : mnSegmentsX(0)
128 , mnSelectedRenderer(-1)
130 #if FIXME_BOUNCE_BUTTON
137 if (!Application::LoadBrandBitmap("intro", maIntro
))
138 Application::Abort("Failed to load intro image");
140 maIntroBW
= maIntro
.GetBitmap();
141 maIntroBW
.Filter(BMP_FILTER_EMBOSS_GREY
);
144 mnSegmentsX
= rtl::math::round(sqrt(maRenderers
.size()), 0,
145 rtl_math_RoundingMode_Up
);
146 mnSegmentsY
= rtl::math::round(sqrt(maRenderers
.size()), 0,
147 rtl_math_RoundingMode_Down
);
148 mnSegmentsY
= floor(sqrt(maRenderers
.size()));
151 OUString
getRendererList();
152 double getAndResetBenchmark(RenderStyle style
);
153 void selectRenderer(const OUString
&rName
);
154 int selectNextRenderer();
155 void setIterCount(sal_Int32 iterCount
);
156 sal_Int32
getIterCount();
157 void addTime(int i
, double t
);
160 void SetSizePixel(const Size
&rSize
) { maSize
= rSize
; }
161 Size
GetSizePixel() const { return maSize
; }
164 // more of a 'Window' concept - push upwards ?
165 #if FIXME_BOUNCE_BUTTON
166 // Bouncing windows on click ...
167 PushButton
*mpButton
;
168 FloatingWindow
*mpButtonWin
;
170 int mnBounceX
, mnBounceY
;
171 DECL_LINK(BounceTimerCb
, void *);
174 bool MouseButtonDown(const MouseEvent
& rMEvt
);
175 void KeyInput(const KeyEvent
& rKEvt
);
177 static std::vector
<Rectangle
> partition(const RenderContext
&rCtx
, int nX
, int nY
)
179 return partition(rCtx
.maSize
, nX
, nY
);
182 static std::vector
<Rectangle
> partition(Size aSize
, int nX
, int nY
)
185 std::vector
<Rectangle
> aRegions
;
187 // Make small cleared area for these guys
188 long nBorderSize
= aSize
.Width() / 32;
189 long nBoxWidth
= (aSize
.Width() - nBorderSize
*(nX
+1)) / nX
;
190 long nBoxHeight
= (aSize
.Height() - nBorderSize
*(nY
+1)) / nY
;
191 for (int y
= 0; y
< nY
; y
++)
193 for (int x
= 0; x
< nX
; x
++)
195 r
.SetPos(Point(nBorderSize
+ (nBorderSize
+ nBoxWidth
) * x
,
196 nBorderSize
+ (nBorderSize
+ nBoxHeight
) * y
));
197 r
.SetSize(Size(nBoxWidth
, nBoxHeight
));
198 aRegions
.push_back(r
);
205 static void clearRects(OutputDevice
&rDev
, std::vector
<Rectangle
> &rRects
)
207 for (size_t i
= 0; i
< rRects
.size(); i
++)
209 // knock up a nice little border
210 rDev
.SetLineColor(COL_GRAY
);
211 rDev
.SetFillColor(COL_LIGHTGRAY
);
214 int nBorderSize
= rRects
[i
].GetWidth() / 5;
215 rDev
.DrawRect(rRects
[i
], nBorderSize
, nBorderSize
);
218 rDev
.DrawRect(rRects
[i
]);
222 static void drawBackground(OutputDevice
&rDev
, const Rectangle
& r
)
226 aGradient
.SetStartColor(COL_BLUE
);
227 aGradient
.SetEndColor(COL_GREEN
);
228 aGradient
.SetStyle(GradientStyle_LINEAR
);
229 rDev
.DrawGradient(r
, aGradient
);
232 struct DrawLines
: public RegionRenderer
234 RENDER_DETAILS(lines
,KEY_L
,100)
235 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
236 const RenderContext
&rCtx
) SAL_OVERRIDE
238 if (rCtx
.meStyle
== RENDER_EXPANDED
)
240 AntialiasingFlags nOldAA
= rDev
.GetAntialiasing();
241 rDev
.SetAntialiasing(AntialiasingFlags::EnableB2dDraw
);
243 std::vector
<Rectangle
> aRegions(DemoRenderer::partition(rCtx
, 4, 4));
244 DemoRenderer::clearRects(rDev
, aRegions
);
246 #if 0 // FIXME: get this through to the backend ...
247 double nTransparency
[] = {
254 drawing::LineCap eLineCaps
[] = {
255 drawing::LineCap_BUTT
, drawing::LineCap_ROUND
, drawing::LineCap_SQUARE
, drawing::LineCap_BUTT
,
256 drawing::LineCap_BUTT
, drawing::LineCap_ROUND
, drawing::LineCap_SQUARE
, drawing::LineCap_BUTT
,
257 drawing::LineCap_BUTT
, drawing::LineCap_ROUND
, drawing::LineCap_SQUARE
, drawing::LineCap_BUTT
,
258 drawing::LineCap_BUTT
, drawing::LineCap_ROUND
, drawing::LineCap_SQUARE
, drawing::LineCap_BUTT
260 ::basegfx::B2DLineJoin eJoins
[] = {
261 basegfx::B2DLINEJOIN_NONE
, basegfx::B2DLINEJOIN_MIDDLE
, basegfx::B2DLINEJOIN_BEVEL
, basegfx::B2DLINEJOIN_MITER
,
262 basegfx::B2DLINEJOIN_ROUND
, basegfx::B2DLINEJOIN_NONE
, basegfx::B2DLINEJOIN_MIDDLE
, basegfx::B2DLINEJOIN_BEVEL
,
263 basegfx::B2DLINEJOIN_MITER
, basegfx::B2DLINEJOIN_ROUND
, basegfx::B2DLINEJOIN_NONE
, basegfx::B2DLINEJOIN_MIDDLE
,
264 basegfx::B2DLINEJOIN_BEVEL
, basegfx::B2DLINEJOIN_MITER
, basegfx::B2DLINEJOIN_ROUND
, basegfx::B2DLINEJOIN_NONE
266 double aLineWidths
[] = {
267 10.0, 15.0, 20.0, 10.0,
268 10.0, 15.0, 20.0, 10.0,
269 10.0, 15.0, 20.0, 10.0,
272 for (size_t i
= 0; i
< aRegions
.size(); i
++)
274 // Half of them not-anti-aliased ..
275 if (i
>= aRegions
.size()/2)
276 rDev
.SetAntialiasing(nOldAA
);
278 static const struct {
281 { 0.2, 0.2 }, { 0.8, 0.3 }, { 0.7, 0.8 }
283 rDev
.SetLineColor(Color(COL_BLACK
));
284 basegfx::B2DPolygon aPoly
;
285 Rectangle
aSub(aRegions
[i
]);
286 for (size_t j
= 0; j
< SAL_N_ELEMENTS(aPoints
); j
++)
288 aPoly
.append(basegfx::B2DPoint(aSub
.Left() + aSub
.GetWidth() * aPoints
[j
].nX
,
289 aSub
.Top() + aSub
.GetHeight() * aPoints
[j
].nY
));
291 rDev
.DrawPolyLine(aPoly
, aLineWidths
[i
], eJoins
[i
], eLineCaps
[i
]);
296 rDev
.SetFillColor(Color(COL_LIGHTRED
));
297 rDev
.SetLineColor(Color(COL_BLACK
));
300 for(int i
=0; i
<r
.GetHeight(); i
+=15)
301 rDev
.DrawLine(Point(r
.Left(), r
.Top()+i
), Point(r
.Right(), r
.Bottom()-i
));
302 for(int i
=0; i
<r
.GetWidth(); i
+=15)
303 rDev
.DrawLine(Point(r
.Left()+i
, r
.Bottom()), Point(r
.Right()-i
, r
.Top()));
305 // Should draw a white-line across the middle
306 Color
aLastPixel(COL_WHITE
);
307 Point
aCenter((r
.Left() + r
.Right())/2 - 4,
308 (r
.Top() + r
.Bottom())/2 - 4);
309 for(int i
=0; i
<8; i
++)
311 rDev
.DrawPixel(aCenter
, aLastPixel
);
312 aLastPixel
= rDev
.GetPixel(aCenter
);
319 struct DrawText
: public RegionRenderer
321 RENDER_DETAILS(text
,KEY_T
,1)
323 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
324 const RenderContext
&rCtx
) SAL_OVERRIDE
326 if (rCtx
.meStyle
== RENDER_EXPANDED
)
328 std::vector
<Rectangle
> aRegions(DemoRenderer::partition(rCtx
, 4, 2));
329 DemoRenderer::clearRects(rDev
, aRegions
);
331 bool bClip
=true, bArabicText
=true, bRotate
=true;
335 for (int nClipRow
=0; nClipRow
< 2; nClipRow
++)
340 for (int nArabicRow
=0; nArabicRow
< 2; nArabicRow
++)
345 for (int nRotateRow
=0; nRotateRow
< 2; nRotateRow
++)
347 drawText( rDev
, aRegions
[nRegions
], bClip
, bArabicText
, bRotate
);
361 drawText(rDev
, r
, false, false, false);
365 static void drawText (OutputDevice
&rDev
, Rectangle r
, bool bClip
, bool bArabicText
, bool bRotate
)
367 rDev
.SetClipRegion( vcl::Region(r
) );
369 OUString
aLatinText("Click any rect to zoom!!!!");
371 const unsigned char pTextUTF8
[] = {
372 0xd9, 0x88, 0xd8, 0xa7, 0xd8, 0xad, 0xd9, 0x90,
373 0xd8, 0xaf, 0xd9, 0x92, 0x20, 0xd8, 0xa5, 0xd8,
374 0xab, 0xd9, 0x8d, 0xd9, 0x86, 0xd9, 0x8a, 0xd9,
375 0x86, 0x20, 0xd8, 0xab, 0xd9, 0x84, 0xd8, 0xa7,
376 0xd8, 0xab, 0xd8, 0xa9, 0xd9, 0x8c, 0x00
378 OUString
aArabicText( reinterpret_cast<char const *>(pTextUTF8
),
379 SAL_N_ELEMENTS( pTextUTF8
) - 1,
380 RTL_TEXTENCODING_UTF8
);
384 // To have more text displayed one after the other (overlapping, and in different colours), then
386 const int nPrintNumCopies
=1;
393 std::vector
<OUString
> maFontNames
;
395 sal_uInt32 nCols
[] = {
396 COL_BLACK
, COL_BLUE
, COL_GREEN
, COL_CYAN
, COL_RED
, COL_MAGENTA
,
397 COL_BROWN
, COL_GRAY
, COL_LIGHTGRAY
, COL_LIGHTBLUE
, COL_LIGHTGREEN
,
398 COL_LIGHTCYAN
, COL_LIGHTRED
, COL_LIGHTMAGENTA
, COL_YELLOW
, COL_WHITE
401 // a few fonts to start with
402 const char *pNames
[] = {
403 "Times", "Liberation Sans", "Arial", "Linux Biolinum G", "Linux Libertine Display G"
406 size_t nNumFontNames
= SAL_N_ELEMENTS(pNames
);
408 for (size_t i
= 0; i
< nNumFontNames
; i
++)
409 maFontNames
.push_back(OUString::createFromAscii(pNames
[i
]));
411 if (bClip
&& !bRotate
)
413 // only show the first quarter of the text
414 Rectangle
aRect( r
.TopLeft(), Size( r
.GetWidth()/2, r
.GetHeight()/2 ) );
415 rDev
.SetClipRegion( vcl::Region( aRect
) );
418 for (int i
= 1; i
< nPrintNumCopies
+1; i
++)
420 int nFontHeight
=0, nFontIndex
=0, nFontColorIndex
=0;
422 if (nPrintNumCopies
== 1)
424 float nFontMagnitude
= 0.25f
;
425 // random font size to avoid buffering
426 nFontHeight
= 1 + nFontMagnitude
* (0.9 + comphelper::rng::uniform_real_distribution(0.0, std::nextafter(0.1, DBL_MAX
))) * (r
.Bottom() - r
.Top());
432 // random font size to avoid buffering
433 nFontHeight
= 1 + i
* (0.9 + comphelper::rng::uniform_real_distribution(0.0, std::nextafter(0.1, DBL_MAX
))) * (r
.Top() - r
.Bottom()) / nPrintNumCopies
;
434 nFontIndex
= (i
% maFontNames
.size());
435 nFontColorIndex
=(i
% maFontNames
.size());
438 rDev
.SetTextColor(Color(nCols
[nFontColorIndex
]));
439 vcl::Font
aFont( maFontNames
[nFontIndex
], Size(0, nFontHeight
));
443 Rectangle aFontRect
= r
;
445 int nHeight
= r
.GetHeight();
447 // move the text to the bottom of the bounding rect before rotating
448 aFontRect
.Top() += nHeight
;
449 aFontRect
.Bottom() += nHeight
;
453 aFont
.SetOrientation(nDegrees
* 10);
456 rDev
.DrawText(aFontRect
, aText
);
460 Rectangle
aClipRect( Point( r
.Left(), r
.Top() + ( r
.GetHeight()/2 ) ) , Size( r
.GetWidth()/2, r
.GetHeight()/2 ) );
461 rDev
.SetClipRegion( vcl::Region( aClipRect
) );
464 rDev
.SetClipRegion( vcl::Region(r
) );
469 rDev
.DrawText(r
, aText
);
473 rDev
.SetClipRegion();
477 struct DrawCheckered
: public RegionRenderer
479 RENDER_DETAILS(checks
,KEY_C
,20)
480 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
481 const RenderContext
&rCtx
) SAL_OVERRIDE
483 if (rCtx
.meStyle
== RENDER_EXPANDED
)
485 std::vector
<Rectangle
> aRegions(DemoRenderer::partition(rCtx
, 2, 2));
486 for (size_t i
= 0; i
< aRegions
.size(); i
++)
489 Rectangle
aSub(aRegions
[i
]);
490 Rectangle
aSmaller(aSub
);
491 aSmaller
.Move(10,10);
492 aSmaller
.setWidth(aSmaller
.getWidth()-20);
493 aSmaller
.setHeight(aSmaller
.getHeight()-24);
496 aRegion
= vcl::Region(aSub
);
499 aRegion
= vcl::Region(aSmaller
);
505 aPoly
.Rotate(aSub
.Center(), 450);
506 aPoly
.Clip(aSmaller
);
507 aRegion
= vcl::Region(aPoly
);
512 tools::PolyPolygon aPolyPoly
;
513 sal_Int32 nTW
= aSub
.GetWidth()/6;
514 sal_Int32 nTH
= aSub
.GetHeight()/6;
515 Rectangle
aTiny(Point(4, 4), Size(nTW
*2, nTH
*2));
516 aPolyPoly
.Insert(Polygon(aTiny
));
517 aTiny
.Move(nTW
*3, nTH
*3);
518 aPolyPoly
.Insert(Polygon(aTiny
));
519 aTiny
.Move(nTW
, nTH
);
520 aPolyPoly
.Insert(Polygon(aTiny
));
522 aRegion
= vcl::Region(aPolyPoly
);
526 rDev
.SetClipRegion(aRegion
);
527 rDev
.DrawCheckered(aSub
.TopLeft(), aSub
.GetSize());
528 rDev
.SetClipRegion();
533 rDev
.DrawCheckered(r
.TopLeft(), r
.GetSize());
538 struct DrawPoly
: public RegionRenderer
540 RENDER_DETAILS(poly
,KEY_P
,20)
541 DrawCheckered maCheckered
;
542 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
543 const RenderContext
&rCtx
) SAL_OVERRIDE
545 maCheckered
.RenderRegion(rDev
, r
, rCtx
);
547 long nDx
= r
.GetWidth()/20;
548 long nDy
= r
.GetHeight()/20;
549 Rectangle
aShrunk(r
);
550 aShrunk
.Move(nDx
, nDy
);
551 aShrunk
.SetSize(Size(r
.GetWidth()-nDx
*2,
552 r
.GetHeight()-nDy
*2));
553 Polygon
aPoly(aShrunk
);
554 tools::PolyPolygon
aPPoly(aPoly
);
555 rDev
.SetLineColor(Color(COL_RED
));
556 rDev
.SetFillColor(Color(COL_RED
));
557 // This hits the optional 'drawPolyPolygon' code-path
558 rDev
.DrawTransparent(aPPoly
, 64);
562 struct DrawEllipse
: public RegionRenderer
564 RENDER_DETAILS(ellipse
,KEY_E
,5000)
565 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
566 const RenderContext
&) SAL_OVERRIDE
568 rDev
.SetLineColor(Color(COL_RED
));
569 rDev
.SetFillColor(Color(COL_GREEN
));
574 struct DrawGradient
: public RegionRenderer
576 RENDER_DETAILS(gradient
,KEY_G
,50)
577 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
578 const RenderContext
&rCtx
) SAL_OVERRIDE
580 if (rCtx
.meStyle
== RENDER_EXPANDED
)
582 std::vector
<Rectangle
> aRegions(DemoRenderer::partition(rCtx
,5, 4));
583 sal_uInt32 nStartCols
[] = {
584 COL_RED
, COL_RED
, COL_RED
, COL_GREEN
, COL_GREEN
,
585 COL_BLUE
, COL_BLUE
, COL_BLUE
, COL_CYAN
, COL_CYAN
,
586 COL_BLACK
, COL_LIGHTGRAY
, COL_WHITE
, COL_BLUE
, COL_CYAN
,
587 COL_WHITE
, COL_WHITE
, COL_WHITE
, COL_BLACK
, COL_BLACK
589 sal_uInt32 nEndCols
[] = {
590 COL_WHITE
, COL_WHITE
, COL_WHITE
, COL_BLACK
, COL_BLACK
,
591 COL_RED
, COL_RED
, COL_RED
, COL_GREEN
, COL_GREEN
,
592 COL_GRAY
, COL_GRAY
, COL_LIGHTGRAY
, COL_LIGHTBLUE
, COL_LIGHTCYAN
,
593 COL_BLUE
, COL_BLUE
, COL_BLUE
, COL_CYAN
, COL_CYAN
595 GradientStyle eStyles
[] = {
596 GradientStyle_LINEAR
, GradientStyle_AXIAL
, GradientStyle_RADIAL
, GradientStyle_ELLIPTICAL
, GradientStyle_SQUARE
,
597 GradientStyle_RECT
, GradientStyle_FORCE_EQUAL_SIZE
, GradientStyle_LINEAR
, GradientStyle_RADIAL
, GradientStyle_LINEAR
,
598 GradientStyle_LINEAR
, GradientStyle_AXIAL
, GradientStyle_RADIAL
, GradientStyle_ELLIPTICAL
, GradientStyle_SQUARE
,
599 GradientStyle_RECT
, GradientStyle_FORCE_EQUAL_SIZE
, GradientStyle_LINEAR
, GradientStyle_RADIAL
, GradientStyle_LINEAR
601 sal_uInt16 nAngles
[] = {
604 90, 120, 135, 160, 180,
607 sal_uInt16 nBorders
[] = {
614 DemoRenderer::clearRects(rDev
, aRegions
);
615 assert(aRegions
.size() <= SAL_N_ELEMENTS(nStartCols
));
616 assert(aRegions
.size() <= SAL_N_ELEMENTS(nEndCols
));
617 assert(aRegions
.size() <= SAL_N_ELEMENTS(eStyles
));
618 assert(aRegions
.size() <= SAL_N_ELEMENTS(nAngles
));
619 assert(aRegions
.size() <= SAL_N_ELEMENTS(nBorders
));
620 for (size_t i
= 0; i
< aRegions
.size(); i
++)
622 Rectangle aSub
= aRegions
[i
];
624 aGradient
.SetStartColor(Color(nStartCols
[i
]));
625 aGradient
.SetEndColor(Color(nEndCols
[i
]));
626 aGradient
.SetStyle(eStyles
[i
]);
627 aGradient
.SetAngle(nAngles
[i
]);
628 aGradient
.SetBorder(nBorders
[i
]);
629 rDev
.DrawGradient(aSub
, aGradient
);
635 aGradient
.SetStartColor(COL_YELLOW
);
636 aGradient
.SetEndColor(COL_RED
);
637 aGradient
.SetStyle(GradientStyle_RECT
);
638 aGradient
.SetBorder(r
.GetSize().Width()/20);
639 rDev
.DrawGradient(r
, aGradient
);
644 struct DrawBitmap
: public RegionRenderer
646 RENDER_DETAILS(bitmap
,KEY_B
,10)
648 // Simulate Page Borders rendering - which ultimately should
649 // be done with a shader / gradient
650 static void SimulateBorderStretch(OutputDevice
&rDev
, const Rectangle
& r
)
652 BitmapEx
aPageShadowMask("sw/res/page-shadow-mask.png");
654 BitmapEx
aRight(aPageShadowMask
);
655 sal_Int32 nSlice
= (aPageShadowMask
.GetSizePixel().Width() - 3) / 4;
657 aRight
.Crop(Rectangle(Point((nSlice
* 3) + 3, (nSlice
* 2) + 1),
659 AlphaMask
aAlphaMask(aRight
.GetBitmap());
660 Bitmap aBlockColor
= Bitmap(aAlphaMask
.GetSizePixel(), 24);
661 aBlockColor
.Erase(COL_RED
);
662 BitmapEx aShadowStretch
= BitmapEx(aBlockColor
, aAlphaMask
);
664 Point
aRenderPt(r
.TopLeft());
666 long aSizes
[] = { 200, 100, 200, 100, 50, 5, 2 };
668 // and yes - we really do this in the page border rendering code ...
669 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aSizes
); i
++)
671 aShadowStretch
.Scale(Size(aShadowStretch
.GetSizePixel().Width(), aSizes
[i
]),
674 rDev
.DrawBitmapEx(aRenderPt
, aShadowStretch
);
675 aRenderPt
.Move(aShadowStretch
.GetSizePixel().Width() + 4, 0);
678 AlphaMask
aWholeMask(aPageShadowMask
.GetBitmap());
679 aBlockColor
= Bitmap(aPageShadowMask
.GetSizePixel(), 24);
680 aBlockColor
.Erase(COL_GREEN
);
681 BitmapEx
aWhole(aBlockColor
, aWholeMask
);
683 aRenderPt
= Point(r
.Center());
684 aRenderPt
.Move(nSlice
+1, 0);
686 // An offset background for alpha rendering
687 rDev
.SetFillColor(COL_BLUE
);
688 Rectangle
aSurround(r
.Center(), Size(aPageShadowMask
.GetSizePixel()));
689 rDev
.DrawRect(aSurround
);
690 rDev
.DrawBitmapEx(aRenderPt
, aWhole
);
693 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
694 const RenderContext
&rCtx
) SAL_OVERRIDE
696 Bitmap
aBitmap(rCtx
.mpDemoRenderer
->maIntroBW
);
697 aBitmap
.Scale(r
.GetSize(), BmpScaleFlag::BestQuality
);
698 rDev
.DrawBitmap(r
.TopLeft(), aBitmap
);
700 SimulateBorderStretch(rDev
, r
);
704 struct DrawBitmapEx
: public RegionRenderer
706 RENDER_DETAILS(bitmapex
,KEY_X
,2)
707 DrawCheckered maCheckered
;
708 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
709 const RenderContext
&rCtx
) SAL_OVERRIDE
711 maCheckered
.RenderRegion(rDev
, r
, rCtx
);
713 BitmapEx
aBitmap(rCtx
.mpDemoRenderer
->maIntro
);
714 aBitmap
.Scale(r
.GetSize(), BmpScaleFlag::BestQuality
);
715 AlphaMask
aSemiTransp(aBitmap
.GetSizePixel());
716 aSemiTransp
.Erase(64);
717 rDev
.DrawBitmapEx(r
.TopLeft(), BitmapEx(aBitmap
.GetBitmap(),
722 struct DrawPolyPolygons
: public RegionRenderer
724 RENDER_DETAILS(polypoly
,KEY_N
,100)
725 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
726 const RenderContext
&) SAL_OVERRIDE
730 } aPoints
[] = { { 0.1, 0.1 }, { 0.9, 0.9 },
731 #if FIXME_SELF_INTERSECTING_WORKING
732 { 0.9, 0.1 }, { 0.1, 0.9 },
735 { 0.1, 0.9 }, { 0.5, 0.5 },
736 { 0.9, 0.1 }, { 0.1, 0.1 }
740 tools::PolyPolygon aPolyPoly
;
741 // Render 4x polygons & aggregate into another PolyPolygon
742 for (int x
= 0; x
< 2; x
++)
744 for (int y
= 0; y
< 2; y
++)
746 Rectangle
aSubRect(r
);
747 aSubRect
.Move(x
* r
.GetWidth()/3, y
* r
.GetHeight()/3);
748 aSubRect
.SetSize(Size(r
.GetWidth()/2, r
.GetHeight()/4));
749 Polygon
aPoly(SAL_N_ELEMENTS(aPoints
));
750 for (size_t v
= 0; v
< SAL_N_ELEMENTS(aPoints
); v
++)
752 aPoly
.SetPoint(Point(aSubRect
.Left() +
753 aSubRect
.GetWidth() * aPoints
[v
].nX
,
755 aSubRect
.GetHeight() * aPoints
[v
].nY
),
758 rDev
.SetLineColor(Color(COL_YELLOW
));
759 rDev
.SetFillColor(Color(COL_BLACK
));
760 rDev
.DrawPolygon(aPoly
);
762 // now move and add to the polypolygon
763 aPoly
.Move(0, r
.GetHeight()/2);
764 aPolyPoly
.Insert(aPoly
);
767 rDev
.SetLineColor(Color(COL_LIGHTRED
));
768 rDev
.SetFillColor(Color(COL_GREEN
));
769 rDev
.DrawTransparent(aPolyPoly
, 50);
773 struct DrawToVirtualDevice
: public RegionRenderer
775 RENDER_DETAILS(vdev
,KEY_V
,1)
780 RENDER_AS_ALPHA_OUTDEV
783 static void SizeAndRender(OutputDevice
&rDev
, const Rectangle
& r
, RenderType eType
,
784 const RenderContext
&rCtx
)
786 ScopedVclPtr
<VirtualDevice
> pNested
;
788 if ((int)eType
< RENDER_AS_BITMAPEX
)
789 pNested
= VclPtr
<VirtualDevice
>::Create(rDev
).get();
791 pNested
= VclPtr
<VirtualDevice
>::Create(rDev
,0,0).get();
793 pNested
->SetOutputSizePixel(r
.GetSize());
794 Rectangle
aWhole(Point(0,0), r
.GetSize());
797 rCtx
.mpDemoRenderer
->drawToDevice(*pNested
, r
.GetSize(), true);
799 if (eType
== RENDER_AS_BITMAP
)
801 Bitmap
aBitmap(pNested
->GetBitmap(Point(0,0),aWhole
.GetSize()));
802 rDev
.DrawBitmap(r
.TopLeft(), aBitmap
);
804 else if (eType
== RENDER_AS_BITMAPEX
)
806 BitmapEx
aBitmapEx(pNested
->GetBitmapEx(Point(0,0),aWhole
.GetSize()));
807 rDev
.DrawBitmapEx(r
.TopLeft(), aBitmapEx
);
809 else if (eType
== RENDER_AS_OUTDEV
||
810 eType
== RENDER_AS_ALPHA_OUTDEV
)
812 rDev
.DrawOutDev(r
.TopLeft(), r
.GetSize(),
813 aWhole
.TopLeft(), aWhole
.GetSize(),
817 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
818 const RenderContext
&rCtx
) SAL_OVERRIDE
820 // avoid infinite recursion
824 if (rCtx
.meStyle
== RENDER_EXPANDED
)
826 std::vector
<Rectangle
> aRegions(DemoRenderer::partition(rCtx
,2, 2));
827 DemoRenderer::clearRects(rDev
, aRegions
);
829 RenderType eRenderTypes
[] = { RENDER_AS_BITMAP
, RENDER_AS_OUTDEV
,
830 RENDER_AS_BITMAPEX
, RENDER_AS_ALPHA_OUTDEV
};
831 for (size_t i
= 0; i
< aRegions
.size(); i
++)
832 SizeAndRender(rDev
, aRegions
[i
], eRenderTypes
[i
], rCtx
);
835 SizeAndRender(rDev
, r
, RENDER_AS_BITMAP
, rCtx
);
839 struct DrawIcons
: public RegionRenderer
841 RENDER_DETAILS(icons
,KEY_I
,1)
843 std::vector
<OUString
> maIconNames
;
844 std::vector
<BitmapEx
> maIcons
;
846 DrawIcons() : bHasLoadedAll(false)
848 // a few icons to start with
849 const char *pNames
[] = {
850 "cmd/lc_openurl.png",
852 "cmd/lc_choosemacro.png",
855 "cmd/lc_importdialog.png",
856 "cmd/lc_sendmail.png",
857 "cmd/lc_editdoc.png",
859 "cmd/lc_combobox.png",
860 "cmd/lc_insertformcombo.png",
861 "cmd/lc_printpreview.png",
865 "cmd/sc_autopilotmenu.png",
866 "cmd/lc_formatpaintbrush.png",
870 "cmd/lc_fieldnames.png",
871 "cmd/lc_hyperlinkdialog.png",
873 for (size_t i
= 0; i
< SAL_N_ELEMENTS(pNames
); i
++)
875 maIconNames
.push_back(OUString::createFromAscii(pNames
[i
]));
876 maIcons
.push_back(BitmapEx(maIconNames
[i
]));
884 bHasLoadedAll
= true;
886 css::uno::Sequence
< OUString
> aAllIcons
= ImageTree_getAllImageNames();
887 for (sal_Int32 i
= 0; i
< aAllIcons
.getLength(); i
++)
889 maIconNames
.push_back(aAllIcons
[i
]);
890 maIcons
.push_back(BitmapEx(aAllIcons
[i
]));
894 void doDrawIcons(OutputDevice
&rDev
, Rectangle r
, bool bExpanded
)
897 Point
p(r
.LeftCenter());
898 size_t nToRender
= maIcons
.size();
900 if (!bExpanded
&& maIcons
.size() > 64)
902 for (size_t i
= 0; i
< nToRender
; i
++)
904 Size
aSize(maIcons
[i
].GetSizePixel());
905 // sAL_DEBUG("Draw icon '" << maIconNames[i] << "'");
908 rDev
.DrawBitmapEx(p
, maIcons
[i
]);
911 basegfx::B2DHomMatrix aTransform
;
912 aTransform
.scale(aSize
.Width(), aSize
.Height());
916 aTransform
.shearX((double)((i
>> 2) % 8) / 8);
917 aTransform
.shearY((double)((i
>> 4) % 8) / 8);
920 aTransform
.translate(-aSize
.Width()/2, -aSize
.Height()/2);
921 aTransform
.rotate(i
);
924 aTransform
.shearX((double)((i
>> 2) % 8) / 8);
925 aTransform
.shearY((double)((i
>> 4) % 8) / 8);
927 aTransform
.translate(aSize
.Width()/2, aSize
.Height()/2);
930 aTransform
.translate(-aSize
.Width()/2, -aSize
.Height()/2);
931 aTransform
.rotate(2 * F_2PI
* i
/ nToRender
);
932 aTransform
.translate(aSize
.Width()/2, aSize
.Height()/2);
935 aTransform
.translate(p
.X(), p
.Y());
936 rDev
.DrawTransformedBitmapEx(aTransform
, maIcons
[i
]);
940 p
.Move(aSize
.Width(), 0);
941 if (aSize
.Height() > nMaxH
)
942 nMaxH
= aSize
.Height();
943 if (p
.X() >= r
.Right()) // wrap to next line
945 p
= Point(r
.Left(), p
.Y() + nMaxH
);
948 if (p
.Y() >= r
.Bottom()) // re-start at middle
953 static BitmapEx
AlphaRecovery(OutputDevice
&rDev
, Point aPt
, BitmapEx
&aSrc
)
955 // Compositing onto 2x colors beyond our control
956 ScopedVclPtrInstance
< VirtualDevice
> aWhite
;
957 ScopedVclPtrInstance
< VirtualDevice
> aBlack
;
958 aWhite
->SetOutputSizePixel(aSrc
.GetSizePixel());
959 aWhite
->SetBackground(Wallpaper(COL_WHITE
));
961 aBlack
->SetOutputSizePixel(aSrc
.GetSizePixel());
962 aBlack
->SetBackground(Wallpaper(COL_BLACK
));
964 aWhite
->DrawBitmapEx(Point(), aSrc
);
965 aBlack
->DrawBitmapEx(Point(), aSrc
);
967 // Now recover that alpha...
968 Bitmap aWhiteBmp
= aWhite
->GetBitmap(Point(),aSrc
.GetSizePixel());
969 Bitmap aBlackBmp
= aBlack
->GetBitmap(Point(),aSrc
.GetSizePixel());
970 AlphaMask
aMask(aSrc
.GetSizePixel());
971 Bitmap
aRecovered(aSrc
.GetSizePixel(), 24);
973 AlphaMask::ScopedWriteAccess
pMaskAcc(aMask
);
974 Bitmap::ScopedWriteAccess
pRecAcc(aRecovered
);
975 Bitmap::ScopedReadAccess
pAccW(aWhiteBmp
); // a * pix + (1-a)
976 Bitmap::ScopedReadAccess
pAccB(aBlackBmp
); // a * pix + 0
977 int nSizeX
= aSrc
.GetSizePixel().Width();
978 int nSizeY
= aSrc
.GetSizePixel().Height();
979 for (int y
= 0; y
< nSizeY
; y
++)
981 for (int x
= 0; x
< nSizeX
; x
++)
983 BitmapColor aColW
= pAccW
->GetPixel(y
,x
);
984 BitmapColor aColB
= pAccB
->GetPixel(y
,x
);
985 long nAR
= (long)(aColW
.GetRed() - aColB
.GetRed()); // (1-a)
986 long nAG
= (long)(aColW
.GetGreen() - aColB
.GetGreen()); // (1-a)
987 long nAB
= (long)(aColW
.GetBlue() - aColB
.GetBlue()); // (1-a)
989 #define CLAMP(a,b,c) (((a)<=(b))?(b):(((a)>=(c))?(c):(a)))
991 // we get the most precision from the largest delta
992 long nInverseAlpha
= std::max(nAR
, std::max(nAG
, nAB
)); // (1-a)
993 nInverseAlpha
= CLAMP(nInverseAlpha
, 0, 255);
994 long nAlpha
= 255 - nInverseAlpha
;
996 pMaskAcc
->SetPixel(y
,x
,BitmapColor((sal_Int8
)CLAMP(nInverseAlpha
,0,255)));
997 // now recover the pixels
998 long nR
= (aColW
.GetRed() + aColB
.GetRed() - nInverseAlpha
) * 128;
999 long nG
= (aColW
.GetGreen() + aColB
.GetGreen() - nInverseAlpha
) * 128;
1000 long nB
= (aColW
.GetBlue() + aColB
.GetBlue() - nInverseAlpha
) * 128;
1002 { // doesn't matter what's behind transparency
1007 nR
/= nAlpha
; nG
/= nAlpha
; nB
/= nAlpha
;
1009 pRecAcc
->SetPixel(y
,x
,BitmapColor(
1010 (sal_uInt8
)CLAMP(nR
,0,255),
1011 (sal_uInt8
)CLAMP(nG
,0,255),
1012 (sal_uInt8
)CLAMP(nB
,0,255)));
1017 rDev
.DrawBitmap(aPt
, aWhiteBmp
);
1018 aPt
.Move(aSrc
.GetSizePixel().Width(), 0);
1019 rDev
.DrawBitmap(aPt
, aBlackBmp
);
1020 aPt
.Move(aSrc
.GetSizePixel().Width(), 0);
1021 rDev
.DrawBitmap(aPt
, aRecovered
);
1022 aPt
.Move(aSrc
.GetSizePixel().Width(), 0);
1023 rDev
.DrawBitmap(aPt
, aMask
.GetBitmap());
1024 aPt
.Move(aSrc
.GetSizePixel().Width(), 0);
1026 return BitmapEx(aRecovered
, aMask
);
1029 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
1030 const RenderContext
&rCtx
) SAL_OVERRIDE
1032 if (rCtx
.meStyle
== RENDER_EXPANDED
)
1036 Point
aLocation(0,maIcons
[0].GetSizePixel().Height() + 8);
1037 for (size_t i
= 0; i
< 100; i
++)
1039 BitmapEx aSrc
= maIcons
[i
];
1042 Point
aAbove(aLocation
);
1043 aAbove
.Move(0,-aSrc
.GetSizePixel().Height() - 4);
1044 rDev
.DrawBitmapEx(aAbove
, aSrc
);
1045 aAbove
.Move(aSrc
.GetSizePixel().Width(),0);
1046 aAbove
.Move(aSrc
.GetSizePixel().Width(),0);
1047 rDev
.DrawBitmap(aAbove
, aSrc
.GetBitmap());
1048 aAbove
.Move(aSrc
.GetSizePixel().Width(),0);
1049 rDev
.DrawBitmap(aAbove
, aSrc
.GetMask());
1051 // intermediates middle
1052 BitmapEx aResult
= AlphaRecovery(rDev
, aLocation
, aSrc
);
1055 Point
aBelow(aLocation
);
1056 aBelow
.Move(0,aResult
.GetSizePixel().Height());
1057 rDev
.DrawBitmapEx(aBelow
, aResult
);
1059 aLocation
.Move(aSrc
.GetSizePixel().Width()*6,0);
1060 if (aLocation
.X() > r
.Right())
1061 aLocation
= Point(0,aLocation
.Y()+aSrc
.GetSizePixel().Height()*3+4);
1064 // now go crazy with random foo
1065 doDrawIcons(rDev
, r
, true);
1069 doDrawIcons(rDev
, r
, false);
1074 struct FetchDrawBitmap
: public RegionRenderer
1076 RENDER_DETAILS(fetchdraw
,KEY_F
,50)
1077 virtual void RenderRegion(OutputDevice
&rDev
, Rectangle r
,
1078 const RenderContext
&) SAL_OVERRIDE
1080 Bitmap
aBitmap(rDev
.GetBitmap(Point(0,0),rDev
.GetOutputSizePixel()));
1081 aBitmap
.Scale(r
.GetSize(), BmpScaleFlag::BestQuality
);
1082 rDev
.DrawBitmap(r
.TopLeft(), aBitmap
);
1086 void drawToDevice(vcl::RenderContext
& rDev
, Size aSize
, bool bVDev
)
1090 aCtx
.mbVDev
= bVDev
;
1091 aCtx
.mpDemoRenderer
= this;
1092 aCtx
.maSize
= aSize
;
1093 Rectangle
aWholeWin(Point(0,0), rDev
.GetOutputSizePixel());
1095 drawBackground(rDev
, aWholeWin
);
1097 if (!bVDev
/* want everything in the vdev */ &&
1098 mnSelectedRenderer
>= 0)
1100 aCtx
.meStyle
= RENDER_EXPANDED
;
1101 RegionRenderer
* r
= maRenderers
[mnSelectedRenderer
];
1103 if (getIterCount() > 0)
1105 mnStartTime
= getTimeNow();
1106 for (int i
= 0; i
< r
->getTestRepeatCount(); i
++)
1107 r
->RenderRegion(rDev
, aWholeWin
, aCtx
);
1108 addTime(mnSelectedRenderer
, getTimeNow() - mnStartTime
);
1110 r
->RenderRegion(rDev
, aWholeWin
, aCtx
);
1114 aCtx
.meStyle
= RENDER_THUMB
;
1115 std::vector
<Rectangle
> aRegions(partition(aSize
, mnSegmentsX
, mnSegmentsY
));
1116 DemoRenderer::clearRects(rDev
, aRegions
);
1117 for (size_t i
= 0; i
< maRenderers
.size(); i
++)
1119 RegionRenderer
* r
= maRenderers
[i
];
1121 rDev
.SetClipRegion( vcl::Region( aRegions
[i
] ) );
1124 if (getIterCount() > 0)
1128 mnStartTime
= getTimeNow();
1129 for (int j
= 0; j
< r
->getTestRepeatCount() * THUMB_REPEAT_FACTOR
; j
++)
1130 r
->RenderRegion(rDev
, aRegions
[i
], aCtx
);
1131 addTime(i
, (getTimeNow() - mnStartTime
) / THUMB_REPEAT_FACTOR
);
1133 for (int j
= 0; j
< r
->getTestRepeatCount(); j
++)
1134 r
->RenderRegion(rDev
, aRegions
[i
], aCtx
);
1138 r
->RenderRegion(rDev
, aRegions
[i
], aCtx
);
1141 rDev
.SetClipRegion();
1145 std::vector
<VclPtr
<vcl::Window
> > maInvalidates
;
1146 void addInvalidate(vcl::Window
*pWindow
) { maInvalidates
.push_back(pWindow
); };
1147 void removeInvalidate(vcl::Window
*pWindow
)
1149 for (auto aIt
= maInvalidates
.begin(); aIt
!= maInvalidates
.end(); ++aIt
)
1151 if (*aIt
== pWindow
)
1153 maInvalidates
.erase(aIt
);
1160 for (size_t i
= 0; i
< maInvalidates
.size(); ++i
)
1161 maInvalidates
[i
]->Invalidate();
1165 #if FIXME_BOUNCE_BUTTON
1166 IMPL_LINK_NOARG(DemoRenderer
,BounceTimerCb
)
1168 mpButton
->Check(mnBounceX
>0);
1169 mpButton
->SetPressed(mnBounceY
>0);
1171 Point aCur
= mpButtonWin
->GetPosPixel();
1172 static const int nMovePix
= 10;
1173 aCur
.Move(mnBounceX
* nMovePix
, mnBounceX
* nMovePix
);
1174 Size aWinSize
= GetSizePixel();
1175 if (aCur
.X() <= 0 || aCur
.X() >= aWinSize
.Width())
1177 if (aCur
.Y() <= 0 || aCur
.Y() >= aWinSize
.Height())
1179 mpButtonWin
->SetPosPixel(aCur
);
1181 // All smoke and mirrors to test sub-region invalidation underneath
1182 Rectangle
aRect(aCur
, mpButtonWin
->GetSizePixel());
1188 void DemoRenderer::KeyInput(const KeyEvent
&rKEvt
)
1190 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
1192 // click to zoom out
1193 if (mnSelectedRenderer
>= 0)
1195 if (nCode
== KEY_ESCAPE
|| nCode
== KEY_BACKSPACE
)
1197 mnSelectedRenderer
= -1;
1204 for (size_t i
= 0; i
< maRenderers
.size(); i
++)
1206 if (nCode
== maRenderers
[i
]->getAccelerator())
1208 mnSelectedRenderer
= i
;
1216 bool DemoRenderer::MouseButtonDown(const MouseEvent
& rMEvt
)
1218 // click to zoom out
1219 if (mnSelectedRenderer
>= 0)
1221 mnSelectedRenderer
= -1;
1226 // click on a region to zoom into it
1227 std::vector
<Rectangle
> aRegions(partition(GetSizePixel(), mnSegmentsX
, mnSegmentsY
));
1228 for (size_t i
= 0; i
< aRegions
.size(); i
++)
1230 if (aRegions
[i
].IsInside(rMEvt
.GetPosPixel()))
1232 mnSelectedRenderer
= i
;
1238 #if FIXME_BOUNCE_BUTTON
1239 // otherwise bounce floating windows
1242 mpButtonWin
= VclPtr
<FloatingWindow
>::Create(this);
1243 mpButton
= VclPtr
<PushButton
>::Create(mpButtonWin
);
1244 mpButton
->SetSymbol(SymbolType::HELP
);
1245 mpButton
->SetText("PushButton demo");
1246 mpButton
->SetPosSizePixel(Point(0,0), mpButton
->GetOptimalSize());
1248 mpButtonWin
->SetPosSizePixel(Point(0,0), mpButton
->GetOptimalSize());
1249 mpButtonWin
->Show();
1250 mnBounceX
= 1; mnBounceX
= 1;
1251 maBounce
.SetTimeoutHdl(LINK(this,DemoRenderer
,BounceTimerCb
));
1252 maBounce
.SetTimeout(55);
1266 void DemoRenderer::InitRenderers()
1268 maRenderers
.push_back(new DrawLines());
1269 maRenderers
.push_back(new DrawText());
1270 maRenderers
.push_back(new DrawPoly());
1271 maRenderers
.push_back(new DrawEllipse());
1272 maRenderers
.push_back(new DrawCheckered());
1273 maRenderers
.push_back(new DrawBitmapEx());
1274 maRenderers
.push_back(new DrawBitmap());
1275 maRenderers
.push_back(new DrawGradient());
1276 maRenderers
.push_back(new DrawPolyPolygons());
1277 maRenderers
.push_back(new DrawToVirtualDevice());
1278 maRenderers
.push_back(new DrawIcons());
1279 maRenderers
.push_back(new FetchDrawBitmap());
1282 OUString
DemoRenderer::getRendererList()
1284 OUStringBuffer aBuf
;
1285 for (size_t i
= 0; i
< maRenderers
.size(); i
++)
1287 aBuf
.append(maRenderers
[i
]->getName());
1290 return aBuf
.makeStringAndClear();
1293 double DemoRenderer::getAndResetBenchmark(const RenderStyle style
)
1295 double geomean
= 1.0;
1296 fprintf(stderr
, "Rendering: %s, Times (ms):\n", style
== RENDER_THUMB
? "THUMB": "EXPANDED");
1297 for (size_t i
= 0; i
< maRenderers
.size(); i
++)
1299 double avgtime
= maRenderers
[i
]->sumTime
/ maRenderers
[i
]->countTime
;
1301 fprintf(stderr
, "%s: %f (iteration: %d*%d*%d)\n",
1302 rtl::OUStringToOString(maRenderers
[i
]->getName(),
1303 RTL_TEXTENCODING_UTF8
).getStr(), avgtime
,
1304 maRenderers
[i
]->countTime
, maRenderers
[i
]->getTestRepeatCount(),
1305 (style
== RENDER_THUMB
) ? THUMB_REPEAT_FACTOR
: 1);
1306 maRenderers
[i
]->sumTime
= 0;
1307 maRenderers
[i
]->countTime
= 0;
1309 geomean
= pow(geomean
, static_cast<double>(1.0)/maRenderers
.size());
1310 fprintf(stderr
, "GEOMEAN_%s: %f\n", style
== RENDER_THUMB
? "THUMB": "EXPANDED", geomean
);
1314 void DemoRenderer::setIterCount(sal_Int32 i
)
1319 sal_Int32
DemoRenderer::getIterCount()
1324 void DemoRenderer::addTime(int i
, double t
)
1326 maRenderers
[i
]->sumTime
+= t
/ maRenderers
[i
]->getTestRepeatCount();
1327 maRenderers
[i
]->countTime
++;
1330 void DemoRenderer::selectRenderer(const OUString
&rName
)
1332 for (size_t i
= 0; i
< maRenderers
.size(); i
++)
1334 if (maRenderers
[i
]->getName() == rName
)
1336 mnSelectedRenderer
= i
;
1343 int DemoRenderer::selectNextRenderer()
1345 mnSelectedRenderer
++;
1346 if (mnSelectedRenderer
== (signed) maRenderers
.size())
1347 mnSelectedRenderer
= -1;
1349 return mnSelectedRenderer
;
1352 class DemoWin
: public WorkWindow
1354 DemoRenderer
&mrRenderer
;
1358 class RenderThread
: public salhelper::Thread
{
1362 RenderThread(DemoWin
&rWin
, sal_uInt32 nDelaySecs
)
1363 : Thread("vcldemo render thread")
1366 maDelay
.Seconds
= nDelaySecs
;
1367 maDelay
.Nanosec
= 0;
1370 virtual ~RenderThread()
1374 virtual void execute() SAL_OVERRIDE
1376 osl_waitThread(&maDelay
);
1378 SolarMutexGuard aGuard
;
1379 fprintf (stderr
, "render from a different thread\n");
1383 rtl::Reference
<RenderThread
> mxThread
;
1386 DemoWin(DemoRenderer
&rRenderer
, bool bThreads
) :
1387 WorkWindow(NULL
, WB_APP
| WB_STDWORK
),
1388 mrRenderer(rRenderer
),
1389 testThreads(bThreads
)
1391 mrRenderer
.addInvalidate(this);
1392 underTesting
= false;
1398 virtual void dispose() SAL_OVERRIDE
1401 mrRenderer
.removeInvalidate(this);
1402 WorkWindow::dispose();
1404 virtual void MouseButtonDown(const MouseEvent
& rMEvt
) SAL_OVERRIDE
1406 mrRenderer
.SetSizePixel(GetSizePixel());
1407 if (!mrRenderer
.MouseButtonDown(rMEvt
))
1410 { // render this window asynchronously in a new thread
1411 sal_uInt32 nDelaySecs
= 0;
1412 if (rMEvt
.GetButtons() & MOUSE_RIGHT
)
1414 mxThread
= new RenderThread(*this, nDelaySecs
);
1417 { // spawn another window
1418 VclPtrInstance
<DemoWin
> pNewWin(mrRenderer
, testThreads
);
1419 pNewWin
->SetText("Another interactive VCL demo window");
1424 virtual void KeyInput(const KeyEvent
& rKEvt
) SAL_OVERRIDE
1426 mrRenderer
.SetSizePixel(GetSizePixel());
1427 mrRenderer
.KeyInput(rKEvt
);
1429 virtual void Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& rRect
) SAL_OVERRIDE
1431 mrRenderer
.SetSizePixel(GetSizePixel());
1432 fprintf(stderr
, "DemoWin::Paint(%ld,%ld,%ld,%ld)\n", rRect
.getX(), rRect
.getY(), rRect
.getWidth(), rRect
.getHeight());
1433 if (mrRenderer
.getIterCount() == 0)
1434 mrRenderer
.drawToDevice(rRenderContext
, GetSizePixel(), false);
1436 TestAndQuit(rRenderContext
);
1439 void TestAndQuit(vcl::RenderContext
& rRenderContext
)
1443 underTesting
= true;
1444 for (sal_Int32 i
= 0; i
< mrRenderer
.getIterCount(); i
++)
1446 while (mrRenderer
.selectNextRenderer() > -1)
1448 mrRenderer
.drawToDevice(rRenderContext
, GetSizePixel(), false);
1452 double expandedGEOMEAN
= mrRenderer
.getAndResetBenchmark(RENDER_EXPANDED
);
1454 for (sal_Int32 i
= 0; i
< mrRenderer
.getIterCount(); i
++)
1455 mrRenderer
.drawToDevice(rRenderContext
, GetSizePixel(), false);
1457 double thumbGEOMEAN
= mrRenderer
.getAndResetBenchmark(RENDER_THUMB
);
1459 fprintf(stderr
, "GEOMEAN_TOTAL: %f\n", pow(thumbGEOMEAN
* expandedGEOMEAN
, static_cast<double>(0.5)));
1460 Application::Quit();
1464 class DemoWidgets
: public WorkWindow
1466 VclPtr
<VclBox
> mpBox
;
1467 VclPtr
<ToolBox
> mpToolbox
;
1468 VclPtr
<PushButton
> mpButton
;
1469 VclPtr
<VclHBox
> mpHBox
;
1470 VclPtr
<CheckBox
> mpGLCheck
;
1471 VclPtr
<ComboBox
> mpGLCombo
;
1472 VclPtr
<PushButton
> mpGLButton
;
1474 DECL_LINK(GLTestClick
, void *);
1478 WorkWindow(NULL
, WB_STDWORK
),
1479 mpBox(VclPtrInstance
<VclVBox
>(this, false, 3)),
1480 mpToolbox(VclPtrInstance
<ToolBox
>(mpBox
.get())),
1481 mpButton(VclPtrInstance
<PushButton
>(mpBox
.get())),
1482 mpHBox(VclPtrInstance
<VclHBox
>(mpBox
.get(), true, 3)),
1483 mpGLCheck(VclPtrInstance
<CheckBox
>(mpHBox
.get())),
1484 mpGLCombo(VclPtrInstance
<ComboBox
>(mpHBox
.get())),
1485 mpGLButton(VclPtrInstance
<PushButton
>(mpHBox
.get()))
1487 SetText("VCL widget demo");
1489 Wallpaper
aWallpaper(BitmapEx("sfx2/res/startcenter-logo.png"));
1490 aWallpaper
.SetStyle(WALLPAPER_BOTTOMRIGHT
);
1491 aWallpaper
.SetColor(COL_RED
);
1493 mpBox
->SetBackground(aWallpaper
);
1496 Help::EnableBalloonHelp();
1497 mpToolbox
->SetHelpText("Help text");
1498 mpToolbox
->InsertItem(0, "Toolbar item");
1499 mpToolbox
->SetQuickHelpText(0, "This is a tooltip popup");
1500 mpToolbox
->InsertSeparator();
1503 mpButton
->SetText("Click me; go on");
1506 mpGLCheck
->SetText("Test in OGL zone");
1508 mpGLCombo
->InsertEntry("sleep 1 second");
1509 mpGLCombo
->InsertEntry("sleep 3 seconds");
1510 mpGLCombo
->InsertEntry("sleep 7 seconds");
1511 mpGLCombo
->SelectEntryPos(2);
1513 mpGLButton
->SetText("Execute test");
1514 mpGLButton
->SetClickHdl(LINK(this,DemoWidgets
,GLTestClick
));
1520 virtual ~DemoWidgets() { disposeOnce(); }
1521 virtual void dispose() SAL_OVERRIDE
1523 mpGLButton
.disposeAndClear();
1524 mpGLCombo
.disposeAndClear();
1525 mpGLCheck
.disposeAndClear();
1526 mpHBox
.disposeAndClear();
1527 mpBox
.disposeAndClear();
1528 mpToolbox
.disposeAndClear();
1529 mpButton
.disposeAndClear();
1530 WorkWindow::dispose();
1532 virtual void Paint(vcl::RenderContext
& /*rRenderContext*/, const Rectangle
&) SAL_OVERRIDE
1534 Rectangle
aWholeSize(Point(0, 0),GetOutputSizePixel());
1535 vcl::Region
aClip(aWholeSize
);
1536 Rectangle
aExclude(Rectangle(Point(50,50),Size(100,100)));
1537 aClip
.Exclude(aExclude
);
1539 Wallpaper
aWallpaper(COL_GREEN
);
1541 Push(PushFlags::CLIPREGION
);
1542 IntersectClipRegion(aClip
);
1543 DrawWallpaper(aWholeSize
, aWallpaper
);
1546 ScopedVclPtrInstance
< VirtualDevice
> pDev(*this);
1547 pDev
->EnableRTL(IsRTLEnabled());
1548 pDev
->SetOutputSizePixel(aExclude
.GetSize());
1550 Rectangle
aSubRect(aWholeSize
);
1551 aSubRect
.Move(-aExclude
.Left(), -aExclude
.Top());
1552 pDev
->DrawWallpaper(aSubRect
, aWallpaper
);
1554 DrawOutDev(aExclude
.TopLeft(), aExclude
.GetSize(),
1555 Point( 0, 0 ), aExclude
.GetSize(), *pDev
.get() );
1559 class OpenGLZoneTest
{
1561 static void enter() { OpenGLZone::enter(); }
1562 static void leave() { OpenGLZone::leave(); }
1565 IMPL_LINK_NOARG(DemoWidgets
,GLTestClick
)
1567 sal_Int32 nSelected
= mpGLCombo
->GetSelectEntryPos();
1587 bool bEnterLeave
= mpGLCheck
->IsChecked();
1589 OpenGLZoneTest::enter();
1591 osl_waitThread(&aDelay
);
1594 OpenGLZoneTest::leave();
1599 class DemoPopup
: public FloatingWindow
1602 DemoPopup() : FloatingWindow( NULL
, WB_SYSTEMWINDOW
|WB_TOOLTIPWIN
)
1604 SetType( WINDOW_HELPTEXTWINDOW
);
1606 SetOutputSizePixel( Size( 300, 30 ) );
1607 SetBackground(Wallpaper(COL_YELLOW
));
1609 Show( true, SHOW_NOACTIVATE
);
1613 virtual void Paint(vcl::RenderContext
& /*rRenderContext*/, const Rectangle
&) SAL_OVERRIDE
1615 // Interestingly in GL mode on Windows, this doesn't render.
1617 Size aSize
= GetOutputSizePixel();
1618 Rectangle
aTextRect(Point(6, 6), aSize
);
1620 SetTextColor(COL_BLACK
);
1621 SetTextAlign(ALIGN_TOP
);
1622 DrawText(aTextRect
, "This is a standalone help text test",
1623 DrawTextFlags::MultiLine
|DrawTextFlags::WordBreak
|
1624 DrawTextFlags::Left
|DrawTextFlags::Top
);
1626 SetLineColor(COL_BLACK
);
1628 DrawRect( Rectangle( Point(), aSize
) );
1630 aSize
.Height() -= 2;
1631 Color
aColor( GetLineColor() );
1632 SetLineColor( ( COL_GRAY
) );
1633 DrawRect( Rectangle( Point( 1, 1 ), aSize
) );
1634 SetLineColor( aColor
);
1640 VclPtr
<WorkWindow
> mxWinA
;
1641 VclPtr
<WorkWindow
> mxWinB
;
1642 OpenGLSalGraphicsImpl
*mpImplA
;
1643 OpenGLSalGraphicsImpl
*mpImplB
;
1644 rtl::Reference
<OpenGLContext
> mpA
;
1645 rtl::Reference
<OpenGLContext
> mpB
;
1647 static OpenGLSalGraphicsImpl
*getImpl(const VclPtr
<WorkWindow
> &xWin
)
1649 SalGraphics
*pGraphics
= xWin
->GetGraphics();
1650 return dynamic_cast<OpenGLSalGraphicsImpl
*>(pGraphics
->GetImpl());
1654 mxWinA(VclPtr
<WorkWindow
>::Create(nullptr, WB_APP
| WB_STDWORK
)),
1655 mxWinB(VclPtr
<WorkWindow
>::Create(nullptr, WB_APP
| WB_STDWORK
))
1657 if (!OpenGLHelper::isVCLOpenGLEnabled())
1659 fprintf (stderr
, "OpenGL is not enabled: try SAL_FORCEGL=1\n");
1663 mpImplA
= getImpl(mxWinA
);
1664 mpImplB
= getImpl(mxWinB
);
1665 assert (mpImplA
&& mpImplB
);
1666 mpA
= mpImplA
->GetOpenGLContext();
1667 mpB
= mpImplB
->GetOpenGLContext();
1669 assert (mpA
.is() && mpB
.is());
1670 assert (mpA
!= mpB
);
1674 mxWinB
.disposeAndClear();
1675 mxWinA
.disposeAndClear();
1678 void testCurrentFramebuffer()
1680 fprintf(stderr
,"test OpenGLContext's framebuffer association.\n");
1682 OpenGLFramebuffer
*pBuffer
;
1684 OpenGLTexture
aTexture(256,128);
1685 pBuffer
= mpA
->AcquireFramebuffer(aTexture
);
1686 pBuffer
->DetachTexture(); // TESTME - remove this line too ...
1688 assert (pBuffer
->IsFree());
1690 assert (mpA
->mpCurrentFramebuffer
== NULL
);
1695 if (!OpenGLHelper::isVCLOpenGLEnabled())
1698 testCurrentFramebuffer();
1704 class DemoApp
: public Application
1706 static int showHelp(DemoRenderer
&rRenderer
)
1708 fprintf(stderr
,"vcldemo - a VCL test app\n");
1709 fprintf(stderr
," --help - print this text\n");
1710 fprintf(stderr
," --show <renderer> - start with a given renderer, options are:\n");
1711 OUString
aRenderers(rRenderer
.getRendererList());
1712 fprintf(stderr
," %s\n",
1713 rtl::OUStringToOString(aRenderers
, RTL_TEXTENCODING_UTF8
).getStr());
1714 fprintf(stderr
," --test <iterCount> - create benchmark data\n");
1715 fprintf(stderr
," --widgets - launch the widget test.\n");
1716 fprintf(stderr
," --threads - render from multiple threads.\n");
1717 fprintf(stderr
," --gltest - run openGL regression tests.\n");
1718 fprintf(stderr
, "\n");
1725 virtual int Main() SAL_OVERRIDE
1729 bool bWidgets
= false, bThreads
= false;
1730 bool bPopup
= false, bGLTest
= false;
1731 DemoRenderer aRenderer
;
1733 for (sal_Int32 i
= 0; i
< GetCommandLineParamCount(); i
++)
1735 bool bLast
= i
== GetCommandLineParamCount() - 1;
1736 OUString aArg
= GetCommandLineParam(i
);
1737 if (aArg
== "--help" || aArg
== "-h")
1738 return showHelp(aRenderer
);
1739 if (aArg
== "--show")
1742 return showHelp(aRenderer
);
1744 aRenderer
.selectRenderer(GetCommandLineParam(++i
));
1746 else if (aArg
== "--test")
1749 return showHelp(aRenderer
);
1751 aRenderer
.setIterCount(GetCommandLineParam(++i
).toInt32());
1753 else if (aArg
== "--widgets")
1755 else if (aArg
== "--popup")
1757 else if (aArg
== "--gltest")
1759 else if (aArg
== "--threads")
1761 else if (aArg
.startsWith("--"))
1763 fprintf(stderr
,"Unknown argument '%s'\n",
1764 rtl::OUStringToOString(aArg
, RTL_TEXTENCODING_UTF8
).getStr());
1765 return showHelp(aRenderer
);
1769 ScopedVclPtrInstance
<DemoWin
> aMainWin(aRenderer
, bThreads
);
1770 VclPtr
<DemoWidgets
> xWidgets
;
1771 VclPtr
<DemoPopup
> xPopup
;
1773 aMainWin
->SetText("Interactive VCL demo #1");
1778 return aTests
.execute();
1781 xWidgets
= VclPtr
< DemoWidgets
>::Create ();
1783 xPopup
= VclPtrInstance
< DemoPopup
> ();
1787 Application::Execute();
1789 xWidgets
.disposeAndClear();
1790 xPopup
.disposeAndClear();
1792 catch (const css::uno::Exception
& e
)
1794 SAL_WARN("vcl.app", "Fatal exception: " << e
.Message
);
1797 catch (const std::exception
& e
)
1799 SAL_WARN("vcl.app", "Fatal exception: " << e
.what());
1806 uno::Reference
<lang::XMultiServiceFactory
> xMSF
;
1807 void Init() SAL_OVERRIDE
1811 uno::Reference
<uno::XComponentContext
> xComponentContext
1812 = ::cppu::defaultBootstrap_InitialComponentContext();
1813 xMSF
= uno::Reference
<lang::XMultiServiceFactory
>
1814 (xComponentContext
->getServiceManager(), uno::UNO_QUERY
);
1816 Application::Abort("Bootstrap failure - no service manager");
1818 ::comphelper::setProcessServiceFactory(xMSF
);
1820 catch (const uno::Exception
&e
)
1822 Application::Abort("Bootstrap exception " + e
.Message
);
1825 void DeInit() SAL_OVERRIDE
1827 uno::Reference
< lang::XComponent
>(
1828 comphelper::getProcessComponentContext(),
1829 uno::UNO_QUERY_THROW
)-> dispose();
1830 ::comphelper::setProcessServiceFactory(NULL
);
1834 void vclmain::createApplication()
1836 static DemoApp aApp
;
1839 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */