Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

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 wmfwr.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/filter/wmf/wmfwr.cxx

/home/maarten/src/libreoffice/core/vcl/source/filter/wmf/wmfwr.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 <sal/config.h>
21#include <osl/diagnose.h>
22
23#include <algorithm>
24
25#include "wmfwr.hxx"
26#include "emfwr.hxx"
27#include <rtl/crc.h>
28#include <rtl/tencinfo.h>
29#include <tools/bigint.hxx>
30#include <tools/helpers.hxx>
31#include <tools/tenccvt.hxx>
32#include <tools/fract.hxx>
33#include <tools/stream.hxx>
34#include <vcl/dibtools.hxx>
35#include <vcl/metaact.hxx>
36#include <vcl/FilterConfigItem.hxx>
37#include <basegfx/polygon/b2dpolygon.hxx>
38#include <basegfx/polygon/b2dpolypolygon.hxx>
39#include <memory>
40#include <vcl/fontcharmap.hxx>
41
42// MS Windows defines
43
44#define W_META_SETBKMODE0x0102 0x0102
45#define W_META_SETROP20x0104 0x0104
46#define W_META_SETSTRETCHBLTMODE0x0107 0x0107
47#define W_META_SETTEXTCOLOR0x0209 0x0209
48#define W_META_SETWINDOWORG0x020B 0x020B
49#define W_META_SETWINDOWEXT0x020C 0x020C
50#define W_META_LINETO0x0213 0x0213
51#define W_META_MOVETO0x0214 0x0214
52#define W_META_INTERSECTCLIPRECT0x0416 0x0416
53#define W_META_ARC0x0817 0x0817
54#define W_META_ELLIPSE0x0418 0x0418
55#define W_META_PIE0x081A 0x081A
56#define W_META_RECTANGLE0x041B 0x041B
57#define W_META_ROUNDRECT0x061C 0x061C
58#define W_META_SAVEDC0x001E 0x001E
59#define W_META_SETPIXEL0x041F 0x041F
60#define W_META_TEXTOUT0x0521 0x0521
61#define W_META_POLYGON0x0324 0x0324
62#define W_META_POLYLINE0x0325 0x0325
63#define W_META_ESCAPE0x0626 0x0626
64#define W_META_RESTOREDC0x0127 0x0127
65#define W_META_SELECTOBJECT0x012D 0x012D
66#define W_META_SETTEXTALIGN0x012E 0x012E
67#define W_META_CHORD0x0830 0x0830
68#define W_META_EXTTEXTOUT0x0a32 0x0a32
69#define W_META_POLYPOLYGON0x0538 0x0538
70#define W_META_STRETCHDIB0x0f43 0x0f43
71#define W_META_DELETEOBJECT0x01f0 0x01f0
72#define W_META_CREATEPENINDIRECT0x02FA 0x02FA
73#define W_META_CREATEFONTINDIRECT0x02FB 0x02FB
74#define W_META_CREATEBRUSHINDIRECT0x02FC 0x02FC
75
76#define W_TRANSPARENT1 1
77#define W_OPAQUE2 2
78
79#define W_R2_NOT6 6
80#define W_R2_XORPEN7 7
81#define W_R2_COPYPEN13 13
82
83#define W_TA_NOUPDATECP0x0000 0x0000
84#define W_TA_LEFT0x0000 0x0000
85#define W_TA_RIGHT0x0002 0x0002
86#define W_TA_TOP0x0000 0x0000
87#define W_TA_BOTTOM0x0008 0x0008
88#define W_TA_BASELINE0x0018 0x0018
89#define W_TA_RTLREADING0x0100 0x0100
90
91#define W_SRCCOPY0x00CC0020L 0x00CC0020L
92#define W_SRCPAINT0x00EE0086L 0x00EE0086L
93#define W_SRCAND0x008800C6L 0x008800C6L
94#define W_SRCINVERT0x00660046L 0x00660046L
95#define W_DSTINVERT0x00550009L 0x00550009L
96
97#define W_PS_SOLID0 0
98#define W_PS_DASH1 1
99#define W_PS_DOT2 2
100#define W_PS_DASHDOT3 3
101#define W_PS_DASHDOTDOT4 4
102#define W_PS_NULL5 5
103
104#define W_LF_FACESIZE32 32
105
106#define W_ANSI_CHARSET0 0
107
108#define W_DEFAULT_PITCH0x00 0x00
109#define W_FIXED_PITCH0x01 0x01
110#define W_VARIABLE_PITCH0x02 0x02
111
112#define W_FF_DONTCARE0x00 0x00
113#define W_FF_ROMAN0x10 0x10
114#define W_FF_SWISS0x20 0x20
115#define W_FF_MODERN0x30 0x30
116#define W_FF_SCRIPT0x40 0x40
117#define W_FF_DECORATIVE0x50 0x50
118
119#define W_FW_DONTCARE0 0
120#define W_FW_THIN100 100
121#define W_FW_LIGHT300 300
122#define W_FW_NORMAL400 400
123#define W_FW_MEDIUM500 500
124#define W_FW_SEMIBOLD600 600
125#define W_FW_BOLD700 700
126#define W_FW_ULTRALIGHT200 200
127#define W_FW_ULTRABOLD800 800
128#define W_FW_BLACK900 900
129
130#define W_BS_SOLID0 0
131#define W_BS_HOLLOW1 1
132
133#define W_MFCOMMENT15 15
134
135#define PRIVATE_ESCAPE_UNICODE2 2
136
137WMFWriter::WMFWriter()
138 : bStatus(false)
139 , nLastPercent(0)
140 , pWMF(nullptr)
141 , pVirDev(nullptr)
142 , nMetafileHeaderPos(0)
143 , nMaxRecordSize(0)
144 , nActRecordPos(0)
145 , eSrcRasterOp(RasterOp::OverPaint)
146 , eSrcTextAlign(ALIGN_BASELINE)
147 , pAttrStack(nullptr)
148 , eSrcHorTextAlign(W_TA_LEFT0x0000)
149 , eDstROP2(RasterOp::OverPaint)
150 , eDstTextAlign(ALIGN_BASELINE)
151 , eDstHorTextAlign(W_TA_LEFT0x0000)
152 , bHandleAllocated{}
153 , nDstPenHandle(0)
154 , nDstFontHandle(0)
155 , nDstBrushHandle(0)
156 , nNumberOfActions(0)
157 , nNumberOfBitmaps(0)
158 , nWrittenActions(0)
159 , nWrittenBitmaps(0)
160 , nActBitmapPercent(0)
161 , bEmbedEMF(false)
162{
163}
164
165void WMFWriter::MayCallback()
166{
167 if ( !xStatusIndicator.is() )
168 return;
169
170 sal_uLong nPercent;
171
172 // we simply assume that 16386 actions match to a bitmap
173 // (normally a metafile either contains only actions or some bitmaps and
174 // almost no actions. In which case the ratio is less important)
175
176 nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
177 *100
178 /((nNumberOfBitmaps<<14)+nNumberOfActions);
179
180 if ( nPercent >= nLastPercent + 3 )
181 {
182 nLastPercent = nPercent;
183 if( nPercent <= 100 )
184 xStatusIndicator->setValue( nPercent );
185 }
186}
187
188void WMFWriter::CountActionsAndBitmaps( const GDIMetaFile & rMTF )
189{
190 size_t nAction, nActionCount;
191
192 nActionCount = rMTF.GetActionSize();
193
194 for ( nAction=0; nAction < nActionCount; nAction++ )
195 {
196 MetaAction* pMA = rMTF.GetAction( nAction );
197
198 switch( pMA->GetType() )
199 {
200 case MetaActionType::BMP:
201 case MetaActionType::BMPSCALE:
202 case MetaActionType::BMPSCALEPART:
203 case MetaActionType::BMPEX:
204 case MetaActionType::BMPEXSCALE:
205 case MetaActionType::BMPEXSCALEPART:
206 nNumberOfBitmaps++;
207 break;
208 default: break;
209 }
210 nNumberOfActions++;
211 }
212}
213
214void WMFWriter::WritePointXY(const Point & rPoint)
215{
216 Point aPt( OutputDevice::LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
217 pWMF->WriteInt16( aPt.X() ).WriteInt16( aPt.Y() );
218}
219
220void WMFWriter::WritePointYX(const Point & rPoint)
221{
222 Point aPt( OutputDevice::LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
223 pWMF->WriteInt16( aPt.Y() ).WriteInt16( aPt.X() );
224}
225
226sal_Int32 WMFWriter::ScaleWidth( sal_Int32 nDX )
227{
228 Size aSz( OutputDevice::LogicToLogic(Size(nDX,0),aSrcMapMode,aTargetMapMode) );
229 return aSz.Width();
230}
231
232void WMFWriter::WriteSize(const Size & rSize)
233{
234 Size aSz( OutputDevice::LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
235 pWMF->WriteInt16( aSz.Width() ).WriteInt16( aSz.Height() );
236}
237
238void WMFWriter::WriteHeightWidth(const Size & rSize)
239{
240 Size aSz( OutputDevice::LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
241 pWMF->WriteInt16( aSz.Height() ).WriteInt16( aSz.Width() );
242}
243
244void WMFWriter::WriteRectangle(const tools::Rectangle & rRect)
245{
246 WritePointYX(Point(rRect.Right()+1,rRect.Bottom()+1));
247 WritePointYX(rRect.TopLeft());
248}
249
250void WMFWriter::WriteColor(const Color & rColor)
251{
252 pWMF->WriteUChar( rColor.GetRed() ).WriteUChar( rColor.GetGreen() ).WriteUChar( rColor.GetBlue() ).WriteUChar( 0 );
253}
254
255void WMFWriter::WriteRecordHeader(sal_uInt32 nSizeWords, sal_uInt16 nType)
256{
257 nActRecordPos=pWMF->Tell();
258 if (nSizeWords>nMaxRecordSize) nMaxRecordSize=nSizeWords;
259 pWMF->WriteUInt32( nSizeWords ).WriteUInt16( nType );
260}
261
262void WMFWriter::UpdateRecordHeader()
263{
264 sal_uLong nPos;
265 sal_uInt32 nSize;
266
267 nPos=pWMF->Tell(); nSize=nPos-nActRecordPos;
268 if ((nSize & 1)!=0) {
269 pWMF->WriteUChar( 0 );
270 nPos++; nSize++;
271 }
272 nSize/=2;
273 if (nSize>nMaxRecordSize) nMaxRecordSize=nSize;
274 pWMF->Seek(nActRecordPos);
275 pWMF->WriteUInt32( nSize );
276 pWMF->Seek(nPos);
277}
278
279void WMFWriter::WMFRecord_Arc(const tools::Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
280{
281 WriteRecordHeader(0x0000000b,W_META_ARC0x0817);
282 WritePointYX(rEndPt);
283 WritePointYX(rStartPt);
284 WriteRectangle(rRect);
285}
286
287void WMFWriter::WMFRecord_Chord(const tools::Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
288{
289 WriteRecordHeader(0x0000000b,W_META_CHORD0x0830);
290 WritePointYX(rEndPt);
291 WritePointYX(rStartPt);
292 WriteRectangle(rRect);
293}
294
295void WMFWriter::WMFRecord_CreateBrushIndirect(const Color& rColor)
296{
297 WriteRecordHeader(0x00000007,W_META_CREATEBRUSHINDIRECT0x02FC);
298
299 if( rColor==COL_TRANSPARENT )
300 pWMF->WriteUInt16( W_BS_HOLLOW1 );
301 else
302 pWMF->WriteUInt16( W_BS_SOLID0 );
303
304 WriteColor( rColor );
305 pWMF->WriteUInt16( 0 );
306}
307
308void WMFWriter::WMFRecord_CreateFontIndirect(const vcl::Font & rFont)
309{
310 sal_uInt16 nWeight,i;
311 sal_uInt8 nPitchFamily;
312
313 WriteRecordHeader(0x00000000,W_META_CREATEFONTINDIRECT0x02FB);
314 WriteHeightWidth(Size(rFont.GetFontSize().Width(),-rFont.GetFontSize().Height()));
315 pWMF->WriteInt16( rFont.GetOrientation() ).WriteInt16( rFont.GetOrientation() );
316
317 switch (rFont.GetWeight()) {
318 case WEIGHT_THIN: nWeight=W_FW_THIN100; break;
319 case WEIGHT_ULTRALIGHT: nWeight=W_FW_ULTRALIGHT200; break;
320 case WEIGHT_LIGHT: nWeight=W_FW_LIGHT300; break;
321 case WEIGHT_SEMILIGHT: nWeight=W_FW_LIGHT300; break;
322 case WEIGHT_NORMAL: nWeight=W_FW_NORMAL400; break;
323 case WEIGHT_MEDIUM: nWeight=W_FW_MEDIUM500; break;
324 case WEIGHT_SEMIBOLD: nWeight=W_FW_SEMIBOLD600; break;
325 case WEIGHT_BOLD: nWeight=W_FW_BOLD700; break;
326 case WEIGHT_ULTRABOLD: nWeight=W_FW_ULTRABOLD800; break;
327 case WEIGHT_BLACK: nWeight=W_FW_BLACK900; break;
328 default: nWeight=W_FW_DONTCARE0;
329 }
330 pWMF->WriteUInt16( nWeight );
331
332 if (rFont.GetItalic()==ITALIC_NONE) pWMF->WriteUChar( 0 ); else pWMF->WriteUChar( 1 );
333 if (rFont.GetUnderline()==LINESTYLE_NONE) pWMF->WriteUChar( 0 ); else pWMF->WriteUChar( 1 );
334 if (rFont.GetStrikeout()==STRIKEOUT_NONE) pWMF->WriteUChar( 0 ); else pWMF->WriteUChar( 1 );
335
336 rtl_TextEncoding eFontNameEncoding = rFont.GetCharSet();
337 sal_uInt8 nCharSet = rtl_getBestWindowsCharsetFromTextEncoding( eFontNameEncoding );
338 if ( eFontNameEncoding == RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)) )
339 eFontNameEncoding = RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1));
340 if ( nCharSet == 1 )
341 nCharSet = W_ANSI_CHARSET0;
342 pWMF->WriteUChar( nCharSet );
343
344 pWMF->WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
345
346 switch (rFont.GetPitch()) {
347 case PITCH_FIXED: nPitchFamily=W_FIXED_PITCH0x01; break;
348 case PITCH_VARIABLE: nPitchFamily=W_VARIABLE_PITCH0x02; break;
349 default: nPitchFamily=W_DEFAULT_PITCH0x00;
350 }
351 switch (rFont.GetFamilyType()) {
352 case FAMILY_DECORATIVE: nPitchFamily|=W_FF_DECORATIVE0x50; break;
353 case FAMILY_MODERN: nPitchFamily|=W_FF_MODERN0x30; break;
354 case FAMILY_ROMAN: nPitchFamily|=W_FF_ROMAN0x10; break;
355 case FAMILY_SCRIPT: nPitchFamily|=W_FF_SCRIPT0x40; break;
356 case FAMILY_SWISS: nPitchFamily|=W_FF_SWISS0x20; break;
357 default: nPitchFamily|=W_FF_DONTCARE0x00;
358 }
359 pWMF->WriteUChar( nPitchFamily );
360
361 OString aFontName(OUStringToOString(rFont.GetFamilyName(), eFontNameEncoding));
362 for ( i = 0; i < W_LF_FACESIZE32; i++ )
363 {
364 char nChar = ( i < aFontName.getLength() ) ? aFontName[i] : 0;
365 pWMF->WriteChar( nChar );
366 }
367 UpdateRecordHeader();
368}
369
370void WMFWriter::WMFRecord_CreatePenIndirect(const Color& rColor, const LineInfo& rLineInfo )
371{
372 WriteRecordHeader(0x00000008,W_META_CREATEPENINDIRECT0x02FA);
373 sal_uInt16 nStyle = rColor == COL_TRANSPARENT ? W_PS_NULL5 : W_PS_SOLID0;
374 switch( rLineInfo.GetStyle() )
375 {
376 case LineStyle::Dash :
377 {
378 if ( rLineInfo.GetDotCount() )
379 {
380 if ( !rLineInfo.GetDashCount() )
381 nStyle = W_PS_DOT2;
382 else
383 {
384 if ( rLineInfo.GetDotCount() == 1 )
385 nStyle = W_PS_DASHDOT3;
386 else
387 nStyle = W_PS_DASHDOTDOT4;
388 }
389 }
390 else
391 nStyle = W_PS_DASH1;
392 }
393 break;
394 case LineStyle::NONE :
395 nStyle = W_PS_NULL5;
396 break;
397 default:
398 break;
399 }
400 pWMF->WriteUInt16( nStyle );
401
402 WriteSize( Size( rLineInfo.GetWidth(), 0 ) );
403 WriteColor( rColor );
404}
405
406void WMFWriter::WMFRecord_DeleteObject(sal_uInt16 nObjectHandle)
407{
408 WriteRecordHeader(0x00000004,W_META_DELETEOBJECT0x01f0);
409 pWMF->WriteUInt16( nObjectHandle );
410}
411
412void WMFWriter::WMFRecord_Ellipse(const tools::Rectangle & rRect)
413{
414 WriteRecordHeader(0x00000007,W_META_ELLIPSE0x0418);
415 WriteRectangle(rRect);
416}
417
418void WMFWriter::WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_Int8* pData )
419{
420#ifdef OSL_BIGENDIAN
421 sal_uInt32 nTmp = OSL_SWAPDWORD( nEsc )((sal_uInt32)((((sal_uInt16)((sal_uInt16)((((sal_uInt8)(((sal_uInt16
)(((sal_uInt16)(((sal_uInt32)(nEsc) >> 16) & 0xFFFF
))) >> 8) & 0xFF))) & 0xFF) | (((sal_uInt16)(((
sal_uInt8)((sal_uInt16)(((sal_uInt16)(((sal_uInt32)(nEsc) >>
16) & 0xFFFF))) & 0xFF))) & 0xFF) << 8))))
& 0xFFFF) | (((sal_uInt32)(((sal_uInt16)((sal_uInt16)(((
(sal_uInt8)(((sal_uInt16)(((sal_uInt16)((sal_uInt32)(nEsc) &
0xFFFF))) >> 8) & 0xFF))) & 0xFF) | (((sal_uInt16
)(((sal_uInt8)((sal_uInt16)(((sal_uInt16)((sal_uInt32)(nEsc) &
0xFFFF))) & 0xFF))) & 0xFF) << 8)))) & 0xFFFF
) << 16))
;
422 sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
423#else
424 sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
425#endif
426 if ( nLen )
427 nCheckSum = rtl_crc32( nCheckSum, pData, nLen );
428
429 WriteRecordHeader( 3 + 9 + ( ( nLen + 1 ) >> 1 ), W_META_ESCAPE0x0626 );
430 pWMF->WriteUInt16( W_MFCOMMENT15 )
431 .WriteUInt16( nLen + 14 ) // we will always have a fourteen byte escape header:
432 .WriteUInt16( 0x4f4f ) // OO
433 .WriteUInt32( 0xa2c2a ) // evil magic number
434 .WriteUInt32( nCheckSum ) // crc32 checksum about nEsc & pData
435 .WriteUInt32( nEsc ); // escape number
436 pWMF->WriteBytes( pData, nLen );
437 if ( nLen & 1 )
438 pWMF->WriteUChar( 0 ); // pad byte
439}
440
441/* if return value is true, then a complete unicode string and also a polygon replacement has been written,
442 so there is no more action necessary
443*/
444bool WMFWriter::WMFRecord_Escape_Unicode( const Point& rPoint, const OUString& rUniStr, const long* pDXAry )
445{
446 bool bEscapeUsed = false;
447
448 sal_uInt32 i, nStringLen = rUniStr.getLength();
449 if ( nStringLen )
450 {
451 // first we will check if a comment is necessary
452 if ( aSrcFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)) ) // symbol is always byte character, so there is no unicode loss
453 {
454 const sal_Unicode* pBuf = rUniStr.getStr();
455 const rtl_TextEncoding aTextEncodingOrg = aSrcFont.GetCharSet();
456 OString aByteStr(OUStringToOString(rUniStr, aTextEncodingOrg));
457 OUString aUniStr2(OStringToOUString(aByteStr, aTextEncodingOrg));
458 const sal_Unicode* pConversion = aUniStr2.getStr(); // this is the unicode array after bytestring <-> unistring conversion
459 for ( i = 0; i < nStringLen; i++ )
460 {
461 if ( *pBuf++ != *pConversion++ )
462 break;
463 }
464
465 if ( i != nStringLen ) // after conversion the characters are not original,
466 { // try again, with determining a better charset from unicode char
467 pBuf = rUniStr.getStr();
468 const sal_Unicode* pCheckChar = pBuf;
469 rtl_TextEncoding aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the first character
470 if (aTextEncoding == RTL_TEXTENCODING_DONTKNOW(((rtl_TextEncoding) 0))) {
471 aTextEncoding = aTextEncodingOrg;
472 }
473 for ( i = 1; i < nStringLen; i++)
474 {
475 if (aTextEncoding != aTextEncodingOrg) // found something
476 break;
477 pCheckChar++;
478 aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the next character
479 if (aTextEncoding == RTL_TEXTENCODING_DONTKNOW(((rtl_TextEncoding) 0))) {
480 aTextEncoding = aTextEncodingOrg;
481 }
482 }
483
484 aByteStr = OUStringToOString(rUniStr, aTextEncoding);
485 aUniStr2 = OStringToOUString(aByteStr, aTextEncoding);
486 pConversion = aUniStr2.getStr(); // this is the unicode array after bytestring <-> unistring conversion
487 for ( i = 0; i < nStringLen; i++ )
488 {
489 if ( *pBuf++ != *pConversion++ )
490 break;
491 }
492 if (i == nStringLen)
493 {
494 aSrcFont.SetCharSet (aTextEncoding);
495 SetAllAttr();
496 }
497 }
498
499 if ( ( i != nStringLen ) || IsStarSymbol( aSrcFont.GetFamilyName() ) ) // after conversion the characters are not original, so we
500 { // will store the unicode string and a polypoly replacement
501 Color aOldFillColor( aSrcFillColor );
502 Color aOldLineColor( aSrcLineColor );
503 aSrcLineInfo = LineInfo();
504 aSrcFillColor = aSrcTextColor;
505 aSrcLineColor = COL_TRANSPARENT;
506 SetLineAndFillAttr();
507 pVirDev->SetFont( aSrcFont );
508 std::vector<tools::PolyPolygon> aPolyPolyVec;
509 if ( pVirDev->GetTextOutlines( aPolyPolyVec, rUniStr ) )
510 {
511 sal_uInt32 nDXCount = pDXAry ? nStringLen : 0;
512 sal_uInt32 nSkipActions = aPolyPolyVec.size();
513 sal_Int32 nStrmLen = 8 +
514 + sizeof( nStringLen ) + ( nStringLen * 2 )
515 + sizeof( nDXCount ) + ( nDXCount * 4 )
516 + sizeof( nSkipActions );
517
518 SvMemoryStream aMemoryStream( nStrmLen );
519 Point aPt( OutputDevice::LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode ) );
520 aMemoryStream.WriteInt32( aPt.X() )
521 .WriteInt32( aPt.Y() )
522 .WriteUInt32( nStringLen );
523 for ( i = 0; i < nStringLen; i++ )
524 aMemoryStream.WriteUInt16( rUniStr[ i ] );
525 aMemoryStream.WriteUInt32( nDXCount );
526 for ( i = 0; i < nDXCount; i++ )
527 aMemoryStream.WriteInt32( pDXAry[ i ] );
528 aMemoryStream.WriteUInt32( nSkipActions );
529 WMFRecord_Escape( PRIVATE_ESCAPE_UNICODE2, nStrmLen, static_cast<const sal_Int8*>(aMemoryStream.GetData()) );
530
531 for ( const auto& rPolyPoly : aPolyPolyVec )
532 {
533 tools::PolyPolygon aPolyPoly( rPolyPoly );
534 aPolyPoly.Move( rPoint.X(), rPoint.Y() );
535 WMFRecord_PolyPolygon( aPolyPoly );
536 }
537 aSrcFillColor = aOldFillColor;
538 aSrcLineColor = aOldLineColor;
539 bEscapeUsed = true;
540 }
541 }
542 }
543 }
544 return bEscapeUsed;
545}
546
547void WMFWriter::WMFRecord_ExtTextOut( const Point& rPoint,
548 const OUString& rString,
549 const long* pDXAry )
550{
551 sal_Int32 nOriginalTextLen = rString.getLength();
552
553 if ( (nOriginalTextLen <= 1) || (pDXAry == nullptr) )
554 {
555 WMFRecord_TextOut(rPoint, rString);
556 return;
557 }
558 rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
559 OString aByteString(OUStringToOString(rString, eChrSet));
560 TrueExtTextOut(rPoint, rString, aByteString, pDXAry);
561}
562
563void WMFWriter::TrueExtTextOut( const Point& rPoint, const OUString& rString,
564 const OString& rByteString, const long* pDXAry )
565{
566 WriteRecordHeader( 0, W_META_EXTTEXTOUT0x0a32 );
567 WritePointYX( rPoint );
568 sal_uInt16 nNewTextLen = static_cast<sal_uInt16>(rByteString.getLength());
569 pWMF->WriteUInt16( nNewTextLen ).WriteUInt16( 0 );
570 write_uInt8s_FromOString(*pWMF, rByteString, nNewTextLen);
571 if ( nNewTextLen & 1 )
572 pWMF->WriteUChar( 0 );
573
574 sal_Int32 nOriginalTextLen = rString.getLength();
575 std::unique_ptr<sal_Int16[]> pConvertedDXAry(new sal_Int16[ nOriginalTextLen ]);
576 sal_Int32 j = 0;
577 pConvertedDXAry[ j++ ] = static_cast<sal_Int16>(ScaleWidth( pDXAry[ 0 ] ));
578 for (sal_Int32 i = 1; i < ( nOriginalTextLen - 1 ); ++i)
579 pConvertedDXAry[ j++ ] = static_cast<sal_Int16>(ScaleWidth( pDXAry[ i ] - pDXAry[ i - 1 ] ));
580 pConvertedDXAry[ j ] = static_cast<sal_Int16>(ScaleWidth( pDXAry[ nOriginalTextLen - 2 ] / ( nOriginalTextLen - 1 ) ));
581
582 for (sal_Int32 i = 0; i < nOriginalTextLen; ++i)
583 {
584 sal_Int16 nDx = pConvertedDXAry[ i ];
585 pWMF->WriteInt16( nDx );
586 if ( nOriginalTextLen < nNewTextLen )
587 {
588 sal_Unicode nUniChar = rString[i];
589 OString aTemp(&nUniChar, 1, aSrcFont.GetCharSet());
590 j = aTemp.getLength();
591 while ( --j > 0 )
592 pWMF->WriteUInt16( 0 );
593 }
594 }
595 pConvertedDXAry.reset();
596 UpdateRecordHeader();
597}
598
599void WMFWriter::WMFRecord_LineTo(const Point & rPoint)
600{
601 WriteRecordHeader(0x00000005,W_META_LINETO0x0213);
602 WritePointYX(rPoint);
603}
604
605void WMFWriter::WMFRecord_MoveTo(const Point & rPoint)
606{
607 WriteRecordHeader(0x00000005,W_META_MOVETO0x0214);
608 WritePointYX(rPoint);
609}
610
611void WMFWriter::WMFRecord_Pie(const tools::Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
612{
613 WriteRecordHeader(0x0000000b,W_META_PIE0x081A);
614 WritePointYX(rEndPt);
615 WritePointYX(rStartPt);
616 WriteRectangle(rRect);
617}
618
619void WMFWriter::WMFRecord_Polygon(const tools::Polygon & rPoly)
620{
621 tools::Polygon aSimplePoly;
622 if ( rPoly.HasFlags() )
623 rPoly.AdaptiveSubdivide( aSimplePoly );
624 else
625 aSimplePoly = rPoly;
626 const sal_uInt16 nSize = aSimplePoly.GetSize();
627 WriteRecordHeader(static_cast<sal_uInt32>(nSize)*2+4,W_META_POLYGON0x0324);
628 pWMF->WriteUInt16( nSize );
629 for (sal_uInt16 i=0; i<nSize; ++i)
630 WritePointXY(aSimplePoly.GetPoint(i));
631}
632
633void WMFWriter::WMFRecord_PolyLine(const tools::Polygon & rPoly)
634{
635 tools::Polygon aSimplePoly;
636 if ( rPoly.HasFlags() )
637 rPoly.AdaptiveSubdivide( aSimplePoly );
638 else
639 aSimplePoly = rPoly;
640 const sal_uInt16 nSize = aSimplePoly.GetSize();
641 WriteRecordHeader(static_cast<sal_uInt32>(nSize)*2+4,W_META_POLYLINE0x0325);
642 pWMF->WriteUInt16( nSize );
643 for (sal_uInt16 i=0; i<nSize; ++i)
644 WritePointXY(aSimplePoly.GetPoint(i));
645}
646
647void WMFWriter::WMFRecord_PolyPolygon(const tools::PolyPolygon & rPolyPoly)
648{
649 const tools::Polygon * pPoly;
650 sal_uInt16 nCount,nSize,i,j;
651
652 nCount=rPolyPoly.Count();
653 tools::PolyPolygon aSimplePolyPoly( rPolyPoly );
654 for ( i = 0; i < nCount; i++ )
655 {
656 if ( aSimplePolyPoly[ i ].HasFlags() )
657 {
658 tools::Polygon aSimplePoly;
659 aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
660 aSimplePolyPoly[ i ] = aSimplePoly;
661 }
662 }
663 WriteRecordHeader(0,W_META_POLYPOLYGON0x0538);
664 pWMF->WriteUInt16( nCount );
665 for (i=0; i<nCount; i++) pWMF->WriteUInt16( aSimplePolyPoly.GetObject(i).GetSize() );
666 for (i=0; i<nCount; i++) {
667 pPoly=&(aSimplePolyPoly.GetObject(i));
668 nSize=pPoly->GetSize();
669 for (j=0; j<nSize; j++) WritePointXY(pPoly->GetPoint(j));
670 }
671 UpdateRecordHeader();
672}
673
674void WMFWriter::WMFRecord_Rectangle(const tools::Rectangle & rRect)
675{
676 WriteRecordHeader( 0x00000007,W_META_RECTANGLE0x041B );
677 WriteRectangle( rRect );
678}
679
680void WMFWriter::WMFRecord_RestoreDC()
681{
682 WriteRecordHeader(0x00000004,W_META_RESTOREDC0x0127);
683 pWMF->WriteInt16( -1 );
684}
685
686void WMFWriter::WMFRecord_RoundRect(const tools::Rectangle & rRect, long nHorzRound, long nVertRound)
687{
688 WriteRecordHeader(0x00000009,W_META_ROUNDRECT0x061C);
689 WriteHeightWidth(Size(nHorzRound,nVertRound));
690 WriteRectangle(rRect);
691}
692
693void WMFWriter::WMFRecord_SaveDC()
694{
695 WriteRecordHeader(0x00000003,W_META_SAVEDC0x001E);
696}
697
698void WMFWriter::WMFRecord_SelectObject(sal_uInt16 nObjectHandle)
699{
700 WriteRecordHeader(0x00000004,W_META_SELECTOBJECT0x012D);
701 pWMF->WriteUInt16( nObjectHandle );
702}
703
704void WMFWriter::WMFRecord_SetBkMode(bool bTransparent)
705{
706 WriteRecordHeader(0x00000004,W_META_SETBKMODE0x0102);
707 if (bTransparent) pWMF->WriteUInt16( W_TRANSPARENT1 );
708 else pWMF->WriteUInt16( W_OPAQUE2 );
709}
710
711void WMFWriter::WMFRecord_SetStretchBltMode()
712{
713 WriteRecordHeader( 0x00000004, W_META_SETSTRETCHBLTMODE0x0107 );
714 pWMF->WriteUInt16( 3 ); // STRETCH_DELETESCANS
715}
716
717void WMFWriter::WMFRecord_SetPixel(const Point & rPoint, const Color & rColor)
718{
719 WriteRecordHeader(0x00000007,W_META_SETPIXEL0x041F);
720 WriteColor(rColor);
721 WritePointYX(rPoint);
722}
723
724void WMFWriter::WMFRecord_SetROP2(RasterOp eROP)
725{
726 sal_uInt16 nROP2;
727
728 switch (eROP) {
729 case RasterOp::Invert: nROP2=W_R2_NOT6; break;
730 case RasterOp::Xor: nROP2=W_R2_XORPEN7; break;
731 default: nROP2=W_R2_COPYPEN13;
732 }
733 WriteRecordHeader(0x00000004,W_META_SETROP20x0104);
734 pWMF->WriteUInt16( nROP2 );
735}
736
737void WMFWriter::WMFRecord_SetTextAlign(FontAlignTextAlign eFontAlign, sal_uInt16 eHorTextAlign)
738{
739 sal_uInt16 nAlign;
740
741 switch (eFontAlign) {
742 case ALIGN_TOP: nAlign=W_TA_TOP0x0000; break;
743 case ALIGN_BOTTOM: nAlign=W_TA_BOTTOM0x0008; break;
744 default: nAlign=W_TA_BASELINE0x0018;
745 }
746 nAlign|=eHorTextAlign;
747 nAlign|=W_TA_NOUPDATECP0x0000;
748
749 WriteRecordHeader(0x00000004,W_META_SETTEXTALIGN0x012E);
750 pWMF->WriteUInt16( nAlign );
751}
752
753void WMFWriter::WMFRecord_SetTextColor(const Color & rColor)
754{
755 WriteRecordHeader(0x00000005,W_META_SETTEXTCOLOR0x0209);
756 WriteColor(rColor);
757}
758
759void WMFWriter::WMFRecord_SetWindowExt(const Size & rSize)
760{
761 WriteRecordHeader(0x00000005,W_META_SETWINDOWEXT0x020C);
762 WriteHeightWidth(rSize);
763}
764
765void WMFWriter::WMFRecord_SetWindowOrg(const Point & rPoint)
766{
767 WriteRecordHeader(0x00000005,W_META_SETWINDOWORG0x020B);
768 WritePointYX(rPoint);
769}
770
771void WMFWriter::WMFRecord_StretchDIB( const Point & rPoint, const Size & rSize,
772 const Bitmap & rBitmap, sal_uInt32 nROP )
773{
774 sal_uLong nPosAnf,nPosEnd;
775
776 nActBitmapPercent=50;
777 MayCallback();
778
779 WriteRecordHeader(0x00000000,W_META_STRETCHDIB0x0f43);
780
781 // The sequence in the metafile should be:
782 // some parameters (length 22), then the bitmap without FILEHEADER.
783 // As *pWMF << rBitmap generates a FILEHEADER of size 14,
784 // we first write the bitmap at the right position
785 // and overwrite later the FILEHEADER with the parameters.
786 nPosAnf=pWMF->Tell(); // remember position, where parameters should be stored
787 pWMF->WriteInt32( 0 ).WriteInt32( 0 ); // replenish 8 bytes (these 8 bytes +
788 // 14 bytes superfluous FILEHEADER
789 // = 22 bytes parameter)
790
791 // write bitmap
792 WriteDIB(rBitmap, *pWMF, false, true);
793
794 // write the parameters:
795 nPosEnd=pWMF->Tell();
796 pWMF->Seek(nPosAnf);
797
798 // determine raster-op, if nothing was passed
799 if( !nROP )
800 {
801 switch( eSrcRasterOp )
802 {
803 case RasterOp::Invert: nROP = W_DSTINVERT0x00550009L; break;
804 case RasterOp::Xor: nROP = W_SRCINVERT0x00660046L; break;
805 default: nROP = W_SRCCOPY0x00CC0020L;
806 }
807 }
808
809 pWMF->WriteUInt32( nROP ).
810 WriteInt16( 0 ).
811 WriteInt16( rBitmap.GetSizePixel().Height() ).
812 WriteInt16( rBitmap.GetSizePixel().Width() ).
813 WriteInt16( 0 ).
814 WriteInt16( 0 );
815
816 WriteHeightWidth(rSize);
817 WritePointYX(rPoint);
818 pWMF->Seek(nPosEnd);
819
820 UpdateRecordHeader();
821
822 nWrittenBitmaps++;
823 nActBitmapPercent=0;
824}
825
826void WMFWriter::WMFRecord_TextOut(const Point & rPoint, const OUString & rStr)
827{
828 rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
829 OString aString(OUStringToOString(rStr, eChrSet));
830 TrueTextOut(rPoint, aString);
831}
832
833void WMFWriter::TrueTextOut(const Point & rPoint, const OString& rString)
834{
835 WriteRecordHeader(0,W_META_TEXTOUT0x0521);
836
837 write_uInt16_lenPrefixed_uInt8s_FromOString(*pWMF, rString);
838 sal_Int32 nLen = rString.getLength();
839 if ((nLen&1)!=0) pWMF->WriteUChar( 0 );
840 WritePointYX(rPoint);
841 UpdateRecordHeader();
842}
843
844void WMFWriter::WMFRecord_IntersectClipRect( const tools::Rectangle& rRect )
845{
846 WriteRecordHeader( 0x00000007, W_META_INTERSECTCLIPRECT0x0416 );
847 WriteRectangle(rRect);
848}
849
850sal_uInt16 WMFWriter::AllocHandle()
851{
852 sal_uInt16 i;
853
854 for (i=0; i<MAXOBJECTHANDLES16; i++) {
855 if (!bHandleAllocated[i]) {
856 bHandleAllocated[i]=true;
857 return i;
858 }
859 }
860 bStatus=false;
861 return 0xffff;
862}
863
864void WMFWriter::FreeHandle(sal_uInt16 nObjectHandle)
865{
866 if (nObjectHandle<MAXOBJECTHANDLES16) bHandleAllocated[nObjectHandle]=false;
867}
868
869void WMFWriter::CreateSelectDeletePen( const Color& rColor, const LineInfo& rLineInfo )
870{
871 sal_uInt16 nOldHandle;
872
873 nOldHandle=nDstPenHandle;
874 nDstPenHandle=AllocHandle();
875 WMFRecord_CreatePenIndirect( rColor, rLineInfo );
876 WMFRecord_SelectObject(nDstPenHandle);
877 if (nOldHandle<MAXOBJECTHANDLES16) {
878 WMFRecord_DeleteObject(nOldHandle);
879 FreeHandle(nOldHandle);
880 }
881}
882
883void WMFWriter::CreateSelectDeleteFont(const vcl::Font & rFont)
884{
885 sal_uInt16 nOldHandle;
886
887 nOldHandle=nDstFontHandle;
888 nDstFontHandle=AllocHandle();
889 WMFRecord_CreateFontIndirect(rFont);
890 WMFRecord_SelectObject(nDstFontHandle);
891 if (nOldHandle<MAXOBJECTHANDLES16) {
892 WMFRecord_DeleteObject(nOldHandle);
893 FreeHandle(nOldHandle);
894 }
895}
896
897void WMFWriter::CreateSelectDeleteBrush(const Color& rColor)
898{
899 sal_uInt16 nOldHandle;
900
901 nOldHandle=nDstBrushHandle;
902 nDstBrushHandle=AllocHandle();
903 WMFRecord_CreateBrushIndirect(rColor);
904 WMFRecord_SelectObject(nDstBrushHandle);
905 if (nOldHandle<MAXOBJECTHANDLES16) {
906 WMFRecord_DeleteObject(nOldHandle);
907 FreeHandle(nOldHandle);
908 }
909}
910
911void WMFWriter::SetLineAndFillAttr()
912{
913 if ( eDstROP2 != eSrcRasterOp )
914 {
915 eDstROP2=eSrcRasterOp;
916 WMFRecord_SetROP2(eDstROP2);
917 }
918 if ( ( aDstLineColor != aSrcLineColor ) || ( aDstLineInfo != aSrcLineInfo ) )
919 {
920 aDstLineColor = aSrcLineColor;
921 aDstLineInfo = aSrcLineInfo;
922 CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
923 }
924 if ( aDstFillColor != aSrcFillColor )
925 {
926 aDstFillColor = aSrcFillColor;
927 CreateSelectDeleteBrush( aDstFillColor );
928 }
929}
930
931void WMFWriter::SetAllAttr()
932{
933 SetLineAndFillAttr();
934 if ( aDstTextColor != aSrcTextColor )
935 {
936 aDstTextColor = aSrcTextColor;
937 WMFRecord_SetTextColor(aDstTextColor);
938 }
939 if ( eDstTextAlign != eSrcTextAlign || eDstHorTextAlign != eSrcHorTextAlign )
940 {
941 eDstTextAlign = eSrcTextAlign;
942 eDstHorTextAlign = eSrcHorTextAlign;
943 WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
944 }
945 if ( aDstFont == aSrcFont )
946 return;
947
948 pVirDev->SetFont(aSrcFont);
949 if ( aDstFont.GetFamilyName() != aSrcFont.GetFamilyName() )
950 {
951 FontCharMapRef xFontCharMap;
952 if ( pVirDev->GetFontCharMap( xFontCharMap ) )
953 {
954 if ( ( xFontCharMap->GetFirstChar() & 0xff00 ) == 0xf000 )
955 aSrcFont.SetCharSet( RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)) );
956 else if ( aSrcFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)) )
957 aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1)) );
958 }
959 }
960
961 aDstFont = aSrcFont;
962 CreateSelectDeleteFont(aDstFont);
963}
964
965void WMFWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
966{
967 if(!rLinePolygon.count())
968 return;
969
970 basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
971 basegfx::B2DPolyPolygon aFillPolyPolygon;
972
973 rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
974
975 if(aLinePolyPolygon.count())
976 {
977 aSrcLineInfo = rInfo;
978 SetLineAndFillAttr();
979
980 for(auto const& rB2DPolygon : aLinePolyPolygon)
981 {
982 WMFRecord_PolyLine( tools::Polygon(rB2DPolygon) );
983 }
984 }
985
986 if(!aFillPolyPolygon.count())
987 return;
988
989 const Color aOldLineColor(aSrcLineColor);
990 const Color aOldFillColor(aSrcFillColor);
991
992 aSrcLineColor = COL_TRANSPARENT;
993 aSrcFillColor = aOldLineColor;
994 SetLineAndFillAttr();
995
996 for(auto const& rB2DPolygon : aFillPolyPolygon)
997 {
998 WMFRecord_Polygon( tools::Polygon(rB2DPolygon) );
999 }
1000
1001 aSrcLineColor = aOldLineColor;
1002 aSrcFillColor = aOldFillColor;
1003 SetLineAndFillAttr();
1004}
1005
1006void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
1007{
1008 if( !bStatus )
1009 return;
1010
1011 size_t nACount = rMTF.GetActionSize();
1012
1013 WMFRecord_SetStretchBltMode();
1014
1015 for( size_t nA = 0; nA < nACount; nA++ )
1016 {
1017 MetaAction* pMA = rMTF.GetAction( nA );
1018
1019 switch( pMA->GetType() )
1020 {
1021 case MetaActionType::PIXEL:
1022 {
1023 const MetaPixelAction* pA = static_cast<const MetaPixelAction *>(pMA);
1024 aSrcLineInfo = LineInfo();
1025 SetLineAndFillAttr();
1026 WMFRecord_SetPixel( pA->GetPoint(), pA->GetColor() );
1027 }
1028 break;
1029
1030 case MetaActionType::POINT:
1031 {
1032 const MetaPointAction* pA = static_cast<const MetaPointAction*>(pMA);
1033 const Point& rPt = pA->GetPoint();
1034 aSrcLineInfo = LineInfo();
1035 SetLineAndFillAttr();
1036 WMFRecord_MoveTo( rPt);
1037 WMFRecord_LineTo( rPt );
1038 }
1039 break;
1040
1041 case MetaActionType::LINE:
1042 {
1043 const MetaLineAction* pA = static_cast<const MetaLineAction *>(pMA);
1044 if(pA->GetLineInfo().IsDefault())
1045 {
1046 aSrcLineInfo = pA->GetLineInfo();
1047 SetLineAndFillAttr();
1048 WMFRecord_MoveTo( pA->GetStartPoint() );
1049 WMFRecord_LineTo( pA->GetEndPoint() );
1050 }
1051 else
1052 {
1053 // LineInfo used; handle Dash/Dot and fat lines
1054 basegfx::B2DPolygon aPolygon;
1055 aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
1056 aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
1057 HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
1058 }
1059 }
1060 break;
1061
1062 case MetaActionType::RECT:
1063 {
1064 const MetaRectAction* pA = static_cast<const MetaRectAction*>(pMA);
1065 aSrcLineInfo = LineInfo();
1066 SetLineAndFillAttr();
1067 WMFRecord_Rectangle( pA->GetRect() );
1068 }
1069 break;
1070
1071 case MetaActionType::ROUNDRECT:
1072 {
1073 const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pMA);
1074 aSrcLineInfo = LineInfo();
1075 SetLineAndFillAttr();
1076 WMFRecord_RoundRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
1077 }
1078 break;
1079
1080 case MetaActionType::ELLIPSE:
1081 {
1082 const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pMA);
1083 aSrcLineInfo = LineInfo();
1084 SetLineAndFillAttr();
1085 WMFRecord_Ellipse( pA->GetRect() );
1086 }
1087 break;
1088
1089 case MetaActionType::ARC:
1090 {
1091 const MetaArcAction* pA = static_cast<const MetaArcAction*>(pMA);
1092 aSrcLineInfo = LineInfo();
1093 SetLineAndFillAttr();
1094 WMFRecord_Arc( pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint() );
1095 }
1096 break;
1097
1098 case MetaActionType::PIE:
1099 {
1100 const MetaPieAction* pA = static_cast<const MetaPieAction*>(pMA);
1101 aSrcLineInfo = LineInfo();
1102 SetLineAndFillAttr();
1103 WMFRecord_Pie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1104 }
1105 break;
1106
1107 case MetaActionType::CHORD:
1108 {
1109 const MetaChordAction* pA = static_cast<const MetaChordAction*>(pMA);
1110 aSrcLineInfo = LineInfo();
1111 SetLineAndFillAttr();
1112 WMFRecord_Chord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1113 }
1114 break;
1115
1116 case MetaActionType::POLYLINE:
1117 {
1118 const MetaPolyLineAction* pA = static_cast<const MetaPolyLineAction*>(pMA);
1119 const tools::Polygon& rPoly = pA->GetPolygon();
1120
1121 if( rPoly.GetSize() )
1122 {
1123 if(pA->GetLineInfo().IsDefault())
1124 {
1125 aSrcLineInfo = pA->GetLineInfo();
1126 SetLineAndFillAttr();
1127 WMFRecord_PolyLine( rPoly );
1128 }
1129 else
1130 {
1131 // LineInfo used; handle Dash/Dot and fat lines
1132 HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
1133 }
1134 }
1135 }
1136 break;
1137
1138 case MetaActionType::POLYGON:
1139 {
1140 const MetaPolygonAction* pA = static_cast<const MetaPolygonAction*>(pMA);
1141 aSrcLineInfo = LineInfo();
1142 SetLineAndFillAttr();
1143 WMFRecord_Polygon( pA->GetPolygon() );
1144 }
1145 break;
1146
1147 case MetaActionType::POLYPOLYGON:
1148 {
1149 const MetaPolyPolygonAction* pA = static_cast<const MetaPolyPolygonAction*>(pMA);
1150 aSrcLineInfo = LineInfo();
1151 SetLineAndFillAttr();
1152 WMFRecord_PolyPolygon( pA->GetPolyPolygon() );
1153 }
1154 break;
1155
1156 case MetaActionType::TEXTRECT:
1157 {
1158 const MetaTextRectAction * pA = static_cast<const MetaTextRectAction*>(pMA);
1159 OUString aTemp( pA->GetText() );
1160 aSrcLineInfo = LineInfo();
1161 SetAllAttr();
1162
1163 Point aPos( pA->GetRect().TopLeft() );
1164 if ( !WMFRecord_Escape_Unicode( aPos, aTemp, nullptr ) )
1165 WMFRecord_TextOut( aPos, aTemp );
1166 }
1167 break;
1168
1169 case MetaActionType::TEXT:
1170 {
1171 const MetaTextAction * pA = static_cast<const MetaTextAction*>(pMA);
1172 OUString aTemp = pA->GetText().copy( pA->GetIndex(), std::min<sal_Int32>(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
1173 aSrcLineInfo = LineInfo();
1174 SetAllAttr();
1175 if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, nullptr ) )
1176 WMFRecord_TextOut( pA->GetPoint(), aTemp );
1177 }
1178 break;
1179
1180 case MetaActionType::TEXTARRAY:
1181 {
1182 const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pMA);
1183
1184 OUString aTemp = pA->GetText().copy( pA->GetIndex(), std::min<sal_Int32>(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
1185 aSrcLineInfo = LineInfo();
1186 SetAllAttr();
1187 if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pA->GetDXArray() ) )
1188 WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pA->GetDXArray() );
1189 }
1190 break;
1191
1192 case MetaActionType::STRETCHTEXT:
1193 {
1194 const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction *>(pMA);
1195 OUString aTemp = pA->GetText().copy( pA->GetIndex(), std::min<sal_Int32>(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
1196
1197 pVirDev->SetFont( aSrcFont );
1198 const sal_Int32 nLen = aTemp.getLength();
1199 std::unique_ptr<long[]> pDXAry(nLen ? new long[ nLen ] : nullptr);
1200 const sal_Int32 nNormSize = pVirDev->GetTextArray( aTemp, pDXAry.get() );
1201 if (nLen && nNormSize == 0)
1202 {
1203 OSL_FAIL("Impossible div by 0 action: MetaStretchTextAction!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/filter/wmf/wmfwr.cxx"
":" "1203" ": "), "%s", "Impossible div by 0 action: MetaStretchTextAction!"
); } } while (false)
;
1204 }
1205 else
1206 {
1207 for ( sal_Int32 i = 0; i < ( nLen - 1 ); i++ )
1208 pDXAry[ i ] = pDXAry[ i ] * static_cast<sal_Int32>(pA->GetWidth()) / nNormSize;
1209 if ( ( nLen <= 1 ) || ( static_cast<sal_Int32>(pA->GetWidth()) == nNormSize ) )
1210 pDXAry.reset();
1211 aSrcLineInfo = LineInfo();
1212 SetAllAttr();
1213 if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pDXAry.get() ) )
1214 WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pDXAry.get() );
1215 }
1216 }
1217 break;
1218
1219 case MetaActionType::BMP:
1220 {
1221 const MetaBmpAction* pA = static_cast<const MetaBmpAction *>(pMA);
1222 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetBitmap().GetSizePixel(), pA->GetBitmap() );
1223 }
1224 break;
1225
1226 case MetaActionType::BMPSCALE:
1227 {
1228 const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pMA);
1229 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() );
1230 }
1231 break;
1232
1233 case MetaActionType::BMPSCALEPART:
1234 {
1235 const MetaBmpScalePartAction* pA = static_cast<const MetaBmpScalePartAction*>(pMA);
1236 Bitmap aTmp( pA->GetBitmap() );
1237
1238 if( aTmp.Crop( tools::Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
1239 WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aTmp );
1240 }
1241 break;
1242
1243 case MetaActionType::BMPEX:
1244 {
1245 const MetaBmpExAction* pA = static_cast<const MetaBmpExAction *>(pMA);
1246 Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1247 Bitmap aMsk( pA->GetBitmapEx().GetMask() );
1248
1249 if( !!aMsk )
1250 {
1251 aBmp.Replace( aMsk, COL_WHITE );
1252 aMsk.Invert();
1253 WMFRecord_StretchDIB( pA->GetPoint(), aMsk.GetSizePixel(), aBmp, W_SRCPAINT0x00EE0086L );
1254 WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp, W_SRCAND0x008800C6L );
1255 }
1256 else
1257 WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp );
1258 }
1259 break;
1260
1261 case MetaActionType::BMPEXSCALE:
1262 {
1263 const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pMA);
1264 Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1265 Bitmap aMsk( pA->GetBitmapEx().GetMask() );
1266
1267 if( !!aMsk )
1268 {
1269 aBmp.Replace( aMsk, COL_WHITE );
1270 aMsk.Invert();
1271 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aMsk, W_SRCPAINT0x00EE0086L );
1272 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp, W_SRCAND0x008800C6L );
1273 }
1274 else
1275 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp );
1276 }
1277 break;
1278
1279 case MetaActionType::BMPEXSCALEPART:
1280 {
1281 const MetaBmpExScalePartAction* pA = static_cast<const MetaBmpExScalePartAction*>(pMA);
1282 BitmapEx aBmpEx( pA->GetBitmapEx() );
1283 aBmpEx.Crop( tools::Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1284 Bitmap aBmp( aBmpEx.GetBitmap() );
1285 Bitmap aMsk( aBmpEx.GetMask() );
1286
1287 if( !!aMsk )
1288 {
1289 aBmp.Replace( aMsk, COL_WHITE );
1290 aMsk.Invert();
1291 WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aMsk, W_SRCPAINT0x00EE0086L );
1292 WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp, W_SRCAND0x008800C6L );
1293 }
1294 else
1295 WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
1296 }
1297 break;
1298
1299 case MetaActionType::GRADIENT:
1300 {
1301 const MetaGradientAction* pA = static_cast<const MetaGradientAction*>(pMA);
1302 GDIMetaFile aTmpMtf;
1303
1304 pVirDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
1305 WriteRecords( aTmpMtf );
1306 }
1307 break;
1308
1309 case MetaActionType::HATCH:
1310 {
1311 const MetaHatchAction* pA = static_cast<const MetaHatchAction*>(pMA);
1312 GDIMetaFile aTmpMtf;
1313
1314 pVirDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1315 WriteRecords( aTmpMtf );
1316 }
1317 break;
1318
1319 case MetaActionType::WALLPAPER:
1320 {
1321 const MetaWallpaperAction* pA = static_cast<const MetaWallpaperAction*>(pMA);
1322 const Color& rColor = pA->GetWallpaper().GetColor();
1323 const Color aOldLineColor( aSrcLineColor );
1324 const Color aOldFillColor( aSrcFillColor );
1325
1326 aSrcLineColor = rColor;
1327 aSrcFillColor = rColor;
1328 aSrcLineInfo = LineInfo();
1329 SetLineAndFillAttr();
1330 WMFRecord_Rectangle( pA->GetRect() );
1331 aSrcLineColor = aOldLineColor;
1332 aSrcFillColor = aOldFillColor;
1333 }
1334 break;
1335
1336 case MetaActionType::ISECTRECTCLIPREGION:
1337 {
1338 const MetaISectRectClipRegionAction* pA = static_cast<const MetaISectRectClipRegionAction*>(pMA);
1339 WMFRecord_IntersectClipRect( pA->GetRect() );
1340 }
1341 break;
1342
1343 case MetaActionType::LINECOLOR:
1344 {
1345 const MetaLineColorAction* pA = static_cast<const MetaLineColorAction*>(pMA);
1346
1347 if( pA->IsSetting() )
1348 aSrcLineColor = pA->GetColor();
1349 else
1350 aSrcLineColor = COL_TRANSPARENT;
1351 }
1352 break;
1353
1354 case MetaActionType::FILLCOLOR:
1355 {
1356 const MetaFillColorAction* pA = static_cast<const MetaFillColorAction*>(pMA);
1357
1358 if( pA->IsSetting() )
1359 aSrcFillColor = pA->GetColor();
1360 else
1361 aSrcFillColor = COL_TRANSPARENT;
1362 }
1363 break;
1364
1365 case MetaActionType::TEXTCOLOR:
1366 {
1367 const MetaTextColorAction* pA = static_cast<const MetaTextColorAction*>(pMA);
1368 aSrcTextColor = pA->GetColor();
1369 }
1370 break;
1371
1372 case MetaActionType::TEXTFILLCOLOR:
1373 {
1374 const MetaTextFillColorAction* pA = static_cast<const MetaTextFillColorAction*>(pMA);
1375 if( pA->IsSetting() )
1376 aSrcFont.SetFillColor( pA->GetColor() );
1377 else
1378 aSrcFont.SetFillColor( COL_TRANSPARENT );
1379 }
1380 break;
1381
1382 case MetaActionType::TEXTALIGN:
1383 {
1384 const MetaTextAlignAction* pA = static_cast<const MetaTextAlignAction*>(pMA);
1385 eSrcTextAlign = pA->GetTextAlign();
1386 }
1387 break;
1388
1389 case MetaActionType::MAPMODE:
1390 {
1391 const MetaMapModeAction* pA = static_cast<const MetaMapModeAction*>(pMA);
1392
1393 if (aSrcMapMode!=pA->GetMapMode())
1394 {
1395 if( pA->GetMapMode().GetMapUnit() == MapUnit::MapRelative )
1396 {
1397 const MapMode& aMM = pA->GetMapMode();
1398 Fraction aScaleX = aMM.GetScaleX();
1399 Fraction aScaleY = aMM.GetScaleY();
1400
1401 Point aOrigin = aSrcMapMode.GetOrigin();
1402 BigInt aX( aOrigin.X() );
1403 aX *= BigInt( aScaleX.GetDenominator() );
1404 if( aOrigin.X() >= 0 )
1405 if( aScaleX.GetNumerator() >= 0 )
1406 aX += BigInt( aScaleX.GetNumerator()/2 );
1407 else
1408 aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
1409 else
1410 if( aScaleX.GetNumerator() >= 0 )
1411 aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
1412 else
1413 aX += BigInt( aScaleX.GetNumerator()/2 );
1414 aX /= BigInt( aScaleX.GetNumerator() );
1415 aOrigin.setX( static_cast<long>(aX) + aMM.GetOrigin().X() );
1416 BigInt aY( aOrigin.Y() );
1417 aY *= BigInt( aScaleY.GetDenominator() );
1418 if( aOrigin.Y() >= 0 )
1419 if( aScaleY.GetNumerator() >= 0 )
1420 aY += BigInt( aScaleY.GetNumerator()/2 );
1421 else
1422 aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
1423 else
1424 if( aScaleY.GetNumerator() >= 0 )
1425 aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
1426 else
1427 aY += BigInt( aScaleY.GetNumerator()/2 );
1428 aY /= BigInt( aScaleY.GetNumerator() );
1429 aOrigin.setY( static_cast<long>(aY) + aMM.GetOrigin().Y() );
1430 aSrcMapMode.SetOrigin( aOrigin );
1431
1432 aScaleX *= aSrcMapMode.GetScaleX();
1433 aScaleY *= aSrcMapMode.GetScaleY();
1434 aSrcMapMode.SetScaleX( aScaleX );
1435 aSrcMapMode.SetScaleY( aScaleY );
1436 }
1437 else
1438 aSrcMapMode=pA->GetMapMode();
1439 }
1440 }
1441 break;
1442
1443 case MetaActionType::FONT:
1444 {
1445 const MetaFontAction* pA = static_cast<const MetaFontAction*>(pMA);
1446 aSrcFont = pA->GetFont();
1447
1448 if ( (aSrcFont.GetCharSet() == RTL_TEXTENCODING_DONTKNOW(((rtl_TextEncoding) 0)))
1449 || (aSrcFont.GetCharSet() == RTL_TEXTENCODING_UNICODE(((rtl_TextEncoding) 0xFFFF))) )
1450 {
1451 aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1)) );
1452 }
1453 eSrcTextAlign = aSrcFont.GetAlignment();
1454 aSrcTextColor = aSrcFont.GetColor();
1455 aSrcFont.SetAlignment( ALIGN_BASELINE );
1456 aSrcFont.SetColor( COL_WHITE );
1457 }
1458 break;
1459
1460 case MetaActionType::PUSH:
1461 {
1462 const MetaPushAction* pA = static_cast<const MetaPushAction*>(pMA);
1463
1464 WMFWriterAttrStackMember* pAt = new WMFWriterAttrStackMember;
1465 pAt->nFlags = pA->GetFlags();
1466 pAt->aClipRegion = aSrcClipRegion;
1467 pAt->aLineColor=aSrcLineColor;
1468 pAt->aFillColor=aSrcFillColor;
1469 pAt->eRasterOp=eSrcRasterOp;
1470 pAt->aFont=aSrcFont;
1471 pAt->eTextAlign=eSrcTextAlign;
1472 pAt->aTextColor=aSrcTextColor;
1473 pAt->aMapMode=aSrcMapMode;
1474 pAt->aLineInfo=aDstLineInfo;
1475 pAt->pSucc=pAttrStack;
1476 pAttrStack=pAt;
1477
1478 SetAllAttr(); // update ( now all source attributes are equal to the destination attributes )
1479 WMFRecord_SaveDC();
1480
1481 }
1482 break;
1483
1484 case MetaActionType::POP:
1485 {
1486 WMFWriterAttrStackMember * pAt=pAttrStack;
1487
1488 if( pAt )
1489 {
1490 aDstLineInfo = pAt->aLineInfo;
1491 aDstLineColor = pAt->aLineColor;
1492 if ( pAt->nFlags & PushFlags::LINECOLOR )
1493 aSrcLineColor = pAt->aLineColor;
1494 aDstFillColor = pAt->aFillColor;
1495 if ( pAt->nFlags & PushFlags::FILLCOLOR )
1496 aSrcFillColor = pAt->aFillColor;
1497 eDstROP2 = pAt->eRasterOp;
1498 if ( pAt->nFlags & PushFlags::RASTEROP )
1499 eSrcRasterOp = pAt->eRasterOp;
1500 aDstFont = pAt->aFont;
1501 if ( pAt->nFlags & PushFlags::FONT )
1502 aSrcFont = pAt->aFont;
1503 eDstTextAlign = pAt->eTextAlign;
1504 if ( pAt->nFlags & ( PushFlags::FONT | PushFlags::TEXTALIGN ) )
1505 eSrcTextAlign = pAt->eTextAlign;
1506 aDstTextColor = pAt->aTextColor;
1507 if ( pAt->nFlags & ( PushFlags::FONT | PushFlags::TEXTCOLOR ) )
1508 aSrcTextColor = pAt->aTextColor;
1509 if ( pAt->nFlags & PushFlags::MAPMODE )
1510 aSrcMapMode = pAt->aMapMode;
1511 aDstClipRegion = pAt->aClipRegion;
1512 if ( pAt->nFlags & PushFlags::CLIPREGION )
1513 aSrcClipRegion = pAt->aClipRegion;
1514
1515 WMFRecord_RestoreDC();
1516 pAttrStack = pAt->pSucc;
1517 delete pAt;
1518 }
1519 }
1520 break;
1521
1522 case MetaActionType::EPS :
1523 {
1524 const MetaEPSAction* pA = static_cast<const MetaEPSAction*>(pMA);
1525 const GDIMetaFile& aGDIMetaFile( pA->GetSubstitute() );
1526
1527 size_t nCount = aGDIMetaFile.GetActionSize();
1528 for ( size_t i = 0; i < nCount; i++ )
1529 {
1530 const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
1531 if ( pMetaAct->GetType() == MetaActionType::BMPSCALE )
1532 {
1533 const MetaBmpScaleAction* pBmpScaleAction = static_cast<const MetaBmpScaleAction*>(pMetaAct);
1534 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() );
1535 break;
1536 }
1537 }
1538 }
1539 break;
1540
1541 case MetaActionType::RASTEROP:
1542 {
1543 const MetaRasterOpAction* pA = static_cast<const MetaRasterOpAction*>(pMA);
1544 eSrcRasterOp=pA->GetRasterOp();
1545 }
1546 break;
1547
1548 case MetaActionType::Transparent:
1549 {
1550 aSrcLineInfo = LineInfo();
1551 SetLineAndFillAttr();
1552 WMFRecord_PolyPolygon( static_cast<const MetaTransparentAction*>(pMA)->GetPolyPolygon() );
1553 }
1554 break;
1555
1556 case MetaActionType::FLOATTRANSPARENT:
1557 {
1558 const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pMA);
1559
1560 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1561 Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1562 const Size aSrcSize( aTmpMtf.GetPrefSize() );
1563 const Point aDestPt( pA->GetPoint() );
1564 const Size aDestSize( pA->GetSize() );
1565 const double fScaleX = aSrcSize.Width() ? static_cast<double>(aDestSize.Width()) / aSrcSize.Width() : 1.0;
1566 const double fScaleY = aSrcSize.Height() ? static_cast<double>(aDestSize.Height()) / aSrcSize.Height() : 1.0;
1567 long nMoveX, nMoveY;
1568
1569 aSrcLineInfo = LineInfo();
1570 SetAllAttr();
1571
1572 if( fScaleX != 1.0 || fScaleY != 1.0 )
1573 {
1574 aTmpMtf.Scale( fScaleX, fScaleY );
1575 aSrcPt.setX( FRound( aSrcPt.X() * fScaleX ) );
1576 aSrcPt.setY( FRound( aSrcPt.Y() * fScaleY ) );
1577 }
1578
1579 nMoveX = aDestPt.X() - aSrcPt.X();
1580 nMoveY = aDestPt.Y() - aSrcPt.Y();
1581
1582 if( nMoveX || nMoveY )
1583 aTmpMtf.Move( nMoveX, nMoveY );
1584
1585 WriteRecords( aTmpMtf );
1586 }
1587 break;
1588
1589 case MetaActionType::LAYOUTMODE:
1590 {
1591 ComplexTextLayoutFlags nLayoutMode = static_cast<const MetaLayoutModeAction*>(pMA)->GetLayoutMode();
1592 eSrcHorTextAlign = 0; // TA_LEFT
1593 if ((nLayoutMode & ComplexTextLayoutFlags::BiDiRtl) != ComplexTextLayoutFlags::Default)
1594 {
1595 eSrcHorTextAlign = W_TA_RIGHT0x0002 | W_TA_RTLREADING0x0100;
1596 }
1597 if ((nLayoutMode & ComplexTextLayoutFlags::TextOriginRight) != ComplexTextLayoutFlags::Default)
1598 eSrcHorTextAlign |= W_TA_RIGHT0x0002;
1599 else if ((nLayoutMode & ComplexTextLayoutFlags::TextOriginLeft) != ComplexTextLayoutFlags::Default)
1600 eSrcHorTextAlign &= ~W_TA_RIGHT0x0002;
1601 break;
1602 }
1603
1604 case MetaActionType::CLIPREGION:
1605 case MetaActionType::TEXTLANGUAGE:
1606 case MetaActionType::COMMENT:
1607 // Explicitly ignored cases
1608 break;
1609
1610 default:
1611 // TODO: Implement more cases as necessary. Let's not bother with a warning.
1612 break;
1613 }
1614
1615 nWrittenActions++;
1616 MayCallback();
1617
1618 if (pWMF->GetError())
1619 bStatus=false;
1620
1621 if(!bStatus)
1622 break;
1623 }
1624}
1625
1626void WMFWriter::WriteHeader( bool bPlaceable )
1627{
1628 if( bPlaceable )
1629 {
1630 sal_uInt16 nCheckSum, nValue;
1631 Size aSize( OutputDevice::LogicToLogic(Size(1,1),MapMode(MapUnit::MapInch), aTargetMapMode) );
1632 sal_uInt16 nUnitsPerInch = static_cast<sal_uInt16>( ( aSize.Width() + aSize.Height() ) >> 1 );
1633
1634 nCheckSum=0;
1635 nValue=0xcdd7; nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
1636 nValue=0x9ac6; nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
1637 nValue=0x0000; nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
1638 nValue=0x0000; nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
1639 nValue=0x0000; nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
1640 nValue=static_cast<sal_uInt16>(aTargetSize.Width()); nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
1641 nValue=static_cast<sal_uInt16>(aTargetSize.Height()); nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
1642 nValue=nUnitsPerInch; nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
1643 nValue=0x0000; nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
1644 nValue=0x0000; nCheckSum^=nValue; pWMF->WriteUInt16( nValue );
1645 pWMF->WriteUInt16( nCheckSum );
1646 }
1647
1648 nMetafileHeaderPos=pWMF->Tell();
1649 pWMF->WriteUInt16( 0x0001 ) // type: file
1650 .WriteUInt16( 0x0009 ) // header length in words
1651 .WriteUInt16( 0x0300 ) // Version as BCD number
1652 .WriteUInt32( 0x00000000 ) // file length (without 1st header), is later corrected by UpdateHeader()
1653 .WriteUInt16( MAXOBJECTHANDLES16 ) // maximum number of simultaneous objects
1654 .WriteUInt32( 0x00000000 ) // maximum record length, is later corrected by UpdateHeader()
1655 .WriteUInt16( 0x0000 ); // reserved
1656}
1657
1658void WMFWriter::UpdateHeader()
1659{
1660 sal_uLong nPos;
1661 sal_uInt32 nFileSize;
1662
1663 nPos=pWMF->Tell(); // endposition = total size of file
1664 nFileSize=nPos-nMetafileHeaderPos; // subtract size of 1st header
1665 if ((nFileSize&1)!=0) { // if needed round to words
1666 pWMF->WriteUChar( 0 );
1667 nPos++;
1668 nFileSize++;
1669 }
1670 nFileSize>>=1; // convert to number of words
1671 pWMF->Seek(nMetafileHeaderPos+6); // to filesize entry in second header
1672 pWMF->WriteUInt32( nFileSize ); // rectify file size
1673 pWMF->SeekRel(2); // to max-record-length-entry in second header
1674 pWMF->WriteUInt32( nMaxRecordSize ); // and rectify
1675 pWMF->Seek(nPos);
1676}
1677
1678bool WMFWriter::WriteWMF( const GDIMetaFile& rMTF, SvStream& rTargetStream,
1679 FilterConfigItem const * pFConfigItem, bool bPlaceable )
1680{
1681 WMFWriterAttrStackMember * pAt;
1682
1683 bEmbedEMF = true;
1684 bStatus=true;
1685 pVirDev = VclPtr<VirtualDevice>::Create();
1686
1687 if (pFConfigItem)
1688 {
1689 xStatusIndicator = pFConfigItem->GetStatusIndicator();
1690 if ( xStatusIndicator.is() )
1691 {
1692 xStatusIndicator->start( OUString(), 100 );
1693 }
1694 }
1695 nLastPercent=0;
1696
1697 pWMF=&rTargetStream;
1698 pWMF->SetEndian(SvStreamEndian::LITTLE);
1699
1700 nMaxRecordSize=0;
1701
1702 aSrcMapMode=rMTF.GetPrefMapMode();
1703
1704 if( bPlaceable )
1705 {
1706 aTargetMapMode = aSrcMapMode;
1707 aTargetSize = rMTF.GetPrefSize();
1708 sal_uInt16 nTargetDivisor = CalcSaveTargetMapMode(aTargetMapMode, aTargetSize);
1709 aTargetSize.setWidth( aTargetSize.Width() / nTargetDivisor );
1710 aTargetSize.setHeight( aTargetSize.Height() / nTargetDivisor );
1711 }
1712 else
1713 {
1714 aTargetMapMode = MapMode( MapUnit::MapInch );
1715
1716 const long nUnit = pVirDev->LogicToPixel( Size( 1, 1 ), aTargetMapMode ).Width();
1717 const Fraction aFrac( 1, nUnit );
1718
1719 aTargetMapMode.SetScaleX( aFrac );
1720 aTargetMapMode.SetScaleY( aFrac );
1721 aTargetSize = OutputDevice::LogicToLogic( rMTF.GetPrefSize(), aSrcMapMode, aTargetMapMode );
1722 }
1723
1724 pVirDev->SetMapMode( aTargetMapMode );
1725
1726 pAttrStack=nullptr;
1727
1728 for (bool & rn : bHandleAllocated)
1729 rn=false;
1730
1731 nDstPenHandle=0xffff;
1732 nDstFontHandle=0xffff;
1733 nDstBrushHandle=0xffff;
1734
1735 nNumberOfActions=0;
1736 nNumberOfBitmaps=0;
1737 nWrittenActions=0;
1738 nWrittenBitmaps=0;
1739 nActBitmapPercent=0;
1740
1741 CountActionsAndBitmaps(rMTF);
1742
1743 WriteHeader(bPlaceable);
1744 if( bEmbedEMF )
1745 WriteEmbeddedEMF( rMTF );
1746 WMFRecord_SetWindowOrg(Point(0,0));
1747 WMFRecord_SetWindowExt(rMTF.GetPrefSize());
1748 WMFRecord_SetBkMode( true );
1749
1750 eDstROP2 = eSrcRasterOp = RasterOp::OverPaint;
1751 WMFRecord_SetROP2(eDstROP2);
1752
1753 aDstLineInfo = LineInfo();
1754 aDstLineColor = aSrcLineColor = COL_BLACK;
1755 CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
1756
1757 aDstFillColor = aSrcFillColor = COL_WHITE;
1758 CreateSelectDeleteBrush( aDstFillColor );
1759
1760 aDstClipRegion = aSrcClipRegion = vcl::Region();
1761
1762 vcl::Font aFont;
1763 aFont.SetCharSet( GetExtendedTextEncoding( RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1)) ) );
1764 aFont.SetColor( COL_WHITE );
1765 aFont.SetAlignment( ALIGN_BASELINE );
1766 aDstFont = aSrcFont = aFont;
1767 CreateSelectDeleteFont(aDstFont);
1768
1769 eDstTextAlign = eSrcTextAlign = ALIGN_BASELINE;
1770 eDstHorTextAlign = eSrcHorTextAlign = W_TA_LEFT0x0000;
1771 WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
1772
1773 aDstTextColor = aSrcTextColor = COL_WHITE;
1774 WMFRecord_SetTextColor(aDstTextColor);
1775
1776 // Write records
1777 WriteRecords(rMTF);
1778
1779 WriteRecordHeader(0x00000003,0x0000); // end of file
1780 UpdateHeader();
1781
1782 while(pAttrStack)
1783 {
1784 pAt=pAttrStack;
1785 pAttrStack=pAt->pSucc;
1786 delete pAt;
1787 }
1788
1789 pVirDev.disposeAndClear();
1790
1791 if ( xStatusIndicator.is() )
1792 xStatusIndicator->end();
1793
1794 return bStatus;
1795}
1796
1797sal_uInt16 WMFWriter::CalcSaveTargetMapMode(MapMode& rMapMode,
1798 const Size& rPrefSize)
1799{
1800 Fraction aDivFrac(2, 1);
1801 sal_uInt16 nDivisor = 1;
1802
1803 Size aSize = OutputDevice::LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
1804
1805 while( nDivisor <= 64 && (aSize.Width() > 32767 || aSize.Height() > 32767) )
1806 {
1807 Fraction aFrac = rMapMode.GetScaleX();
1808
1809 aFrac *= aDivFrac;
1810 rMapMode.SetScaleX(aFrac);
1811 aFrac = rMapMode.GetScaleY();
1812 aFrac *= aDivFrac;
1813 rMapMode.SetScaleY(aFrac);
1814 nDivisor <<= 1;
1815 aSize = OutputDevice::LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
1816 }
1817
1818 return nDivisor;
1819}
1820
1821void WMFWriter::WriteEmbeddedEMF( const GDIMetaFile& rMTF )
1822{
1823 SvMemoryStream aStream;
1824 EMFWriter aEMFWriter(aStream);
1825
1826 if( !aEMFWriter.WriteEMF( rMTF ) )
1
Assuming the condition is true
2
Taking true branch
1827 return;
3
Calling implicit destructor for 'EMFWriter'
4
Calling '~ScopedVclPtr'
1828
1829 sal_uInt64 const nTotalSize = aStream.Tell();
1830 if( nTotalSize > SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF) )
1831 return;
1832 aStream.Seek( 0 );
1833 sal_uInt32 nRemainingSize = static_cast< sal_uInt32 >( nTotalSize );
1834 sal_uInt32 nRecCounts = ( (nTotalSize - 1) / 0x2000 ) + 1;
1835 sal_uInt16 nCheckSum = 0, nWord;
1836
1837 sal_uInt32 nPos = 0;
1838
1839 while( nPos + 1 < nTotalSize )
1840 {
1841 aStream.ReadUInt16( nWord );
1842 nCheckSum ^= nWord;
1843 nPos += 2;
1844 }
1845
1846 nCheckSum = static_cast< sal_uInt16 >( nCheckSum * -1 );
1847
1848 aStream.Seek( 0 );
1849 while( nRemainingSize > 0 )
1850 {
1851 sal_uInt32 nCurSize;
1852 if( nRemainingSize > 0x2000 )
1853 {
1854 nCurSize = 0x2000;
1855 nRemainingSize -= 0x2000;
1856 }
1857 else
1858 {
1859 nCurSize = nRemainingSize;
1860 nRemainingSize = 0;
1861 }
1862 WriteEMFRecord( aStream,
1863 nCurSize,
1864 nRemainingSize,
1865 nTotalSize,
1866 nRecCounts,
1867 nCheckSum );
1868 nCheckSum = 0;
1869 }
1870
1871}
1872
1873void WMFWriter::WriteEMFRecord( SvMemoryStream& rStream, sal_uInt32 nCurSize, sal_uInt32 nRemainingSize,
1874 sal_uInt32 nTotalSize, sal_uInt32 nRecCounts, sal_uInt16 nCheckSum )
1875{
1876 // according to http://msdn.microsoft.com/en-us/library/dd366152%28PROT.13%29.aspx
1877 WriteRecordHeader( 0, W_META_ESCAPE0x0626 );
1878 pWMF->WriteUInt16( W_MFCOMMENT15 ) // same as META_ESCAPE_ENHANCED_METAFILE
1879 .WriteUInt16( nCurSize + 34 ) // we will always have a 34 byte escape header:
1880 .WriteUInt32( 0x43464D57 ) // WMFC
1881 .WriteUInt32( 0x00000001 ) // Comment type
1882 .WriteUInt32( 0x00010000 ) // version
1883 .WriteUInt16( nCheckSum ) // check sum
1884 .WriteUInt32( 0 ) // flags = 0
1885 .WriteUInt32( nRecCounts ) // total number of records
1886 .WriteUInt32( nCurSize ) // size of this record's data
1887 .WriteUInt32( nRemainingSize ) // remaining size of data in following records, missing in MSDN documentation
1888 .WriteUInt32( nTotalSize ); // total size of EMF stream
1889
1890 pWMF->WriteBytes(static_cast<const char*>(rStream.GetData()) + rStream.Tell(), nCurSize);
1891 rStream.SeekRel( nCurSize );
1892 UpdateRecordHeader();
1893}
1894
1895/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

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#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
6
Calling copy constructor for 'Reference<VirtualDevice>'
9
Returning from copy constructor for 'Reference<VirtualDevice>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
10
Calling 'Reference::clear'
17
Returning; memory was released
205 if (aTmp.get()) {
18
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
5
Calling 'VclPtr::disposeAndClear'
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
7
Assuming field 'm_pBody' is non-null
8
Taking true branch
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
10.1
Field 'm_pBody' is non-null
10.1
Field 'm_pBody' is non-null
10.1
Field 'm_pBody' is non-null
10.1
Field 'm_pBody' is non-null
)
11
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
12
Calling 'VclReferenceBase::release'
16
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
19
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
13
Assuming the condition is true
14
Taking true branch
40 delete this;
15
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif