Bug Summary

File:home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx
Warning:line 614, column 9
Address of stack memory associated with local variable 'pJustification' is still referred to by the static variable 'aRuns' upon returning to the caller. This will be a dangling reference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name vcldemo.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/glm -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D GLM_FORCE_CTOR_INIT -D VCL_INTERNALS -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/harfbuzz/src -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/vcl/inc -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx
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#include <sal/config.h>
11
12#include <memory>
13
14#include <config_features.h>
15
16#include <math.h>
17#include <rtl/math.hxx>
18#include <sal/log.hxx>
19
20#include <comphelper/processfactory.hxx>
21#include <comphelper/random.hxx>
22#include <cppuhelper/bootstrap.hxx>
23#include <com/sun/star/lang/XMultiServiceFactory.hpp>
24#include <com/sun/star/lang/XInitialization.hpp>
25#include <com/sun/star/registry/XSimpleRegistry.hpp>
26#include <com/sun/star/ucb/UniversalContentBroker.hpp>
27#include <com/sun/star/uno/Reference.hxx>
28#include <com/sun/star/uno/Sequence.hxx>
29#include <com/sun/star/container/XNameAccess.hpp>
30#include <o3tl/safeint.hxx>
31#include <osl/time.h>
32#include <vcl/gradient.hxx>
33#include <vcl/vclmain.hxx>
34#include <vcl/layout.hxx>
35#include <vcl/ptrstyle.hxx>
36#include <salhelper/thread.hxx>
37
38#include <tools/diagnose_ex.h>
39#include <tools/urlobj.hxx>
40#include <tools/stream.hxx>
41#include <vcl/svapp.hxx>
42#include <vcl/pngread.hxx>
43#include <vcl/wrkwin.hxx>
44#include <vcl/virdev.hxx>
45#include <vcl/graphicfilter.hxx>
46#include <vcl/toolkit/button.hxx>
47#include <vcl/toolkit/combobox.hxx>
48#include <vcl/toolbox.hxx>
49#include <vcl/pngwrite.hxx>
50#include <vcl/floatwin.hxx>
51#include <vcl/bitmapaccess.hxx>
52#include <vcl/help.hxx>
53#include <vcl/menu.hxx>
54#include <vcl/ImageTree.hxx>
55#include <vcl/BitmapEmbossGreyFilter.hxx>
56#include <bitmapwriteaccess.hxx>
57
58#include <basegfx/numeric/ftools.hxx>
59#include <basegfx/matrix/b2dhommatrix.hxx>
60#include <opengl/zone.hxx>
61
62// internal headers for OpenGLTests class.
63#if HAVE_FEATURE_OPENGL1
64#include <salgdi.hxx>
65#include <salframe.hxx>
66#include <opengl/gdiimpl.hxx>
67#include <opengl/texture.hxx>
68#include <opengl/framebuffer.hxx>
69#include <vcl/opengl/OpenGLHelper.hxx>
70#endif
71
72#define FIXME_SELF_INTERSECTING_WORKING0 0
73#define FIXME_BOUNCE_BUTTON0 0
74#define THUMB_REPEAT_FACTOR10 10
75
76using namespace com::sun::star;
77
78namespace {
79 double getTimeNow()
80 {
81 TimeValue aValue;
82 osl_getSystemTime(&aValue);
83 return static_cast<double>(aValue.Seconds) * 1000 +
84 static_cast<double>(aValue.Nanosec) / (1000*1000);
85 }
86
87}
88
89namespace {
90
91enum RenderStyle {
92 RENDER_THUMB, // small view <n> to a page
93 RENDER_EXPANDED, // expanded view of this renderer
94};
95
96class DemoRenderer
97{
98 Bitmap maIntroBW;
99 BitmapEx maIntro;
100
101 int mnSegmentsX;
102 int mnSegmentsY;
103
104 struct RenderContext {
105 RenderStyle meStyle;
106 bool mbVDev;
107 DemoRenderer *mpDemoRenderer;
108 Size maSize;
109 };
110 struct RegionRenderer {
111 public:
112 RegionRenderer() :
113 sumTime(0),
114 countTime(0)
115 { }
116 virtual ~RegionRenderer() {}
117 virtual OUString getName() = 0;
118 virtual sal_uInt16 getAccelerator() = 0;
119 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
120 const RenderContext &rCtx) = 0;
121 // repeating count for profiling (to exceed the poor time resolution on Windows)
122 virtual sal_uInt16 getTestRepeatCount() = 0;
123#define RENDER_DETAILS(name,key,repeat)virtual OUString getName() override { return "name"; } virtual
sal_uInt16 getAccelerator() override { return key; } virtual
sal_uInt16 getTestRepeatCount() override { return repeat; }
\
124 virtual OUString getName() override \
125 { return SAL_STRINGIFY(name)"name"; } \
126 virtual sal_uInt16 getAccelerator() override \
127 { return key; } \
128 virtual sal_uInt16 getTestRepeatCount() override \
129 { return repeat; }
130
131 double sumTime;
132 int countTime;
133 };
134
135 std::vector< RegionRenderer * > maRenderers;
136 sal_Int32 mnSelectedRenderer;
137 sal_Int32 iterCount;
138
139 void InitRenderers();
140
141public:
142 DemoRenderer() : mnSegmentsX(0)
143 , mnSegmentsY(0)
144 , mnSelectedRenderer(-1)
145 , iterCount(0)
146#if FIXME_BOUNCE_BUTTON0
147 , mpButton(NULL__null)
148 , mpButtonWin(NULL__null)
149 , mnBounceX(1)
150 , mnBounceY(1)
151#endif
152 {
153 if (!Application::LoadBrandBitmap("intro", maIntro))
154 Application::Abort("Failed to load intro image");
155
156 maIntroBW = maIntro.GetBitmap();
157
158 BitmapEx aTmpBmpEx(maIntroBW);
159 BitmapFilter::Filter(aTmpBmpEx, BitmapEmbossGreyFilter(0, 0));
160 maIntroBW = aTmpBmpEx.GetBitmap();
161
162 InitRenderers();
163 mnSegmentsY = rtl::math::round(std::sqrt(maRenderers.size()), 0,
164 rtl_math_RoundingMode_Down);
165 mnSegmentsX = (maRenderers.size() + mnSegmentsY - 1)/mnSegmentsY;
166 }
167
168 OUString getRendererList();
169 double getAndResetBenchmark(RenderStyle style);
170 void selectRenderer(const OUString &rName);
171 int selectNextRenderer();
172 void setIterCount(sal_Int32 iterCount);
173 sal_Int32 getIterCount() const;
174 void addTime(int i, double t);
175
176 Size maSize;
177 void SetSizePixel(const Size &rSize) { maSize = rSize; }
178 const Size& GetSizePixel() const { return maSize; }
179
180
181// more of a 'Window' concept - push upwards ?
182#if FIXME_BOUNCE_BUTTON0
183 // Bouncing windows on click ...
184 PushButton *mpButton;
185 FloatingWindow *mpButtonWin;
186 AutoTimer maBounce;
187 int mnBounceX, mnBounceY;
188 DECL_LINK(BounceTimerCb, Timer*, void)static void LinkStubBounceTimerCb(void *, Timer*); void BounceTimerCb
(Timer*)
;
189#endif
190
191 bool MouseButtonDown(const MouseEvent& rMEvt);
192 void KeyInput(const KeyEvent& rKEvt);
193
194 static std::vector<tools::Rectangle> partition(const tools::Rectangle &rRect, int nX, int nY)
195 {
196 std::vector<tools::Rectangle> aRegions = partition(rRect.GetSize(), nX, nY);
197 for (auto & region : aRegions)
198 region.Move(rRect.Left(), rRect.Top());
199
200 return aRegions;
201 }
202
203 static std::vector<tools::Rectangle> partition(const RenderContext &rCtx, int nX, int nY)
204 {
205 return partition(rCtx.maSize, nX, nY);
206 }
207
208 static std::vector<tools::Rectangle> partition(Size aSize, int nX, int nY)
209 {
210 tools::Rectangle r;
211 std::vector<tools::Rectangle> aRegions;
212
213 // Make small cleared area for these guys
214 long nBorderSize = std::min(aSize.Height() / 32, aSize.Width() / 32);
215 long nBoxWidth = (aSize.Width() - nBorderSize*(nX+1)) / nX;
216 long nBoxHeight = (aSize.Height() - nBorderSize*(nY+1)) / nY;
217 for (int y = 0; y < nY; y++)
218 {
219 for (int x = 0; x < nX; x++)
220 {
221 r.SetPos(Point(nBorderSize + (nBorderSize + nBoxWidth) * x,
222 nBorderSize + (nBorderSize + nBoxHeight) * y));
223 r.SetSize(Size(nBoxWidth, nBoxHeight));
224 aRegions.push_back(r);
225 }
226 }
227
228 return aRegions;
229 }
230
231 static void clearRects(OutputDevice &rDev, std::vector<tools::Rectangle> &rRects)
232 {
233 for (size_t i = 0; i < rRects.size(); i++)
234 {
235 // knock up a nice little border
236 rDev.SetLineColor(COL_GRAY);
237 rDev.SetFillColor(COL_LIGHTGRAY);
238 if (i % 2)
239 {
240 int nBorderSize = rRects[i].GetWidth() / 5;
241 rDev.DrawRect(rRects[i], nBorderSize, nBorderSize);
242 }
243 else
244 rDev.DrawRect(rRects[i]);
245 }
246 }
247
248 static void drawBackground(OutputDevice &rDev, const tools::Rectangle& r)
249 {
250 rDev.Erase();
251 Gradient aGradient;
252 aGradient.SetStartColor(COL_BLUE);
253 aGradient.SetEndColor(COL_GREEN);
254 aGradient.SetStyle(GradientStyle::Linear);
255 rDev.DrawGradient(r, aGradient);
256 }
257
258 struct DrawLines : public RegionRenderer
259 {
260 RENDER_DETAILS(lines,KEY_L,100)virtual OUString getName() override { return "lines"; } virtual
sal_uInt16 getAccelerator() override { return KEY_L; } virtual
sal_uInt16 getTestRepeatCount() override { return 100; }
261 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
262 const RenderContext &rCtx) override
263 {
264 if (rCtx.meStyle == RENDER_EXPANDED)
265 {
266 AntialiasingFlags nOldAA = rDev.GetAntialiasing();
267 rDev.SetAntialiasing(AntialiasingFlags::Enable);
268
269 std::vector<tools::Rectangle> aRegions(DemoRenderer::partition(rCtx, 4, 4));
270 DemoRenderer::clearRects(rDev, aRegions);
271
272#if 0 // FIXME: get this through to the backend ...
273 double nTransparency[] = {
274 1.0, 1.0, 1.0, 1.0,
275 0.8, 0.8, 0.8, 0.8,
276 0.5, 0.5, 0.5, 0.5,
277 0.1, 0.1, 0.1, 0.1
278 };
279#endif
280 drawing::LineCap const eLineCaps[] = {
281 drawing::LineCap_BUTT, drawing::LineCap_ROUND, drawing::LineCap_SQUARE, drawing::LineCap_BUTT,
282 drawing::LineCap_BUTT, drawing::LineCap_ROUND, drawing::LineCap_SQUARE, drawing::LineCap_BUTT,
283 drawing::LineCap_BUTT, drawing::LineCap_ROUND, drawing::LineCap_SQUARE, drawing::LineCap_BUTT,
284 drawing::LineCap_BUTT, drawing::LineCap_ROUND, drawing::LineCap_SQUARE, drawing::LineCap_BUTT
285 };
286 basegfx::B2DLineJoin const eJoins[] = {
287 basegfx::B2DLineJoin::NONE, basegfx::B2DLineJoin::Bevel, basegfx::B2DLineJoin::Miter, basegfx::B2DLineJoin::Round,
288 basegfx::B2DLineJoin::NONE, basegfx::B2DLineJoin::Bevel, basegfx::B2DLineJoin::Miter, basegfx::B2DLineJoin::Round,
289 basegfx::B2DLineJoin::NONE, basegfx::B2DLineJoin::Bevel, basegfx::B2DLineJoin::Miter, basegfx::B2DLineJoin::Round,
290 basegfx::B2DLineJoin::NONE, basegfx::B2DLineJoin::Bevel, basegfx::B2DLineJoin::Miter, basegfx::B2DLineJoin::Round
291 };
292 double const aLineWidths[] = {
293 10.0, 15.0, 20.0, 10.0,
294 10.0, 15.0, 20.0, 10.0,
295 10.0, 15.0, 20.0, 10.0,
296 0.1, 1.0, 10.0, 50.0
297 };
298 for (size_t i = 0; i < aRegions.size(); i++)
299 {
300 // Half of them not-anti-aliased ..
301 if (i >= aRegions.size()/2)
302 rDev.SetAntialiasing(nOldAA);
303
304 static const struct {
305 double nX, nY;
306 } aPoints[] = {
307 { 0.2, 0.2 }, { 0.8, 0.3 }, { 0.7, 0.8 }
308 };
309 rDev.SetLineColor(COL_BLACK);
310 basegfx::B2DPolygon aPoly;
311 tools::Rectangle aSub(aRegions[i]);
312 for (size_t j = 0; j < SAL_N_ELEMENTS(aPoints)(sizeof(sal_n_array_size(aPoints))); j++)
313 {
314 aPoly.append(basegfx::B2DPoint(aSub.Left() + aSub.GetWidth() * aPoints[j].nX,
315 aSub.Top() + aSub.GetHeight() * aPoints[j].nY));
316 }
317 rDev.DrawPolyLine(aPoly, aLineWidths[i], eJoins[i], eLineCaps[i]);
318 }
319 }
320 else
321 {
322 rDev.SetFillColor(COL_LIGHTRED);
323 rDev.SetLineColor(COL_BLACK);
324 rDev.DrawRect(r);
325
326 for(long i=0; i<r.GetHeight(); i+=15)
327 rDev.DrawLine(Point(r.Left(), r.Top()+i), Point(r.Right(), r.Bottom()-i));
328 for(long i=0; i<r.GetWidth(); i+=15)
329 rDev.DrawLine(Point(r.Left()+i, r.Bottom()), Point(r.Right()-i, r.Top()));
330
331 // Should draw a white-line across the middle
332 Color aLastPixel(COL_WHITE);
333 Point aCenter((r.Left() + r.Right())/2 - 4,
334 (r.Top() + r.Bottom())/2 - 4);
335 for(int i=0; i<8; i++)
336 {
337 rDev.DrawPixel(aCenter, aLastPixel);
338 aLastPixel = rDev.GetPixel(aCenter);
339 aCenter.Move(1,1);
340 }
341 }
342 }
343 };
344
345 struct DrawText : public RegionRenderer
346 {
347 RENDER_DETAILS(text,KEY_T,1)virtual OUString getName() override { return "text"; } virtual
sal_uInt16 getAccelerator() override { return KEY_T; } virtual
sal_uInt16 getTestRepeatCount() override { return 1; }
348
349 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
350 const RenderContext &rCtx) override
351 {
352 if (rCtx.meStyle == RENDER_EXPANDED)
353 {
354 std::vector<tools::Rectangle> aToplevelRegions(
355 DemoRenderer::partition(rCtx, 1, 3));
356 std::vector<tools::Rectangle> aSubRegions(
357 DemoRenderer::partition(aToplevelRegions[0], 4, 2));
358 tools::Rectangle aBottom(aToplevelRegions[1].TopLeft(),
359 aToplevelRegions[2].BottomRight());
360 DemoRenderer::clearRects(rDev,aSubRegions);
361 static struct {
362 bool mbClip;
363 bool mbArabicText;
364 bool mbRotate;
365 } const aRenderData[] = {
366 { false, false, false },
367 { false, true, false },
368 { false, true, true },
369 { false, false, true },
370 { true, false, true },
371 { true, true, true },
372 { true, true, false },
373 { true, false, false },
374 };
375
376 size_t i = 0;
377 for (int y = 0; y < 2; y++)
378 {
379 for (int x = 0; x < 4; x++)
380 {
381 assert(i < SAL_N_ELEMENTS(aRenderData))(static_cast <bool> (i < (sizeof(sal_n_array_size(aRenderData
)))) ? void (0) : __assert_fail ("i < SAL_N_ELEMENTS(aRenderData)"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 381, __extension__ __PRETTY_FUNCTION__))
;
382 drawText(rDev, aSubRegions[i], aRenderData[i].mbClip,
383 aRenderData[i].mbArabicText, aRenderData[i].mbRotate);
384 i++;
385 }
386 }
387
388 drawComplex(rDev, aBottom);
389 }
390 else
391 {
392 drawText(rDev, r, false, false, false);
393 }
394 }
395
396 static void drawText (OutputDevice &rDev, tools::Rectangle r, bool bClip, bool bArabicText, bool bRotate)
397 {
398 rDev.SetClipRegion( vcl::Region(r) );
399
400 const unsigned char pTextUTF8[] = {
401 0xd9, 0x88, 0xd8, 0xa7, 0xd8, 0xad, 0xd9, 0x90,
402 0xd8, 0xaf, 0xd9, 0x92, 0x20, 0xd8, 0xa5, 0xd8,
403 0xab, 0xd9, 0x8d, 0xd9, 0x86, 0xd9, 0x8a, 0xd9,
404 0x86, 0x20, 0xd8, 0xab, 0xd9, 0x84, 0xd8, 0xa7,
405 0xd8, 0xab, 0xd8, 0xa9, 0xd9, 0x8c, 0x00
406 };
407 OUString aArabicText( reinterpret_cast<char const *>(pTextUTF8),
408 SAL_N_ELEMENTS( pTextUTF8 )(sizeof(sal_n_array_size(pTextUTF8))) - 1,
409 RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)) );
410
411 OUString aText;
412
413 // To have more text displayed one after the other (overlapping, and in different colours), then
414 // change this value
415 const int nPrintNumCopies=1;
416
417 if (bArabicText)
418 aText = aArabicText;
419 else
420 aText = "Click any rect to zoom!!!!";
421
422 std::vector<OUString> aFontNames;
423
424 static Color const nCols[] = {
425 COL_BLACK, COL_BLUE, COL_GREEN, COL_CYAN, COL_RED, COL_MAGENTA,
426 COL_BROWN, COL_GRAY, COL_LIGHTGRAY, COL_LIGHTBLUE, COL_LIGHTGREEN,
427 COL_LIGHTCYAN, COL_LIGHTRED, COL_LIGHTMAGENTA, COL_YELLOW, COL_WHITE
428 };
429
430 // a few fonts to start with
431 const char *pNames[] = {
432 "Times", "Liberation Sans", "Arial", "Linux Biolinum G", "Linux Libertine Display G"
433 };
434
435 for (size_t i = 0; i < SAL_N_ELEMENTS(pNames)(sizeof(sal_n_array_size(pNames))); i++)
436 aFontNames.push_back(OUString::createFromAscii(pNames[i]));
437
438 if (bClip && !bRotate)
439 {
440 // only show the first quarter of the text
441 tools::Rectangle aRect( r.TopLeft(), Size( r.GetWidth()/2, r.GetHeight()/2 ) );
442 rDev.SetClipRegion( vcl::Region( aRect ) );
443 }
444
445 for (int i = 1; i < nPrintNumCopies+1; i++)
446 {
447 int nFontHeight=0, nFontIndex=0, nFontColorIndex=0;
448
449 if (nPrintNumCopies == 1)
450 {
451 float const nFontMagnitude = 0.25f;
452 // random font size to avoid buffering
453 nFontHeight = 1 + nFontMagnitude * (0.9 + comphelper::rng::uniform_real_distribution(0.0, std::nextafter(0.1, DBL_MAX1.7976931348623157e+308))) * (r.Bottom() - r.Top());
454 nFontIndex=0;
455 nFontColorIndex=0;
456 }
457 else
458 {
459 // random font size to avoid buffering
460 nFontHeight = 1 + i * (0.9 + comphelper::rng::uniform_real_distribution(0.0, std::nextafter(0.1, DBL_MAX1.7976931348623157e+308))) * (r.Top() - r.Bottom()) / nPrintNumCopies;
461 nFontIndex = (i % aFontNames.size());
462 nFontColorIndex=(i % aFontNames.size());
463 }
464
465 rDev.SetTextColor(nCols[nFontColorIndex]);
466 vcl::Font aFont( aFontNames[nFontIndex], Size(0, nFontHeight ));
467
468 if (bRotate)
469 {
470 tools::Rectangle aFontRect = r;
471
472 int nHeight = r.GetHeight();
473
474 // move the text to the bottom of the bounding rect before rotating
475 aFontRect.AdjustTop(nHeight/2 );
476 aFontRect.AdjustBottom(nHeight );
477
478 aFont.SetOrientation(45 * 10); // 45 degrees
479
480 rDev.SetFont(aFont);
481 rDev.DrawText(aFontRect, aText);
482
483 if (bClip)
484 {
485 tools::Rectangle aClipRect( Point( r.Left(), r.Top() + ( r.GetHeight()/2 ) ) , Size( r.GetWidth()/2, r.GetHeight()/2 ) );
486 rDev.SetClipRegion( vcl::Region( aClipRect ) );
487 }
488 else
489 rDev.SetClipRegion( vcl::Region(r) );
490 }
491 else
492 {
493 rDev.SetFont(aFont);
494 rDev.DrawText(r, aText);
495 }
496 }
497
498 rDev.SetClipRegion();
499 }
500
501 static void drawComplex (OutputDevice &rDev, tools::Rectangle r)
502 {
503 const unsigned char pInvalid[] = { 0xfe, 0x1f, 0 };
504 const unsigned char pDiacritic1[] = { 0x61, 0xcc, 0x8a, 0xcc, 0x8c, 0 };
505 const unsigned char pDiacritic2[] = { 0x61, 0xcc, 0x88, 0xcc, 0x86, 0 };
506 const unsigned char pDiacritic3[] = { 0x61, 0xcc, 0x8b, 0xcc, 0x87, 0 };
507 const unsigned char pJustification[] = {
508 0x64, 0x20, 0xc3, 0xa1, 0xc3, 0xa9, 0x77, 0xc4, 0x8d,
509 0xc5, 0xa1, 0xc3, 0xbd, 0xc5, 0x99, 0x20, 0xc4, 0x9b, 0
510 };
511 const unsigned char pEmojis[] = {
512 0xf0, 0x9f, 0x8d, 0x80, 0xf0, 0x9f, 0x91, 0x98,
513 0xf0, 0x9f, 0x92, 0x8a, 0xf0, 0x9f, 0x92, 0x99,
514 0xf0, 0x9f, 0x92, 0xa4, 0xf0, 0x9f, 0x94, 0x90, 0
515 };
516 const unsigned char pThreeBowlG[] = {
517 0xe2, 0x9a, 0x82, 0xe2, 0x99, 0xa8, 0xc4, 0x9e, 0
518 };
519 const unsigned char pWavesAndDomino[] = {
520 0xe2, 0x99, 0x92, 0xf0, 0x9f, 0x81, 0xa0,
521 0xf0, 0x9f, 0x82, 0x93, 0
522 };
523 const unsigned char pSpadesAndBits[] = {
524 0xf0, 0x9f, 0x82, 0xa1, 0xc2, 0xa2, 0xc2, 0xa2, 0
525 };
526
527 static struct {
528 const char *mpFont;
529 const char *mpString;
530 } const aRuns[] = {
531#define SET(font,string){ font, reinterpret_cast<const char *>(string) } { font, reinterpret_cast<const char *>(string) }
532 {"sans", "a"}, // logical font - no 'sans' font.
533 {"opensymbol", "#$%"}, // font fallback - $ is missing.
534 SET("sans", pInvalid){ "sans", reinterpret_cast<const char *>(pInvalid) }, // unicode invalid character
535 // tdf#96266 - stacking diacritics
536 SET("carlito", pDiacritic1){ "carlito", reinterpret_cast<const char *>(pDiacritic1
) }
,
537 SET("carlito", pDiacritic2){ "carlito", reinterpret_cast<const char *>(pDiacritic2
) }
,
538 SET("carlito", pDiacritic3){ "carlito", reinterpret_cast<const char *>(pDiacritic3
) }
,
539 SET("liberation sans", pDiacritic1){ "liberation sans", reinterpret_cast<const char *>(pDiacritic1
) }
,
540 SET("liberation sans", pDiacritic2){ "liberation sans", reinterpret_cast<const char *>(pDiacritic2
) }
,
541 SET("liberation sans", pDiacritic3){ "liberation sans", reinterpret_cast<const char *>(pDiacritic3
) }
,
542 SET("liberation sans", pDiacritic3){ "liberation sans", reinterpret_cast<const char *>(pDiacritic3
) }
,
543
544 // tdf#95222 - justification issue
545 // - FIXME: replicate justification
546 SET("gentium basic", pJustification){ "gentium basic", reinterpret_cast<const char *>(pJustification
) }
,
547
548 // tdf#97319 - Unicode beyond BMP; SMP & Plane 2
549 SET("symbola", pEmojis){ "symbola", reinterpret_cast<const char *>(pEmojis) },
550 SET("symbola", pThreeBowlG){ "symbola", reinterpret_cast<const char *>(pThreeBowlG
) }
,
551 SET("symbola", pWavesAndDomino){ "symbola", reinterpret_cast<const char *>(pWavesAndDomino
) }
,
552 SET("symbola", pSpadesAndBits){ "symbola", reinterpret_cast<const char *>(pSpadesAndBits
) }
,
553 };
554
555 // Nice clean white background
556 rDev.DrawWallpaper(r, Wallpaper(COL_WHITE));
557 rDev.SetClipRegion(vcl::Region(r));
558
559 Point aPos(r.Left(), r.Top()+20);
560
561 long nMaxTextHeight = 0;
562 for (size_t i = 0; i < SAL_N_ELEMENTS(aRuns)(sizeof(sal_n_array_size(aRuns))); ++i)
1
Loop condition is true. Entering loop body
563 {
564 // Legend
565 vcl::Font aIndexFont("sans", Size(0,20));
566 aIndexFont.SetColor( COL_BLACK);
567 tools::Rectangle aTextRect;
568 rDev.SetFont(aIndexFont);
569 OUString aText = OUString::number(i) + ".";
570 rDev.DrawText(aPos, aText);
571 if (rDev.GetTextBoundRect(aTextRect, aText))
2
Assuming the condition is false
3
Taking false branch
572 aPos.Move(aTextRect.GetWidth() + 8, 0);
573
574 // Text
575 FontWeight aWeights[] = { WEIGHT_NORMAL,
576 WEIGHT_BOLD,
577 WEIGHT_NORMAL };
578 FontItalic const aItalics[] = { ITALIC_NONE,
579 ITALIC_NONE,
580 ITALIC_NORMAL };
581 vcl::Font aFont(OUString::createFromAscii(
582 aRuns[i].mpFont),
583 Size(0,42));
584 aFont.SetColor(COL_BLACK);
585 for (size_t j = 0; j < SAL_N_ELEMENTS(aWeights)(sizeof(sal_n_array_size(aWeights))); ++j)
4
Loop condition is true. Entering loop body
586 {
587 aFont.SetItalic(aItalics[j]);
588 aFont.SetWeight(aWeights[j]);
589 rDev.SetFont(aFont);
590
591 OUString aString(aRuns[i].mpString,
592 strlen(aRuns[i].mpString),
593 RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)));
594 long nNewX = drawStringBox(rDev, aPos, aString,
595 nMaxTextHeight);
596
597 aPos.setX( nNewX );
598
599 if (aPos.X() >= r.Right())
5
Assuming the condition is false
6
Taking false branch
600 {
601 aPos = Point(r.Left(), aPos.Y() + nMaxTextHeight + 15);
602 nMaxTextHeight = 0;
603 if(j>0)
604 j--; // re-render the last point.
605 }
606 if (aPos.Y() > r.Bottom())
7
Assuming the condition is true
8
Taking true branch
607 break;
9
Execution continues on line 609
608 }
609 if (aPos.Y() > r.Bottom())
10
Assuming the condition is true
11
Taking true branch
610 break;
12
Execution continues on line 613
611 }
612
613 rDev.SetClipRegion();
614 }
13
Address of stack memory associated with local variable 'pJustification' is still referred to by the static variable 'aRuns' upon returning to the caller. This will be a dangling reference
615 // render text, bbox, DX arrays etc.
616 static long drawStringBox(OutputDevice &rDev, Point aPos,
617 const OUString &aText,
618 long &nMaxTextHeight)
619 {
620 rDev.Push();
621 {
622 tools::Rectangle aTextRect;
623
624 rDev.DrawText(aPos,aText);
625
626 if (rDev.GetTextBoundRect(aTextRect, aText))
627 {
628 aTextRect.Move(aPos.X(), aPos.Y());
629 rDev.SetFillColor();
630 rDev.SetLineColor(COL_BLACK);
631 rDev.DrawRect(aTextRect);
632 if (aTextRect.GetHeight() > nMaxTextHeight)
633 nMaxTextHeight = aTextRect.GetHeight();
634 // This should intersect with the text
635 tools::Rectangle aInnerRect(
636 aTextRect.Left()+1, aTextRect.Top()+1,
637 aTextRect.Right()-1, aTextRect.Bottom()-1);
638 rDev.SetLineColor(COL_WHITE);
639 rDev.SetRasterOp(RasterOp::Xor);
640 rDev.DrawRect(aInnerRect);
641 rDev.SetRasterOp(RasterOp::OverPaint);
642 }
643
644 // DX array rendering
645 std::unique_ptr<long[]> pItems(new long[aText.getLength()+10]);
646 rDev.GetTextArray(aText, pItems.get());
647 for (long j = 0; j < aText.getLength(); ++j)
648 {
649 Point aTop = aTextRect.TopLeft();
650 Point aBottom = aTop;
651 aTop.Move(pItems[j], 0);
652 aBottom.Move(pItems[j], aTextRect.GetHeight());
653 rDev.SetLineColor(COL_RED);
654 rDev.SetRasterOp(RasterOp::Xor);
655 rDev.DrawLine(aTop,aBottom);
656 rDev.SetRasterOp(RasterOp::OverPaint);
657 }
658
659 aPos.Move(aTextRect.GetWidth() + 16, 0);
660 }
661 rDev.Pop();
662 return aPos.X();
663 }
664 };
665
666 struct DrawCheckered : public RegionRenderer
667 {
668 RENDER_DETAILS(checks,KEY_C,20)virtual OUString getName() override { return "checks"; } virtual
sal_uInt16 getAccelerator() override { return KEY_C; } virtual
sal_uInt16 getTestRepeatCount() override { return 20; }
669 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
670 const RenderContext &rCtx) override
671 {
672 if (rCtx.meStyle == RENDER_EXPANDED)
673 {
674 std::vector<tools::Rectangle> aRegions(DemoRenderer::partition(rCtx, 2, 2));
675 for (size_t i = 0; i < aRegions.size(); i++)
676 {
677 vcl::Region aRegion;
678 tools::Rectangle aSub(aRegions[i]);
679 tools::Rectangle aSmaller(aSub);
680 aSmaller.Move(10,10);
681 aSmaller.setWidth(aSmaller.getWidth()-20);
682 aSmaller.setHeight(aSmaller.getHeight()-24);
683 switch (i) {
684 case 0:
685 aRegion = vcl::Region(aSub);
686 break;
687 case 1:
688 aRegion = vcl::Region(aSmaller);
689 aRegion.XOr(aSub);
690 break;
691 case 2:
692 {
693 tools::Polygon aPoly(aSub);
694 aPoly.Rotate(aSub.Center(), 450);
695 aPoly.Clip(aSmaller);
696 aRegion = vcl::Region(aPoly);
697 break;
698 }
699 case 3:
700 {
701 tools::PolyPolygon aPolyPoly;
702 sal_Int32 nTW = aSub.GetWidth()/6;
703 sal_Int32 nTH = aSub.GetHeight()/6;
704 tools::Rectangle aTiny(Point(4, 4), Size(nTW*2, nTH*2));
705 aPolyPoly.Insert( tools::Polygon(aTiny));
706 aTiny.Move(nTW*3, nTH*3);
707 aPolyPoly.Insert( tools::Polygon(aTiny));
708 aTiny.Move(nTW, nTH);
709 aPolyPoly.Insert( tools::Polygon(aTiny));
710
711 aRegion = vcl::Region(aPolyPoly);
712 break;
713 }
714 } // switch
715 rDev.SetClipRegion(aRegion);
716 rDev.DrawCheckered(aSub.TopLeft(), aSub.GetSize());
717 rDev.SetClipRegion();
718 }
719 }
720 else
721 {
722 rDev.DrawCheckered(r.TopLeft(), r.GetSize());
723 }
724 }
725 };
726
727 struct DrawPoly : public RegionRenderer
728 {
729 RENDER_DETAILS(poly,KEY_P,20)virtual OUString getName() override { return "poly"; } virtual
sal_uInt16 getAccelerator() override { return KEY_P; } virtual
sal_uInt16 getTestRepeatCount() override { return 20; }
730 DrawCheckered maCheckered;
731 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
732 const RenderContext &rCtx) override
733 {
734 maCheckered.RenderRegion(rDev, r, rCtx);
735
736 long nDx = r.GetWidth()/20;
737 long nDy = r.GetHeight()/20;
738 tools::Rectangle aShrunk(r);
739 aShrunk.Move(nDx, nDy);
740 aShrunk.SetSize(Size(r.GetWidth()-nDx*2,
741 r.GetHeight()-nDy*2));
742 tools::Polygon aPoly(aShrunk);
743 tools::PolyPolygon aPPoly(aPoly);
744 rDev.SetLineColor(COL_RED);
745 rDev.SetFillColor(COL_RED);
746 // This hits the optional 'drawPolyPolygon' code-path
747 rDev.DrawTransparent(aPPoly, 64);
748 }
749 };
750
751 struct DrawEllipse : public RegionRenderer
752 {
753 RENDER_DETAILS(ellipse,KEY_E,500)virtual OUString getName() override { return "ellipse"; } virtual
sal_uInt16 getAccelerator() override { return KEY_E; } virtual
sal_uInt16 getTestRepeatCount() override { return 500; }
754 static void doInvert(OutputDevice &rDev, const tools::Rectangle &r,
755 InvertFlags nFlags)
756 {
757 rDev.Invert(r, nFlags);
758 if (r.GetWidth() > 10 && r.GetHeight() > 10)
759 {
760 tools::Rectangle aSmall(r.Center()-Point(4,4), Size(8,8));
761 rDev.Invert(aSmall,nFlags);
762 }
763 }
764 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
765 const RenderContext &rCtx) override
766 {
767 rDev.SetLineColor(COL_RED);
768 rDev.SetFillColor(COL_GREEN);
769 rDev.DrawEllipse(r);
770
771 if (rCtx.meStyle == RENDER_EXPANDED)
772 {
773 auto aRegions = partition(rCtx, 2, 2);
774 doInvert(rDev, aRegions[0], InvertFlags::NONE);
775 rDev.DrawText(aRegions[0], "InvertFlags::NONE");
776 doInvert(rDev, aRegions[1], InvertFlags::N50);
777 rDev.DrawText(aRegions[1], "InvertFlags::N50");
778 doInvert(rDev, aRegions[3], InvertFlags::TrackFrame);
779 rDev.DrawText(aRegions[3], "InvertFlags::TrackFrame");
780 }
781 }
782 };
783
784 struct DrawGradient : public RegionRenderer
785 {
786 RENDER_DETAILS(gradient,KEY_G,50)virtual OUString getName() override { return "gradient"; } virtual
sal_uInt16 getAccelerator() override { return KEY_G; } virtual
sal_uInt16 getTestRepeatCount() override { return 50; }
787 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
788 const RenderContext &rCtx) override
789 {
790 if (rCtx.meStyle == RENDER_EXPANDED)
791 {
792 std::vector<tools::Rectangle> aRegions(DemoRenderer::partition(rCtx,5, 4));
793 static Color const nStartCols[] = {
794 COL_RED, COL_RED, COL_RED, COL_GREEN, COL_GREEN,
795 COL_BLUE, COL_BLUE, COL_BLUE, COL_CYAN, COL_CYAN,
796 COL_BLACK, COL_LIGHTGRAY, COL_WHITE, COL_BLUE, COL_CYAN,
797 COL_WHITE, COL_WHITE, COL_WHITE, COL_BLACK, COL_BLACK
798 };
799 static Color const nEndCols[] = {
800 COL_WHITE, COL_WHITE, COL_WHITE, COL_BLACK, COL_BLACK,
801 COL_RED, COL_RED, COL_RED, COL_GREEN, COL_GREEN,
802 COL_GRAY, COL_GRAY, COL_LIGHTGRAY, COL_LIGHTBLUE, COL_LIGHTCYAN,
803 COL_BLUE, COL_BLUE, COL_BLUE, COL_CYAN, COL_CYAN
804 };
805 GradientStyle eStyles[] = {
806 GradientStyle::Linear, GradientStyle::Axial, GradientStyle::Radial, GradientStyle::Elliptical, GradientStyle::Square,
807 GradientStyle::Rect, GradientStyle::FORCE_EQUAL_SIZE, GradientStyle::Linear, GradientStyle::Radial, GradientStyle::Linear,
808 GradientStyle::Linear, GradientStyle::Axial, GradientStyle::Radial, GradientStyle::Elliptical, GradientStyle::Square,
809 GradientStyle::Rect, GradientStyle::FORCE_EQUAL_SIZE, GradientStyle::Linear, GradientStyle::Radial, GradientStyle::Linear
810 };
811 sal_uInt16 nAngles[] = {
812 0, 0, 0, 0, 0,
813 15, 30, 45, 60, 75,
814 90, 120, 135, 160, 180,
815 0, 0, 0, 0, 0
816 };
817 sal_uInt16 nBorders[] = {
818 0, 0, 0, 0, 0,
819 1, 10, 100, 10, 1,
820 0, 0, 0, 0, 0,
821 1, 10, 20, 10, 1,
822 0, 0, 0, 0, 0
823 };
824 DemoRenderer::clearRects(rDev, aRegions);
825 assert(aRegions.size() <= SAL_N_ELEMENTS(nStartCols))(static_cast <bool> (aRegions.size() <= (sizeof(sal_n_array_size
(nStartCols)))) ? void (0) : __assert_fail ("aRegions.size() <= SAL_N_ELEMENTS(nStartCols)"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 825, __extension__ __PRETTY_FUNCTION__))
;
826 assert(aRegions.size() <= SAL_N_ELEMENTS(nEndCols))(static_cast <bool> (aRegions.size() <= (sizeof(sal_n_array_size
(nEndCols)))) ? void (0) : __assert_fail ("aRegions.size() <= SAL_N_ELEMENTS(nEndCols)"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 826, __extension__ __PRETTY_FUNCTION__))
;
827 assert(aRegions.size() <= SAL_N_ELEMENTS(eStyles))(static_cast <bool> (aRegions.size() <= (sizeof(sal_n_array_size
(eStyles)))) ? void (0) : __assert_fail ("aRegions.size() <= SAL_N_ELEMENTS(eStyles)"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 827, __extension__ __PRETTY_FUNCTION__))
;
828 assert(aRegions.size() <= SAL_N_ELEMENTS(nAngles))(static_cast <bool> (aRegions.size() <= (sizeof(sal_n_array_size
(nAngles)))) ? void (0) : __assert_fail ("aRegions.size() <= SAL_N_ELEMENTS(nAngles)"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 828, __extension__ __PRETTY_FUNCTION__))
;
829 assert(aRegions.size() <= SAL_N_ELEMENTS(nBorders))(static_cast <bool> (aRegions.size() <= (sizeof(sal_n_array_size
(nBorders)))) ? void (0) : __assert_fail ("aRegions.size() <= SAL_N_ELEMENTS(nBorders)"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 829, __extension__ __PRETTY_FUNCTION__))
;
830 for (size_t i = 0; i < aRegions.size(); i++)
831 {
832 tools::Rectangle aSub = aRegions[i];
833 Gradient aGradient;
834 aGradient.SetStartColor(nStartCols[i]);
835 aGradient.SetEndColor(nEndCols[i]);
836 aGradient.SetStyle(eStyles[i]);
837 aGradient.SetAngle(nAngles[i]);
838 aGradient.SetBorder(nBorders[i]);
839 rDev.DrawGradient(aSub, aGradient);
840 }
841 }
842 else
843 {
844 Gradient aGradient;
845 aGradient.SetStartColor(COL_YELLOW);
846 aGradient.SetEndColor(COL_RED);
847 aGradient.SetStyle(GradientStyle::Rect);
848 aGradient.SetBorder(r.GetSize().Width()/20);
849 rDev.DrawGradient(r, aGradient);
850 }
851 }
852 };
853
854 struct DrawBitmap : public RegionRenderer
855 {
856 RENDER_DETAILS(bitmap,KEY_B,10)virtual OUString getName() override { return "bitmap"; } virtual
sal_uInt16 getAccelerator() override { return KEY_B; } virtual
sal_uInt16 getTestRepeatCount() override { return 10; }
857
858 // Simulate Page Borders rendering - which ultimately should
859 // be done with a shader / gradient
860 static void SimulateBorderStretch(OutputDevice &rDev, const tools::Rectangle& r)
861 {
862 BitmapEx aPageShadowMask("sw/res/page-shadow-mask.png");
863
864 BitmapEx aRight(aPageShadowMask);
865 sal_Int32 nSlice = (aPageShadowMask.GetSizePixel().Width() - 3) / 4;
866 // a width x 1 slice
867 aRight.Crop(tools::Rectangle(Point((nSlice * 3) + 3, (nSlice * 2) + 1),
868 Size(nSlice, 1)));
869 AlphaMask aAlphaMask(aRight.GetBitmap());
870 Bitmap aBlockColor(aAlphaMask.GetSizePixel(), 24);
871 aBlockColor.Erase(COL_RED);
872 BitmapEx aShadowStretch(aBlockColor, aAlphaMask);
873
874 Point aRenderPt(r.TopLeft());
875
876 long aSizes[] = { 200, 100, 200, 100, 50, 5, 2 };
877
878 // and yes - we really do this in the page border rendering code ...
879 for (size_t i = 0; i < SAL_N_ELEMENTS(aSizes)(sizeof(sal_n_array_size(aSizes))); i++)
880 {
881 aShadowStretch.Scale(Size(aShadowStretch.GetSizePixel().Width(), aSizes[i]),
882 BmpScaleFlag::Fast);
883
884 rDev.DrawBitmapEx(aRenderPt, aShadowStretch);
885 aRenderPt.Move(aShadowStretch.GetSizePixel().Width() + 4, 0);
886 }
887
888 AlphaMask aWholeMask(aPageShadowMask.GetBitmap());
889 aBlockColor = Bitmap(aPageShadowMask.GetSizePixel(), 24);
890 aBlockColor.Erase(COL_GREEN);
891 BitmapEx aWhole(aBlockColor, aWholeMask);
892
893 aRenderPt = r.Center();
894 aRenderPt.Move(nSlice+1, 0);
895
896 // An offset background for alpha rendering
897 rDev.SetFillColor(COL_BLUE);
898 tools::Rectangle aSurround(r.Center(), aPageShadowMask.GetSizePixel());
899 rDev.DrawRect(aSurround);
900 rDev.DrawBitmapEx(aRenderPt, aWhole);
901 }
902
903 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
904 const RenderContext &rCtx) override
905 {
906 Bitmap aBitmap(rCtx.mpDemoRenderer->maIntroBW);
907 aBitmap.Scale(r.GetSize(), BmpScaleFlag::BestQuality);
908 rDev.DrawBitmap(r.TopLeft(), aBitmap);
909
910 SimulateBorderStretch(rDev, r);
911 }
912 };
913
914 struct DrawBitmapEx : public RegionRenderer
915 {
916 RENDER_DETAILS(bitmapex,KEY_X,2)virtual OUString getName() override { return "bitmapex"; } virtual
sal_uInt16 getAccelerator() override { return KEY_X; } virtual
sal_uInt16 getTestRepeatCount() override { return 2; }
917 DrawCheckered maCheckered;
918 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
919 const RenderContext &rCtx) override
920 {
921 maCheckered.RenderRegion(rDev, r, rCtx);
922
923 BitmapEx aBitmap(rCtx.mpDemoRenderer->maIntro);
924 aBitmap.Scale(r.GetSize(), BmpScaleFlag::BestQuality);
925 AlphaMask aSemiTransp(aBitmap.GetSizePixel());
926 aSemiTransp.Erase(64);
927 rDev.DrawBitmapEx(r.TopLeft(), BitmapEx(aBitmap.GetBitmap(),
928 aSemiTransp));
929 }
930 };
931
932 struct DrawPolyPolygons : public RegionRenderer
933 {
934 RENDER_DETAILS(polypoly,KEY_N,100)virtual OUString getName() override { return "polypoly"; } virtual
sal_uInt16 getAccelerator() override { return KEY_N; } virtual
sal_uInt16 getTestRepeatCount() override { return 100; }
935 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
936 const RenderContext &) override
937 {
938 static struct {
939 double nX, nY;
940 } const aPoints[] = { { 0.1, 0.1 }, { 0.9, 0.9 },
941#if FIXME_SELF_INTERSECTING_WORKING0
942 { 0.9, 0.1 }, { 0.1, 0.9 },
943 { 0.1, 0.1 }
944#else
945 { 0.1, 0.9 }, { 0.5, 0.5 },
946 { 0.9, 0.1 }, { 0.1, 0.1 }
947#endif
948 };
949
950 tools::PolyPolygon aPolyPoly;
951 // Render 4x polygons & aggregate into another PolyPolygon
952 for (int x = 0; x < 2; x++)
953 {
954 for (int y = 0; y < 2; y++)
955 {
956 tools::Rectangle aSubRect(r);
957 aSubRect.Move(x * r.GetWidth()/3, y * r.GetHeight()/3);
958 aSubRect.SetSize(Size(r.GetWidth()/2, r.GetHeight()/4));
959 tools::Polygon aPoly(SAL_N_ELEMENTS(aPoints)(sizeof(sal_n_array_size(aPoints))));
960 for (size_t v = 0; v < SAL_N_ELEMENTS(aPoints)(sizeof(sal_n_array_size(aPoints))); v++)
961 {
962 aPoly.SetPoint(Point(aSubRect.Left() +
963 aSubRect.GetWidth() * aPoints[v].nX,
964 aSubRect.Top() +
965 aSubRect.GetHeight() * aPoints[v].nY),
966 v);
967 }
968 rDev.SetLineColor(COL_YELLOW);
969 rDev.SetFillColor(COL_BLACK);
970 rDev.DrawPolygon(aPoly);
971
972 // now move and add to the polypolygon
973 aPoly.Move(0, r.GetHeight()/2);
974 aPolyPoly.Insert(aPoly);
975 }
976 }
977 rDev.SetLineColor(COL_LIGHTRED);
978 rDev.SetFillColor(COL_GREEN);
979 rDev.DrawTransparent(aPolyPoly, 50);
980 }
981 };
982
983 struct DrawClipped : public RegionRenderer
984 {
985 RENDER_DETAILS(clip,KEY_D,10)virtual OUString getName() override { return "clip"; } virtual
sal_uInt16 getAccelerator() override { return KEY_D; } virtual
sal_uInt16 getTestRepeatCount() override { return 10; }
986 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
987 const RenderContext &) override
988 {
989 std::vector<tools::Rectangle> aRegions(DemoRenderer::partition(r, 2, 2));
990 const int nLimits[] = { 4, -100 };
991 for (int i = 0; i < 2; ++i)
992 {
993 sal_uInt16 nHue = 0;
994 rDev.Push(PushFlags::CLIPREGION);
995 tools::Rectangle aOuter = aRegions[i];
996 tools::Rectangle aInner = aOuter;
997 while (aInner.GetWidth() > nLimits[i] && aInner.GetHeight() > nLimits[i])
998 {
999 aInner.expand(-1);
1000 rDev.SetClipRegion(vcl::Region(aInner));
1001 rDev.SetFillColor(Color::HSBtoRGB(nHue, 75, 100));
1002 nHue = (nHue + 97) % 360;
1003 rDev.DrawRect(aOuter);
1004 }
1005 rDev.Pop();
1006 }
1007
1008 {
1009 sal_uInt16 nHue = 0;
1010 tools::Rectangle aOuter = aRegions[2];
1011 std::vector<tools::Rectangle> aPieces(DemoRenderer::partition(aOuter, 2, 2));
1012 for (int j = 0; j < std::min(aOuter.GetWidth(), aOuter.GetHeight())/5; ++j)
1013 {
1014 rDev.Push(PushFlags::CLIPREGION);
1015
1016 vcl::Region aClipRegion;
1017 for (int i = 0; i < 4; ++i)
1018 {
1019 aPieces[i].expand(-1);
1020 aPieces[i].Move(2 - i/2, 2 - i/2);
1021 aClipRegion.Union(aPieces[i]);
1022 }
1023 assert (aClipRegion.getRegionBand())(static_cast <bool> (aClipRegion.getRegionBand()) ? void
(0) : __assert_fail ("aClipRegion.getRegionBand()", "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 1023, __extension__ __PRETTY_FUNCTION__))
;
1024 rDev.SetClipRegion(aClipRegion);
1025 rDev.SetFillColor(Color::HSBtoRGB(nHue, 75, 75));
1026 nHue = (nHue + 97) % 360;
1027 rDev.DrawRect(aOuter);
1028
1029 rDev.Pop();
1030 }
1031 }
1032
1033 {
1034 sal_uInt16 nHue = 0;
1035 tools::Rectangle aOuter = aRegions[3];
1036 std::vector<tools::Rectangle> aPieces(DemoRenderer::partition(aOuter, 2, 2));
1037 bool bDone = false;
1038 for (int j = 0; !bDone; ++j)
1039 {
1040 rDev.Push(PushFlags::CLIPREGION);
1041
1042 for (int i = 0; i < 4; ++i)
1043 {
1044 vcl::Region aClipRegion;
1045 tools::Polygon aPoly;
1046 switch (i) {
1047 case 3:
1048 case 0: // 45degree rectangle.
1049 aPoly = tools::Polygon(aPieces[i]);
1050 aPoly.Rotate(aPieces[i].Center(), 450);
1051 break;
1052 case 1: // arc
1053 aPoly = tools::Polygon(aPieces[i],
1054 aPieces[i].TopLeft(),
1055 aPieces[i].BottomRight());
1056 break;
1057 case 2:
1058 aPoly = tools::Polygon(aPieces[i],
1059 aPieces[i].GetWidth()/5,
1060 aPieces[i].GetHeight()/5);
1061 aPoly.Rotate(aPieces[i].Center(), 450);
1062 break;
1063 }
1064 aClipRegion = vcl::Region(aPoly);
1065 aPieces[i].expand(-1);
1066 aPieces[i].Move(2 - i/2, 2 - i/2);
1067
1068 bDone = aPieces[i].GetWidth() < 4 ||
1069 aPieces[i].GetHeight() < 4;
1070
1071 if (!bDone)
1072 {
1073 assert (!aClipRegion.getRegionBand())(static_cast <bool> (!aClipRegion.getRegionBand()) ? void
(0) : __assert_fail ("!aClipRegion.getRegionBand()", "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 1073, __extension__ __PRETTY_FUNCTION__))
;
1074
1075 rDev.SetClipRegion(aClipRegion);
1076 rDev.SetFillColor(Color::HSBtoRGB(nHue, 50, 75));
1077 nHue = (nHue + 97) % 360;
1078 rDev.DrawRect(aOuter);
1079 }
1080 }
1081
1082 rDev.Pop();
1083 }
1084 }
1085 }
1086 };
1087
1088 struct DrawToVirtualDevice : public RegionRenderer
1089 {
1090 RENDER_DETAILS(vdev,KEY_V,1)virtual OUString getName() override { return "vdev"; } virtual
sal_uInt16 getAccelerator() override { return KEY_V; } virtual
sal_uInt16 getTestRepeatCount() override { return 1; }
1091 enum RenderType {
1092 RENDER_AS_BITMAP,
1093 RENDER_AS_OUTDEV,
1094 RENDER_AS_BITMAPEX,
1095 RENDER_AS_ALPHA_OUTDEV
1096 };
1097
1098 static void SizeAndRender(OutputDevice &rDev, const tools::Rectangle& r, RenderType eType,
1099 const RenderContext &rCtx)
1100 {
1101 ScopedVclPtr<VirtualDevice> pNested;
1102
1103 if (static_cast<int>(eType) < RENDER_AS_BITMAPEX)
1104 pNested = VclPtr<VirtualDevice>::Create(rDev).get();
1105 else
1106 pNested = VclPtr<VirtualDevice>::Create(rDev,DeviceFormat::DEFAULT,DeviceFormat::DEFAULT).get();
1107
1108 pNested->SetOutputSizePixel(r.GetSize());
1109 tools::Rectangle aWhole(Point(0,0), r.GetSize());
1110
1111 // mini me
1112 rCtx.mpDemoRenderer->drawToDevice(*pNested, r.GetSize(), true);
1113
1114 if (eType == RENDER_AS_BITMAP)
1115 {
1116 Bitmap aBitmap(pNested->GetBitmap(Point(0,0),aWhole.GetSize()));
1117 rDev.DrawBitmap(r.TopLeft(), aBitmap);
1118 }
1119 else if (eType == RENDER_AS_BITMAPEX)
1120 {
1121 BitmapEx aBitmapEx(pNested->GetBitmapEx(Point(0,0),aWhole.GetSize()));
1122 rDev.DrawBitmapEx(r.TopLeft(), aBitmapEx);
1123 }
1124 else if (eType == RENDER_AS_OUTDEV ||
1125 eType == RENDER_AS_ALPHA_OUTDEV)
1126 {
1127 rDev.DrawOutDev(r.TopLeft(), r.GetSize(),
1128 aWhole.TopLeft(), aWhole.GetSize(),
1129 *pNested);
1130 }
1131 }
1132 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
1133 const RenderContext &rCtx) override
1134 {
1135 // avoid infinite recursion
1136 if (rCtx.mbVDev)
1137 return;
1138
1139 if (rCtx.meStyle == RENDER_EXPANDED)
1140 {
1141 std::vector<tools::Rectangle> aRegions(DemoRenderer::partition(rCtx,2, 2));
1142 DemoRenderer::clearRects(rDev, aRegions);
1143
1144 RenderType const eRenderTypes[] { RENDER_AS_BITMAP, RENDER_AS_OUTDEV,
1145 RENDER_AS_BITMAPEX, RENDER_AS_ALPHA_OUTDEV };
1146 for (size_t i = 0; i < aRegions.size(); i++)
1147 SizeAndRender(rDev, aRegions[i], eRenderTypes[i], rCtx);
1148 }
1149 else
1150 SizeAndRender(rDev, r, RENDER_AS_BITMAP, rCtx);
1151 }
1152 };
1153
1154 struct DrawXOR : public RegionRenderer
1155 {
1156 RENDER_DETAILS(xor,KEY_X,1)virtual OUString getName() override { return "xor"; } virtual
sal_uInt16 getAccelerator() override { return KEY_X; } virtual
sal_uInt16 getTestRepeatCount() override { return 1; }
1157
1158 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
1159 const RenderContext &rCtx) override
1160 {
1161 // avoid infinite recursion
1162 if (rCtx.mbVDev)
1163 return;
1164
1165 rDev.Push();
1166
1167 AntialiasingFlags nFlags = rDev.GetAntialiasing();
1168 rDev.SetAntialiasing(nFlags & ~AntialiasingFlags::Enable);
1169 rDev.SetRasterOp( RasterOp::Xor );
1170
1171 rCtx.mpDemoRenderer->drawThumbs(rDev, r, true);
1172
1173 rDev.Pop();
1174 }
1175 };
1176
1177 struct DrawIcons : public RegionRenderer
1178 {
1179 RENDER_DETAILS(icons,KEY_I,1)virtual OUString getName() override { return "icons"; } virtual
sal_uInt16 getAccelerator() override { return KEY_I; } virtual
sal_uInt16 getTestRepeatCount() override { return 1; }
1180
1181 std::vector<OUString> maIconNames;
1182 std::vector<BitmapEx> maIcons;
1183 bool bHasLoadedAll;
1184 DrawIcons() : bHasLoadedAll(false)
1185 {
1186 // a few icons to start with
1187 const char *pNames[] = {
1188 "cmd/lc_openurl.png",
1189 "cmd/lc_newdoc.png",
1190 "cmd/lc_choosemacro.png",
1191 "cmd/lc_save.png",
1192 "cmd/lc_saveas.png",
1193 "cmd/lc_importdialog.png",
1194 "cmd/lc_sendmail.png",
1195 "cmd/lc_editdoc.png",
1196 "cmd/lc_print.png",
1197 "cmd/lc_combobox.png",
1198 "cmd/lc_insertformcombo.png",
1199 "cmd/lc_printpreview.png",
1200 "cmd/lc_cut.png",
1201 "cmd/lc_copy.png",
1202 "cmd/lc_paste.png",
1203 "cmd/sc_autopilotmenu.png",
1204 "cmd/lc_formatpaintbrush.png",
1205 "cmd/lc_undo.png",
1206 "cmd/lc_redo.png",
1207 "cmd/lc_marks.png",
1208 "cmd/lc_fieldnames.png",
1209 "cmd/lc_hyperlinkdialog.png",
1210 "cmd/lc_basicshapes.rectangle.png",
1211 "cmd/lc_basicshapes.round-rectangle.png"
1212 };
1213 for (size_t i = 0; i < SAL_N_ELEMENTS(pNames)(sizeof(sal_n_array_size(pNames))); i++)
1214 {
1215 maIconNames.push_back(OUString::createFromAscii(pNames[i]));
1216 maIcons.emplace_back(maIconNames[i]);
1217 }
1218 }
1219
1220 void LoadAllImages()
1221 {
1222 if (bHasLoadedAll)
1223 return;
1224 bHasLoadedAll = true;
1225
1226 css::uno::Reference<css::container::XNameAccess> xRef(ImageTree::get().getNameAccess());
1227 const css::uno::Sequence< OUString > aAllIcons = xRef->getElementNames();
1228
1229 for (const auto& rIcon : aAllIcons)
1230 {
1231 if (rIcon.endsWithIgnoreAsciiCase("svg"))
1232 continue; // too slow to load.
1233 maIconNames.push_back(rIcon);
1234 maIcons.emplace_back(rIcon);
1235 }
1236 }
1237
1238 void doDrawIcons(OutputDevice &rDev, tools::Rectangle r, bool bExpanded)
1239 {
1240 long nMaxH = 0;
1241 Point p(r.LeftCenter());
1242 size_t nToRender = maIcons.size();
1243
1244 if (!bExpanded && maIcons.size() > 64)
1245 nToRender = 64;
1246 for (size_t i = 0; i < nToRender; i++)
1247 {
1248 Size aSize(maIcons[i].GetSizePixel());
1249// sAL_DEBUG("Draw icon '" << maIconNames[i] << "'");
1250
1251 if (!(i % 4))
1252 rDev.DrawBitmapEx(p, maIcons[i]);
1253 else
1254 {
1255 basegfx::B2DHomMatrix aTransform;
1256 aTransform.scale(aSize.Width(), aSize.Height());
1257 switch (i % 4)
1258 {
1259 case 2:
1260 aTransform.shearX(static_cast<double>((i >> 2) % 8) / 8);
1261 aTransform.shearY(static_cast<double>((i >> 4) % 8) / 8);
1262 break;
1263 case 3:
1264 aTransform.translate(-aSize.Width()/2, -aSize.Height()/2);
1265 aTransform.rotate(i);
1266 if (i & 0x100)
1267 {
1268 aTransform.shearX(static_cast<double>((i >> 2) % 8) / 8);
1269 aTransform.shearY(static_cast<double>((i >> 4) % 8) / 8);
1270 }
1271 aTransform.translate(aSize.Width()/2, aSize.Height()/2);
1272 break;
1273 default:
1274 aTransform.translate(-aSize.Width()/2, -aSize.Height()/2);
1275 aTransform.rotate(2 * F_2PI(2.0*3.14159265358979323846) * i / nToRender);
1276 aTransform.translate(aSize.Width()/2, aSize.Height()/2);
1277 break;
1278 }
1279 aTransform.translate(p.X(), p.Y());
1280 rDev.DrawTransformedBitmapEx(aTransform, maIcons[i]);
1281 }
1282
1283 // next position
1284 p.Move(aSize.Width(), 0);
1285 if (aSize.Height() > nMaxH)
1286 nMaxH = aSize.Height();
1287 if (p.X() >= r.Right()) // wrap to next line
1288 {
1289 p = Point(r.Left(), p.Y() + nMaxH);
1290 nMaxH = 0;
1291 }
1292 if (p.Y() >= r.Bottom()) // re-start at middle
1293 p = r.LeftCenter();
1294 }
1295 }
1296
1297 static BitmapEx AlphaRecovery(OutputDevice &rDev, Point aPt, BitmapEx const &aSrc)
1298 {
1299 // Compositing onto 2x colors beyond our control
1300 ScopedVclPtrInstance< VirtualDevice > aWhite;
1301 ScopedVclPtrInstance< VirtualDevice > aBlack;
1302 aWhite->SetOutputSizePixel(aSrc.GetSizePixel());
1303 aWhite->SetBackground(Wallpaper(COL_WHITE));
1304 aWhite->Erase();
1305 aBlack->SetOutputSizePixel(aSrc.GetSizePixel());
1306 aBlack->SetBackground(Wallpaper(COL_BLACK));
1307 aBlack->Erase();
1308 aWhite->DrawBitmapEx(Point(), aSrc);
1309 aBlack->DrawBitmapEx(Point(), aSrc);
1310
1311 // Now recover that alpha...
1312 Bitmap aWhiteBmp = aWhite->GetBitmap(Point(),aSrc.GetSizePixel());
1313 Bitmap aBlackBmp = aBlack->GetBitmap(Point(),aSrc.GetSizePixel());
1314 AlphaMask aMask(aSrc.GetSizePixel());
1315 Bitmap aRecovered(aSrc.GetSizePixel(), 24);
1316 {
1317 AlphaScopedWriteAccess pMaskAcc(aMask);
1318 BitmapScopedWriteAccess pRecAcc(aRecovered);
1319 Bitmap::ScopedReadAccess pAccW(aWhiteBmp); // a * pix + (1-a)
1320 Bitmap::ScopedReadAccess pAccB(aBlackBmp); // a * pix + 0
1321 int nSizeX = aSrc.GetSizePixel().Width();
1322 int nSizeY = aSrc.GetSizePixel().Height();
1323 for (int y = 0; y < nSizeY; y++)
1324 {
1325 Scanline pScanlineMask = pMaskAcc->GetScanline( y );
1326 Scanline pScanlineRec = pRecAcc->GetScanline( y );
1327 Scanline pScanlineW = pAccW->GetScanline( y );
1328 Scanline pScanlineB = pAccB->GetScanline( y );
1329 for (int x = 0; x < nSizeX; x++)
1330 {
1331 BitmapColor aColW = pAccW->GetPixelFromData(pScanlineW,x);
1332 BitmapColor aColB = pAccB->GetPixelFromData(pScanlineB,x);
1333 long nAR = static_cast<long>(aColW.GetRed() - aColB.GetRed()); // (1-a)
1334 long nAG = static_cast<long>(aColW.GetGreen() - aColB.GetGreen()); // (1-a)
1335 long nAB = static_cast<long>(aColW.GetBlue() - aColB.GetBlue()); // (1-a)
1336
1337#define CLAMP(a,b,c) (((a)<=(b))?(b):(((a)>=(c))?(c):(a)))
1338
1339 // we get the most precision from the largest delta
1340 long nInverseAlpha = std::max(nAR, std::max(nAG, nAB)); // (1-a)
1341 nInverseAlpha = CLAMP(nInverseAlpha, 0, 255);
1342 long nAlpha = 255 - nInverseAlpha;
1343
1344 pMaskAcc->SetPixelOnData(pScanlineMask,x,BitmapColor(static_cast<sal_Int8>(CLAMP(nInverseAlpha,0,255))));
1345 // now recover the pixels
1346 long nR = (aColW.GetRed() + aColB.GetRed() - nInverseAlpha) * 128;
1347 long nG = (aColW.GetGreen() + aColB.GetGreen() - nInverseAlpha) * 128;
1348 long nB = (aColW.GetBlue() + aColB.GetBlue() - nInverseAlpha) * 128;
1349 if (nAlpha == 0)
1350 { // doesn't matter what's behind transparency
1351 nR = nG = nB = 0;
1352 }
1353 else
1354 {
1355 nR /= nAlpha; nG /= nAlpha; nB /= nAlpha;
1356 }
1357 pRecAcc->SetPixelOnData(pScanlineRec,x,BitmapColor(
1358 static_cast<sal_uInt8>(CLAMP(nR,0,255)),
1359 static_cast<sal_uInt8>(CLAMP(nG,0,255)),
1360 static_cast<sal_uInt8>(CLAMP(nB,0,255))));
1361#undef CLAMP
1362 }
1363 }
1364 }
1365 rDev.DrawBitmap(aPt, aWhiteBmp);
1366 aPt.Move(aSrc.GetSizePixel().Width(), 0);
1367 rDev.DrawBitmap(aPt, aBlackBmp);
1368 aPt.Move(aSrc.GetSizePixel().Width(), 0);
1369 rDev.DrawBitmap(aPt, aRecovered);
1370 aPt.Move(aSrc.GetSizePixel().Width(), 0);
1371 rDev.DrawBitmap(aPt, aMask.GetBitmap());
1372 aPt.Move(aSrc.GetSizePixel().Width(), 0);
1373
1374 return BitmapEx(aRecovered, aMask);
1375 }
1376
1377 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
1378 const RenderContext &rCtx) override
1379 {
1380 if (rCtx.meStyle == RENDER_EXPANDED)
1381 {
1382 LoadAllImages();
1383
1384 Point aLocation(0,maIcons[0].GetSizePixel().Height() + 8);
1385 for (size_t i = 0; i < maIcons.size(); i++)
1386 {
1387 BitmapEx aSrc = maIcons[i];
1388
1389 // original above
1390 Point aAbove(aLocation);
1391 aAbove.Move(0,-aSrc.GetSizePixel().Height() - 4);
1392 rDev.DrawBitmapEx(aAbove, aSrc);
1393 aAbove.Move(aSrc.GetSizePixel().Width(),0);
1394 aAbove.Move(aSrc.GetSizePixel().Width(),0);
1395 rDev.DrawBitmap(aAbove, aSrc.GetBitmap());
1396 aAbove.Move(aSrc.GetSizePixel().Width(),0);
1397 rDev.DrawBitmap(aAbove, aSrc.GetMask());
1398
1399 // intermediates middle
1400 BitmapEx aResult = AlphaRecovery(rDev, aLocation, aSrc);
1401
1402 // result below
1403 Point aBelow(aLocation);
1404 aBelow.Move(0,aResult.GetSizePixel().Height());
1405 rDev.DrawBitmapEx(aBelow, aResult);
1406
1407 // mini convert test.
1408 aBelow.Move(aResult.GetSizePixel().Width()+4,0);
1409 rDev.DrawBitmapEx(aBelow, aResult);
1410
1411 Bitmap aGrey = aSrc.GetBitmap();
1412 aGrey.Convert(BmpConversion::N8BitGreys);
1413 rDev.DrawBitmap(aBelow, aGrey);
1414
1415 aBelow.Move(aGrey.GetSizePixel().Width(),0);
1416 BitmapEx aGreyMask(aSrc.GetBitmap(),
1417 AlphaMask(aSrc.GetMask()));
1418 rDev.DrawBitmapEx(aBelow, aGreyMask);
1419
1420 aLocation.Move(aSrc.GetSizePixel().Width()*6,0);
1421 if (aLocation.X() > r.Right())
1422 aLocation = Point(0,aLocation.Y()+aSrc.GetSizePixel().Height()*3+4);
1423 }
1424
1425 // now go crazy with random foo
1426 doDrawIcons(rDev, r, true);
1427 }
1428 else
1429 {
1430 doDrawIcons(rDev, r, false);
1431 }
1432 }
1433 };
1434
1435 struct FetchDrawBitmap : public RegionRenderer
1436 {
1437 RENDER_DETAILS(fetchdraw,KEY_F,50)virtual OUString getName() override { return "fetchdraw"; } virtual
sal_uInt16 getAccelerator() override { return KEY_F; } virtual
sal_uInt16 getTestRepeatCount() override { return 50; }
1438 virtual void RenderRegion(OutputDevice &rDev, tools::Rectangle r,
1439 const RenderContext &) override
1440 {
1441 Bitmap aBitmap(rDev.GetBitmap(Point(0,0),rDev.GetOutputSizePixel()));
1442 aBitmap.Scale(r.GetSize(), BmpScaleFlag::BestQuality);
1443 rDev.DrawBitmap(r.TopLeft(), aBitmap);
1444 }
1445 };
1446
1447 void drawThumbs(vcl::RenderContext& rDev, tools::Rectangle aRect, bool bVDev)
1448 {
1449 RenderContext aCtx;
1450 aCtx.meStyle = RENDER_THUMB;
1451 aCtx.mbVDev = bVDev;
1452 aCtx.mpDemoRenderer = this;
1453 aCtx.maSize = aRect.GetSize();
1454 std::vector<tools::Rectangle> aRegions(partition(aRect, mnSegmentsX, mnSegmentsY));
1455 DemoRenderer::clearRects(rDev, aRegions);
1456 for (size_t i = 0; i < maRenderers.size(); i++)
1457 {
1458 RegionRenderer * r = maRenderers[i];
1459
1460 rDev.SetClipRegion( vcl::Region( aRegions[i] ) );
1461
1462 // profiling?
1463 if (getIterCount() > 0)
1464 {
1465 if (!bVDev)
1466 {
1467 double nStartTime = getTimeNow();
1468 for (int j = 0; j < r->getTestRepeatCount() * THUMB_REPEAT_FACTOR10; j++)
1469 r->RenderRegion(rDev, aRegions[i], aCtx);
1470 addTime(i, (getTimeNow() - nStartTime) / THUMB_REPEAT_FACTOR10);
1471 } else
1472 for (int j = 0; j < r->getTestRepeatCount(); j++)
1473 r->RenderRegion(rDev, aRegions[i], aCtx);
1474 }
1475 else
1476 r->RenderRegion(rDev, aRegions[i], aCtx);
1477
1478 rDev.SetClipRegion();
1479 }
1480 }
1481
1482 void drawToDevice(vcl::RenderContext& rDev, Size aSize, bool bVDev)
1483 {
1484 RenderContext aCtx;
1485 aCtx.mbVDev = bVDev;
1486 aCtx.mpDemoRenderer = this;
1487 aCtx.maSize = aSize;
1488 tools::Rectangle aWholeWin(Point(0,0), rDev.GetOutputSizePixel());
1489
1490 drawBackground(rDev, aWholeWin);
1491
1492 if (!bVDev /* want everything in the vdev */ &&
1493 mnSelectedRenderer >= 0 &&
1494 o3tl::make_unsigned(mnSelectedRenderer) < maRenderers.size())
1495 {
1496 aCtx.meStyle = RENDER_EXPANDED;
1497 RegionRenderer * r = maRenderers[mnSelectedRenderer];
1498 // profiling?
1499 if (getIterCount() > 0)
1500 {
1501 double nStartTime = getTimeNow();
1502 for (int i = 0; i < r->getTestRepeatCount(); i++)
1503 r->RenderRegion(rDev, aWholeWin, aCtx);
1504 addTime(mnSelectedRenderer, getTimeNow() - nStartTime);
1505 } else
1506 r->RenderRegion(rDev, aWholeWin, aCtx);
1507 }
1508 else
1509 drawThumbs(rDev, aWholeWin, bVDev);
1510 }
1511 std::vector<VclPtr<vcl::Window> > maInvalidates;
1512 void addInvalidate(vcl::Window *pWindow) { maInvalidates.emplace_back(pWindow); };
1513 void removeInvalidate(vcl::Window *pWindow)
1514 {
1515 auto aIt = std::find(maInvalidates.begin(), maInvalidates.end(), pWindow);
1516 if (aIt != maInvalidates.end())
1517 maInvalidates.erase(aIt);
1518 }
1519 void Invalidate()
1520 {
1521 for (auto const& invalidate : maInvalidates)
1522 invalidate->Invalidate();
1523 }
1524};
1525
1526}
1527
1528#if FIXME_BOUNCE_BUTTON0
1529IMPL_LINK_NOARG(DemoRenderer,BounceTimerCb,Timer*,void)void DemoRenderer::LinkStubBounceTimerCb(void * instance, Timer
* data) { return static_cast<DemoRenderer *>(instance)->
BounceTimerCb(data); } void DemoRenderer::BounceTimerCb(__attribute__
((unused)) Timer*)
1530{
1531 mpButton->Check(mnBounceX>0);
1532 mpButton->SetPressed(mnBounceY>0);
1533
1534 Point aCur = mpButtonWin->GetPosPixel();
1535 static const int nMovePix = 10;
1536 aCur.Move(mnBounceX * nMovePix, mnBounceX * nMovePix);
1537 Size aWinSize = GetSizePixel();
1538 if (aCur.X() <= 0 || aCur.X() >= aWinSize.Width())
1539 mnBounceX *= -1;
1540 if (aCur.Y() <= 0 || aCur.Y() >= aWinSize.Height())
1541 mnBounceX *= -1;
1542 mpButtonWin->SetPosPixel(aCur);
1543
1544 // All smoke and mirrors to test sub-region invalidation underneath
1545 Rectangle aRect(aCur, mpButtonWin->GetSizePixel());
1546 Invalidate(aRect);
1547}
1548#endif
1549
1550void DemoRenderer::KeyInput(const KeyEvent &rKEvt)
1551{
1552 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
1553
1554 // click to zoom out
1555 if (mnSelectedRenderer >= 0)
1556 {
1557 if (nCode == KEY_ESCAPE || nCode == KEY_BACKSPACE)
1558 {
1559 mnSelectedRenderer = -1;
1560 Invalidate();
1561 return;
1562 }
1563 }
1564 else
1565 {
1566 for (size_t i = 0; i < maRenderers.size(); i++)
1567 {
1568 if (nCode == maRenderers[i]->getAccelerator())
1569 {
1570 mnSelectedRenderer = i;
1571 Invalidate();
1572 return;
1573 }
1574 }
1575 }
1576}
1577
1578bool DemoRenderer::MouseButtonDown(const MouseEvent& rMEvt)
1579{
1580 // click to zoom out
1581 if (mnSelectedRenderer >= 0)
1582 {
1583 mnSelectedRenderer = -1;
1584 Invalidate();
1585 return true;
1586 }
1587
1588 // click on a region to zoom into it
1589 std::vector<tools::Rectangle> aRegions(partition(GetSizePixel(), mnSegmentsX, mnSegmentsY));
1590 for (size_t i = 0; i < aRegions.size(); i++)
1591 {
1592 if (aRegions[i].IsInside(rMEvt.GetPosPixel()))
1593 {
1594 mnSelectedRenderer = i;
1595 Invalidate();
1596 return true;
1597 }
1598 }
1599
1600#if FIXME_BOUNCE_BUTTON0
1601 // otherwise bounce floating windows
1602 if (!mpButton)
1603 {
1604 mpButtonWin = VclPtr<FloatingWindow>::Create(this);
1605 mpButton = VclPtr<PushButton>::Create(mpButtonWin);
1606 mpButton->SetSymbol(SymbolType::HELP);
1607 mpButton->SetText("PushButton demo");
1608 mpButton->SetPosSizePixel(Point(0,0), mpButton->GetOptimalSize());
1609 mpButton->Show();
1610 mpButtonWin->SetPosSizePixel(Point(0,0), mpButton->GetOptimalSize());
1611 mpButtonWin->Show();
1612 mnBounceX = 1; mnBounceX = 1;
1613 maBounce.SetInvokeHandler(LINK(this,DemoRenderer,BounceTimerCb)::tools::detail::makeLink( ::tools::detail::castTo<DemoRenderer
*>(this), &DemoRenderer::LinkStubBounceTimerCb)
);
1614 maBounce.SetTimeout(55);
1615 maBounce.Start();
1616 }
1617 else
1618 {
1619 maBounce.Stop();
1620 delete mpButtonWin;
1621 mpButtonWin = NULL__null;
1622 mpButton = NULL__null;
1623 }
1624#endif
1625 return false;
1626}
1627
1628void DemoRenderer::InitRenderers()
1629{
1630 maRenderers.push_back(new DrawLines);
1631 maRenderers.push_back(new DrawText);
1632 maRenderers.push_back(new DrawPoly);
1633 maRenderers.push_back(new DrawEllipse);
1634 maRenderers.push_back(new DrawCheckered);
1635 maRenderers.push_back(new DrawBitmapEx);
1636 maRenderers.push_back(new DrawBitmap);
1637 maRenderers.push_back(new DrawGradient);
1638 maRenderers.push_back(new DrawPolyPolygons);
1639 maRenderers.push_back(new DrawClipped);
1640 maRenderers.push_back(new DrawToVirtualDevice);
1641 maRenderers.push_back(new DrawXOR);
1642 maRenderers.push_back(new DrawIcons());
1643 maRenderers.push_back(new FetchDrawBitmap);
1644}
1645
1646OUString DemoRenderer::getRendererList()
1647{
1648 OUStringBuffer aBuf;
1649 for (size_t i = 0; i < maRenderers.size(); i++)
1650 {
1651 aBuf.append(maRenderers[i]->getName());
1652 aBuf.append(' ');
1653 }
1654 return aBuf.makeStringAndClear();
1655}
1656
1657double DemoRenderer::getAndResetBenchmark(const RenderStyle style)
1658{
1659 double geomean = 1.0;
1660 fprintf(stderrstderr, "Rendering: %s, Times (ms):\n", style == RENDER_THUMB ? "THUMB": "EXPANDED");
1661 for (size_t i = 0; i < maRenderers.size(); i++)
1662 {
1663 double avgtime = maRenderers[i]->sumTime / maRenderers[i]->countTime;
1664 geomean *= avgtime;
1665 fprintf(stderrstderr, "%s: %f (iteration: %d*%d*%d)\n",
1666 OUStringToOString(maRenderers[i]->getName(),
1667 RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76))).getStr(), avgtime,
1668 maRenderers[i]->countTime, maRenderers[i]->getTestRepeatCount(),
1669 (style == RENDER_THUMB) ? THUMB_REPEAT_FACTOR10 : 1);
1670 maRenderers[i]->sumTime = 0;
1671 maRenderers[i]->countTime = 0;
1672 }
1673 geomean = pow(geomean, 1.0/maRenderers.size());
1674 fprintf(stderrstderr, "GEOMEAN_%s: %f\n", style == RENDER_THUMB ? "THUMB": "EXPANDED", geomean);
1675 return geomean;
1676}
1677
1678void DemoRenderer::setIterCount(sal_Int32 i)
1679{
1680 iterCount = i;
1681}
1682
1683sal_Int32 DemoRenderer::getIterCount() const
1684{
1685 return iterCount;
1686}
1687
1688void DemoRenderer::addTime(int i, double t)
1689{
1690 maRenderers[i]->sumTime += t / maRenderers[i]->getTestRepeatCount();
1691 maRenderers[i]->countTime++;
1692}
1693
1694void DemoRenderer::selectRenderer(const OUString &rName )
1695{
1696 for (size_t i = 0; i < maRenderers.size(); i++)
1697 {
1698 if (maRenderers[i]->getName() == rName)
1699 {
1700 mnSelectedRenderer = i;
1701 Invalidate();
1702 return;
1703 }
1704 }
1705}
1706
1707int DemoRenderer::selectNextRenderer()
1708{
1709 mnSelectedRenderer++;
1710 if (mnSelectedRenderer == static_cast<signed>(maRenderers.size()))
1711 mnSelectedRenderer = -1;
1712 Invalidate();
1713 return mnSelectedRenderer;
1714}
1715
1716namespace {
1717
1718class DemoWin : public WorkWindow
1719{
1720 DemoRenderer &mrRenderer;
1721 bool underTesting;
1722 bool testThreads;
1723
1724 class RenderThread final : public salhelper::Thread {
1725 DemoWin &mrWin;
1726 sal_uInt32 const mnDelaySecs = 0;
1727 public:
1728 RenderThread(DemoWin &rWin, sal_uInt32 nDelaySecs)
1729 : Thread("vcldemo render thread")
1730 , mrWin(rWin)
1731 , mnDelaySecs(nDelaySecs)
1732 {
1733 launch();
1734 }
1735 virtual ~RenderThread() override
1736 {
1737 join();
1738 }
1739 virtual void execute() override
1740 {
1741 wait(std::chrono::seconds(mnDelaySecs));
1742
1743 SolarMutexGuard aGuard;
1744 fprintf (stderrstderr, "render from a different thread\n");
1745 mrWin.Invalidate();
1746 }
1747 };
1748 rtl::Reference<RenderThread> mxThread;
1749
1750public:
1751 DemoWin(DemoRenderer &rRenderer, bool bThreads) :
1752 WorkWindow(nullptr, WB_APP | WB_STDWORK),
1753 mrRenderer(rRenderer),
1754 testThreads(bThreads)
1755 {
1756 mrRenderer.addInvalidate(this);
1757 underTesting = false;
1758 }
1759 virtual ~DemoWin() override
1760 {
1761 disposeOnce();
1762 }
1763 virtual void dispose() override
1764 {
1765 mxThread.clear();
1766 mrRenderer.removeInvalidate(this);
1767 WorkWindow::dispose();
1768 }
1769 virtual void MouseButtonDown(const MouseEvent& rMEvt) override
1770 {
1771 mrRenderer.SetSizePixel(GetSizePixel());
1772 if (mrRenderer.MouseButtonDown(rMEvt))
1773 return;
1774
1775 if (testThreads)
1776 { // render this window asynchronously in a new thread
1777 sal_uInt32 nDelaySecs = 0;
1778 if (rMEvt.GetButtons() & MOUSE_RIGHT(sal_uInt16(0x0004)))
1779 nDelaySecs = 5;
1780 mxThread = new RenderThread(*this, nDelaySecs);
1781 }
1782 else
1783 { // spawn another window
1784 VclPtrInstance<DemoWin> pNewWin(mrRenderer, testThreads);
1785 pNewWin->SetText("Another interactive VCL demo window");
1786 pNewWin->Show();
1787 }
1788 }
1789 virtual void KeyInput(const KeyEvent& rKEvt) override
1790 {
1791 mrRenderer.SetSizePixel(GetSizePixel());
1792 mrRenderer.KeyInput(rKEvt);
1793 }
1794 virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override
1795 {
1796 mrRenderer.SetSizePixel(GetSizePixel());
1797 fprintf(stderrstderr, "DemoWin::Paint(%ld,%ld,%ld,%ld)\n", rRect.getX(), rRect.getY(), rRect.getWidth(), rRect.getHeight());
1798 if (mrRenderer.getIterCount() == 0)
1799 mrRenderer.drawToDevice(rRenderContext, GetSizePixel(), false);
1800 else
1801 TestAndQuit(rRenderContext);
1802 }
1803
1804 void TestAndQuit(vcl::RenderContext& rRenderContext)
1805 {
1806 if (underTesting)
1807 return;
1808 underTesting = true;
1809 for (sal_Int32 i = 0; i < mrRenderer.getIterCount(); i++)
1810 {
1811 while (mrRenderer.selectNextRenderer() > -1)
1812 {
1813 mrRenderer.drawToDevice(rRenderContext, GetSizePixel(), false);
1814 }
1815 }
1816
1817 double expandedGEOMEAN = mrRenderer.getAndResetBenchmark(RENDER_EXPANDED);
1818
1819 for (sal_Int32 i = 0; i < mrRenderer.getIterCount(); i++)
1820 mrRenderer.drawToDevice(rRenderContext, GetSizePixel(), false);
1821
1822 double thumbGEOMEAN = mrRenderer.getAndResetBenchmark(RENDER_THUMB);
1823
1824 fprintf(stderrstderr, "GEOMEAN_TOTAL: %f\n", pow(thumbGEOMEAN * expandedGEOMEAN, 0.5));
1825 Application::Quit();
1826 }
1827};
1828
1829struct PointerData {
1830 PointerStyle eStyle;
1831 const char * name;
1832};
1833
1834}
1835
1836const PointerData gvPointerData [] = {
1837 { PointerStyle::Null, "Null" },
1838 { PointerStyle::Magnify, "Magnify" },
1839 { PointerStyle::Fill, "Fill" },
1840 { PointerStyle::MoveData, "MoveData" },
1841 { PointerStyle::CopyData, "CopyData" },
1842 { PointerStyle::MoveFile, "MoveFile" },
1843 { PointerStyle::CopyFile, "CopyFile" },
1844 { PointerStyle::MoveFiles, "MoveFiles" },
1845 { PointerStyle::CopyFiles, "CopyFiles" },
1846 { PointerStyle::NotAllowed, "NotAllowed" },
1847 { PointerStyle::Rotate, "Rotate" },
1848 { PointerStyle::HShear, "HShear" },
1849 { PointerStyle::VShear, "VShear" },
1850 { PointerStyle::DrawLine, "DrawLine" },
1851 { PointerStyle::DrawRect, "DrawRect" },
1852 { PointerStyle::DrawPolygon, "DrawPolygon" },
1853 { PointerStyle::DrawBezier, "DrawBezier" },
1854 { PointerStyle::DrawArc, "DrawArc" },
1855 { PointerStyle::DrawPie, "DrawPie" },
1856 { PointerStyle::DrawCircleCut, "DrawCircleCut" },
1857 { PointerStyle::DrawEllipse, "DrawEllipse" },
1858 { PointerStyle::DrawConnect, "DrawConnect" },
1859 { PointerStyle::DrawText, "DrawText" },
1860 { PointerStyle::Mirror, "Mirror" },
1861 { PointerStyle::Crook, "Crook" },
1862 { PointerStyle::Crop, "Crop" },
1863 { PointerStyle::MovePoint, "MovePoint" },
1864 { PointerStyle::MoveBezierWeight, "MoveBezierWeight" },
1865 { PointerStyle::DrawFreehand, "DrawFreehand" },
1866 { PointerStyle::DrawCaption, "DrawCaption" },
1867 { PointerStyle::LinkData, "LinkData" },
1868 { PointerStyle::MoveDataLink, "MoveDataLink" },
1869 { PointerStyle::CopyDataLink, "CopyDataLink" },
1870 { PointerStyle::LinkFile, "LinkFile" },
1871 { PointerStyle::MoveFileLink, "MoveFileLink" },
1872 { PointerStyle::CopyFileLink, "CopyFileLink" },
1873 { PointerStyle::Chart, "Chart" },
1874 { PointerStyle::Detective, "Detective" },
1875 { PointerStyle::PivotCol, "PivotCol" },
1876 { PointerStyle::PivotRow, "PivotRow" },
1877 { PointerStyle::PivotField, "PivotField" },
1878 { PointerStyle::PivotDelete, "PivotDelete" },
1879 { PointerStyle::Chain, "Chain" },
1880 { PointerStyle::ChainNotAllowed, "ChainNotAllowed" },
1881 { PointerStyle::AutoScrollN, "AutoScrollN" },
1882 { PointerStyle::AutoScrollS, "AutoScrollS" },
1883 { PointerStyle::AutoScrollW, "AutoScrollW" },
1884 { PointerStyle::AutoScrollE, "AutoScrollE" },
1885 { PointerStyle::AutoScrollNW, "AutoScrollNW" },
1886 { PointerStyle::AutoScrollNE, "AutoScrollNE" },
1887 { PointerStyle::AutoScrollSW, "AutoScrollSW" },
1888 { PointerStyle::AutoScrollSE, "AutoScrollSE" },
1889 { PointerStyle::AutoScrollNS, "AutoScrollNS" },
1890 { PointerStyle::AutoScrollWE, "AutoScrollWE" },
1891 { PointerStyle::AutoScrollNSWE, "AutoScrollNSWE" },
1892 { PointerStyle::TextVertical, "TextVertical" },
1893 { PointerStyle::TabSelectS, "TabSelectS" },
1894 { PointerStyle::TabSelectE, "TabSelectE" },
1895 { PointerStyle::TabSelectSE, "TabSelectSE" },
1896 { PointerStyle::TabSelectW, "TabSelectW" },
1897 { PointerStyle::TabSelectSW, "TabSelectSW" },
1898 { PointerStyle::HideWhitespace, "HideWhitespace" },
1899 { PointerStyle::ShowWhitespace, "ShowWhitespace" },
1900};
1901
1902namespace {
1903
1904class DemoWidgets : public WorkWindow
1905{
1906 VclPtr<MenuBar> mpBar;
1907 VclPtr<VclBox> mpBox;
1908 VclPtr<ToolBox> mpToolbox;
1909 VclPtr<PushButton> mpButton;
1910 VclPtr<VclHBox> mpHBox;
1911 VclPtr<CheckBox> mpGLCheck;
1912 VclPtr<ComboBox> mpGLCombo;
1913 VclPtr<PushButton> mpGLButton;
1914 std::vector<VclPtr<VclHBox>> mvCursorBoxes;
1915 std::vector<VclPtr<PushButton>> mvCursorButtons;
1916
1917 DECL_LINK(GLTestClick, Button*, void)static void LinkStubGLTestClick(void *, Button*); void GLTestClick
(Button*)
;
1918 DECL_LINK(CursorButtonClick, Button*, void)static void LinkStubCursorButtonClick(void *, Button*); void CursorButtonClick
(Button*)
;
1919
1920public:
1921 DemoWidgets() :
1922 WorkWindow(nullptr, WB_APP | WB_STDWORK),
1923 mpBox(VclPtrInstance<VclVBox>(this, false, 3)),
1924 mpToolbox(VclPtrInstance<ToolBox>(mpBox.get())),
1925 mpButton(VclPtrInstance<PushButton>(mpBox.get())),
1926 mpHBox(VclPtrInstance<VclHBox>(mpBox.get(), true, 3)),
1927 mpGLCheck(VclPtrInstance<CheckBox>(mpHBox.get())),
1928 mpGLCombo(VclPtrInstance<ComboBox>(mpHBox.get())),
1929 mpGLButton(VclPtrInstance<PushButton>(mpHBox.get()))
1930 {
1931 SetText("VCL widget demo");
1932
1933 Wallpaper aWallpaper(BitmapEx("sfx2/res/startcenter-logo.png"));
1934 aWallpaper.SetStyle(WallpaperStyle::BottomRight);
1935 aWallpaper.SetColor(COL_RED);
1936
1937 mpBox->SetBackground(aWallpaper);
1938 mpBox->Show();
1939
1940 Help::EnableBalloonHelp();
1941 mpToolbox->SetHelpText("Help text");
1942 mpToolbox->InsertItem(0, "Toolbar item");
1943 mpToolbox->SetQuickHelpText(0, "This is a tooltip popup");
1944 mpToolbox->InsertSeparator();
1945 mpToolbox->Show();
1946
1947 mpButton->SetText("Click me; go on");
1948 mpButton->Show();
1949
1950 mpGLCheck->SetText("Test in OGL zone");
1951 mpGLCheck->Show();
1952 mpGLCombo->InsertEntry("sleep 1 second");
1953 mpGLCombo->InsertEntry("sleep 3 seconds");
1954 mpGLCombo->InsertEntry("sleep 7 seconds");
1955 mpGLCombo->SelectEntryPos(2);
1956 mpGLCombo->Show();
1957 mpGLButton->SetText("Execute test");
1958 mpGLButton->SetClickHdl(LINK(this,DemoWidgets,GLTestClick)::tools::detail::makeLink( ::tools::detail::castTo<DemoWidgets
*>(this), &DemoWidgets::LinkStubGLTestClick)
);
1959 mpGLButton->Show();
1960 mpHBox->Show();
1961
1962 int i = 0;
1963 VclHBox* pCurrentCursorHBox = nullptr;
1964 constexpr int numButtonsPerRow = 9;
1965 for (auto & rData : gvPointerData)
1966 {
1967 if (i % numButtonsPerRow == 0)
1968 {
1969 mvCursorBoxes.push_back(VclPtrInstance<VclHBox>(mpBox.get(), true, numButtonsPerRow));
1970 pCurrentCursorHBox = mvCursorBoxes.back().get();
1971 pCurrentCursorHBox->Show();
1972 }
1973 mvCursorButtons.emplace_back(VclPtrInstance<PushButton>(pCurrentCursorHBox));
1974 PushButton& rButton = *mvCursorButtons.back();
1975 rButton.SetText(OUString::createFromAscii(rData.name));
1976 rButton.SetClickHdl(LINK(this,DemoWidgets,CursorButtonClick)::tools::detail::makeLink( ::tools::detail::castTo<DemoWidgets
*>(this), &DemoWidgets::LinkStubCursorButtonClick)
);
1977 rButton.Show();
1978 ++i;
1979 }
1980
1981 mpBar = VclPtr<MenuBar>::Create();
1982 mpBar->InsertItem(0,"File");
1983 VclPtrInstance<PopupMenu> pPopup;
1984 pPopup->InsertItem(0,"Item");
1985 mpBar->SetPopupMenu(0, pPopup);
1986 SetMenuBar(mpBar);
1987
1988 Show();
1989 }
1990 virtual ~DemoWidgets() override { disposeOnce(); }
1991 virtual void dispose() override
1992 {
1993 mpGLButton.disposeAndClear();
1994 mpGLCombo.disposeAndClear();
1995 mpGLCheck.disposeAndClear();
1996 mpHBox.disposeAndClear();
1997 for (auto & p : mvCursorButtons)
1998 p.disposeAndClear();
1999 mvCursorButtons.clear();
2000 for (auto & p : mvCursorBoxes)
2001 p.disposeAndClear();
2002 mvCursorBoxes.clear();
2003 mpToolbox.disposeAndClear();
2004 mpButton.disposeAndClear();
2005 mpBox.disposeAndClear();
2006 mpBar.disposeAndClear();
2007 WorkWindow::dispose();
2008 }
2009 virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override
2010 {
2011 tools::Rectangle aWholeSize(Point(0, 0),GetOutputSizePixel());
2012 vcl::Region aClip(aWholeSize);
2013 tools::Rectangle aExclude(tools::Rectangle(Point(50,50),Size(100,100)));
2014 aClip.Exclude(aExclude);
2015
2016 Wallpaper aWallpaper(COL_GREEN);
2017
2018 rRenderContext.Push(PushFlags::CLIPREGION);
2019 rRenderContext.IntersectClipRegion(aClip);
2020 rRenderContext.DrawWallpaper(aWholeSize, aWallpaper);
2021 rRenderContext.Pop();
2022
2023 ScopedVclPtrInstance< VirtualDevice > pDev(*this);
2024 pDev->EnableRTL(IsRTLEnabled());
2025 pDev->SetOutputSizePixel(aExclude.GetSize());
2026
2027 tools::Rectangle aSubRect(aWholeSize);
2028 aSubRect.Move(-aExclude.Left(), -aExclude.Top());
2029 pDev->DrawWallpaper(aSubRect, aWallpaper );
2030
2031 rRenderContext.DrawOutDev(aExclude.TopLeft(), aExclude.GetSize(),
2032 Point( 0, 0 ), aExclude.GetSize(), *pDev );
2033 }
2034};
2035
2036}
2037
2038IMPL_LINK_NOARG(DemoWidgets, GLTestClick, Button*, void)void DemoWidgets::LinkStubGLTestClick(void * instance, Button
* data) { return static_cast<DemoWidgets *>(instance)->
GLTestClick(data); } void DemoWidgets::GLTestClick(__attribute__
((unused)) Button*)
2039{
2040 sal_Int32 nSelected = mpGLCombo->GetSelectedEntryPos();
2041 sal_uInt32 nDelaySeconds = 0;
2042
2043 switch (nSelected)
2044 {
2045 case 0:
2046 nDelaySeconds = 1;
2047 break;
2048 case 1:
2049 nDelaySeconds = 3;
2050 break;
2051 case 2:
2052 nDelaySeconds = 7;
2053 break;
2054 default:
2055 break;
2056 }
2057
2058 // Only create OpenGLZone RAII object if asked for:
2059 std::unique_ptr<OpenGLZone> zone;
2060 if (mpGLCheck->IsChecked()) {
2061 zone.reset(new OpenGLZone);
2062 }
2063
2064 osl::Thread::wait(std::chrono::seconds(nDelaySeconds));
2065}
2066
2067IMPL_LINK(DemoWidgets, CursorButtonClick, Button*, pButton, void)void DemoWidgets::LinkStubCursorButtonClick(void * instance, Button
* data) { return static_cast<DemoWidgets *>(instance)->
CursorButtonClick(data); } void DemoWidgets::CursorButtonClick
(Button* pButton)
2068{
2069 for (size_t i=0; i<SAL_N_ELEMENTS(gvPointerData)(sizeof(sal_n_array_size(gvPointerData))); ++i)
2070 {
2071 if (mvCursorButtons[i].get() == pButton)
2072 {
2073 mpBox->SetPointer( gvPointerData[i].eStyle );
2074 return;
2075 }
2076 }
2077 assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail (
"false", "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2077, __extension__ __PRETTY_FUNCTION__))
;
2078}
2079
2080namespace {
2081
2082class DemoPopup : public FloatingWindow
2083{
2084 public:
2085 DemoPopup() : FloatingWindow( nullptr, WB_SYSTEMWINDOW|WB_TOOLTIPWIN)
2086 {
2087 SetType( WindowType::HELPTEXTWINDOW );
2088
2089 SetOutputSizePixel( Size( 300, 30 ) );
2090 SetBackground(Wallpaper(COL_YELLOW));
2091
2092 Show( true, ShowFlags::NoActivate );
2093 PaintImmediately();
2094 }
2095
2096 virtual void Paint(vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle&) override
2097 {
2098 // Interestingly in GL mode on Windows, this doesn't render.
2099
2100 Size aSize = GetOutputSizePixel();
2101 tools::Rectangle aTextRect(Point(6, 6), aSize);
2102
2103 SetTextColor(COL_BLACK);
2104 SetTextAlign(ALIGN_TOP);
2105 DrawText(aTextRect, "This is a standalone help text test",
2106 DrawTextFlags::MultiLine|DrawTextFlags::WordBreak|
2107 DrawTextFlags::Left|DrawTextFlags::Top);
2108
2109 SetLineColor(COL_BLACK);
2110 SetFillColor();
2111 DrawRect( tools::Rectangle( Point(), aSize ) );
2112 aSize.AdjustWidth( -2 );
2113 aSize.AdjustHeight( -2 );
2114 Color aColor( GetLineColor() );
2115 SetLineColor( COL_GRAY );
2116 DrawRect( tools::Rectangle( Point( 1, 1 ), aSize ) );
2117 SetLineColor( aColor );
2118 }
2119
2120 virtual void MouseButtonDown( const MouseEvent & ) override
2121 {
2122 Application::Quit();
2123 }
2124};
2125
2126}
2127
2128class OpenGLTests
2129{
2130 VclPtr<WorkWindow> mxWinA;
2131 VclPtr<WorkWindow> mxWinB;
2132 rtl::Reference<OpenGLContext> mpA;
2133 rtl::Reference<OpenGLContext> mpB;
2134
2135 static OpenGLSalGraphicsImpl *getImpl(const VclPtr<OutputDevice> &xOut)
2136 {
2137 SalGraphics *pGraphics = xOut->GetGraphics();
2138 return dynamic_cast<OpenGLSalGraphicsImpl *>(pGraphics->GetImpl());
2139 }
2140public:
2141 OpenGLTests() :
2142 mxWinA(VclPtr<WorkWindow>::Create(nullptr, WB_APP | WB_STDWORK)),
2143 mxWinB(VclPtr<WorkWindow>::Create(nullptr, WB_APP | WB_STDWORK))
2144 {
2145 OpenGLSalGraphicsImpl *pImplA;
2146 OpenGLSalGraphicsImpl *pImplB;
2147 if (!OpenGLHelper::isVCLOpenGLEnabled())
2148 {
2149 pImplA = pImplB = nullptr;
2150 fprintf (stderrstderr, "OpenGL is not enabled: try SAL_FORCEGL=1\n");
2151 return;
2152 }
2153
2154 pImplA = getImpl(mxWinA);
2155 pImplB = getImpl(mxWinB);
2156 assert (pImplA && pImplB)(static_cast <bool> (pImplA && pImplB) ? void (
0) : __assert_fail ("pImplA && pImplB", "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2156, __extension__ __PRETTY_FUNCTION__))
;
2157 mpA = pImplA->GetOpenGLContext();
2158 mpB = pImplB->GetOpenGLContext();
2159
2160 assert (mpA.is() && mpB.is())(static_cast <bool> (mpA.is() && mpB.is()) ? void
(0) : __assert_fail ("mpA.is() && mpB.is()", "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2160, __extension__ __PRETTY_FUNCTION__))
;
2161 assert (mpA != mpB)(static_cast <bool> (mpA != mpB) ? void (0) : __assert_fail
("mpA != mpB", "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2161, __extension__ __PRETTY_FUNCTION__))
;
2162 }
2163 ~OpenGLTests()
2164 {
2165 mxWinB.disposeAndClear();
2166 mxWinA.disposeAndClear();
2167 }
2168
2169 void testCurrentFramebuffer()
2170 {
2171 fprintf(stderrstderr,"test OpenGLContext's framebuffer association.\n");
2172 mpA->makeCurrent();
2173 OpenGLFramebuffer *pBuffer;
2174 {
2175 OpenGLTexture aTexture(256,128);
2176 pBuffer = mpA->AcquireFramebuffer(aTexture);
2177 }
2178 assert (pBuffer->IsFree())(static_cast <bool> (pBuffer->IsFree()) ? void (0) :
__assert_fail ("pBuffer->IsFree()", "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2178, __extension__ __PRETTY_FUNCTION__))
; (void)pBuffer;
2179 mpB->makeCurrent();
2180 assert (mpA->mpCurrentFramebuffer == nullptr)(static_cast <bool> (mpA->mpCurrentFramebuffer == nullptr
) ? void (0) : __assert_fail ("mpA->mpCurrentFramebuffer == nullptr"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2180, __extension__ __PRETTY_FUNCTION__))
;
2181 }
2182
2183 void testVirtualDevice()
2184 {
2185 fprintf(stderrstderr, "test sharing OpenGLContexts with virtual-devices reference counting\n");
2186 VclPtrInstance<WorkWindow> xTempWin(nullptr, WB_STDWORK);
2187 xTempWin->Show();
2188 // forcibly make this context current by rendering
2189 xTempWin->DrawPixel(Point(0, 0), COL_RED);
2190
2191 // get some other guys to leach off this context
2192 VclPtrInstance<VirtualDevice> xVDev;
2193 OpenGLSalGraphicsImpl* pImpl = getImpl(xVDev);
2194 assert(pImpl)(static_cast <bool> (pImpl) ? void (0) : __assert_fail (
"pImpl", "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2194, __extension__ __PRETTY_FUNCTION__))
;
2195 rtl::Reference<OpenGLContext> pContext = pImpl->GetOpenGLContext();
2196 VclPtrInstance<VirtualDevice> xVDev2;
2197 OpenGLSalGraphicsImpl* pImpl2 = getImpl(xVDev2);
2198 assert(pImpl2)(static_cast <bool> (pImpl2) ? void (0) : __assert_fail
("pImpl2", "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2198, __extension__ __PRETTY_FUNCTION__))
;
2199 rtl::Reference<OpenGLContext> pContext2 = pImpl2->GetOpenGLContext();
2200
2201 // sharing the same off-screen context.
2202 assert(pContext == pContext2)(static_cast <bool> (pContext == pContext2) ? void (0) :
__assert_fail ("pContext == pContext2", "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2202, __extension__ __PRETTY_FUNCTION__))
;
2203 assert(pContext == getImpl(xTempWin)->GetOpenGLContext())(static_cast <bool> (pContext == getImpl(xTempWin)->
GetOpenGLContext()) ? void (0) : __assert_fail ("pContext == getImpl(xTempWin)->GetOpenGLContext()"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2203, __extension__ __PRETTY_FUNCTION__))
;
2204 assert(pContext != mpA && pContext != mpB)(static_cast <bool> (pContext != mpA && pContext
!= mpB) ? void (0) : __assert_fail ("pContext != mpA && pContext != mpB"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2204, __extension__ __PRETTY_FUNCTION__))
;
2205 (void)pContext; (void)pContext2;
2206
2207 // Kill the parent we free-ride on ...
2208 xTempWin.disposeAndClear();
2209
2210 // This appears to continue working; fun.
2211 Point aPt(0, 0);
2212 xVDev->DrawPixel(aPt, COL_GREEN);
2213 assert(xVDev->GetPixel(aPt) == COL_GREEN)(static_cast <bool> (xVDev->GetPixel(aPt) == COL_GREEN
) ? void (0) : __assert_fail ("xVDev->GetPixel(aPt) == COL_GREEN"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2213, __extension__ __PRETTY_FUNCTION__))
;
2214 xVDev.disposeAndClear();
2215
2216 // Switch context to see if we can switch back.
2217 mxWinA->DrawPixel(aPt, COL_WHITE);
2218
2219 // Now try switching back to this guy ...
2220 xVDev2->DrawPixel(aPt, COL_BLUE);
2221 assert(xVDev2->GetPixel(aPt) == COL_BLUE)(static_cast <bool> (xVDev2->GetPixel(aPt) == COL_BLUE
) ? void (0) : __assert_fail ("xVDev2->GetPixel(aPt) == COL_BLUE"
, "/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
, 2221, __extension__ __PRETTY_FUNCTION__))
;
2222 xVDev2.disposeAndClear();
2223 }
2224
2225 int execute()
2226 {
2227 if (!OpenGLHelper::isVCLOpenGLEnabled())
2228 return 1;
2229
2230 testCurrentFramebuffer();
2231 testVirtualDevice();
2232
2233 return 0;
2234 }
2235};
2236
2237namespace {
2238 void renderFonts()
2239 {
2240 ScopedVclPtrInstance<VirtualDevice> xDevice;
2241 Size aSize(1024, 1024);
2242 xDevice->SetOutputSizePixel(aSize);
2243
2244#if 0
2245 for (auto & aFontName : aFontNames)
2246 {
2247 vcl::Font aFont(aFontName, Size(0,96));
2248
2249 aFont.Set(COL_BLACK);
2250 xDevice->SetFont(aFont);
2251 xDevice->Erase();
2252
2253 FontMetric aMetric = xDevice->GetFontMetric(aFont);
2254
2255 FontCharMapRef xMap;
2256 if (xDevice->GetFontCharMap(xMap))
2257 {
2258 ... iterate through glyphs ...
2259 }
2260
2261
2262 bool GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr, int nIndex,
2263 int nLen, int nBase, MetricVector& rVector );
2264
2265include/vcl/outdev.hxx:typedef std::vector< Rectangle > MetricVector;
2266include/vcl/outdev.hxx: MetricVector* pVector = nullptr, OUString* pDisplayText = nullptr );
2267include/vcl/outdev.hxx: MetricVector* pVector = nullptr, OUString* pDisplayText = nullptr,
2268include/vcl/outdev.hxx: MetricVector* pVector, OUString* pDisplayText, vcl::ITextLayout& _rLayout );
2269include/vcl/outdev.hxx: DrawTextFlags nStyle = DrawTextFlags::Mnemonic, MetricVector* pVector = nullp
2270
2271 bool GetTextBoundRect( Rectangle& rRect,
2272 const OUString& rStr, sal_Int32 nBase = 0, sal_Int32 nIndex = 0, sal_Int32 nLen = -1,
2273 sal_uLong nLayoutWidth = 0, const long* pDXArray = nullptr ) const;
2274
2275
2276 void DrawText( const Point& rStartPt, const OUString& rStr,
2277 sal_Int32 nIndex = 0, sal_Int32 nLen = -1,
2278 MetricVector* pVector = nullptr, OUString* pDisplayText = nullptr );
2279
2280 void DrawText( const Rectangle& rRect,
2281 const OUString& rStr, DrawTextFlags nStyle = DrawTextFlags::NONE,
2282 MetricVector* pVector = nullptr, OUString* pDisplayText = nullptr,
2283 vcl::ITextLayout* _pTextLayout = nullptr );
2284
2285 Rectangle GetTextRect( const Rectangle& rRect,
2286 const OUString& rStr, DrawTextFlags nStyle = DrawTextFlags::WordBreak,
2287 TextRectInfo* pInfo = nullptr,
2288 const vcl::ITextLayout* _pTextLayout = nullptr ) const;
2289
2290 }
2291#endif
2292
2293 }
2294};
2295
2296namespace {
2297
2298class DemoApp : public Application
2299{
2300 static int showHelp(DemoRenderer &rRenderer)
2301 {
2302 fprintf(stderrstderr,"vcldemo - a VCL test app\n");
2303 fprintf(stderrstderr," --help - print this text\n");
2304 fprintf(stderrstderr," --show <renderer> - start with a given renderer, options are:\n");
2305 OUString aRenderers(rRenderer.getRendererList());
2306 fprintf(stderrstderr," %s\n",
2307 OUStringToOString(aRenderers, RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76))).getStr());
2308 fprintf(stderrstderr," --test <iterCount> - create benchmark data\n");
2309 fprintf(stderrstderr," --widgets - launch the widget test.\n");
2310 fprintf(stderrstderr," --popup - launch the popup test.\n");
2311 fprintf(stderrstderr," --threads - render from multiple threads.\n");
2312 fprintf(stderrstderr," --gltest - run openGL regression tests.\n");
2313 fprintf(stderrstderr," --font <fontname> - run the font render test.\n");
2314 fprintf(stderrstderr, "\n");
2315 return 0;
2316 }
2317
2318public:
2319 DemoApp() {}
2320
2321 virtual int Main() override
2322 {
2323 try
2324 {
2325 bool bWidgets = false, bThreads = false;
2326 bool bPopup = false, bGLTest = false;
2327 DemoRenderer aRenderer;
2328 std::vector<OUString> aFontNames;
2329
2330 for (sal_uInt16 i = 0; i < GetCommandLineParamCount(); ++i)
2331 {
2332 bool bLast = i == GetCommandLineParamCount() - 1;
2333 OUString aArg = GetCommandLineParam(i);
2334 if (aArg == "--help" || aArg == "-h")
2335 return showHelp(aRenderer);
2336 if (aArg == "--show")
2337 {
2338 if (bLast)
2339 return showHelp(aRenderer);
2340 else
2341 aRenderer.selectRenderer(GetCommandLineParam(++i));
2342 }
2343 else if (aArg == "--test")
2344 {
2345 if (bLast)
2346 return showHelp(aRenderer);
2347 else
2348 aRenderer.setIterCount(GetCommandLineParam(++i).toInt32());
2349 }
2350 else if (aArg == "--widgets")
2351 bWidgets = true;
2352 else if (aArg == "--popup")
2353 bPopup = true;
2354 else if (aArg == "--gltest")
2355 bGLTest = true;
2356 else if (aArg == "--threads")
2357 bThreads = true;
2358 else if (aArg == "--font" && !bLast)
2359 aFontNames.push_back(GetCommandLineParam(++i));
2360 else if (aArg.startsWith("--"))
2361 {
2362 fprintf(stderrstderr,"Unknown argument '%s'\n",
2363 OUStringToOString(aArg, RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76))).getStr());
2364 return showHelp(aRenderer);
2365 }
2366 }
2367
2368 ScopedVclPtrInstance<DemoWin> aMainWin(aRenderer, bThreads);
2369 VclPtr<DemoWidgets> xWidgets;
2370 VclPtr<DemoPopup> xPopup;
2371
2372 aMainWin->SetText("Interactive VCL demo #1");
2373#if HAVE_FEATURE_OPENGL1
2374 if (bGLTest)
2375 {
2376 OpenGLTests aTests;
2377 return aTests.execute();
2378 }
2379 else
2380#endif
2381 if (bWidgets)
2382 xWidgets = VclPtr< DemoWidgets >::Create ();
2383 else if (bPopup)
2384 xPopup = VclPtrInstance< DemoPopup> ();
2385 else if (!aFontNames.empty())
2386 renderFonts();
2387 else
2388 aMainWin->Show();
2389
2390 Application::Execute();
2391
2392 xWidgets.disposeAndClear();
2393 xPopup.disposeAndClear();
2394 }
2395 catch (const css::uno::Exception&)
2396 {
2397 TOOLS_WARN_EXCEPTION("vcl.app", "Fatal")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.app")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Fatal" << " " <<
exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.app"), ("/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
":" "2397" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Fatal" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Fatal" << " " << exceptionToString
(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.app"), ("/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
":" "2397" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Fatal" << " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"vcl.app"), ("/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
":" "2397" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Fatal" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Fatal" << " " << exceptionToString
(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.app"), ("/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
":" "2397" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
2398 return 1;
2399 }
2400 catch (const std::exception& e)
2401 {
2402 SAL_WARN("vcl.app", "Fatal: " << e.what())do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.app")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Fatal: " << e.
what()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.app"), ("/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
":" "2402" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Fatal: " << e.what()), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"Fatal: " << e.what(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.app"), ("/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
":" "2402" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Fatal: " << e.what()) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.app"), ("/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
":" "2402" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Fatal: " << e.what()), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"Fatal: " << e.what(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.app"), ("/home/maarten/src/libreoffice/core/vcl/workben/vcldemo.cxx"
":" "2402" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2403 return 1;
2404 }
2405 return 0;
2406 }
2407
2408protected:
2409 void Init() override
2410 {
2411 try
2412 {
2413 uno::Reference<uno::XComponentContext> xComponentContext
2414 = ::cppu::defaultBootstrap_InitialComponentContext();
2415 uno::Reference<lang::XMultiServiceFactory> xMSF;
2416 xMSF.set(xComponentContext->getServiceManager(), uno::UNO_QUERY);
2417 if(!xMSF.is())
2418 Application::Abort("Bootstrap failure - no service manager");
2419
2420 ::comphelper::setProcessServiceFactory(xMSF);
2421 }
2422 catch (const uno::Exception &e)
2423 {
2424 Application::Abort("Bootstrap exception " + e.Message);
2425 }
2426 }
2427 void DeInit() override
2428 {
2429 uno::Reference< lang::XComponent >(
2430 comphelper::getProcessComponentContext(),
2431 uno::UNO_QUERY_THROW)-> dispose();
2432 ::comphelper::setProcessServiceFactory(nullptr);
2433 }
2434};
2435
2436}
2437
2438void vclmain::createApplication()
2439{
2440#ifdef _WIN32
2441 _putenv_s("LIBO_VCL_DEMO", "1");
2442#else
2443 setenv("LIBO_VCL_DEMO", "1", 0);
2444#endif
2445 static DemoApp aApp;
2446}
2447
2448/* vim:set shiftwidth=4 softtabstop=4 expandtab: */