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