Bug Summary

File:home/maarten/src/libreoffice/core/filter/source/graphicfilter/ipict/ipict.cxx
Warning:line 796, column 34
Although the value stored to 'nCmpSize' is used in the enclosing expression, the value is never actually read from 'nCmpSize'

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
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;
Although the value stored to 'nCmpSize' is used in the enclosing expression, the value is never actually read from 'nCmpSize'
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 (;;) {
1936
1937 if (IsVersion2 )
1938 pPict->ReadUInt16( nOpcode );
1939 else
1940 {
1941 pPict->ReadUChar( nOneByteOpcode );
1942 nOpcode=static_cast<sal_uInt16>(nOneByteOpcode);
1943 }
1944
1945 if (pPict->GetError())
1946 break;
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();
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);
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 );
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: */