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