Bug Summary

File:home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx
Warning:line 994, column 28
Assigned value is garbage or undefined

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 salgdilayout.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 -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/libmount -isystem /usr/include/blkid -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/libxml2 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/dbus-1.0 -isystem /usr/lib64/dbus-1.0/include -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -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 VCL_DLLIMPLEMENTATION -D DLLIMPLEMENTATION_UITEST -D CUI_DLL_NAME="libcuilo.so" -D DESKTOP_DETECTOR_DLL_NAME="libdesktop_detectorlo.so" -D TK_DLL_NAME="libtklo.so" -D SYSTEM_ZLIB -D GLM_FORCE_CTOR_INIT -D SK_USER_CONFIG_HEADER=</home/maarten/src/libreoffice/core/config_host/config_skia.h> -D SKIA_DLL -D ENABLE_CUPS -D HAVE_VALGRIND_HEADERS -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/skia/include/core -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/effects -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/config -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/ports -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/third_party/vulkan -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/tools/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia -I /home/maarten/src/libreoffice/core/external/skia/inc/ -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/lcms2/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/harfbuzz/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/graphite/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libpng -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libjpeg-turbo -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/vcl/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libxml2 -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/source/gdi/salgdilayout.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 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <memory>
21#include <config_features.h>
22#include <sal/log.hxx>
23#if HAVE_FEATURE_OPENGL1
24#include <opengl/gdiimpl.hxx>
25#include <opengl/zone.hxx>
26#include <desktop/exithelper.h>
27#ifdef _WIN32
28#include <svsys.h>
29#endif
30#endif
31#include <PhysicalFontFace.hxx>
32#include <fontsubset.hxx>
33#include <salgdi.hxx>
34#include <salframe.hxx>
35#include <sft.hxx>
36#include <basegfx/matrix/b2dhommatrix.hxx>
37#include <basegfx/matrix/b2dhommatrixtools.hxx>
38#include <FileDefinitionWidgetDraw.hxx>
39
40// The only common SalFrame method
41
42SalFrameGeometry SalFrame::GetGeometry() const
43{
44 // mirror frame coordinates at parent
45 SalFrame *pParent = GetParent();
46 if( pParent && AllSettings::GetLayoutRTL() )
47 {
48 SalFrameGeometry aGeom = maGeometry;
49 int parent_x = aGeom.nX - pParent->maGeometry.nX;
50 aGeom.nX = pParent->maGeometry.nX + pParent->maGeometry.nWidth - maGeometry.nWidth - parent_x;
51 return aGeom;
52 }
53 else
54 return maGeometry;
55}
56
57SalGraphics::SalGraphics()
58: m_nLayout( SalLayoutFlags::NONE ),
59 m_aLastMirror(),
60 m_aLastMirrorW(0),
61 m_bAntiAlias(false)
62{
63 // read global RTL settings
64 if( AllSettings::GetLayoutRTL() )
65 m_nLayout = SalLayoutFlags::BiDiRtl;
66}
67
68bool SalGraphics::initWidgetDrawBackends(bool bForce)
69{
70 bool bFileDefinitionsWidgetDraw = !!getenv("VCL_DRAW_WIDGETS_FROM_FILE");
71
72 if (bFileDefinitionsWidgetDraw || bForce)
73 {
74 m_pWidgetDraw.reset(new vcl::FileDefinitionWidgetDraw(*this));
75 auto pFileDefinitionWidgetDraw = static_cast<vcl::FileDefinitionWidgetDraw*>(m_pWidgetDraw.get());
76 if (!pFileDefinitionWidgetDraw->isActive())
77 {
78 m_pWidgetDraw.reset();
79 return false;
80 }
81 return true;
82 }
83 return false;
84}
85
86SalGraphics::~SalGraphics() COVERITY_NOEXCEPT_FALSE
87{
88 // can't call ReleaseFonts here, as the destructor just calls this classes SetFont (pure virtual)!
89}
90
91#if HAVE_FEATURE_OPENGL1
92
93namespace
94{
95 void disableOpenGLAndTerminateForRestart()
96 {
97 OpenGLZone::hardDisable();
98#ifdef _WIN32
99 TerminateProcess(GetCurrentProcess(), EXITHELPER_NORMAL_RESTART);
100#endif
101 }
102}
103
104rtl::Reference<OpenGLContext> SalGraphics::GetOpenGLContext() const
105{
106 OpenGLSalGraphicsImpl *pImpl = dynamic_cast<OpenGLSalGraphicsImpl*>(GetImpl());
107 if (pImpl)
108 {
109 // If we notice that OpenGL is broken the first time being called, it is not too late to call
110 // disableOpenGLAndTerminateForRestart(). The first time this will be called is from displaying
111 // the splash screen, so if OpenGL is broken, it is "early enough" for us to be able to disable
112 // OpenGL and terminate bluntly with EXITHELPER_NORMAL_RESTART, thus causing the wrapper process
113 // to restart us, then without using OpenGL.
114 static bool bFirstCall = true;
115 rtl::Reference<OpenGLContext> xRet(pImpl->GetOpenGLContext());
116 if (!xRet.is() && bFirstCall)
117 disableOpenGLAndTerminateForRestart();
118 bFirstCall = false;
119 return xRet;
120 }
121 return nullptr;
122}
123
124#endif
125
126bool SalGraphics::drawTransformedBitmap(
127 const basegfx::B2DPoint& /* rNull */,
128 const basegfx::B2DPoint& /* rX */,
129 const basegfx::B2DPoint& /* rY */,
130 const SalBitmap& /* rSourceBitmap */,
131 const SalBitmap* /* pAlphaBitmap */)
132{
133 // here direct support for transformed bitmaps can be implemented
134 return false;
135}
136
137long SalGraphics::mirror2( long x, const OutputDevice *pOutDev ) const
138{
139 mirror(x, pOutDev);
140 return x;
141}
142
143inline long SalGraphics::GetDeviceWidth(const OutputDevice* pOutDev) const
144{
145 return (pOutDev && pOutDev->IsVirtual())
146 ? pOutDev->GetOutputWidthPixel() : GetGraphicsWidth();
147}
148
149void SalGraphics::mirror( long& x, const OutputDevice *pOutDev ) const
150{
151 const long w = GetDeviceWidth(pOutDev);
152 if( !w )
153 return;
154
155 if( pOutDev && pOutDev->ImplIsAntiparallel() )
156 {
157 OutputDevice *pOutDevRef = const_cast<OutputDevice*>(pOutDev);
158 // mirror this window back
159 if( m_nLayout & SalLayoutFlags::BiDiRtl )
160 {
161 long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
162 x = devX + (x - pOutDevRef->GetOutOffXPixel());
163 }
164 else
165 {
166 long devX = pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
167 x = pOutDevRef->GetOutputWidthPixel() - (x - devX) + pOutDevRef->GetOutOffXPixel() - 1;
168 }
169 }
170 else if( m_nLayout & SalLayoutFlags::BiDiRtl )
171 x = w-1-x;
172}
173
174void SalGraphics::mirror( long& x, long nWidth, const OutputDevice *pOutDev, bool bBack ) const
175{
176 const long w = GetDeviceWidth(pOutDev);
177 if( !w )
178 return;
179
180 if( pOutDev && pOutDev->ImplIsAntiparallel() )
181 {
182 OutputDevice *pOutDevRef = const_cast<OutputDevice*>(pOutDev);
183 // mirror this window back
184 if( m_nLayout & SalLayoutFlags::BiDiRtl )
185 {
186 long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
187 if( bBack )
188 x = x - devX + pOutDevRef->GetOutOffXPixel();
189 else
190 x = devX + (x - pOutDevRef->GetOutOffXPixel());
191 }
192 else
193 {
194 long devX = pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
195 if( bBack )
196 x = devX + (pOutDevRef->GetOutputWidthPixel() + devX) - (x + nWidth);
197 else
198 x = pOutDevRef->GetOutputWidthPixel() - (x - devX) + pOutDevRef->GetOutOffXPixel() - nWidth;
199 }
200 }
201 else if( m_nLayout & SalLayoutFlags::BiDiRtl )
202 x = w-nWidth-x;
203}
204
205bool SalGraphics::mirror( sal_uInt32 nPoints, const SalPoint *pPtAry, SalPoint *pPtAry2, const OutputDevice *pOutDev ) const
206{
207 const long w = GetDeviceWidth(pOutDev);
208 if( w )
209 {
210 sal_uInt32 i, j;
211
212 if( pOutDev && pOutDev->ImplIsAntiparallel() )
213 {
214 OutputDevice *pOutDevRef = const_cast<OutputDevice*>(pOutDev);
215 // mirror this window back
216 if( m_nLayout & SalLayoutFlags::BiDiRtl )
217 {
218 long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
219 for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
220 {
221 pPtAry2[j].mnX = devX + (pPtAry[i].mnX - pOutDevRef->GetOutOffXPixel());
222 pPtAry2[j].mnY = pPtAry[i].mnY;
223 }
224 }
225 else
226 {
227 long devX = pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
228 for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
229 {
230 pPtAry2[j].mnX = pOutDevRef->GetOutputWidthPixel() - (pPtAry[i].mnX - devX) + pOutDevRef->GetOutOffXPixel() - 1;
231 pPtAry2[j].mnY = pPtAry[i].mnY;
232 }
233 }
234 }
235 else if( m_nLayout & SalLayoutFlags::BiDiRtl )
236 {
237 for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
238 {
239 pPtAry2[j].mnX = w-1-pPtAry[i].mnX;
240 pPtAry2[j].mnY = pPtAry[i].mnY;
241 }
242 }
243 return true;
244 }
245 else
246 return false;
247}
248
249void SalGraphics::mirror( vcl::Region& rRgn, const OutputDevice *pOutDev ) const
250{
251 if( rRgn.HasPolyPolygonOrB2DPolyPolygon() )
252 {
253 const basegfx::B2DPolyPolygon aPolyPoly(mirror(rRgn.GetAsB2DPolyPolygon(), pOutDev));
254
255 rRgn = vcl::Region(aPolyPoly);
256 }
257 else
258 {
259 RectangleVector aRectangles;
260 rRgn.GetRegionRectangles(aRectangles);
261 rRgn.SetEmpty();
262
263 for (auto & rectangle : aRectangles)
264 {
265 mirror(rectangle, pOutDev);
266 rRgn.Union(rectangle);
267 }
268
269 //ImplRegionInfo aInfo;
270 //bool bRegionRect;
271 //Region aMirroredRegion;
272 //long nX, nY, nWidth, nHeight;
273
274 //bRegionRect = rRgn.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
275 //while ( bRegionRect )
276 //{
277 // Rectangle aRect( Point(nX, nY), Size(nWidth, nHeight) );
278 // mirror( aRect, pOutDev, bBack );
279 // aMirroredRegion.Union( aRect );
280 // bRegionRect = rRgn.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
281 //}
282 //rRgn = aMirroredRegion;
283 }
284}
285
286void SalGraphics::mirror( tools::Rectangle& rRect, const OutputDevice *pOutDev, bool bBack ) const
287{
288 long nWidth = rRect.GetWidth();
289 long x = rRect.Left();
290 long x_org = x;
291
292 mirror( x, nWidth, pOutDev, bBack );
293 rRect.Move( x - x_org, 0 );
294}
295
296basegfx::B2DPolyPolygon SalGraphics::mirror( const basegfx::B2DPolyPolygon& i_rPoly, const OutputDevice* i_pOutDev ) const
297{
298 const basegfx::B2DHomMatrix& rMirror(getMirror(i_pOutDev));
299
300 if(rMirror.isIdentity())
301 {
302 return i_rPoly;
303 }
304 else
305 {
306 basegfx::B2DPolyPolygon aRet(i_rPoly);
307 aRet.transform(rMirror);
308 aRet.flip();
309 return aRet;
310 }
311}
312
313const basegfx::B2DHomMatrix& SalGraphics::getMirror( const OutputDevice* i_pOutDev ) const
314{
315 // get mirroring transformation
316 const long w = GetDeviceWidth(i_pOutDev);
317 SAL_WARN_IF( !w, "vcl", "missing graphics width" )do { if (true && (!w)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "missing graphics width"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "317" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "missing graphics width"), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"missing graphics width"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "317" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "missing graphics width") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "317" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "missing graphics width"), 0); } else {
::std::ostringstream sal_detail_stream; sal_detail_stream <<
"missing graphics width"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "317" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
318
319 if(w != m_aLastMirrorW)
320 {
321 const_cast<SalGraphics*>(this)->m_aLastMirrorW = w;
322
323 if(w)
324 {
325 if(nullptr != i_pOutDev && !i_pOutDev->IsRTLEnabled())
326 {
327 // Original code was (removed here already pOutDevRef->i_pOutDev):
328 // // mirror this window back
329 // double devX = w-i_pOutDev->GetOutputWidthPixel()-i_pOutDev->GetOutOffXPixel(); // re-mirrored mnOutOffX
330 // aRet.setX( devX + (i_rPoint.getX() - i_pOutDev->GetOutOffXPixel()) );
331 // I do not really understand the comment 'mirror this window back', so cannot guarantee
332 // that this works as before, but I have reduced this (by re-placing and re-formatting) to
333 // a simple translation:
334 const_cast<SalGraphics*>(this)->m_aLastMirror = basegfx::utils::createTranslateB2DHomMatrix(
335 w - i_pOutDev->GetOutputWidthPixel() - (2 * i_pOutDev->GetOutOffXPixel()),
336 0.0);
337 }
338 else
339 {
340 // Original code was:
341 // aRet.setX( w-1-i_rPoint.getX() );
342 // -mirror X -> scale(-1.0, 1.0)
343 // -translate X -> translate(w-1, 0)
344 // Checked this one, works as expected.
345 const_cast<SalGraphics*>(this)->m_aLastMirror = basegfx::utils::createScaleTranslateB2DHomMatrix(
346 -1.0,
347 1.0,
348 w-1,
349 0.0);
350 }
351 }
352 else
353 {
354 const_cast<SalGraphics*>(this)->m_aLastMirror.identity();
355 }
356 }
357
358 return m_aLastMirror;
359}
360
361bool SalGraphics::SetClipRegion( const vcl::Region& i_rClip, const OutputDevice *pOutDev )
362{
363 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
364 {
365 vcl::Region aMirror( i_rClip );
366 mirror( aMirror, pOutDev );
367 return setClipRegion( aMirror );
368 }
369 return setClipRegion( i_rClip );
370}
371
372void SalGraphics::DrawPixel( long nX, long nY, const OutputDevice *pOutDev )
373{
374 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
375 mirror( nX, pOutDev );
376 drawPixel( nX, nY );
377}
378
379void SalGraphics::DrawPixel( long nX, long nY, Color nColor, const OutputDevice *pOutDev )
380{
381 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
382 mirror( nX, pOutDev );
383 drawPixel( nX, nY, nColor );
384}
385
386void SalGraphics::DrawLine( long nX1, long nY1, long nX2, long nY2, const OutputDevice *pOutDev )
387{
388 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
389 {
390 mirror( nX1, pOutDev );
391 mirror( nX2, pOutDev );
392 }
393 drawLine( nX1, nY1, nX2, nY2 );
394}
395
396void SalGraphics::DrawRect( long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev )
397{
398 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
399 mirror( nX, nWidth, pOutDev );
400 drawRect( nX, nY, nWidth, nHeight );
401}
402
403void SalGraphics::DrawPolyLine( sal_uInt32 nPoints, SalPoint const * pPtAry, const OutputDevice *pOutDev )
404{
405 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
406 {
407 std::unique_ptr<SalPoint[]> pPtAry2(new SalPoint[nPoints]);
408 bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev );
409 drawPolyLine( nPoints, bCopied ? pPtAry2.get() : pPtAry );
410 }
411 else
412 drawPolyLine( nPoints, pPtAry );
413}
414
415void SalGraphics::DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry, const OutputDevice *pOutDev )
416{
417 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
418 {
419 std::unique_ptr<SalPoint[]> pPtAry2(new SalPoint[nPoints]);
420 bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev );
421 drawPolygon( nPoints, bCopied ? pPtAry2.get() : pPtAry );
422 }
423 else
424 drawPolygon( nPoints, pPtAry );
425}
426
427void SalGraphics::DrawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry, const OutputDevice *pOutDev )
428{
429 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
430 {
431 // TODO: optimize, reduce new/delete calls
432 std::unique_ptr<SalPoint*[]> pPtAry2( new SalPoint*[nPoly] );
433 sal_uLong i;
434 for(i=0; i<nPoly; i++)
435 {
436 sal_uLong nPoints = pPoints[i];
437 pPtAry2[i] = new SalPoint[ nPoints ];
438 mirror( nPoints, pPtAry[i], pPtAry2[i], pOutDev );
439 }
440
441 drawPolyPolygon( nPoly, pPoints, const_cast<PCONSTSALPOINT*>(pPtAry2.get()) );
442
443 for(i=0; i<nPoly; i++)
444 delete [] pPtAry2[i];
445 }
446 else
447 drawPolyPolygon( nPoly, pPoints, pPtAry );
448}
449
450namespace
451{
452 basegfx::B2DHomMatrix createTranslateToMirroredBounds(const basegfx::B2DRange &rBoundingBox, const basegfx::B2DHomMatrix& rMirror)
453 {
454 basegfx::B2DRange aRTLBoundingBox(rBoundingBox);
455 aRTLBoundingBox *= rMirror;
456 return basegfx::utils::createTranslateB2DHomMatrix(aRTLBoundingBox.getMinX() - rBoundingBox.getMinX(), 0);
457 }
458}
459
460bool SalGraphics::DrawPolyPolygon(
461 const basegfx::B2DHomMatrix& rObjectToDevice,
462 const basegfx::B2DPolyPolygon& i_rPolyPolygon,
463 double i_fTransparency,
464 const OutputDevice* i_pOutDev)
465{
466 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
467 {
468 // mirroring set
469 const basegfx::B2DHomMatrix& rMirror(getMirror(i_pOutDev));
470 if(!rMirror.isIdentity())
471 {
472 basegfx::B2DRange aBoundingBox(i_rPolyPolygon.getB2DRange());
473 aBoundingBox *= rObjectToDevice;
474 auto aTranslateToMirroredBounds = createTranslateToMirroredBounds(aBoundingBox, rMirror);
475
476 return drawPolyPolygon(
477 aTranslateToMirroredBounds * rObjectToDevice,
478 i_rPolyPolygon,
479 i_fTransparency);
480 }
481 }
482
483 return drawPolyPolygon(
484 rObjectToDevice,
485 i_rPolyPolygon,
486 i_fTransparency);
487}
488
489bool SalGraphics::DrawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry, const OutputDevice* pOutDev )
490{
491 bool bResult = false;
492 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
493 {
494 std::unique_ptr<SalPoint[]> pPtAry2(new SalPoint[nPoints]);
495 bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev );
496 bResult = drawPolyLineBezier( nPoints, bCopied ? pPtAry2.get() : pPtAry, pFlgAry );
497 }
498 else
499 bResult = drawPolyLineBezier( nPoints, pPtAry, pFlgAry );
500 return bResult;
501}
502
503bool SalGraphics::DrawPolygonBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry, const OutputDevice* pOutDev )
504{
505 bool bResult = false;
506 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
507 {
508 std::unique_ptr<SalPoint[]> pPtAry2(new SalPoint[nPoints]);
509 bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev );
510 bResult = drawPolygonBezier( nPoints, bCopied ? pPtAry2.get() : pPtAry, pFlgAry );
511 }
512 else
513 bResult = drawPolygonBezier( nPoints, pPtAry, pFlgAry );
514 return bResult;
515}
516
517bool SalGraphics::DrawPolyPolygonBezier( sal_uInt32 i_nPoly, const sal_uInt32* i_pPoints,
518 const SalPoint* const* i_pPtAry, const PolyFlags* const* i_pFlgAry, const OutputDevice* i_pOutDev )
519{
520 bool bRet = false;
521 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
522 {
523 // TODO: optimize, reduce new/delete calls
524 std::unique_ptr<SalPoint*[]> pPtAry2( new SalPoint*[i_nPoly] );
525 sal_uLong i;
526 for(i=0; i<i_nPoly; i++)
527 {
528 sal_uLong nPoints = i_pPoints[i];
529 pPtAry2[i] = new SalPoint[ nPoints ];
530 mirror( nPoints, i_pPtAry[i], pPtAry2[i], i_pOutDev );
531 }
532
533 bRet = drawPolyPolygonBezier( i_nPoly, i_pPoints, const_cast<PCONSTSALPOINT const *>(pPtAry2.get()), i_pFlgAry );
534
535 for(i=0; i<i_nPoly; i++)
536 delete [] pPtAry2[i];
537 }
538 else
539 bRet = drawPolyPolygonBezier( i_nPoly, i_pPoints, i_pPtAry, i_pFlgAry );
540 return bRet;
541}
542
543bool SalGraphics::DrawPolyLine(
544 const basegfx::B2DHomMatrix& rObjectToDevice,
545 const basegfx::B2DPolygon& i_rPolygon,
546 double i_fTransparency,
547 double i_rLineWidth,
548 const std::vector< double >* i_pStroke, // MM01
549 basegfx::B2DLineJoin i_eLineJoin,
550 css::drawing::LineCap i_eLineCap,
551 double i_fMiterMinimumAngle,
552 bool bPixelSnapHairline,
553 const OutputDevice* i_pOutDev)
554{
555 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
556 {
557 // mirroring set
558 const basegfx::B2DHomMatrix& rMirror(getMirror(i_pOutDev));
559 if(!rMirror.isIdentity())
560 {
561 basegfx::B2DRange aBoundingBox(i_rPolygon.getB2DRange());
562 aBoundingBox *= rObjectToDevice;
563 auto aTranslateToMirroredBounds = createTranslateToMirroredBounds(aBoundingBox, rMirror);
564
565 return drawPolyLine(
566 aTranslateToMirroredBounds * rObjectToDevice,
567 i_rPolygon,
568 i_fTransparency,
569 i_rLineWidth,
570 i_pStroke, // MM01
571 i_eLineJoin,
572 i_eLineCap,
573 i_fMiterMinimumAngle,
574 bPixelSnapHairline);
575 }
576 }
577
578 // no mirroring set (or identity), use standard call
579 return drawPolyLine(
580 rObjectToDevice,
581 i_rPolygon,
582 i_fTransparency,
583 i_rLineWidth,
584 i_pStroke, // MM01
585 i_eLineJoin,
586 i_eLineCap,
587 i_fMiterMinimumAngle,
588 bPixelSnapHairline);
589}
590
591bool SalGraphics::DrawGradient( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient )
592{
593 return drawGradient( rPolyPoly, rGradient );
594}
595
596bool SalGraphics::DrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rSalGradient)
597{
598 return implDrawGradient(rPolyPolygon, rSalGradient);
599}
600
601void SalGraphics::CopyArea( long nDestX, long nDestY,
602 long nSrcX, long nSrcY,
603 long nSrcWidth, long nSrcHeight,
604 const OutputDevice *pOutDev )
605{
606 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
607 {
608 mirror( nDestX, nSrcWidth, pOutDev );
609 mirror( nSrcX, nSrcWidth, pOutDev );
610 }
611 copyArea( nDestX, nDestY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, true/*bWindowInvalidate*/ );
612}
613
614void SalGraphics::CopyBits( const SalTwoRect& rPosAry,
615 SalGraphics* pSrcGraphics, const OutputDevice *pOutDev, const OutputDevice *pSrcOutDev )
616{
617 if( ( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) ||
618 (pSrcGraphics && ( (pSrcGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) || (pSrcOutDev && pSrcOutDev->IsRTLEnabled()) ) ) )
619 {
620 SalTwoRect aPosAry2 = rPosAry;
621 if( (pSrcGraphics && (pSrcGraphics->GetLayout() & SalLayoutFlags::BiDiRtl)) || (pSrcOutDev && pSrcOutDev->IsRTLEnabled()) )
622 mirror( aPosAry2.mnSrcX, aPosAry2.mnSrcWidth, pSrcOutDev );
623 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
624 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
625 copyBits( aPosAry2, pSrcGraphics );
626 }
627 else
628 copyBits( rPosAry, pSrcGraphics );
629}
630
631void SalGraphics::DrawBitmap( const SalTwoRect& rPosAry,
632 const SalBitmap& rSalBitmap, const OutputDevice *pOutDev )
633{
634 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
635 {
636 SalTwoRect aPosAry2 = rPosAry;
637 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
638 drawBitmap( aPosAry2, rSalBitmap );
639 }
640 else
641 drawBitmap( rPosAry, rSalBitmap );
642}
643
644void SalGraphics::DrawBitmap( const SalTwoRect& rPosAry,
645 const SalBitmap& rSalBitmap,
646 const SalBitmap& rTransparentBitmap, const OutputDevice *pOutDev )
647{
648 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
649 {
650 SalTwoRect aPosAry2 = rPosAry;
651 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
652 drawBitmap( aPosAry2, rSalBitmap, rTransparentBitmap );
653 }
654 else
655 drawBitmap( rPosAry, rSalBitmap, rTransparentBitmap );
656}
657
658void SalGraphics::DrawMask( const SalTwoRect& rPosAry,
659 const SalBitmap& rSalBitmap,
660 Color nMaskColor, const OutputDevice *pOutDev )
661{
662 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
663 {
664 SalTwoRect aPosAry2 = rPosAry;
665 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
666 drawMask( aPosAry2, rSalBitmap, nMaskColor );
667 }
668 else
669 drawMask( rPosAry, rSalBitmap, nMaskColor );
670}
671
672std::shared_ptr<SalBitmap> SalGraphics::GetBitmap( long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev )
673{
674 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
675 mirror( nX, nWidth, pOutDev );
676 return getBitmap( nX, nY, nWidth, nHeight );
677}
678
679Color SalGraphics::GetPixel( long nX, long nY, const OutputDevice *pOutDev )
680{
681 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
682 mirror( nX, pOutDev );
683 return getPixel( nX, nY );
684}
685
686void SalGraphics::Invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags, const OutputDevice *pOutDev )
687{
688 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
689 mirror( nX, nWidth, pOutDev );
690 invert( nX, nY, nWidth, nHeight, nFlags );
691}
692
693void SalGraphics::Invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags, const OutputDevice *pOutDev )
694{
695 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
696 {
697 std::unique_ptr<SalPoint[]> pPtAry2(new SalPoint[nPoints]);
698 bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev );
699 invert( nPoints, bCopied ? pPtAry2.get() : pPtAry, nFlags );
700 }
701 else
702 invert( nPoints, pPtAry, nFlags );
703}
704
705bool SalGraphics::DrawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uInt32 nSize, const OutputDevice *pOutDev )
706{
707 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
708 mirror( nX, nWidth, pOutDev );
709 return drawEPS( nX, nY, nWidth, nHeight, pPtr, nSize );
710}
711
712bool SalGraphics::HitTestNativeScrollbar( ControlPart nPart, const tools::Rectangle& rControlRegion,
713 const Point& aPos, bool& rIsInside, const OutputDevice *pOutDev )
714{
715 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
716 {
717 Point pt( aPos );
718 tools::Rectangle rgn( rControlRegion );
719 pt.setX( mirror2( pt.X(), pOutDev ) );
720 mirror( rgn, pOutDev );
721 return forWidget()->hitTestNativeControl( ControlType::Scrollbar, nPart, rgn, pt, rIsInside );
722 }
723 else
724 return forWidget()->hitTestNativeControl( ControlType::Scrollbar, nPart, rControlRegion, aPos, rIsInside );
725}
726
727void SalGraphics::mirror( ImplControlValue& rVal, const OutputDevice* pOutDev ) const
728{
729 switch( rVal.getType() )
730 {
731 case ControlType::Slider:
732 {
733 SliderValue* pSlVal = static_cast<SliderValue*>(&rVal);
734 mirror(pSlVal->maThumbRect,pOutDev);
735 }
736 break;
737 case ControlType::Scrollbar:
738 {
739 ScrollbarValue* pScVal = static_cast<ScrollbarValue*>(&rVal);
740 mirror(pScVal->maThumbRect,pOutDev);
741 mirror(pScVal->maButton1Rect,pOutDev);
742 mirror(pScVal->maButton2Rect,pOutDev);
743 }
744 break;
745 case ControlType::Spinbox:
746 case ControlType::SpinButtons:
747 {
748 SpinbuttonValue* pSpVal = static_cast<SpinbuttonValue*>(&rVal);
749 mirror(pSpVal->maUpperRect,pOutDev);
750 mirror(pSpVal->maLowerRect,pOutDev);
751 }
752 break;
753 case ControlType::Toolbar:
754 {
755 ToolbarValue* pTVal = static_cast<ToolbarValue*>(&rVal);
756 mirror(pTVal->maGripRect,pOutDev);
757 }
758 break;
759 default: break;
760 }
761}
762
763bool SalGraphics::DrawNativeControl( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion,
764 ControlState nState, const ImplControlValue& aValue,
765 const OUString& aCaption, const OutputDevice *pOutDev,
766 const Color& rBackgroundColor)
767{
768 bool bRet = false;
769 tools::Rectangle aControlRegion(rControlRegion);
770 if (aControlRegion.IsEmpty() || aControlRegion.GetWidth() <= 0 || aControlRegion.GetHeight() <= 0)
771 return bRet;
772
773 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
774 {
775 mirror(aControlRegion, pOutDev);
776 std::unique_ptr< ImplControlValue > mirrorValue( aValue.clone());
777 mirror( *mirrorValue, pOutDev );
778 bRet = forWidget()->drawNativeControl(nType, nPart, aControlRegion, nState, *mirrorValue, aCaption, rBackgroundColor);
779 }
780 else
781 bRet = forWidget()->drawNativeControl(nType, nPart, aControlRegion, nState, aValue, aCaption, rBackgroundColor);
782
783 if (bRet && m_pWidgetDraw)
784 handleDamage(aControlRegion);
785 return bRet;
786}
787
788bool SalGraphics::GetNativeControlRegion( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, ControlState nState,
789 const ImplControlValue& aValue,
790 tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion, const OutputDevice *pOutDev )
791{
792 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
793 {
794 tools::Rectangle rgn( rControlRegion );
795 mirror( rgn, pOutDev );
796 std::unique_ptr< ImplControlValue > mirrorValue( aValue.clone());
797 mirror( *mirrorValue, pOutDev );
798 if (forWidget()->getNativeControlRegion(nType, nPart, rgn, nState, *mirrorValue, OUString(), rNativeBoundingRegion, rNativeContentRegion))
799 {
800 mirror( rNativeBoundingRegion, pOutDev, true );
801 mirror( rNativeContentRegion, pOutDev, true );
802 return true;
803 }
804 return false;
805 }
806 else
807 return forWidget()->getNativeControlRegion(nType, nPart, rControlRegion, nState, aValue, OUString(), rNativeBoundingRegion, rNativeContentRegion);
808}
809
810bool SalGraphics::BlendBitmap( const SalTwoRect& rPosAry,
811 const SalBitmap& rBitmap,
812 const OutputDevice *pOutDev )
813{
814 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
815 {
816 SalTwoRect aPosAry2 = rPosAry;
817 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
818 return blendBitmap( aPosAry2, rBitmap );
819 }
820 else
821 return blendBitmap( rPosAry, rBitmap );
822}
823
824bool SalGraphics::BlendAlphaBitmap( const SalTwoRect& rPosAry,
825 const SalBitmap& rSrcBitmap,
826 const SalBitmap& rMaskBitmap,
827 const SalBitmap& rAlphaBitmap,
828 const OutputDevice *pOutDev )
829{
830 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
831 {
832 SalTwoRect aPosAry2 = rPosAry;
833 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
834 return blendAlphaBitmap( aPosAry2, rSrcBitmap, rMaskBitmap, rAlphaBitmap );
835 }
836 else
837 return blendAlphaBitmap( rPosAry, rSrcBitmap, rMaskBitmap, rAlphaBitmap );
838}
839
840bool SalGraphics::DrawAlphaBitmap( const SalTwoRect& rPosAry,
841 const SalBitmap& rSourceBitmap,
842 const SalBitmap& rAlphaBitmap,
843 const OutputDevice *pOutDev )
844{
845 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
846 {
847 SalTwoRect aPosAry2 = rPosAry;
848 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
849 return drawAlphaBitmap( aPosAry2, rSourceBitmap, rAlphaBitmap );
850 }
851 else
852 return drawAlphaBitmap( rPosAry, rSourceBitmap, rAlphaBitmap );
853}
854
855bool SalGraphics::DrawTransformedBitmap(
856 const basegfx::B2DPoint& rNull,
857 const basegfx::B2DPoint& rX,
858 const basegfx::B2DPoint& rY,
859 const SalBitmap& rSourceBitmap,
860 const SalBitmap* pAlphaBitmap,
861 const OutputDevice* pOutDev)
862{
863 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
864 {
865 // mirroring set
866 const basegfx::B2DHomMatrix& rMirror(getMirror(pOutDev));
867 if (!rMirror.isIdentity())
868 {
869 basegfx::B2DPolygon aPoints({rNull, rX, rY});
870 basegfx::B2DRange aBoundingBox(aPoints.getB2DRange());
871 auto aTranslateToMirroredBounds = createTranslateToMirroredBounds(aBoundingBox, rMirror);
872
873 basegfx::B2DPoint aNull = aTranslateToMirroredBounds * rNull;
874 basegfx::B2DPoint aX = aTranslateToMirroredBounds * rX;
875 basegfx::B2DPoint aY = aTranslateToMirroredBounds * rY;
876
877 return drawTransformedBitmap(aNull, aX, aY, rSourceBitmap, pAlphaBitmap);
878 }
879 }
880
881 return drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap);
882}
883
884bool SalGraphics::DrawAlphaRect( long nX, long nY, long nWidth, long nHeight,
885 sal_uInt8 nTransparency, const OutputDevice *pOutDev )
886{
887 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
888 mirror( nX, nWidth, pOutDev );
889
890 return drawAlphaRect( nX, nY, nWidth, nHeight, nTransparency );
891}
892
893OUString SalGraphics::getRenderBackendName() const
894{
895 if (GetImpl())
896 return GetImpl()->getRenderBackendName();
897 return OUString();
898}
899
900void SalGraphics::GetGlyphWidths(const vcl::AbstractTrueTypeFont& rTTF,
901 const PhysicalFontFace& rFontFace, const bool bVertical,
902 std::vector<sal_Int32>& rWidths, Ucs2UIntMap& rUnicodeEnc)
903{
904 rWidths.clear();
905 rUnicodeEnc.clear();
906
907 const int nGlyphCount = rTTF.glyphCount();
908 if (nGlyphCount <= 0)
909 return;
910
911 FontCharMapRef xFCMap = rFontFace.GetFontCharMap();
912 if (!xFCMap.is() || !xFCMap->GetCharCount())
913 {
914 SAL_WARN("vcl.fonts", "no charmap")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.fonts")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "no charmap") == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "914" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "no charmap"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "no charmap"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "914" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "no charmap") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.fonts"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "914" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "no charmap"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "no charmap"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "914" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
915 return;
916 }
917
918 rWidths.resize(nGlyphCount);
919 std::vector<sal_uInt16> aGlyphIds(nGlyphCount);
920 for (int i = 0; i < nGlyphCount; i++)
921 aGlyphIds[i] = static_cast<sal_uInt16>(i);
922
923 std::unique_ptr<sal_uInt16[]> pGlyphMetrics
924 = GetTTSimpleGlyphMetrics(&rTTF, aGlyphIds.data(), nGlyphCount, bVertical);
925 if (pGlyphMetrics)
926 {
927 for (int i = 0; i < nGlyphCount; ++i)
928 rWidths[i] = pGlyphMetrics[i];
929 pGlyphMetrics.reset();
930 }
931
932 int nCharCount = xFCMap->GetCharCount();
933 sal_uInt32 nChar = xFCMap->GetFirstChar();
934 for (; --nCharCount >= 0; nChar = xFCMap->GetNextChar(nChar))
935 {
936 if (nChar > 0xFFFF)
937 continue;
938
939 sal_Ucs nUcsChar = static_cast<sal_Ucs>(nChar);
940 sal_uInt32 nGlyph = xFCMap->GetGlyphIndex(nUcsChar);
941 if (nGlyph > 0)
942 rUnicodeEnc[nUcsChar] = nGlyph;
943 }
944}
945
946bool SalGraphics::CreateTTFfontSubset(vcl::AbstractTrueTypeFont& rTTF, const OString& rSysPath,
947 const bool bVertical, const sal_GlyphId* pGlyphIds,
948 const sal_uInt8* pEncoding, sal_Int32* pGlyphWidths,
949 const int nOrigGlyphCount)
950{
951 // Multiple questions:
952 // - Why is there a glyph limit?
953 // MacOS used to handle 257 glyphs...
954 // Also the much more complex PrintFontManager variant has this limit.
955 // Also the very first implementation has the limit in
956 // commit 8789ed701e98031f2a1657ea0dfd6f7a0b050992
957 // - Why doesn't the PrintFontManager care about the fake glyph? It
958 // is used on all unx platforms to create the subset font.
959 // - Should the SAL_WARN actually be asserts, like on MacOS?
960 if (nOrigGlyphCount > 256)
1
Assuming 'nOrigGlyphCount' is <= 256
2
Taking false branch
961 {
962 SAL_WARN("vcl.fonts", "too many glyphs for subsetting")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.fonts")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "too many glyphs for subsetting"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "962" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "too many glyphs for subsetting"), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "too many glyphs for subsetting"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "962" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "too many glyphs for subsetting") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "962" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "too many glyphs for subsetting"), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "too many glyphs for subsetting"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "962" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
963 return false;
964 }
965
966 int nGlyphCount = nOrigGlyphCount;
967 sal_uInt16 aShortIDs[256];
968 sal_uInt8 aTempEncs[256];
969
970 // handle the undefined / first font glyph
971 int nNotDef = -1, i;
972 for (i = 0; i < nGlyphCount; ++i)
3
Assuming 'i' is >= 'nGlyphCount'
4
Loop condition is false. Execution continues on line 982
973 {
974 aTempEncs[i] = pEncoding[i];
975 aShortIDs[i] = static_cast<sal_uInt16>(pGlyphIds[i]);
976 if (!aShortIDs[i])
977 if (nNotDef < 0)
978 nNotDef = i;
979 }
980
981 // nNotDef glyph must be in pos 0 => swap glyphids
982 if (nNotDef
4.1
'nNotDef' is not equal to 0
!= 0)
5
Taking true branch
983 {
984 if (nNotDef
5.1
'nNotDef' is < 0
< 0)
6
Taking true branch
985 {
986 if (nGlyphCount
6.1
'nGlyphCount' is not equal to 256
== 256)
7
Taking false branch
987 {
988 SAL_WARN("vcl.fonts", "too many glyphs for subsetting")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.fonts")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "too many glyphs for subsetting"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "988" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "too many glyphs for subsetting"), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "too many glyphs for subsetting"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "988" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "too many glyphs for subsetting") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "988" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "too many glyphs for subsetting"), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "too many glyphs for subsetting"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.fonts"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/salgdilayout.cxx"
":" "988" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
989 return false;
990 }
991 nNotDef = nGlyphCount++;
992 }
993
994 aShortIDs[nNotDef] = aShortIDs[0];
8
Assigned value is garbage or undefined
995 aTempEncs[nNotDef] = aTempEncs[0];
996 aShortIDs[0] = 0;
997 aTempEncs[0] = 0;
998 }
999
1000 std::unique_ptr<sal_uInt16[]> pMetrics
1001 = GetTTSimpleGlyphMetrics(&rTTF, aShortIDs, nGlyphCount, bVertical);
1002 if (!pMetrics)
1003 return false;
1004
1005 sal_uInt16 nNotDefAdv = pMetrics[0];
1006 pMetrics[0] = pMetrics[nNotDef];
1007 pMetrics[nNotDef] = nNotDefAdv;
1008 for (i = 0; i < nOrigGlyphCount; ++i)
1009 pGlyphWidths[i] = pMetrics[i];
1010 pMetrics.reset();
1011
1012 // write subset into destination file
1013 return (CreateTTFromTTGlyphs(&rTTF, rSysPath.getStr(), aShortIDs, aTempEncs, nGlyphCount)
1014 == vcl::SFErrCodes::Ok);
1015}
1016
1017bool SalGraphics::CreateCFFfontSubset(const unsigned char* pFontBytes, int nByteLength,
1018 const OString& rSysPath, const sal_GlyphId* pGlyphIds,
1019 const sal_uInt8* pEncoding, sal_Int32* pGlyphWidths,
1020 int nGlyphCount, FontSubsetInfo& rInfo)
1021{
1022 FILE* pOutFile = fopen(rSysPath.getStr(), "wb");
1023 if (!pOutFile)
1024 return false;
1025 rInfo.LoadFont(FontType::CFF_FONT, pFontBytes, nByteLength);
1026 bool bRet = rInfo.CreateFontSubset(FontType::TYPE1_PFB, pOutFile, nullptr, pGlyphIds, pEncoding,
1027 nGlyphCount, pGlyphWidths);
1028 fclose(pOutFile);
1029 return bRet;
1030}
1031
1032void SalGraphics::FillFontSubsetInfo(const vcl::TTGlobalFontInfo& rTTInfo, const OUString& pPSName,
1033 FontSubsetInfo& rInfo)
1034{
1035 rInfo.m_aPSName = pPSName;
1036 rInfo.m_nFontType = FontType::SFNT_TTF;
1037 rInfo.m_aFontBBox
1038 = tools::Rectangle(Point(rTTInfo.xMin, rTTInfo.yMin), Point(rTTInfo.xMax, rTTInfo.yMax));
1039 rInfo.m_nCapHeight = rTTInfo.yMax; // Well ...
1040 rInfo.m_nAscent = rTTInfo.winAscent;
1041 rInfo.m_nDescent = rTTInfo.winDescent;
1042
1043 // mac fonts usually do not have an OS2-table
1044 // => get valid ascent/descent values from other tables
1045 if (!rInfo.m_nAscent)
1046 rInfo.m_nAscent = +rTTInfo.typoAscender;
1047 if (!rInfo.m_nAscent)
1048 rInfo.m_nAscent = +rTTInfo.ascender;
1049 if (!rInfo.m_nDescent)
1050 rInfo.m_nDescent = +rTTInfo.typoDescender;
1051 if (!rInfo.m_nDescent)
1052 rInfo.m_nDescent = -rTTInfo.descender;
1053}
1054
1055/* vim:set shiftwidth=4 softtabstop=4 expandtab: */