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' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
39 | namespace 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 | |
145 | namespace { |
146 | |
147 | enum class PictDrawingMethod { |
148 | FRAME, PAINT, ERASE, INVERT, FILL, |
149 | TEXT, UNDEFINED |
150 | }; |
151 | |
152 | class PictReader { |
153 | typedef class PictReaderInternal::Pattern Pattern; |
154 | private: |
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 | |
253 | public: |
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 | |
273 | static 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 ============================== |
315 | rtl_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 | |
352 | void PictReader::SetLineColor( const Color& rColor ) |
353 | { |
354 | pVirDev->SetLineColor( rColor ); |
355 | } |
356 | |
357 | void PictReader::SetFillColor( const Color& rColor ) |
358 | { |
359 | pVirDev->SetFillColor( rColor ); |
360 | } |
361 | |
362 | Point 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 | |
375 | Point 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 | |
384 | Point 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 | |
393 | Point 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 | |
402 | Point 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 | |
411 | Size 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 | |
420 | Color 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 | |
442 | Color 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 | |
451 | void 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 | |
469 | sal_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 | |
495 | sal_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 | |
527 | sal_uInt8 PictReader::ReadAndDrawRect(PictDrawingMethod eMethod) |
528 | { |
529 | ReadRectangle(aLastRect); |
530 | ReadAndDrawSameRect(eMethod); |
531 | return 8; |
532 | } |
533 | |
534 | sal_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 | |
542 | sal_uInt8 PictReader::ReadAndDrawRoundRect(PictDrawingMethod eMethod) |
543 | { |
544 | ReadRectangle(aLastRoundRect); |
545 | ReadAndDrawSameRoundRect(eMethod); |
546 | return 8; |
547 | } |
548 | |
549 | sal_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 | |
557 | sal_uInt8 PictReader::ReadAndDrawOval(PictDrawingMethod eMethod) |
558 | { |
559 | ReadRectangle(aLastOval); |
560 | ReadAndDrawSameOval(eMethod); |
561 | return 8; |
562 | } |
563 | |
564 | sal_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 | |
572 | sal_uInt64 PictReader::ReadAndDrawPolygon(PictDrawingMethod eMethod) |
573 | { |
574 | sal_uInt64 nDataSize; |
575 | nDataSize=ReadPolygon(aLastPolygon); |
576 | ReadAndDrawSamePolygon(eMethod); |
577 | return nDataSize; |
578 | } |
579 | |
580 | sal_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 | |
589 | sal_uInt8 PictReader::ReadAndDrawArc(PictDrawingMethod eMethod) |
590 | { |
591 | ReadRectangle(aLastArcRect); |
592 | ReadAndDrawSameArc(eMethod); |
593 | return 12; |
594 | } |
595 | |
596 | sal_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 | |
616 | sal_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 | |
639 | sal_uInt8 PictReader::ReadAndDrawSameRgn(PictDrawingMethod eMethod) |
640 | { |
641 | if (IsInvisible(eMethod)) return 0; |
642 | DrawingMethod(eMethod); |
643 | // DISPLAY: ...???... |
644 | return 0; |
645 | } |
646 | |
647 | void 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 | |
701 | sal_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 | |
723 | sal_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 | |
1153 | void 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 |
1284 | static 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 | |
1315 | sal_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 | |
1897 | void 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 | |
1988 | namespace pict { |
1989 | |
1990 | void ReadPictFile(SvStream &rStreamPict, GDIMetaFile& rGDIMetaFile) |
1991 | { |
1992 | PictReader aPictReader; |
1993 | aPictReader.ReadPict(rStreamPict, rGDIMetaFile); |
1994 | } |
1995 | |
1996 | } |
1997 | |
1998 | //================== GraphicImport - the exported function ================ |
1999 | |
2000 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) bool |
2001 | iptGraphicImport( 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: */ |