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