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 ipict.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 -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 EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/filter/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 -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/filter/source/graphicfilter/ipict/ipict.cxx

/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.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 <string.h>
21#include <osl/thread.h>
22#include <sal/log.hxx>
23#include <vcl/BitmapTools.hxx>
24#include <vcl/graph.hxx>
25#include <vcl/gdimtf.hxx>
26#include <tools/poly.hxx>
27#include <tools/fract.hxx>
28#include <tools/stream.hxx>
29#include <vcl/virdev.hxx>
30#include <math.h>
31
32#include "ipict.hxx"
33#include "shape.hxx"
34#include <memory>
35
36#include <vcl/FilterConfigItem.hxx>
37 // complete FilterConfigItem for GraphicImport under -fsanitize=function
38
39namespace PictReaderInternal {
40 namespace {
41
42 //! utilitary class to store a pattern, ...
43 class Pattern {
44 public:
45 //! constructor
46 Pattern() : penStyle(PEN_SOLID),
47 brushStyle(BRUSH_SOLID),
48 nBitCount(64),
49 isColor(false),
50 isRead(false)
51 {}
52
53 //! reads black/white pattern from SvStream
54 sal_uInt8 read(SvStream &stream);
55 //! sets the color
56 void setColor(Color col) { isColor = true; color = col; }
57 /** returns a color which can be "used" to replace the pattern,
58 * created from ForeColor and BackColor, ...
59 *
60 * note: maybe, we must also use some mode PatCopy, ... to define the color
61 */
62 Color getColor(Color bkColor, Color fgColor) const {
63 if (isColor) return color;
64 // we create a gray pattern from nBitCount
65 double alpha = nBitCount / 64.0;
66 return Color(sal_uInt8(alpha*fgColor.GetRed()+(1.0-alpha)*bkColor.GetRed()),
67 sal_uInt8(alpha*fgColor.GetGreen()+(1.0-alpha)*bkColor.GetGreen()),
68 sal_uInt8(alpha*fgColor.GetBlue()+(1.0-alpha)*bkColor.GetBlue()));
69 }
70
71 //! returns true if this is the default pattern
72 bool isDefault() const { return !isRead; }
73
74 enum PenStyle { PEN_NULL, PEN_SOLID, PEN_DOT, PEN_DASH, PEN_DASHDOT };
75 enum BrushStyle { BRUSH_SOLID, BRUSH_HORZ, BRUSH_VERT,
76 BRUSH_CROSS, BRUSH_DIAGCROSS, BRUSH_UPDIAG, BRUSH_DOWNDIAG,
77 BRUSH_25, BRUSH_50, BRUSH_75 };
78 // Data
79 enum PenStyle penStyle;
80 enum BrushStyle brushStyle;
81 short nBitCount;
82
83 bool isColor; // true if it is a color pattern
84 Color color;
85
86 protected:
87 // flag to know if the pattern came from reading the picture, or if it is the default pattern
88 bool isRead;
89 };
90
91 }
92
93 sal_uInt8 Pattern::read(SvStream &stream) {
94 unsigned char nbyte[8];
95 sal_uInt32 nHiBytes, nLoBytes;
96 isColor = false;
97
98 // count the no of bits in pattern which are set to 1:
99 nBitCount=0;
100 for (unsigned char & ny : nbyte) {
101 stream.ReadChar( reinterpret_cast<char&>(ny) );
102 for (short nx=0; nx<8; nx++) {
103 if ( (ny & (1<<nx)) != 0 ) nBitCount++;
104 }
105 }
106
107 // store pattern in 2 long words:
108 nHiBytes=(((((static_cast<sal_uInt32>(nbyte[0])<<8)|
109 static_cast<sal_uInt32>(nbyte[1]))<<8)|
110 static_cast<sal_uInt32>(nbyte[2]))<<8)|
111 static_cast<sal_uInt32>(nbyte[3]);
112 nLoBytes=(((((static_cast<sal_uInt32>(nbyte[4])<<8)|
113 static_cast<sal_uInt32>(nbyte[5]))<<8)|
114 static_cast<sal_uInt32>(nbyte[6]))<<8)|
115 static_cast<sal_uInt32>(nbyte[7]);
116
117 // create a PenStyle:
118 if (nBitCount<=0) penStyle=PEN_NULL;
119 else if (nBitCount<=16) penStyle=PEN_DOT;
120 else if (nBitCount<=32) penStyle=PEN_DASHDOT;
121 else if (nBitCount<=48) penStyle=PEN_DASH;
122 else penStyle=PEN_SOLID;
123
124 // create a BrushStyle:
125 if (nHiBytes==0xffffffff && nLoBytes==0xffffffff) brushStyle=BRUSH_SOLID;
126 else if (nHiBytes==0xff000000 && nLoBytes==0x00000000) brushStyle=BRUSH_HORZ;
127 else if (nHiBytes==0x80808080 && nLoBytes==0x80808080) brushStyle=BRUSH_VERT;
128 else if (nHiBytes==0xff808080 && nLoBytes==0x80808080) brushStyle=BRUSH_CROSS;
129 else if (nHiBytes==0x01824428 && nLoBytes==0x10284482) brushStyle=BRUSH_DIAGCROSS;
130 else if (nHiBytes==0x80402010 && nLoBytes==0x08040201) brushStyle=BRUSH_UPDIAG;
131 else if (nHiBytes==0x01020408 && nLoBytes==0x10204080) brushStyle=BRUSH_DOWNDIAG;
132 else if (nBitCount<=24) brushStyle=BRUSH_25;
133 else if (nBitCount<=40) brushStyle=BRUSH_50;
134 else if (nBitCount<=56) brushStyle=BRUSH_75;
135 else brushStyle=BRUSH_SOLID;
136
137 isRead = true;
138
139 return 8;
140 }
141}
142
143//============================ PictReader ==================================
144
145namespace {
146
147enum class PictDrawingMethod {
148 FRAME, PAINT, ERASE, INVERT, FILL,
149 TEXT, UNDEFINED
150};
151
152class PictReader {
153 typedef class PictReaderInternal::Pattern Pattern;
154private:
155
156 SvStream * pPict; // The Pict file to read.
157 VclPtr<VirtualDevice> pVirDev; // Here the drawing method will be called.
158 // A recording into the GDIMetaFile will take place.
159
160 sal_uInt64 nOrigPos; // Initial position in pPict.
161 bool IsVersion2; // If it is a version 2 Pictfile.
162 tools::Rectangle aBoundingRect; // Min/Max-Rectangle for the whole drawing.
163
164 Point aPenPosition;
165 Point aTextPosition;
166 Color aActForeColor;
167 Color aActBackColor;
168 Pattern eActPenPattern;
169 Pattern eActFillPattern;
170 Pattern eActBackPattern;
171 Size nActPenSize;
172 // Note: Postscript mode is stored by setting eActRop to RasterOp::N1
173 RasterOp eActROP;
174 PictDrawingMethod eActMethod;
175 Size aActOvalSize;
176 vcl::Font aActFont;
177
178 Fraction aHRes;
179 Fraction aVRes;
180
181 Point ReadPoint();
182
183 Point ReadDeltaH(Point aBase);
184 Point ReadDeltaV(Point aBase);
185
186 Point ReadUnsignedDeltaH(Point aBase);
187 Point ReadUnsignedDeltaV(Point aBase);
188
189 Size ReadSize();
190
191 Color ReadColor();
192
193 Color ReadRGBColor();
194
195 void ReadRectangle(tools::Rectangle & rRect);
196
197 sal_uInt64 ReadPolygon(tools::Polygon & rPoly);
198
199 sal_uInt64 ReadPixPattern(Pattern &pattern);
200
201 tools::Rectangle aLastRect;
202 sal_uInt8 ReadAndDrawRect(PictDrawingMethod eMethod);
203 sal_uInt8 ReadAndDrawSameRect(PictDrawingMethod eMethod);
204
205 tools::Rectangle aLastRoundRect;
206 sal_uInt8 ReadAndDrawRoundRect(PictDrawingMethod eMethod);
207 sal_uInt8 ReadAndDrawSameRoundRect(PictDrawingMethod eMethod);
208
209 tools::Rectangle aLastOval;
210 sal_uInt8 ReadAndDrawOval(PictDrawingMethod eMethod);
211 sal_uInt8 ReadAndDrawSameOval(PictDrawingMethod eMethod);
212
213 tools::Polygon aLastPolygon;
214 sal_uInt64 ReadAndDrawPolygon(PictDrawingMethod eMethod);
215 sal_uInt8 ReadAndDrawSamePolygon(PictDrawingMethod eMethod);
216
217 tools::Rectangle aLastArcRect;
218 sal_uInt8 ReadAndDrawArc(PictDrawingMethod eMethod);
219 sal_uInt8 ReadAndDrawSameArc(PictDrawingMethod eMethod);
220
221 sal_uInt64 ReadAndDrawRgn(PictDrawingMethod eMethod);
222 sal_uInt8 ReadAndDrawSameRgn(PictDrawingMethod eMethod);
223
224 // returns true if there's no need to print the shape/text/frame
225 bool IsInvisible( PictDrawingMethod eMethod ) const {
226 if ( eActROP == RasterOp::N1 ) return true;
227 if ( eMethod == PictDrawingMethod::FRAME && nActPenSize.IsEmpty() ) return true;
228 return false;
229 }
230
231 void DrawingMethod(PictDrawingMethod eMethod);
232
233 sal_uInt64 ReadAndDrawText();
234
235 sal_uInt64 ReadPixMapEtc(BitmapEx & rBitmap, bool bBaseAddr, bool bColorTable,
236 tools::Rectangle * pSrcRect, tools::Rectangle * pDestRect,
237 bool bMode, bool bMaskRgn);
238
239 void ReadHeader();
240 // Reads the header of the Pict file, set IsVersion and aBoundingRect
241
242 sal_uInt64 ReadData(sal_uInt16 nOpcode);
243 // Reads the date of anOopcode and executes the operation.
244 // The number of data bytes belonging to the opcode will be returned
245 // in any case.
246
247 void SetLineColor( const Color& rColor );
248 void SetFillColor( const Color& rColor );
249
250 // OSNOLA: returns the text encoding which must be used for system id
251 static rtl_TextEncoding GetTextEncoding (sal_uInt16 fId = 0xFFFF);
252
253public:
254
255 PictReader()
256 : pPict(nullptr)
257 , pVirDev(nullptr)
258 , nOrigPos(0)
259 , IsVersion2(false)
260 , eActROP(RasterOp::OverPaint)
261 , eActMethod(PictDrawingMethod::UNDEFINED)
262 {
263 aActFont.SetCharSet(GetTextEncoding());
264 }
265
266 void ReadPict( SvStream & rStreamPict, GDIMetaFile & rGDIMetaFile );
267 // reads a pict file from the stream and fills the GDIMetaFile
268
269};
270
271}
272
273static void SetByte(sal_uInt16& nx, sal_uInt16 ny, vcl::bitmap::RawBitmap& rBitmap, sal_uInt16 nPixelSize, sal_uInt8 nDat, sal_uInt16 nWidth, std::vector<Color> const & rvPalette)
274{
275 switch (nPixelSize)
276 {
277 case 1:
278 rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 7) & 1]);
279 if ( nx == nWidth ) break;
280 rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 6) & 1]);
281 if ( nx == nWidth ) break;
282 rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 5) & 1]);
283 if ( nx == nWidth ) break;
284 rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 4) & 1]);
285 if ( nx == nWidth ) break;
286 rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 3) & 1]);
287 if ( nx == nWidth ) break;
288 rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 2) & 1]);
289 if ( nx == nWidth ) break;
290 rBitmap.SetPixel(ny, nx++, rvPalette[(nDat >> 1) & 1]);
291 if ( nx == nWidth ) break;
292 rBitmap.SetPixel(ny, nx++, rvPalette[nDat & 1]);
293 break;
294 case 2:
295 rBitmap.SetPixel(ny, nx++, rvPalette[nDat >> 6]);
296 if ( nx == nWidth ) break;
297 rBitmap.SetPixel(ny, nx++, rvPalette[(nDat>>4)&3]);
298 if ( nx == nWidth ) break;
299 rBitmap.SetPixel(ny, nx++, rvPalette[(nDat>>2)&3]);
300 if ( nx == nWidth ) break;
301 rBitmap.SetPixel(ny, nx++, rvPalette[nDat & 3]);
302 break;
303 case 4:
304 rBitmap.SetPixel(ny, nx++, rvPalette[nDat >> 4]);
305 if ( nx == nWidth ) break;
306 rBitmap.SetPixel(ny, nx++, rvPalette[nDat & 0x0f]);
307 break;
308 case 8:
309 rBitmap.SetPixel(ny, nx++, rvPalette[nDat]);
310 break;
311 }
312}
313
314//=================== methods of PictReader ==============================
315rtl_TextEncoding PictReader::GetTextEncoding (sal_uInt16 fId) {
316 static rtl_TextEncoding enc = [&]()
317 {
318 rtl_TextEncoding def = osl_getThreadTextEncoding();
319 // we keep osl_getThreadTextEncoding only if it is a mac encoding
320 switch(def) {
321 case RTL_TEXTENCODING_APPLE_ROMAN(((rtl_TextEncoding) 2)):
322 case RTL_TEXTENCODING_APPLE_ARABIC(((rtl_TextEncoding) 41)):
323 case RTL_TEXTENCODING_APPLE_CENTEURO(((rtl_TextEncoding) 42)):
324 case RTL_TEXTENCODING_APPLE_CROATIAN(((rtl_TextEncoding) 43)):
325 case RTL_TEXTENCODING_APPLE_CYRILLIC(((rtl_TextEncoding) 44)):
326 case RTL_TEXTENCODING_APPLE_DEVANAGARI(((rtl_TextEncoding) 45)):
327 case RTL_TEXTENCODING_APPLE_FARSI(((rtl_TextEncoding) 46)):
328 case RTL_TEXTENCODING_APPLE_GREEK(((rtl_TextEncoding) 47)):
329 case RTL_TEXTENCODING_APPLE_GUJARATI(((rtl_TextEncoding) 48)):
330 case RTL_TEXTENCODING_APPLE_GURMUKHI(((rtl_TextEncoding) 49)):
331 case RTL_TEXTENCODING_APPLE_HEBREW(((rtl_TextEncoding) 50)):
332 case RTL_TEXTENCODING_APPLE_ICELAND(((rtl_TextEncoding) 51)):
333 case RTL_TEXTENCODING_APPLE_ROMANIAN(((rtl_TextEncoding) 52)):
334 case RTL_TEXTENCODING_APPLE_THAI(((rtl_TextEncoding) 53)):
335 case RTL_TEXTENCODING_APPLE_TURKISH(((rtl_TextEncoding) 54)):
336 case RTL_TEXTENCODING_APPLE_UKRAINIAN(((rtl_TextEncoding) 55)):
337 case RTL_TEXTENCODING_APPLE_CHINSIMP(((rtl_TextEncoding) 56)):
338 case RTL_TEXTENCODING_APPLE_CHINTRAD(((rtl_TextEncoding) 57)):
339 case RTL_TEXTENCODING_APPLE_JAPANESE(((rtl_TextEncoding) 58)):
340 case RTL_TEXTENCODING_APPLE_KOREAN(((rtl_TextEncoding) 59)):
341 return def; break;
342 default:
343 break;
344 }
345 return RTL_TEXTENCODING_APPLE_ROMAN(((rtl_TextEncoding) 2));
346 }();
347 if (fId == 13) return RTL_TEXTENCODING_ADOBE_DINGBATS(((rtl_TextEncoding) 94)); // CHECKME
348 if (fId == 23) return RTL_TEXTENCODING_ADOBE_SYMBOL(((rtl_TextEncoding) 92));
349 return enc;
350}
351
352void PictReader::SetLineColor( const Color& rColor )
353{
354 pVirDev->SetLineColor( rColor );
355}
356
357void PictReader::SetFillColor( const Color& rColor )
358{
359 pVirDev->SetFillColor( rColor );
360}
361
362Point PictReader::ReadPoint()
363{
364 short nx,ny;
365
366 pPict->ReadInt16( ny ).ReadInt16( nx );
367
368 Point aPoint( static_cast<long>(nx) - aBoundingRect.Left(),
369 static_cast<long>(ny) - aBoundingRect.Top() );
370
371 SAL_INFO("filter.pict", "ReadPoint: " << aPoint)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "filter.pict")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ReadPoint: " <<
aPoint) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "371" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ReadPoint: " << aPoint), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"ReadPoint: " << aPoint; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "371" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ReadPoint: " << aPoint) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "371" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ReadPoint: " << aPoint), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"ReadPoint: " << aPoint; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "371" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
372 return aPoint;
373}
374
375Point PictReader::ReadDeltaH(Point aBase)
376{
377 signed char ndh;
378
379 pPict->ReadChar( reinterpret_cast<char&>(ndh) );
380
381 return Point( aBase.X() + static_cast<long>(ndh), aBase.Y() );
382}
383
384Point PictReader::ReadDeltaV(Point aBase)
385{
386 signed char ndv;
387
388 pPict->ReadChar( reinterpret_cast<char&>(ndv) );
389
390 return Point( aBase.X(), aBase.Y() + static_cast<long>(ndv) );
391}
392
393Point PictReader::ReadUnsignedDeltaH(Point aBase)
394{
395 sal_uInt8 ndh;
396
397 pPict->ReadUChar( ndh );
398
399 return Point( aBase.X() + static_cast<long>(ndh), aBase.Y() );
400}
401
402Point PictReader::ReadUnsignedDeltaV(Point aBase)
403{
404 sal_uInt8 ndv;
405
406 pPict->ReadUChar( ndv );
407
408 return Point( aBase.X(), aBase.Y() + static_cast<long>(ndv) );
409}
410
411Size PictReader::ReadSize()
412{
413 short nx,ny;
414
415 pPict->ReadInt16( ny ).ReadInt16( nx );
416
417 return Size( static_cast<long>(nx), static_cast<long>(ny) );
418}
419
420Color PictReader::ReadColor()
421{
422 sal_uInt32 nCol;
423 Color aCol;
424
425 pPict->ReadUInt32( nCol );
426 switch (nCol)
427 {
428 case 33: aCol=COL_BLACK; break;
429 case 30: aCol=COL_WHITE; break;
430 case 205: aCol=COL_LIGHTRED; break;
431 case 341: aCol=COL_LIGHTGREEN; break;
432 case 409: aCol=COL_LIGHTBLUE; break;
433 case 273: aCol=COL_LIGHTCYAN; break;
434 case 137: aCol=COL_LIGHTMAGENTA; break;
435 case 69: aCol=COL_YELLOW; break;
436 default: aCol=COL_LIGHTGRAY;
437 }
438 return aCol;
439}
440
441
442Color PictReader::ReadRGBColor()
443{
444 sal_uInt16 nR, nG, nB;
445
446 pPict->ReadUInt16( nR ).ReadUInt16( nG ).ReadUInt16( nB );
447 return Color( static_cast<sal_uInt8>( nR >> 8 ), static_cast<sal_uInt8>( nG >> 8 ), static_cast<sal_uInt8>( nB >> 8 ) );
448}
449
450
451void PictReader::ReadRectangle(tools::Rectangle & rRect)
452{
453 Point aTopLeft, aBottomRight;
454
455 aTopLeft=ReadPoint();
456 aBottomRight=ReadPoint();
457 if (aTopLeft.X() > aBottomRight.X() || aTopLeft.Y() > aBottomRight.Y())
458 {
459 SAL_WARN("filter.pict", "broken rectangle")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "filter.pict")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken rectangle") ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.pict"
), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "459" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "broken rectangle"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"broken rectangle"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "459" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken rectangle") == 1) { ::sal_detail_log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "459" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "broken rectangle"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"broken rectangle"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "459" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
460 pPict->SetError( SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ) );
461 rRect = tools::Rectangle();
462 return;
463 }
464 rRect=tools::Rectangle(aTopLeft,aBottomRight);
465
466 SAL_INFO("filter.pict", "ReadRectangle: " << rRect)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "filter.pict")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ReadRectangle: " <<
rRect) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "466" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ReadRectangle: " << rRect), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ReadRectangle: " << rRect; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "466" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ReadRectangle: " << rRect) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "466" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ReadRectangle: " << rRect), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ReadRectangle: " << rRect; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "466" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
467}
468
469sal_uInt64 PictReader::ReadPolygon(tools::Polygon & rPoly)
470{
471 sal_uInt16 nSize(0);
472 pPict->ReadUInt16(nSize);
473 pPict->SeekRel(8);
474 sal_uInt64 nDataSize = static_cast<sal_uInt64>(nSize);
475 nSize=(nSize-10)/4;
476 const size_t nMaxPossiblePoints = pPict->remainingSize() / 2 * sizeof(sal_uInt16);
477 if (nSize > nMaxPossiblePoints)
478 {
479 SAL_WARN("filter.pict", "pict record claims to have: " << nSize << " points, but only " << nMaxPossiblePoints << " possible, clamping")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "filter.pict")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "pict record claims to have: "
<< nSize << " points, but only " << nMaxPossiblePoints
<< " possible, clamping") == 1) { ::sal_detail_log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "479" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "pict record claims to have: " <<
nSize << " points, but only " << nMaxPossiblePoints
<< " possible, clamping"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "pict record claims to have: "
<< nSize << " points, but only " << nMaxPossiblePoints
<< " possible, clamping"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "479" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "pict record claims to have: " << nSize <<
" points, but only " << nMaxPossiblePoints << " possible, clamping"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("filter.pict"
), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "479" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "pict record claims to have: " <<
nSize << " points, but only " << nMaxPossiblePoints
<< " possible, clamping"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "pict record claims to have: "
<< nSize << " points, but only " << nMaxPossiblePoints
<< " possible, clamping"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "479" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
480 nSize = nMaxPossiblePoints;
481 }
482 rPoly.SetSize(nSize);
483 for (sal_uInt16 i = 0; i < nSize; ++i)
484 {
485 rPoly.SetPoint(ReadPoint(), i);
486 if (!pPict->good())
487 {
488 rPoly.SetSize(i);
489 break;
490 }
491 }
492 return nDataSize;
493}
494
495sal_uInt64 PictReader::ReadPixPattern(PictReader::Pattern &pattern)
496{
497 // Don't know if this is correct because no picture which contains PixPatterns found.
498 // Here again the attempt to calculate the size of the date to create simple StarView-Styles
499 // from them. Luckily a PixPattern always contains a normal pattern.
500
501
502 sal_uInt64 nDataSize;
503 sal_uInt16 nPatType;
504 BitmapEx aBMP;
505
506 pPict->ReadUInt16( nPatType );
507 if (nPatType==1) {
508 pattern.read(*pPict);
509 nDataSize=ReadPixMapEtc(aBMP,false,true,nullptr,nullptr,false,false);
510 // CHANGEME: use average pixmap colors to update the pattern, ...
511 if (nDataSize!=0xffffffff) nDataSize+=10;
512 }
513 else if (nPatType==2) {
514 pattern.read(*pPict);
515 // RGBColor
516 sal_uInt16 nR, nG, nB;
517 pPict->ReadUInt16( nR ).ReadUInt16( nG ).ReadUInt16( nB );
518 Color col(static_cast<sal_uInt8>( nR >> 8 ), static_cast<sal_uInt8>( nG >> 8 ), static_cast<sal_uInt8>( nB >> 8 ) );
519 pattern.setColor(col);
520 nDataSize=16;
521 }
522 else nDataSize=0xffffffff;
523
524 return nDataSize;
525}
526
527sal_uInt8 PictReader::ReadAndDrawRect(PictDrawingMethod eMethod)
528{
529 ReadRectangle(aLastRect);
530 ReadAndDrawSameRect(eMethod);
531 return 8;
532}
533
534sal_uInt8 PictReader::ReadAndDrawSameRect(PictDrawingMethod eMethod)
535{
536 if (IsInvisible(eMethod)) return 0;
537 DrawingMethod(eMethod);
538 PictReaderShape::drawRectangle( pVirDev, eMethod == PictDrawingMethod::FRAME, aLastRect, nActPenSize );
539 return 0;
540}
541
542sal_uInt8 PictReader::ReadAndDrawRoundRect(PictDrawingMethod eMethod)
543{
544 ReadRectangle(aLastRoundRect);
545 ReadAndDrawSameRoundRect(eMethod);
546 return 8;
547}
548
549sal_uInt8 PictReader::ReadAndDrawSameRoundRect(PictDrawingMethod eMethod)
550{
551 if (IsInvisible(eMethod)) return 0;
552 DrawingMethod(eMethod);
553 PictReaderShape::drawRoundRectangle( pVirDev, eMethod == PictDrawingMethod::FRAME, aLastRoundRect, aActOvalSize, nActPenSize );
554 return 0;
555}
556
557sal_uInt8 PictReader::ReadAndDrawOval(PictDrawingMethod eMethod)
558{
559 ReadRectangle(aLastOval);
560 ReadAndDrawSameOval(eMethod);
561 return 8;
562}
563
564sal_uInt8 PictReader::ReadAndDrawSameOval(PictDrawingMethod eMethod)
565{
566 if (IsInvisible(eMethod)) return 0;
567 DrawingMethod(eMethod);
568 PictReaderShape::drawEllipse( pVirDev, eMethod == PictDrawingMethod::FRAME, aLastOval, nActPenSize );
569 return 0;
570}
571
572sal_uInt64 PictReader::ReadAndDrawPolygon(PictDrawingMethod eMethod)
573{
574 sal_uInt64 nDataSize;
575 nDataSize=ReadPolygon(aLastPolygon);
576 ReadAndDrawSamePolygon(eMethod);
577 return nDataSize;
578}
579
580sal_uInt8 PictReader::ReadAndDrawSamePolygon(PictDrawingMethod eMethod)
581{
582 if (IsInvisible(eMethod)) return 0;
583 DrawingMethod(eMethod);
584 PictReaderShape::drawPolygon( pVirDev, eMethod == PictDrawingMethod::FRAME, aLastPolygon, nActPenSize );
585 return 0;
586}
587
588
589sal_uInt8 PictReader::ReadAndDrawArc(PictDrawingMethod eMethod)
590{
591 ReadRectangle(aLastArcRect);
592 ReadAndDrawSameArc(eMethod);
593 return 12;
594}
595
596sal_uInt8 PictReader::ReadAndDrawSameArc(PictDrawingMethod eMethod)
597{
598 short nstartAngle, narcAngle;
599 double fAng1, fAng2;
600
601 pPict->ReadInt16( nstartAngle ).ReadInt16( narcAngle );
602 if (IsInvisible(eMethod)) return 4;
603 DrawingMethod(eMethod);
604
605 if (narcAngle<0) {
606 nstartAngle = nstartAngle + narcAngle;
607 narcAngle=-narcAngle;
608 }
609 const double pi = 2 * acos(0.0);
610 fAng1 = static_cast<double>(nstartAngle) * pi / 180.0;
611 fAng2 = static_cast<double>(nstartAngle + narcAngle) * pi / 180.0;
612 PictReaderShape::drawArc( pVirDev, eMethod == PictDrawingMethod::FRAME, aLastArcRect, fAng1, fAng2, nActPenSize );
613 return 4;
614}
615
616sal_uInt64 PictReader::ReadAndDrawRgn(PictDrawingMethod eMethod)
617{
618 sal_uInt16 nSize;
619
620 pPict->ReadUInt16( nSize );
621 // read the DATA
622 //
623 // a region data is a mask and is probably coded as
624 // - the first 8 bytes: bdbox ( which can be read by ReadRectangle )
625 // - then a list of line modifiers: y_i, a_0, b_0, a_1, b_1, ..., a_{n_i}, b_{n_i}, 0x7fff
626 // - 0x7fff
627 // where y_i is the increasing sequences of line coordinates
628 // and on each line: a0 < b0 < a1 < b1 < ... < a_{n_i} < b_{n_i}
629
630 // it can be probably decoded as :
631 // M=an empty mask: ie. (0, 0, ... ) with (left_box-right_box+1) zeroes
632 // then for each line (y_i):
633 // - takes M and inverts all values in [a_0,b_0-1], in [a_1,b_1-1] ...
634 // - sets M = new y_i line mask
635 ReadAndDrawSameRgn(eMethod);
636 return static_cast<sal_uInt64>(nSize);
637}
638
639sal_uInt8 PictReader::ReadAndDrawSameRgn(PictDrawingMethod eMethod)
640{
641 if (IsInvisible(eMethod)) return 0;
642 DrawingMethod(eMethod);
643 // DISPLAY: ...???...
644 return 0;
645}
646
647void PictReader::DrawingMethod(PictDrawingMethod eMethod)
648{
649 if( eActMethod==eMethod ) return;
650 switch (eMethod) {
651 case PictDrawingMethod::FRAME:
652 if (eActPenPattern.isDefault())
653 SetLineColor( aActForeColor );
654 else
655 SetLineColor(eActPenPattern.getColor(aActBackColor, aActForeColor));
656 SetFillColor( COL_TRANSPARENT );
657 pVirDev->SetRasterOp(eActROP);
658 break;
659 case PictDrawingMethod::PAINT:
660 SetLineColor( COL_TRANSPARENT );
661 if (eActPenPattern.isDefault())
662 SetFillColor( aActForeColor );
663 else
664 SetFillColor(eActPenPattern.getColor(aActBackColor, aActForeColor));
665 pVirDev->SetRasterOp(eActROP);
666 break;
667 case PictDrawingMethod::ERASE:
668 SetLineColor( COL_TRANSPARENT );
669 if (eActBackPattern.isDefault())
670 SetFillColor( aActBackColor );// Osnola: previously aActForeColor
671 else // checkMe
672 SetFillColor(eActBackPattern.getColor(COL_BLACK, aActBackColor));
673 pVirDev->SetRasterOp(RasterOp::OverPaint);
674 break;
675 case PictDrawingMethod::INVERT: // checkme
676 SetLineColor( COL_TRANSPARENT);
677 SetFillColor( COL_BLACK );
678 pVirDev->SetRasterOp(RasterOp::Invert);
679 break;
680 case PictDrawingMethod::FILL:
681 SetLineColor( COL_TRANSPARENT );
682 if (eActFillPattern.isDefault())
683 SetFillColor( aActForeColor );
684 else
685 SetFillColor(eActFillPattern.getColor(aActBackColor, aActForeColor));
686 pVirDev->SetRasterOp(RasterOp::OverPaint);
687 break;
688 case PictDrawingMethod::TEXT:
689 aActFont.SetColor(aActForeColor);
690 aActFont.SetFillColor(aActBackColor);
691 aActFont.SetTransparent(true);
692 pVirDev->SetFont(aActFont);
693 pVirDev->SetRasterOp(RasterOp::OverPaint);
694 break;
695 default:
696 break; // -Wall undefined not handled...
697 }
698 eActMethod=eMethod;
699}
700
701sal_uInt64 PictReader::ReadAndDrawText()
702{
703 char nByteLen;
704 sal_uInt32 nLen, nDataLen;
705 char sText[256];
706
707 pPict->ReadChar( nByteLen ); nLen=static_cast<sal_uInt32>(nByteLen)&0x000000ff;
708 nDataLen = nLen + 1;
709 pPict->ReadBytes(&sText, nLen);
710
711 if (IsInvisible( PictDrawingMethod::TEXT )) return nDataLen;
712 DrawingMethod( PictDrawingMethod::TEXT );
713
714 // remove annoying control characters:
715 while ( nLen > 0 && static_cast<unsigned char>(sText[ nLen - 1 ]) < 32 )
716 nLen--;
717 sText[ nLen ] = 0;
718 OUString aString( sText, strlen(sText), aActFont.GetCharSet());
719 pVirDev->DrawText( Point( aTextPosition.X(), aTextPosition.Y() ), aString );
720 return nDataLen;
721}
722
723sal_uInt64 PictReader::ReadPixMapEtc( BitmapEx &rBitmap, bool bBaseAddr, bool bColorTable, tools::Rectangle* pSrcRect,
724 tools::Rectangle* pDestRect, bool bMode, bool bMaskRgn )
725{
726 std::unique_ptr<vcl::bitmap::RawBitmap> pBitmap;
727 sal_uInt16 nPackType(0), nPixelSize(0), nCmpCount(0), nCmpSize(0);
728 sal_uInt8 nDat(0), nRed(0), nGreen(0), nBlue(0);
729
730 // The calculation of nDataSize is considering the size of the whole data.
731 size_t nDataSize = 0;
732
733 // conditionally skip BaseAddr
734 if ( bBaseAddr )
735 {
736 pPict->SeekRel( 4 );
737 nDataSize += 4;
738 }
739
740 // Read PixMap or Bitmap structure;
741 sal_uInt16 nRowBytes(0), nBndX(0), nBndY(0), nWidth(0), nHeight(0);
742 pPict->ReadUInt16(nRowBytes).ReadUInt16(nBndY).ReadUInt16(nBndX).ReadUInt16(nHeight).ReadUInt16(nWidth);
743 if (nBndY > nHeight)
744 return 0xffffffff;
745 nHeight = nHeight - nBndY;
746 if (nHeight == 0)
747 return 0xffffffff;
748 if (nBndX > nWidth)
749 return 0xffffffff;
750 nWidth = nWidth - nBndX;
751 if (nWidth == 0)
752 return 0xffffffff;
753
754 std::vector<Color> aPalette;
755 const bool bNotMonoChrome = (nRowBytes & 0x8000) != 0;
756 if (bNotMonoChrome)
757 { // it is a PixMap
758 nRowBytes &= 0x3fff;
759 sal_uInt16 nVersion;
760 sal_uInt32 nPackSize;
761 sal_uInt16 nPixelType;
762 sal_uInt32 nPlaneBytes;
763 sal_uInt32 nHRes, nVRes;
764 pPict->ReadUInt16( nVersion ).ReadUInt16( nPackType ).ReadUInt32( nPackSize ).ReadUInt32( nHRes ).ReadUInt32( nVRes ).ReadUInt16( nPixelType ).ReadUInt16( nPixelSize ).ReadUInt16( nCmpCount ).ReadUInt16( nCmpSize ).ReadUInt32( nPlaneBytes );
765
766 pPict->SeekRel( 8 );
767 nDataSize += 46;
768
769 if ( bColorTable )
770 {
771 pPict->SeekRel( 6 );
772 sal_uInt16 nColTabSize(0);
773 pPict->ReadUInt16(nColTabSize);
774
775 if (nColTabSize > 255)
776 return 0xffffffff;
777
778 ++nColTabSize;
779
780 aPalette.resize(nColTabSize);
781
782 for (size_t i = 0; i < nColTabSize; ++i)
783 {
784 pPict->SeekRel(2);
785 sal_uInt8 nDummy;
786 pPict->ReadUChar( nRed ).ReadUChar( nDummy ).ReadUChar( nGreen ).ReadUChar( nDummy ).ReadUChar( nBlue ).ReadUChar( nDummy );
787 aPalette[i] = Color(nRed, nGreen, nBlue);
788 }
789
790 nDataSize += 8 + nColTabSize * 8;
791 }
792 }
793 else
794 {
795 nRowBytes &= 0x3fff;
796 nPixelSize = nCmpCount = nCmpSize = 1;
797 nDataSize += 10;
798 aPalette.resize(2);
799 aPalette[0] = Color(0xff, 0xff, 0xff);
800 aPalette[1] = Color(0, 0, 0);
801 }
802
803 // conditionally read source rectangle:
804 if ( pSrcRect != nullptr)
805 {
806 sal_uInt16 nTop, nLeft, nBottom, nRight;
807 pPict->ReadUInt16( nTop ).ReadUInt16( nLeft ).ReadUInt16( nBottom ).ReadUInt16( nRight );
808 *pSrcRect = tools::Rectangle(nLeft, nTop, nRight, nBottom);
809 nDataSize += 8;
810 }
811
812 // conditionally read destination rectangle:
813 if ( pDestRect != nullptr )
814 {
815 Point aTL, aBR;
816 aTL = ReadPoint();
817 aBR = ReadPoint();
818 *pDestRect = tools::Rectangle( aTL, aBR );
819 nDataSize += 8;
820 }
821
822 // conditionally read mode (or skip it):
823 if ( bMode )
824 {
825 pPict->SeekRel(2);
826 nDataSize += 2;
827 }
828
829 // conditionally read region (or skip it):
830 if ( bMaskRgn )
831 {
832 sal_uInt16 nSize;
833 pPict->ReadUInt16( nSize );
834 pPict->SeekRel( nSize - 2 );
835 nDataSize += nSize;
836 }
837
838 // read and write Bitmap bits:
839 if ( nPixelSize == 1 || nPixelSize == 2 || nPixelSize == 4 || nPixelSize == 8 )
840 {
841 sal_uInt16 nSrcBPL, nDestBPL;
842 size_t nCount;
843
844 if ( nPixelSize == 1 ) nSrcBPL = ( nWidth + 7 ) >> 3;
845 else if ( nPixelSize == 2 ) nSrcBPL = ( nWidth + 3 ) >> 2;
846 else if ( nPixelSize == 4 ) nSrcBPL = ( nWidth + 1 ) >> 1;
847 else nSrcBPL = nWidth;
848 nDestBPL = ( nSrcBPL + 3 ) & 0xfffc;
849 if (!nRowBytes || nRowBytes < nSrcBPL || nRowBytes > nDestBPL)
850 return 0xffffffff;
851
852 if (nRowBytes < 8 || nPackType == 1)
853 {
854 if (nHeight > pPict->remainingSize() / (sizeof(sal_uInt8) * nRowBytes))
855 return 0xffffffff;
856 }
857 else
858 {
859 size_t nByteCountSize = nRowBytes > 250 ? sizeof(sal_uInt16) : sizeof(sal_uInt8);
860 if (nHeight > pPict->remainingSize() / nByteCountSize)
861 return 0xffffffff;
862 }
863
864 pBitmap.reset(new vcl::bitmap::RawBitmap( Size(nWidth, nHeight), 24 ));
865
866 for (sal_uInt16 ny = 0; ny < nHeight; ++ny)
867 {
868 sal_uInt16 nx = 0;
869 if ( nRowBytes < 8 || nPackType == 1 )
870 {
871 for (size_t i = 0; i < nRowBytes; ++i)
872 {
873 pPict->ReadUChar( nDat );
874 if ( nx < nWidth )
875 SetByte(nx, ny, *pBitmap, nPixelSize, nDat, nWidth, aPalette);
876 }
877 nDataSize += nRowBytes;
878 }
879 else
880 {
881 sal_uInt16 nByteCount(0);
882 if ( nRowBytes > 250 )
883 {
884 pPict->ReadUInt16( nByteCount );
885 nDataSize += 2 + static_cast<sal_uInt32>(nByteCount);
886 }
887 else
888 {
889 sal_uInt8 nByteCountAsByte(0);
890 pPict->ReadUChar( nByteCountAsByte );
891 nByteCount = static_cast<sal_uInt16>(nByteCountAsByte) & 0x00ff;
892 nDataSize += 1 + nByteCount;
893 }
894
895 while (pPict->good() && nByteCount)
896 {
897 sal_uInt8 nFlagCounterByte(0);
898 pPict->ReadUChar(nFlagCounterByte);
899 if ( ( nFlagCounterByte & 0x80 ) == 0 )
900 {
901 nCount = static_cast<sal_uInt16>(nFlagCounterByte) + 1;
902 for (size_t i = 0; i < nCount; ++i)
903 {
904 pPict->ReadUChar( nDat );
905 if ( nx < nWidth )
906 SetByte(nx, ny, *pBitmap, nPixelSize, nDat, nWidth, aPalette);
907 }
908 nByteCount -= 1 + nCount;
909 }
910 else
911 {
912 nCount = static_cast<sal_uInt16>( 1 - sal_Int16( static_cast<sal_uInt16>(nFlagCounterByte) | 0xff00 ) );
913 pPict->ReadUChar( nDat );
914 for (size_t i = 0; i < nCount; ++i)
915 {
916 if ( nx < nWidth )
917 SetByte(nx, ny, *pBitmap, nPixelSize, nDat, nWidth, aPalette);
918 }
919 nByteCount -= 2;
920 }
921 }
922 }
923 }
924 }
925 else if ( nPixelSize == 16 )
926 {
927 sal_uInt8 nByteCountAsByte, nFlagCounterByte;
928 sal_uInt16 nByteCount, nCount, nD;
929 sal_uInt64 nSrcBitsPos;
930
931 if (nWidth > nRowBytes / 2)
932 return 0xffffffff;
933
934 if (nRowBytes < 8 || nPackType == 1)
935 {
936 if (nHeight > pPict->remainingSize() / (sizeof(sal_uInt8) * nRowBytes))
937 return 0xffffffff;
938 }
939 else
940 {
941 size_t nByteCountSize = nRowBytes > 250 ? sizeof(sal_uInt16) : sizeof(sal_uInt8);
942 if (nHeight > pPict->remainingSize() / nByteCountSize)
943 return 0xffffffff;
944 }
945
946 pBitmap.reset(new vcl::bitmap::RawBitmap( Size(nWidth, nHeight), 24 ));
947
948 for (sal_uInt16 ny = 0; ny < nHeight; ++ny)
949 {
950 sal_uInt16 nx = 0;
951 if ( nRowBytes < 8 || nPackType == 1 )
952 {
953 for (size_t i = 0; i < nWidth; ++i)
954 {
955 pPict->ReadUInt16( nD );
956 nRed = static_cast<sal_uInt8>( nD >> 7 );
957 nGreen = static_cast<sal_uInt8>( nD >> 2 );
958 nBlue = static_cast<sal_uInt8>( nD << 3 );
959 pBitmap->SetPixel(ny, nx++, Color(nRed, nGreen, nBlue));
960 }
961 nDataSize += static_cast<sal_uInt32>(nWidth) * 2;
962 }
963 else
964 {
965 nSrcBitsPos = pPict->Tell();
966 if ( nRowBytes > 250 )
967 {
968 pPict->ReadUInt16( nByteCount );
969 nByteCount += 2;
970 }
971 else
972 {
973 pPict->ReadUChar( nByteCountAsByte );
974 nByteCount = static_cast<sal_uInt16>(nByteCountAsByte) & 0x00ff;
975 nByteCount++;
976 }
977 while ( nx != nWidth )
978 {
979 pPict->ReadUChar( nFlagCounterByte );
980 if ( (nFlagCounterByte & 0x80) == 0)
981 {
982 nCount=static_cast<sal_uInt16>(nFlagCounterByte)+1;
983 if ( nCount + nx > nWidth)
984 nCount = nWidth - nx;
985 if (pPict->remainingSize() < sizeof(sal_uInt16) * nCount)
986 return 0xffffffff;
987 /* SJ: the RLE decoding seems not to be correct here,
988 I don't want to change this until I have a bugdoc for
989 this case. Have a look at 32bit, there I changed the
990 encoding, so that it is used a straight forward array
991 */
992 for (size_t i = 0; i < nCount; ++i)
993 {
994 pPict->ReadUInt16( nD );
995 nRed = static_cast<sal_uInt8>( nD >> 7 );
996 nGreen = static_cast<sal_uInt8>( nD >> 2 );
997 nBlue = static_cast<sal_uInt8>( nD << 3 );
998 pBitmap->SetPixel(ny, nx++, Color(nRed, nGreen, nBlue));
999 }
1000 }
1001 else
1002 {
1003 if (pPict->remainingSize() < sizeof(sal_uInt16))
1004 return 0xffffffff;
1005 nCount=(1-sal_Int16(static_cast<sal_uInt16>(nFlagCounterByte)|0xff00));
1006 if ( nCount + nx > nWidth )
1007 nCount = nWidth - nx;
1008 pPict->ReadUInt16( nD );
1009 nRed = static_cast<sal_uInt8>( nD >> 7 );
1010 nGreen = static_cast<sal_uInt8>( nD >> 2 );
1011 nBlue = static_cast<sal_uInt8>( nD << 3 );
1012 for (size_t i = 0; i < nCount; ++i)
1013 {
1014 pBitmap->SetPixel(ny, nx++, Color(nRed, nGreen, nBlue));
1015 }
1016 }
1017 }
1018 nDataSize += nByteCount;
1019 pPict->Seek(nSrcBitsPos+nByteCount);
1020 }
1021 }
1022 }
1023 else if ( nPixelSize == 32 )
1024 {
1025 sal_uInt16 nByteCount;
1026 size_t nCount;
1027 sal_uInt64 nSrcBitsPos;
1028 if ( nRowBytes != 4*nWidth )
1029 return 0xffffffff;
1030
1031 if ( nRowBytes < 8 || nPackType == 1 )
1032 {
1033 const size_t nMaxPixels = pPict->remainingSize() / 4;
1034 const size_t nMaxRows = nMaxPixels / nWidth;
1035 if (nHeight > nMaxRows)
1036 return 0xffffffff;
1037 const size_t nMaxCols = nMaxPixels / nHeight;
1038 if (nWidth > nMaxCols)
1039 return 0xffffffff;
1040
1041 pBitmap.reset(new vcl::bitmap::RawBitmap( Size(nWidth, nHeight), 24 ));
1042
1043 for (sal_uInt16 ny = 0; ny < nHeight; ++ny)
1044 {
1045 for (sal_uInt16 nx = 0; nx < nWidth; ++nx)
1046 {
1047 sal_uInt8 nDummy;
1048 pPict->ReadUChar( nDummy ).ReadUChar( nRed ).ReadUChar( nGreen ).ReadUChar( nBlue );
1049 pBitmap->SetPixel(ny, nx, Color(nRed, nGreen, nBlue));
1050 }
1051 nDataSize += static_cast<sal_uInt32>(nWidth) * 4;
1052 }
1053 }
1054 else if ( nPackType == 2 )
1055 {
1056 const size_t nMaxPixels = pPict->remainingSize() / 3;
1057 const size_t nMaxRows = nMaxPixels / nWidth;
1058 if (nHeight > nMaxRows)
1059 return 0xffffffff;
1060 const size_t nMaxCols = nMaxPixels / nHeight;
1061 if (nWidth > nMaxCols)
1062 return 0xffffffff;
1063
1064 pBitmap.reset(new vcl::bitmap::RawBitmap( Size(nWidth, nHeight), 24 ));
1065
1066 for (sal_uInt16 ny = 0; ny < nHeight; ++ny)
1067 {
1068 for (sal_uInt16 nx = 0; nx < nWidth; ++nx)
1069 {
1070 pPict->ReadUChar( nRed ).ReadUChar( nGreen ).ReadUChar( nBlue );
1071 pBitmap->SetPixel(ny, nx, Color(nRed, nGreen, nBlue));
1072 }
1073 nDataSize += static_cast<sal_uInt32>(nWidth) * 3;
1074 }
1075 }
1076 else
1077 {
1078 sal_uInt8 nByteCountAsByte;
1079 sal_uInt8 nFlagCounterByte;
1080 if ( ( nCmpCount == 3 ) || ( nCmpCount == 4 ) )
1081 {
1082 size_t nByteCountSize = nRowBytes > 250 ? sizeof(sal_uInt16) : sizeof(sal_uInt8);
1083 if (nHeight > pPict->remainingSize() / nByteCountSize)
1084 return 0xffffffff;
1085
1086 pBitmap.reset(new vcl::bitmap::RawBitmap( Size(nWidth, nHeight), 24 ));
1087
1088 // cid#1458434 to sanitize Untrusted loop bound
1089 nWidth = pBitmap->Width();
1090
1091 size_t nByteWidth = static_cast<size_t>(nWidth) * nCmpCount;
1092 std::vector<sal_uInt8> aScanline(nByteWidth);
1093 for (sal_uInt16 ny = 0; ny < nHeight; ++ny)
1094 {
1095 nSrcBitsPos = pPict->Tell();
1096 if ( nRowBytes > 250 )
1097 {
1098 pPict->ReadUInt16( nByteCount );
1099 nByteCount += 2;
1100 }
1101 else
1102 {
1103 pPict->ReadUChar( nByteCountAsByte );
1104 nByteCount = nByteCountAsByte;
1105 nByteCount++;
1106 }
1107 size_t i = 0;
1108 while (i < aScanline.size())
1109 {
1110 pPict->ReadUChar( nFlagCounterByte );
1111 if ( ( nFlagCounterByte & 0x80 ) == 0)
1112 {
1113 nCount = static_cast<sal_uInt16>(nFlagCounterByte) + 1;
1114 if ((i + nCount) > aScanline.size())
1115 nCount = aScanline.size() - i;
1116 if (pPict->remainingSize() < nCount)
1117 return 0xffffffff;
1118 while( nCount-- )
1119 {
1120 pPict->ReadUChar( nDat );
1121 aScanline[ i++ ] = nDat;
1122 }
1123 }
1124 else
1125 {
1126 if (pPict->remainingSize() < 1)
1127 return 0xffffffff;
1128 nCount = ( 1 - sal_Int16( static_cast<sal_uInt16>(nFlagCounterByte) | 0xff00 ) );
1129 if (( i + nCount) > aScanline.size())
1130 nCount = aScanline.size() - i;
1131 pPict->ReadUChar( nDat );
1132 while( nCount-- )
1133 aScanline[ i++ ] = nDat;
1134 }
1135 }
1136 sal_uInt8* pTmp = aScanline.data();
1137 if ( nCmpCount == 4 )
1138 pTmp += nWidth;
1139 for (sal_uInt16 nx = 0; nx < nWidth; pTmp++)
1140 pBitmap->SetPixel(ny, nx++, Color(*pTmp, pTmp[ nWidth ], pTmp[ 2 * nWidth ]));
1141 nDataSize += nByteCount;
1142 pPict->Seek( nSrcBitsPos + nByteCount );
1143 }
1144 }
1145 }
1146 }
1147 else
1148 return 0xffffffff;
1149 rBitmap = vcl::bitmap::CreateFromData(std::move(*pBitmap));
1150 return nDataSize;
1151}
1152
1153void PictReader::ReadHeader()
1154{
1155 short y1,x1,y2,x2;
1156
1157 char sBuf[ 2 ];
1158 // previous code considers pPict->Tell() as the normal starting position,
1159 // can we have nStartPos != 0 ?
1160 sal_uInt64 nStartPos = pPict->Tell();
1161 // Standard:
1162 // a picture file begins by 512 bytes (reserved to the application) followed by the picture data
1163 // while clipboard, pictures stored in a document often contain only the picture data.
1164
1165 // Special cases:
1166 // - some Pict v.1 use 0x00 0x11 0x01 ( instead of 0x11 0x01) to store the version op
1167 // (we consider here this as another standard for Pict. v.1 )
1168 // - some files seem to contain extra garbage data at the beginning
1169 // - some picture data seem to contain extra NOP opcode(0x00) between the bounding box and the version opcode
1170
1171 // This code looks hard to find a picture header, ie. it looks at positions
1172 // - nStartPos+0, nStartPos+512 with potential extra NOP codes between bdbox and version (at most 9 extra NOP)
1173 // - 512..1024 with more strict bdbox checking and no extra NOP codes
1174
1175 // Notes:
1176 // - if the header can begin at nStartPos+0 and at nStartPos+512, we try to choose the more
1177 // <<probable>> ( using the variable confidence)
1178 // - svtools/source/filter.vcl/filter/{filter.cxx,filter2.cxx} only check for standard Pict,
1179 // this may cause future problems
1180 int st;
1181 sal_uInt32 nOffset;
1182 int confidence[2] = { 0, 0};
1183 for ( st = 0; st < 3 + 513; st++ )
1184 {
1185 int actualConfid = 20; // the actual confidence
1186 pPict->ResetError();
1187 if (st < 2) nOffset = nStartPos+st*512;
1188 else if (st == 2) {
1189 // choose nStartPos+0 or nStartPos+512 even if there are a little dubious
1190 int actPos = -1, actConf=0;
1191 if (confidence[0] > 0) { actPos = 0; actConf = confidence[0]; }
1192 if (confidence[1] > 0 && confidence[1] >= actConf) actPos = 1;
1193 if (actPos < 0) continue;
1194 nOffset = nStartPos+actPos*512;
1195 }
1196 else {
1197 nOffset = 509+st; // illogical : more logical will be nStartPos+509+st or to consider that nStartPos=0
1198 // a small test to check if versionOp code exists after the bdbox ( with no extra NOP codes)
1199 pPict->Seek(nOffset+10);
1200 pPict->ReadBytes(sBuf, 2);
1201 if (!pPict->good()) break;
1202 if (sBuf[0] == 0x11 || (sBuf[0] == 0x00 && sBuf[1] == 0x11)) ; // maybe ok
1203 else continue;
1204 }
1205 pPict->Seek(nOffset);
1206
1207 // 2 bytes to store size ( version 1 ) ignored
1208 pPict->SeekRel( 2 );
1209 pPict->ReadInt16( y1 ).ReadInt16( x1 ).ReadInt16( y2 ).ReadInt16( x2 ); // frame rectangle of the picture
1210 if (x1 > x2 || y1 > y2) continue; // bad bdbox
1211 if (x1 < -2048 || x2 > 2048 || y1 < -2048 || y2 > 2048 || // origin|dest is very small|large
1212 (x1 == x2 && y1 == y2) ) // 1 pixel pict is dubious
1213 actualConfid-=3;
1214 else if (x2 < x1+8 || y2 < y1+8) // a little dubious
1215 actualConfid-=1;
1216 if (st >= 3 && actualConfid != 20) continue;
1217 aBoundingRect=tools::Rectangle( x1,y1, x2, y2 );
1218
1219 if (!pPict->good()) continue;
1220 // read version
1221 pPict->ReadBytes(sBuf, 2);
1222 // version 1 file
1223 if ( sBuf[ 0 ] == 0x11 && sBuf[ 1 ] == 0x01 ) {
1224 // pict v1 must be rare and we do only few tests
1225 if (st < 2) { confidence[st] = --actualConfid; continue; }
1226 IsVersion2 = false; return;
1227 }
1228 if (sBuf[0] != 0x00) continue; // unrecoverable error
1229 int numZero = 0;
1230 do
1231 {
1232 numZero++;
1233 pPict->SeekRel(-1);
1234 pPict->ReadBytes(sBuf, 2);
1235 }
1236 while ( sBuf[0] == 0x00 && numZero < 10);
1237 actualConfid -= (numZero-1); // extra nop are dubious
1238 if (!pPict->good()) continue;
1239 if (sBuf[0] != 0x11) continue; // not a version opcode
1240 // abnormal version 1 file
1241 if (sBuf[1] == 0x01 ) {
1242 // pict v1 must be rare and we do only few tests
1243 if (st < 2) { confidence[st] = --actualConfid; continue; }
1244 IsVersion2 = false; return;
1245 }
1246 if (sBuf[1] != 0x02 ) continue; // not a version 2 file
1247
1248 IsVersion2=true;
1249 short nExtVer, nReserved;
1250 // 3 Bytes ignored : end of version arg 0x02FF (ie: 0xFF), HeaderOp : 0x0C00
1251 pPict->SeekRel( 3 );
1252 pPict->ReadInt16( nExtVer ).ReadInt16( nReserved );
1253 if (!pPict->good()) continue;
1254
1255 if ( nExtVer == -2 ) // extended version 2 picture
1256 {
1257 sal_Int32 nHResFixed, nVResFixed;
1258 pPict->ReadInt32( nHResFixed ).ReadInt32( nVResFixed );
1259 pPict->ReadInt16( y1 ).ReadInt16( x1 ).ReadInt16( y2 ).ReadInt16( x2 ); // reading the optimal bounding rect
1260 if (x1 > x2 || y1 > y2) continue; // bad bdbox
1261 if (st < 2 && actualConfid != 20) { confidence[st] = actualConfid; continue; }
1262
1263 double fHRes = nHResFixed;
1264 fHRes /= 65536;
1265 double fVRes = nVResFixed;
1266 fVRes /= 65536;
1267 aHRes /= fHRes;
1268 aVRes /= fVRes;
1269 aBoundingRect=tools::Rectangle( x1,y1, x2, y2 );
1270 pPict->SeekRel( 4 ); // 4 bytes reserved
1271 return;
1272 }
1273 else if (nExtVer == -1 ) { // basic version 2 picture
1274 if (st < 2 && actualConfid != 20) { confidence[st] = actualConfid; continue; }
1275 pPict->SeekRel( 16); // bdbox(4 fixed number)
1276 pPict->SeekRel(4); // 4 bytes reserved
1277 return;
1278 }
1279 }
1280 pPict->SetError(SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ));
1281}
1282
1283#if OSL_DEBUG_LEVEL1 > 0
1284static const char* operationName(sal_uInt16 nOpcode)
1285{
1286 // add here whatever makes the debugging easier for you, otherwise you'll
1287 // see only the operation's opcode
1288 switch (nOpcode)
1289 {
1290 case 0x0001: return "Clip";
1291 case 0x0003: return "TxFont";
1292 case 0x0004: return "TxFace";
1293 case 0x0008: return "PnMode";
1294 case 0x0009: return "PnPat";
1295 case 0x000d: return "TxSize";
1296 case 0x001a: return "RGBFgCol";
1297 case 0x001d: return "HiliteColor";
1298 case 0x0020: return "Line";
1299 case 0x0022: return "ShortLine";
1300 case 0x0028: return "LongText";
1301 case 0x0029: return "DHText";
1302 case 0x002a: return "DVText";
1303 case 0x002c: return "fontName";
1304 case 0x002e: return "glyphState";
1305 case 0x0031: return "paintRect";
1306 case 0x0038: return "frameSameRect";
1307 case 0x0070: return "framePoly";
1308 case 0x0071: return "paintPoly";
1309 case 0x00a1: return "LongComment";
1310 default: return "?";
1311 }
1312}
1313#endif
1314
1315sal_uInt64 PictReader::ReadData(sal_uInt16 nOpcode)
1316{
1317 sal_uInt16 nUSHORT;
1318 Point aPoint;
1319 sal_uInt64 nDataSize=0;
1320 PictDrawingMethod shapeDMethod = PictDrawingMethod::UNDEFINED;
1321 switch (nOpcode & 7) {
1322 case 0: shapeDMethod = PictDrawingMethod::FRAME; break;
1323 case 1: shapeDMethod = PictDrawingMethod::PAINT; break;
1324 case 2: shapeDMethod = PictDrawingMethod::ERASE; break;
1325 case 3: shapeDMethod = PictDrawingMethod::INVERT; break;
1326 case 4: shapeDMethod = PictDrawingMethod::FILL; break;
1327 default: break;
1328 }
1329
1330#if OSL_DEBUG_LEVEL1 > 0
1331 SAL_INFO("filter.pict", "Operation: 0x" << OUString::number(nOpcode, 16) << " [" << operationName(nOpcode) << "]")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "filter.pict")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break;
case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Operation: 0x" <<
OUString::number(nOpcode, 16) << " [" << operationName
(nOpcode) << "]") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("filter.pict"), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "1331" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Operation: 0x" << OUString::number
(nOpcode, 16) << " [" << operationName(nOpcode) <<
"]"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Operation: 0x" << OUString::number(nOpcode, 16
) << " [" << operationName(nOpcode) << "]";
::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("filter.pict"
), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "1331" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Operation: 0x" << OUString::number(nOpcode
, 16) << " [" << operationName(nOpcode) << "]"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("filter.pict"
), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "1331" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Operation: 0x" << OUString::number
(nOpcode, 16) << " [" << operationName(nOpcode) <<
"]"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Operation: 0x" << OUString::number(nOpcode, 16
) << " [" << operationName(nOpcode) << "]";
::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("filter.pict"
), ("/home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx"
":" "1331" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1332#endif
1333
1334 switch(nOpcode) {
1335
1336 case 0x0000: // NOP
1337 nDataSize=0;
1338 break;
1339
1340 case 0x0001: { // Clip
1341 tools::Rectangle aRect;
1342 pPict->ReadUInt16( nUSHORT );
1343 nDataSize=nUSHORT;
1344 ReadRectangle(aRect);
1345 // checkme: do we really want to extend the rectangle here ?
1346 // I do that because the clipping is often used to clean a region,
1347 // before drawing some text and also to draw this text.
1348 // So using a too small region can lead to clip the end of the text ;
1349 // but this can be discussable...
1350 aRect.setWidth(aRect.getWidth()+1);
1351 aRect.setHeight(aRect.getHeight()+1);
1352 pVirDev->SetClipRegion( vcl::Region( aRect ) );
1353 break;
1354 }
1355 case 0x0002: // BkPat
1356 nDataSize = eActBackPattern.read(*pPict);
1357 eActMethod = PictDrawingMethod::UNDEFINED;
1358 break;
1359
1360 case 0x0003: // TxFont
1361 pPict->ReadUInt16( nUSHORT );
1362 if (nUSHORT <= 1) aActFont.SetFamily(FAMILY_SWISS);
1363 else if (nUSHORT <= 12) aActFont.SetFamily(FAMILY_DECORATIVE);
1364 else if (nUSHORT <= 20) aActFont.SetFamily(FAMILY_ROMAN);
1365 else if (nUSHORT == 21) aActFont.SetFamily(FAMILY_SWISS);
1366 else if (nUSHORT == 22) aActFont.SetFamily(FAMILY_MODERN);
1367 else if (nUSHORT <= 1023) aActFont.SetFamily(FAMILY_SWISS);
1368 else aActFont.SetFamily(FAMILY_ROMAN);
1369 aActFont.SetCharSet(GetTextEncoding(nUSHORT));
1370 eActMethod = PictDrawingMethod::UNDEFINED;
1371 nDataSize=2;
1372 break;
1373
1374 case 0x0004: { // TxFace
1375 char nFace;
1376 pPict->ReadChar( nFace );
1377 if ( (nFace & 0x01)!=0 ) aActFont.SetWeight(WEIGHT_BOLD);
1378 else aActFont.SetWeight(WEIGHT_NORMAL);
1379 if ( (nFace & 0x02)!=0 ) aActFont.SetItalic(ITALIC_NORMAL);
1380 else aActFont.SetItalic(ITALIC_NONE);
1381 if ( (nFace & 0x04)!=0 ) aActFont.SetUnderline(LINESTYLE_SINGLE);
1382 else aActFont.SetUnderline(LINESTYLE_NONE);
1383 if ( (nFace & 0x08)!=0 ) aActFont.SetOutline(true);
1384 else aActFont.SetOutline(false);
1385 if ( (nFace & 0x10)!=0 ) aActFont.SetShadow(true);
1386 else aActFont.SetShadow(false);
1387 eActMethod = PictDrawingMethod::UNDEFINED;
1388 nDataSize=1;
1389 break;
1390 }
1391 case 0x0005: // TxMode
1392 nDataSize=2;
1393 break;
1394
1395 case 0x0006: // SpExtra
1396 nDataSize=4;
1397 break;
1398
1399 case 0x0007: { // PnSize
1400 nActPenSize=ReadSize();
1401 eActMethod = PictDrawingMethod::UNDEFINED;
1402 nDataSize=4;
1403 break;
1404 }
1405 case 0x0008: // PnMode
1406 pPict->ReadUInt16( nUSHORT );
1407 // internal code for postscript command (Quickdraw Reference Drawing B-30,B-34)
1408 if (nUSHORT==23) eActROP = RasterOp::N1;
1409 else {
1410 switch (nUSHORT & 0x0007) {
1411 case 0: eActROP=RasterOp::OverPaint; break; // Copy
1412 case 1: eActROP=RasterOp::OverPaint; break; // Or
1413 case 2: eActROP=RasterOp::Xor; break; // Xor
1414 case 3: eActROP=RasterOp::OverPaint; break; // Bic
1415 case 4: eActROP=RasterOp::Invert; break; // notCopy
1416 case 5: eActROP=RasterOp::OverPaint; break; // notOr
1417 case 6: eActROP=RasterOp::Xor; break; // notXor
1418 case 7: eActROP=RasterOp::OverPaint; break; // notBic
1419 }
1420 }
1421 eActMethod = PictDrawingMethod::UNDEFINED;
1422 nDataSize=2;
1423 break;
1424
1425 case 0x0009: // PnPat
1426 nDataSize=eActPenPattern.read(*pPict);
1427 eActMethod = PictDrawingMethod::UNDEFINED;
1428 break;
1429
1430 case 0x000a: // FillPat
1431 nDataSize=eActFillPattern.read(*pPict);
1432 eActMethod = PictDrawingMethod::UNDEFINED;
1433 break;
1434
1435 case 0x000b: // OvSize
1436 aActOvalSize=ReadSize();
1437 nDataSize=4;
1438 break;
1439
1440 case 0x000c: // Origin
1441 nDataSize=4;
1442 break;
1443
1444 case 0x000d: // TxSize
1445 {
1446 pPict->ReadUInt16( nUSHORT );
1447 aActFont.SetFontSize( Size( 0, static_cast<long>(nUSHORT) ) );
1448 eActMethod = PictDrawingMethod::UNDEFINED;
1449 nDataSize=2;
1450 }
1451 break;
1452
1453 case 0x000e: // FgColor
1454 aActForeColor=ReadColor();
1455 eActMethod = PictDrawingMethod::UNDEFINED;
1456 nDataSize=4;
1457 break;
1458
1459 case 0x000f: // BkColor
1460 aActBackColor=ReadColor();
1461 nDataSize=4;
1462 break;
1463
1464 case 0x0010: // TxRatio
1465 nDataSize=8;
1466 break;
1467
1468 case 0x0011: // VersionOp
1469 nDataSize=1;
1470 break;
1471
1472 case 0x0012: // BkPixPat
1473 nDataSize=ReadPixPattern(eActBackPattern);
1474 eActMethod = PictDrawingMethod::UNDEFINED;
1475 break;
1476
1477 case 0x0013: // PnPixPat
1478 nDataSize=ReadPixPattern(eActPenPattern);
1479 eActMethod = PictDrawingMethod::UNDEFINED;
1480 break;
1481
1482 case 0x0014: // FillPixPat
1483 nDataSize=ReadPixPattern(eActFillPattern);
1484 eActMethod = PictDrawingMethod::UNDEFINED;
1485 break;
1486
1487 case 0x0015: // PnLocHFrac
1488 nDataSize=2;
1489 break;
1490
1491 case 0x0016: // ChExtra
1492 nDataSize=2;
1493 break;
1494
1495 case 0x0017: // Reserved (0 Bytes)
1496 case 0x0018: // Reserved (0 Bytes)
1497 case 0x0019: // Reserved (0 Bytes)
1498 nDataSize=0;
1499 break;
1500
1501 case 0x001a: // RGBFgCol
1502 aActForeColor=ReadRGBColor();
1503 eActMethod = PictDrawingMethod::UNDEFINED;
1504 nDataSize=6;
1505 break;
1506
1507 case 0x001b: // RGBBkCol
1508 aActBackColor=ReadRGBColor();
1509 eActMethod = PictDrawingMethod::UNDEFINED;
1510 nDataSize=6;
1511 break;
1512
1513 case 0x001c: // HiliteMode
1514 nDataSize=0;
1515 break;
1516
1517 case 0x001d: // HiliteColor
1518 nDataSize=6;
1519 break;
1520
1521 case 0x001e: // DefHilite
1522 nDataSize=0;
1523 break;
1524
1525 case 0x001f: // OpColor
1526 nDataSize=6;
1527 break;
1528
1529 case 0x0020: // Line
1530 aPoint=ReadPoint(); aPenPosition=ReadPoint();
1531 nDataSize=8;
1532
1533 if (IsInvisible( PictDrawingMethod::FRAME )) break;
1534 DrawingMethod( PictDrawingMethod::FRAME );
1535 PictReaderShape::drawLine(pVirDev, aPoint,aPenPosition, nActPenSize);
1536 break;
1537
1538 case 0x0021: // LineFrom
1539 aPoint=aPenPosition; aPenPosition=ReadPoint();
1540 nDataSize=4;
1541
1542 if (IsInvisible( PictDrawingMethod::FRAME )) break;
1543 DrawingMethod( PictDrawingMethod::FRAME );
1544 PictReaderShape::drawLine(pVirDev, aPoint,aPenPosition, nActPenSize);
1545 break;
1546
1547 case 0x0022: // ShortLine
1548 aPoint=ReadPoint();
1549 aPenPosition=ReadDeltaH(aPoint);
1550 aPenPosition=ReadDeltaV(aPenPosition);
1551 nDataSize=6;
1552
1553 if ( IsInvisible(PictDrawingMethod::FRAME) ) break;
1554 DrawingMethod( PictDrawingMethod::FRAME );
1555 PictReaderShape::drawLine(pVirDev, aPoint,aPenPosition, nActPenSize);
1556 break;
1557
1558 case 0x0023: // ShortLineFrom
1559 aPoint=aPenPosition;
1560 aPenPosition=ReadDeltaH(aPoint);
1561 aPenPosition=ReadDeltaV(aPenPosition);
1562 nDataSize=2;
1563
1564 if (IsInvisible( PictDrawingMethod::FRAME )) break;
1565 DrawingMethod( PictDrawingMethod::FRAME );
1566 PictReaderShape::drawLine(pVirDev, aPoint,aPenPosition, nActPenSize);
1567 break;
1568
1569 case 0x0024: // Reserved (n Bytes)
1570 case 0x0025: // Reserved (n Bytes)
1571 case 0x0026: // Reserved (n Bytes)
1572 case 0x0027: // Reserved (n Bytes)
1573 pPict->ReadUInt16( nUSHORT );
1574 nDataSize=2+nUSHORT;
1575 break;
1576
1577 case 0x0028: // LongText
1578 aTextPosition=ReadPoint();
1579 nDataSize=4+ReadAndDrawText();
1580 break;
1581
1582 case 0x0029: // DHText
1583 aTextPosition=ReadUnsignedDeltaH(aTextPosition);
1584 nDataSize=1+ReadAndDrawText();
1585 break;
1586
1587 case 0x002a: // DVText
1588 aTextPosition=ReadUnsignedDeltaV(aTextPosition);
1589 nDataSize=1+ReadAndDrawText();
1590 break;
1591
1592 case 0x002b: // DHDVText
1593 aTextPosition=ReadUnsignedDeltaH(aTextPosition);
1594 aTextPosition=ReadUnsignedDeltaV(aTextPosition);
1595 nDataSize=2+ReadAndDrawText();
1596 break;
1597
1598 case 0x002c: { // fontName
1599 char sFName[ 256 ], nByteLen;
1600 sal_uInt16 nLen;
1601 pPict->ReadUInt16( nUSHORT ); nDataSize=nUSHORT+2;
1602 pPict->ReadUInt16( nUSHORT );
1603 if (nUSHORT <= 1) aActFont.SetFamily(FAMILY_SWISS);
1604 else if (nUSHORT <= 12) aActFont.SetFamily(FAMILY_DECORATIVE);
1605 else if (nUSHORT <= 20) aActFont.SetFamily(FAMILY_ROMAN);
1606 else if (nUSHORT == 21) aActFont.SetFamily(FAMILY_SWISS);
1607 else if (nUSHORT == 22) aActFont.SetFamily(FAMILY_MODERN);
1608 else if (nUSHORT <= 1023) aActFont.SetFamily(FAMILY_SWISS);
1609 else aActFont.SetFamily(FAMILY_ROMAN);
1610 aActFont.SetCharSet(GetTextEncoding(nUSHORT));
1611 pPict->ReadChar( nByteLen ); nLen=static_cast<sal_uInt16>(nByteLen)&0x00ff;
1612 pPict->ReadBytes(&sFName, nLen);
1613 sFName[ nLen ] = 0;
1614 OUString aString( sFName, strlen(sFName), osl_getThreadTextEncoding() );
1615 aActFont.SetFamilyName( aString );
1616 eActMethod = PictDrawingMethod::UNDEFINED;
1617 break;
1618 }
1619 case 0x002d: // lineJustify
1620 nDataSize=10;
1621 break;
1622
1623 case 0x002e: // glyphState
1624 pPict->ReadUInt16( nUSHORT );
1625 nDataSize=2+nUSHORT;
1626 break;
1627
1628 case 0x002f: // Reserved (n Bytes)
1629 pPict->ReadUInt16( nUSHORT );
1630 nDataSize=2+nUSHORT;
1631 break;
1632
1633 case 0x0030: // frameRect
1634 case 0x0031: // paintRect
1635 case 0x0032: // eraseRect
1636 case 0x0033: // invertRect
1637 case 0x0034: // fillRect
1638 nDataSize=ReadAndDrawRect(shapeDMethod);
1639 break;
1640
1641 case 0x0035: // Reserved (8 Bytes)
1642 case 0x0036: // Reserved (8 Bytes)
1643 case 0x0037: // Reserved (8 Bytes)
1644 nDataSize=8;
1645 break;
1646
1647 case 0x0038: // frameSameRect
1648 case 0x0039: // paintSameRect
1649 case 0x003a: // eraseSameRect
1650 case 0x003b: // invertSameRect
1651 case 0x003c: // fillSameRect
1652 nDataSize=ReadAndDrawSameRect(shapeDMethod);
1653 break;
1654
1655 case 0x003d: // Reserved (0 Bytes)
1656 case 0x003e: // Reserved (0 Bytes)
1657 case 0x003f: // Reserved (0 Bytes)
1658 nDataSize=0;
1659 break;
1660
1661 case 0x0040: // frameRRect
1662 case 0x0041: // paintRRect
1663 case 0x0042: // eraseRRect
1664 case 0x0043: // invertRRect
1665 case 0x0044: // fillRRect
1666 nDataSize=ReadAndDrawRoundRect(shapeDMethod);
1667 break;
1668
1669 case 0x0045: // Reserved (8 Bytes)
1670 case 0x0046: // Reserved (8 Bytes)
1671 case 0x0047: // Reserved (8 Bytes)
1672 nDataSize=8;
1673 break;
1674
1675 case 0x0048: // frameSameRRect
1676 case 0x0049: // paintSameRRect
1677 case 0x004a: // eraseSameRRect
1678 case 0x004b: // invertSameRRect
1679 case 0x004c: // fillSameRRect
1680 nDataSize=ReadAndDrawSameRoundRect(shapeDMethod);
1681 break;
1682
1683 case 0x004d: // Reserved (0 Bytes)
1684 case 0x004e: // Reserved (0 Bytes)
1685 case 0x004f: // Reserved (0 Bytes)
1686 nDataSize=0;
1687 break;
1688
1689 case 0x0050: // frameOval
1690 case 0x0051: // paintOval
1691 case 0x0052: // eraseOval
1692 case 0x0053: // invertOval
1693 case 0x0054: // fillOval
1694 nDataSize=ReadAndDrawOval(shapeDMethod);
1695 break;
1696
1697 case 0x0055: // Reserved (8 Bytes)
1698 case 0x0056: // Reserved (8 Bytes)
1699 case 0x0057: // Reserved (8 Bytes)
1700 nDataSize=8;
1701 break;
1702
1703 case 0x0058: // frameSameOval
1704 case 0x0059: // paintSameOval
1705 case 0x005a: // eraseSameOval
1706 case 0x005b: // invertSameOval
1707 case 0x005c: // fillSameOval
1708 nDataSize=ReadAndDrawSameOval(shapeDMethod);
1709 break;
1710
1711 case 0x005d: // Reserved (0 Bytes)
1712 case 0x005e: // Reserved (0 Bytes)
1713 case 0x005f: // Reserved (0 Bytes)
1714 nDataSize=0;
1715 break;
1716
1717 case 0x0060: // frameArc
1718 case 0x0061: // paintArc
1719 case 0x0062: // eraseArc
1720 case 0x0063: // invertArc
1721 case 0x0064: // fillArc
1722 nDataSize=ReadAndDrawArc(shapeDMethod);
1723 break;
1724
1725 case 0x0065: // Reserved (12 Bytes)
1726 case 0x0066: // Reserved (12 Bytes)
1727 case 0x0067: // Reserved (12 Bytes)
1728 nDataSize=12;
1729 break;
1730
1731 case 0x0068: // frameSameArc
1732 case 0x0069: // paintSameArc
1733 case 0x006a: // eraseSameArc
1734 case 0x006b: // invertSameArc
1735 case 0x006c: // fillSameArc
1736 nDataSize=ReadAndDrawSameArc(shapeDMethod);
1737 break;
1738
1739 case 0x006d: // Reserved (4 Bytes)
1740 case 0x006e: // Reserved (4 Bytes)
1741 case 0x006f: // Reserved (4 Bytes)
1742 nDataSize=4;
1743 break;
1744
1745 case 0x0070: // framePoly
1746 case 0x0071: // paintPoly
1747 case 0x0072: // erasePoly
1748 case 0x0073: // invertPoly
1749 case 0x0074: // fillPoly
1750 nDataSize=ReadAndDrawPolygon(shapeDMethod);
1751 break;
1752
1753 case 0x0075: // Reserved (Polygon-Size)
1754 case 0x0076: // Reserved (Polygon-Size)
1755 case 0x0077: // Reserved (Polygon-Size)
1756 pPict->ReadUInt16( nUSHORT ); nDataSize=nUSHORT;
1757 break;
1758
1759 case 0x0078: // frameSamePoly
1760 case 0x0079: // paintSamePoly
1761 case 0x007a: // eraseSamePoly
1762 case 0x007b: // invertSamePoly
1763 case 0x007c: // fillSamePoly
1764 nDataSize=ReadAndDrawSamePolygon(shapeDMethod);
1765 break;
1766
1767 case 0x007d: // Reserved (0 Bytes)
1768 case 0x007e: // Reserved (0 Bytes)
1769 case 0x007f: // Reserved (0 Bytes)
1770 nDataSize=0;
1771 break;
1772
1773 case 0x0080: // frameRgn
1774 case 0x0081: // paintRgn
1775 case 0x0082: // eraseRgn
1776 case 0x0083: // invertRgn
1777 case 0x0084: // fillRgn
1778 nDataSize=ReadAndDrawRgn(shapeDMethod);
1779 break;
1780
1781 case 0x0085: // Reserved (Region-Size)
1782 case 0x0086: // Reserved (Region-Size)
1783 case 0x0087: // Reserved (Region-Size)
1784 pPict->ReadUInt16( nUSHORT ); nDataSize=nUSHORT;
1785 break;
1786
1787 case 0x0088: // frameSameRgn
1788 case 0x0089: // paintSameRgn
1789 case 0x008a: // eraseSameRgn
1790 case 0x008b: // invertSameRgn
1791 case 0x008c: // fillSameRgn
1792 nDataSize=ReadAndDrawSameRgn(shapeDMethod);
1793 break;
1794
1795 case 0x008d: // Reserved (0 Bytes)
1796 case 0x008e: // Reserved (0 Bytes)
1797 case 0x008f: // Reserved (0 Bytes)
1798 nDataSize=0;
1799 break;
1800
1801 case 0x0090: { // BitsRect
1802 BitmapEx aBmp;
1803 tools::Rectangle aSrcRect, aDestRect;
1804 nDataSize=ReadPixMapEtc(aBmp, false, true, &aSrcRect, &aDestRect, true, false);
1805 DrawingMethod( PictDrawingMethod::PAINT );
1806 pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1807 break;
1808 }
1809 case 0x0091: { // BitsRgn
1810 BitmapEx aBmp;
1811 tools::Rectangle aSrcRect, aDestRect;
1812 nDataSize=ReadPixMapEtc(aBmp, false, true, &aSrcRect, &aDestRect, true, true);
1813 DrawingMethod( PictDrawingMethod::PAINT );
1814 pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1815 break;
1816 }
1817 case 0x0092: // Reserved (n Bytes)
1818 case 0x0093: // Reserved (n Bytes)
1819 case 0x0094: // Reserved (n Bytes)
1820 case 0x0095: // Reserved (n Bytes)
1821 case 0x0096: // Reserved (n Bytes)
1822 case 0x0097: // Reserved (n Bytes)
1823 pPict->ReadUInt16( nUSHORT ); nDataSize=2+nUSHORT;
1824 break;
1825
1826 case 0x0098: { // PackBitsRect
1827 BitmapEx aBmp;
1828 tools::Rectangle aSrcRect, aDestRect;
1829 nDataSize=ReadPixMapEtc(aBmp, false, true, &aSrcRect, &aDestRect, true, false);
1830 DrawingMethod( PictDrawingMethod::PAINT );
1831 pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1832 break;
1833 }
1834 case 0x0099: { // PackBitsRgn
1835 BitmapEx aBmp;
1836 tools::Rectangle aSrcRect, aDestRect;
1837 nDataSize=ReadPixMapEtc(aBmp, false, true, &aSrcRect, &aDestRect, true, true);
1838 DrawingMethod( PictDrawingMethod::PAINT );
1839 pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1840 break;
1841 }
1842 case 0x009a: { // DirectBitsRect
1843 BitmapEx aBmp;
1844 tools::Rectangle aSrcRect, aDestRect;
1845 nDataSize=ReadPixMapEtc(aBmp, true, false, &aSrcRect, &aDestRect, true, false);
1846 DrawingMethod( PictDrawingMethod::PAINT );
1847 pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1848 break;
1849 }
1850 case 0x009b: { // DirectBitsRgn
1851 BitmapEx aBmp;
1852 tools::Rectangle aSrcRect, aDestRect;
1853 nDataSize=ReadPixMapEtc(aBmp, true, false, &aSrcRect, &aDestRect, true, true);
1854 DrawingMethod( PictDrawingMethod::PAINT );
1855 pVirDev->DrawBitmapEx(aDestRect.TopLeft(),aDestRect.GetSize(),aBmp);
1856 break;
1857 }
1858 case 0x009c: // Reserved (n Bytes)
1859 case 0x009d: // Reserved (n Bytes)
1860 case 0x009e: // Reserved (n Bytes)
1861 case 0x009f: // Reserved (n Bytes)
1862 pPict->ReadUInt16( nUSHORT ); nDataSize=2+nUSHORT;
1863 break;
1864
1865 case 0x00a0: // ShortComment
1866 nDataSize=2;
1867 break;
1868
1869 case 0x00a1: // LongComment
1870 pPict->SeekRel(2); pPict->ReadUInt16( nUSHORT ); nDataSize=4+nUSHORT;
1871 break;
1872
1873 default: // 0x00a2 bis 0xffff (most times reserved)
1874 if (nOpcode<=0x00af) { pPict->ReadUInt16( nUSHORT ); nDataSize=2+nUSHORT; }
1875 else if (nOpcode<=0x00cf) { nDataSize=0; }
1876 else if (nOpcode<=0x00fe) { sal_uInt32 nTemp; pPict->ReadUInt32( nTemp ) ; nDataSize = nTemp; nDataSize+=4; }
1877 // Osnola: checkme: in the Quickdraw Ref examples ( for pict v2)
1878 // 0x00ff(EndOfPict) is also not followed by any data...
1879 else if (nOpcode==0x00ff) { nDataSize=IsVersion2 ? 2 : 0; } // OpEndPic
1880 else if (nOpcode<=0x01ff) { nDataSize=2; }
1881 else if (nOpcode<=0x0bfe) { nDataSize=4; }
1882 else if (nOpcode<=0x0bff) { nDataSize=22; }
1883 else if (nOpcode==0x0c00) { nDataSize=24; } // HeaderOp
1884 else if (nOpcode<=0x7eff) { nDataSize=24; }
1885 else if (nOpcode<=0x7fff) { nDataSize=254; }
1886 else if (nOpcode<=0x80ff) { nDataSize=0; }
1887 else { sal_uInt32 nTemp; pPict->ReadUInt32( nTemp ) ; nDataSize = nTemp; nDataSize+=4; }
1888 }
1889
1890 if (nDataSize==0xffffffff) {
1891 pPict->SetError(SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ));
1892 return 0;
1893 }
1894 return nDataSize;
1895}
1896
1897void PictReader::ReadPict( SvStream & rStreamPict, GDIMetaFile & rGDIMetaFile )
1898{
1899 try {
1900 sal_uInt16 nOpcode;
1901 sal_uInt8 nOneByteOpcode;
1902 sal_uInt64 nSize;
1903
1904 pPict = &rStreamPict;
1905 nOrigPos = pPict->Tell();
1906 SvStreamEndian nOrigNumberFormat = pPict->GetEndian();
1907
1908 aActForeColor = COL_BLACK;
1909 aActBackColor = COL_WHITE;
1910 nActPenSize = Size(1,1);
1911 eActROP = RasterOp::OverPaint;
1912 eActMethod = PictDrawingMethod::UNDEFINED;
1913 aActOvalSize = Size(1,1);
1914
1915 aActFont.SetCharSet( GetTextEncoding());
1916 aActFont.SetFamily(FAMILY_SWISS);
1917 aActFont.SetFontSize(Size(0,12));
1918 aActFont.SetAlignment(ALIGN_BASELINE);
1919
1920 aHRes = aVRes = Fraction( 1, 1 );
1921
1922 pVirDev = VclPtr<VirtualDevice>::Create();
1923 pVirDev->EnableOutput(false);
1924 rGDIMetaFile.Record(pVirDev);
1925
1926 pPict->SetEndian(SvStreamEndian::BIG);
1927
1928 ReadHeader();
1929
1930 aPenPosition=Point(-aBoundingRect.Left(),-aBoundingRect.Top());
1931 aTextPosition=aPenPosition;
1932
1933 sal_uInt64 nPos=pPict->Tell();
1934
1935 for (;;) {
3
Loop condition is true. Entering loop body
1936
1937 if (IsVersion2 )
4
Assuming field 'IsVersion2' is true
5
Taking true branch
1938 pPict->ReadUInt16( nOpcode );
1939 else
1940 {
1941 pPict->ReadUChar( nOneByteOpcode );
1942 nOpcode=static_cast<sal_uInt16>(nOneByteOpcode);
1943 }
1944
1945 if (pPict->GetError())
6
Taking true branch
1946 break;
7
Execution continues on line 1972
1947
1948 if (pPict->eof())
1949 {
1950 pPict->SetError(SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ));
1951 break;
1952 }
1953
1954 if (nOpcode==0x00ff)
1955 break;
1956
1957 nSize=ReadData(nOpcode);
1958
1959 if ( IsVersion2 )
1960 {
1961 if ( nSize & 1 )
1962 nSize++;
1963
1964 nPos+=2+nSize;
1965 }
1966 else
1967 nPos+=1+nSize;
1968
1969 pPict->Seek(nPos);
1970 }
1971
1972 pVirDev->SetClipRegion();
1973 rGDIMetaFile.Stop();
1974 pVirDev.disposeAndClear();
8
Calling 'VclPtr::disposeAndClear'
1975
1976 rGDIMetaFile.SetPrefMapMode( MapMode( MapUnit::MapInch, Point(), aHRes, aVRes ) );
1977 rGDIMetaFile.SetPrefSize( aBoundingRect.GetSize() );
1978
1979 pPict->SetEndian(nOrigNumberFormat);
1980
1981 if (pPict->GetError()) pPict->Seek(nOrigPos);
1982 } catch (...)
1983 {
1984 rStreamPict.SetError(SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ));
1985 }
1986}
1987
1988namespace pict {
1989
1990void ReadPictFile(SvStream &rStreamPict, GDIMetaFile& rGDIMetaFile)
1991{
1992 PictReader aPictReader;
1993 aPictReader.ReadPict(rStreamPict, rGDIMetaFile);
2
Calling 'PictReader::ReadPict'
1994}
1995
1996}
1997
1998//================== GraphicImport - the exported function ================
1999
2000extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) bool
2001iptGraphicImport( SvStream& rIStm, Graphic & rGraphic, FilterConfigItem* )
2002{
2003 GDIMetaFile aMTF;
2004 bool bRet = false;
2005
2006 pict::ReadPictFile( rIStm, aMTF );
1
Calling 'ReadPictFile'
2007
2008 if ( !rIStm.GetError() )
2009 {
2010 rGraphic = Graphic( aMTF );
2011 bRet = true;
2012 }
2013
2014 return bRet;
2015}
2016
2017/* 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);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
9
Calling 'Reference::clear'
16
Returning; memory was released
205 if (aTmp.get()) {
17
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();
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)
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
9.1
Field 'm_pBody' is non-null
9.1
Field 'm_pBody' is non-null
9.1
Field 'm_pBody' is non-null
9.1
Field 'm_pBody' is non-null
)
10
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
11
Calling 'VclReferenceBase::release'
15
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;
18
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)
12
Assuming the condition is true
13
Taking true branch
40 delete this;
14
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