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