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