Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <vcl/bmpacc.hxx>
21 : #include <vcl/graph.hxx>
22 : #include "rgbtable.hxx"
23 : #define _XPMPRIVATE
24 : #include "xpmread.hxx"
25 :
26 0 : XPMReader::XPMReader(SvStream& rStm)
27 : : mrIStm(rStm)
28 : , mpAcc(NULL)
29 : , mpMaskAcc(NULL)
30 0 : , mnLastPos(rStm.Tell())
31 : , mnWidth(0)
32 : , mnHeight(0)
33 : , mnColors(0)
34 : , mnCpp(0)
35 : , mbTransparent(false)
36 : , mbStatus(true)
37 : , mnStatus( 0 )
38 : , mnIdentifier(XPMIDENTIFIER)
39 : , mcThisByte(0)
40 : , mcLastByte(0)
41 : , mnTempAvail(0)
42 : , mpTempBuf(NULL)
43 : , mpTempPtr(NULL)
44 : , mpFastColorTable(NULL)
45 : , mpColMap(NULL)
46 : , mnStringSize(0)
47 : , mpStringBuf(NULL)
48 : , mnParaSize(0)
49 0 : , mpPara(NULL)
50 : {
51 0 : }
52 :
53 0 : XPMReader::~XPMReader()
54 : {
55 0 : if( mpAcc )
56 0 : maBmp.ReleaseAccess( mpAcc );
57 0 : }
58 :
59 0 : ReadState XPMReader::ReadXPM( Graphic& rGraphic )
60 : {
61 : ReadState eReadState;
62 : sal_uInt8 cDummy;
63 :
64 : // check if we can real ALL
65 0 : mrIStm.Seek( STREAM_SEEK_TO_END );
66 0 : mrIStm.ReadUChar( cDummy );
67 :
68 : // if we could not read all
69 : // return and wait for new data
70 0 : if ( mrIStm.GetError() != ERRCODE_IO_PENDING )
71 : {
72 0 : mrIStm.Seek( mnLastPos );
73 0 : mbStatus = true;
74 :
75 0 : if ( mbStatus )
76 : {
77 0 : mpStringBuf = new sal_uInt8 [ XPMSTRINGBUF ];
78 0 : mpTempBuf = new sal_uInt8 [ XPMTEMPBUFSIZE ];
79 :
80 0 : if ( ( mbStatus = ImplGetString() ) )
81 : {
82 0 : mnIdentifier = XPMVALUES; // fetch Bitmap information
83 0 : mnWidth = ImplGetULONG( 0 );
84 0 : mnHeight = ImplGetULONG( 1 );
85 0 : mnColors = ImplGetULONG( 2 );
86 0 : mnCpp = ImplGetULONG( 3 );
87 : }
88 0 : if ( mnColors > ( SAL_MAX_UINT32 / ( 4 + mnCpp ) ) )
89 0 : mbStatus = false;
90 0 : if ( ( mnWidth * mnCpp ) >= XPMSTRINGBUF )
91 0 : mbStatus = false;
92 0 : if ( mbStatus && mnWidth && mnHeight && mnColors && mnCpp )
93 : {
94 0 : mnIdentifier = XPMCOLORS;
95 :
96 : // mpColMap constitutes for all available
97 : // colour: ( mnCpp )Byte(s)-> ASCII entry assigned to the colour
98 : // 1 Byte -> 0xFF if colour is transparent
99 : // 3 Bytes -> RGB value of the colour
100 0 : mpColMap = new sal_uInt8[ mnColors * ( 4 + mnCpp ) ];
101 0 : if ( mpColMap )
102 : {
103 0 : for ( sal_uLong i = 0; i < mnColors; i++ )
104 : {
105 0 : if ( !ImplGetColor( i ) )
106 : {
107 0 : mbStatus = false;
108 0 : break;
109 : }
110 : }
111 : }
112 : else
113 0 : mbStatus = false;
114 :
115 0 : if ( mbStatus )
116 : {
117 : // create a 24bit graphic when more as 256 colours present
118 0 : sal_uInt16 nBits = 1;
119 0 : if ( mnColors > 256 )
120 0 : nBits = 24;
121 0 : else if ( mnColors > 16 )
122 0 : nBits = 8;
123 0 : else if ( mnColors > 2 )
124 0 : nBits = 4;
125 : else
126 0 : nBits = 1;
127 :
128 0 : maBmp = Bitmap( Size( mnWidth, mnHeight ), nBits );
129 0 : mpAcc = maBmp.AcquireWriteAccess();
130 :
131 : // mbTransparent is TRUE if at least one colour is transparent
132 0 : if ( mbTransparent )
133 : {
134 0 : maMaskBmp = Bitmap( Size( mnWidth, mnHeight ), 1 );
135 0 : if ( ( mpMaskAcc = maMaskBmp.AcquireWriteAccess() ) == NULL )
136 0 : mbStatus = false;
137 : }
138 0 : if( mpAcc && mbStatus )
139 : {
140 : sal_uLong i;
141 0 : if ( mnColors <=256 ) // palette is only needed by using less than 257
142 : { // colors
143 :
144 0 : sal_uInt8* pPtr = &mpColMap[mnCpp];
145 :
146 0 : for ( i = 0; i < mnColors; i++ )
147 : {
148 0 : mpAcc->SetPaletteColor( (sal_uInt8)i, Color( pPtr[1], pPtr[2], pPtr[3] ) );
149 0 : pPtr += ( mnCpp + 4 );
150 : }
151 : // using 2 charakters per pixel and less than 257 Colors we speed up
152 0 : if ( mnCpp == 2 ) // by using a 64kb indexing table
153 : {
154 0 : mpFastColorTable = new sal_uInt8[ 256 * 256 ];
155 0 : for ( pPtr = mpColMap, i = 0; i < mnColors; i++, pPtr += mnCpp + 4 )
156 : {
157 0 : sal_uLong j = pPtr[ 0 ] << 8;
158 0 : j += pPtr[ 1 ];
159 0 : mpFastColorTable[ j ] = (sal_uInt8)i;
160 : }
161 : }
162 : }
163 : // now we get the bitmap data
164 0 : mnIdentifier = XPMPIXELS;
165 0 : for ( i = 0; i < mnHeight; i++ )
166 : {
167 0 : if ( !ImplGetScanLine( i ) )
168 : {
169 0 : mbStatus = false;
170 0 : break;
171 : }
172 : }
173 0 : mnIdentifier = XPMEXTENSIONS;
174 : }
175 : }
176 : }
177 :
178 0 : delete[] mpFastColorTable;
179 0 : delete[] mpColMap;
180 0 : delete[] mpStringBuf;
181 0 : delete[] mpTempBuf;
182 :
183 : }
184 0 : if( mbStatus )
185 : {
186 0 : if ( mpMaskAcc )
187 : {
188 0 : maMaskBmp.ReleaseAccess ( mpMaskAcc), mpMaskAcc = NULL;
189 0 : maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
190 0 : rGraphic = Graphic( BitmapEx( maBmp, maMaskBmp ) );
191 : }
192 : else
193 : {
194 0 : maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
195 0 : rGraphic = maBmp;
196 : }
197 0 : eReadState = XPMREAD_OK;
198 : }
199 : else
200 : {
201 0 : if ( mpMaskAcc ) maMaskBmp.ReleaseAccess ( mpMaskAcc), mpMaskAcc = NULL;
202 0 : if ( mpAcc ) maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
203 0 : eReadState = XPMREAD_ERROR;
204 : }
205 : }
206 : else
207 : {
208 0 : mrIStm.ResetError();
209 0 : eReadState = XPMREAD_NEED_MORE;
210 : }
211 0 : return eReadState;
212 : }
213 :
214 : // ImplGetColor returns variouls colour values,
215 : // returns TRUE if various colours could be assigned
216 :
217 0 : bool XPMReader::ImplGetColor( sal_uLong nNumb )
218 : {
219 0 : sal_uInt8* pString = mpStringBuf;
220 0 : sal_uInt8* pPtr = ( mpColMap + nNumb * ( 4 + mnCpp ) );
221 0 : bool bStatus = ImplGetString();
222 :
223 0 : if ( bStatus )
224 : {
225 0 : for ( sal_uLong i = 0; i < mnCpp; i++ )
226 0 : *pPtr++ = *pString++;
227 0 : bStatus = ImplGetColSub ( pPtr );
228 : }
229 0 : return bStatus;
230 : }
231 :
232 : // ImpGetScanLine reads the string mpBufSize and writes the pixel in the
233 : // Bitmap. Parameter nY is the horizontal position.
234 :
235 0 : bool XPMReader::ImplGetScanLine( sal_uLong nY )
236 : {
237 0 : bool bStatus = ImplGetString();
238 0 : sal_uInt8* pString = mpStringBuf;
239 : sal_uInt8* pColor;
240 0 : BitmapColor aWhite;
241 0 : BitmapColor aBlack;
242 :
243 0 : if ( bStatus )
244 : {
245 0 : if ( mpMaskAcc )
246 : {
247 0 : aWhite = mpMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) );
248 0 : aBlack = mpMaskAcc->GetBestMatchingColor( Color( COL_BLACK ) );
249 : }
250 0 : if ( mnStringSize != ( mnWidth * mnCpp ))
251 0 : bStatus = false;
252 : else
253 : {
254 : sal_uLong i, j;
255 0 : if ( mpFastColorTable )
256 : {
257 0 : for ( i = 0; i < mnWidth; i++ )
258 : {
259 0 : j = (*pString++) << 8;
260 0 : j += *pString++;
261 0 : sal_uInt8 k = (sal_uInt8)mpFastColorTable[ j ];
262 0 : mpAcc->SetPixel( nY, i, BitmapColor( (sal_uInt8)k ) );
263 :
264 0 : if ( mpMaskAcc )
265 : mpMaskAcc->SetPixel( nY, i,
266 0 : ( mpColMap[ k * (mnCpp + 4) + mnCpp] ) ? aWhite : aBlack );
267 : }
268 : }
269 0 : else for ( i = 0; i < mnWidth; i++ )
270 : {
271 0 : pColor = mpColMap;
272 0 : for ( j = 0; j < mnColors; j++ )
273 : {
274 0 : if ( ImplCompare( pString, pColor, mnCpp, XPMCASESENSITIVE ) )
275 : {
276 0 : if ( mnColors > 256 )
277 0 : mpAcc->SetPixel( nY, i, Color ( pColor[3], pColor[4], pColor[5] ) );
278 : else
279 0 : mpAcc->SetPixel( nY, i, BitmapColor( (sal_uInt8) j ) );
280 :
281 0 : if ( mpMaskAcc )
282 : mpMaskAcc->SetPixel( nY, i, (
283 0 : pColor[ mnCpp ] ) ? aWhite : aBlack );
284 :
285 0 : break;
286 : }
287 0 : pColor += ( mnCpp + 4 );
288 : }
289 0 : pString += mnCpp;
290 : }
291 :
292 : }
293 : }
294 0 : return bStatus;
295 : }
296 :
297 : // tries to determine a colour value from mpStringBuf
298 : // if a colour was found the RGB value is written a pDest[1]..pDest[2]
299 : // pDest[0] contains 0xFF if the colour is transparent otherwise 0
300 :
301 0 : bool XPMReader::ImplGetColSub( sal_uInt8* pDest )
302 : {
303 0 : unsigned char cTransparent[] = "None";
304 :
305 0 : bool bColStatus = false;
306 :
307 0 : if ( ImplGetColKey( 'c' ) || ImplGetColKey( 'm' ) || ImplGetColKey( 'g' ) )
308 : {
309 : // hexentry for RGB or HSV color ?
310 0 : if ( *mpPara == '#' )
311 : {
312 0 : *pDest++ = 0;
313 0 : bColStatus = true;
314 0 : switch ( mnParaSize )
315 : {
316 : case 25 :
317 0 : ImplGetRGBHex ( pDest, 6 );
318 0 : break;
319 : case 13 :
320 0 : ImplGetRGBHex ( pDest, 2 );
321 0 : break;
322 : case 7 :
323 0 : ImplGetRGBHex ( pDest, 0 );
324 0 : break;
325 : default:
326 0 : bColStatus = false;
327 0 : break;
328 : }
329 : }
330 : // maybe pixel is transparent
331 0 : else if ( ImplCompare( &cTransparent[0], mpPara, 4 ))
332 : {
333 0 : *pDest++ = 0xff;
334 0 : bColStatus = true;
335 0 : mbTransparent = true;
336 : }
337 : // last we will try to get the colorname
338 0 : else if ( mnParaSize > 2 ) // name must enlarge the minimum size
339 : {
340 0 : sal_uLong i = 0;
341 : while ( true )
342 : {
343 0 : if ( pRGBTable[ i ].name == NULL )
344 0 : break;
345 0 : if ( pRGBTable[ i ].name[ mnParaSize ] == 0 )
346 : {
347 0 : if ( ImplCompare ( (unsigned char*)pRGBTable[ i ].name,
348 0 : mpPara, mnParaSize, XPMCASENONSENSITIVE ) )
349 : {
350 0 : bColStatus = true;
351 0 : *pDest++ = 0;
352 0 : *pDest++ = pRGBTable[ i ].red;
353 0 : *pDest++ = pRGBTable[ i ].green;
354 0 : *pDest++ = pRGBTable[ i ].blue;
355 : }
356 : }
357 0 : i++;
358 0 : }
359 : }
360 : }
361 0 : return bColStatus;
362 : }
363 :
364 : // ImplGetColKey searches string mpStringBuf for a parameter 'nKey'
365 : // and returns a boolean. (if TRUE mpPara and mnParaSize will be set)
366 :
367 0 : bool XPMReader::ImplGetColKey( sal_uInt8 nKey )
368 : {
369 0 : sal_uInt8 nTemp, nPrev = ' ';
370 :
371 0 : mpPara = mpStringBuf + mnCpp + 1;
372 0 : mnParaSize = 0;
373 :
374 0 : while ( *mpPara != 0 )
375 : {
376 0 : if ( *mpPara == nKey )
377 : {
378 0 : nTemp = *( mpPara + 1 );
379 0 : if ( nTemp == ' ' || nTemp == 0x09 )
380 : {
381 0 : if ( nPrev == ' ' || nPrev == 0x09 )
382 : break;
383 : }
384 : }
385 0 : nPrev = *mpPara;
386 0 : mpPara++;
387 : }
388 0 : if ( *mpPara )
389 : {
390 0 : mpPara++;
391 0 : while ( (*mpPara == ' ') || (*mpPara == 0x09) )
392 : {
393 0 : mpPara++;
394 : }
395 0 : if ( *mpPara != 0 )
396 : {
397 0 : while ( *(mpPara+mnParaSize) != ' ' && *(mpPara+mnParaSize) != 0x09 &&
398 0 : *(mpPara+mnParaSize) != 0 )
399 : {
400 0 : mnParaSize++;
401 : }
402 : }
403 : }
404 0 : return ( mnParaSize ) ? true : false;
405 : }
406 :
407 : // ImplGetRGBHex translates the ASCII-Hexadecimalvalue belonging to mpPara
408 : // in a RGB value and writes this to pDest
409 : // below formats should be contained in mpPara:
410 : // if nAdd = 0 : '#12ab12' -> RGB = 0x12, 0xab, 0x12
411 : // 2 : '#1234abcd1234' " " " "
412 : // 6 : '#12345678abcdefab12345678' " " " "
413 :
414 0 : void XPMReader::ImplGetRGBHex( sal_uInt8* pDest,sal_uLong nAdd )
415 : {
416 0 : sal_uInt8* pPtr = mpPara+1;
417 : sal_uInt8 nHex, nTemp;
418 :
419 0 : for ( sal_uLong i = 0; i < 3; i++ )
420 : {
421 0 : nHex = (*pPtr++) - '0';
422 0 : if ( nHex > 9 )
423 0 : nHex = ((nHex - 'A' + '0') & 7) + 10;
424 :
425 0 : nTemp = (*pPtr++) - '0';
426 0 : if ( nTemp > 9 )
427 0 : nTemp = ((nTemp - 'A' + '0') & 7) + 10;
428 0 : nHex = ( nHex << 4 ) + nTemp;
429 :
430 0 : pPtr += nAdd;
431 0 : *pDest++ = (sal_uInt8)nHex;
432 : }
433 0 : }
434 :
435 : // ImplGetUlong returns the value of a up to 6-digit long ASCII-decimal number.
436 :
437 0 : sal_uLong XPMReader::ImplGetULONG( sal_uLong nPara )
438 : {
439 0 : if ( ImplGetPara ( nPara ) )
440 : {
441 0 : sal_uLong nRetValue = 0;
442 0 : sal_uInt8* pPtr = mpPara;
443 :
444 0 : if ( ( mnParaSize > 6 ) || ( mnParaSize == 0 ) ) return 0;
445 0 : for ( sal_uLong i = 0; i < mnParaSize; i++ )
446 : {
447 0 : sal_uInt8 j = (*pPtr++) - 48;
448 0 : if ( j > 9 ) return 0; // ascii is invalid
449 0 : nRetValue*=10;
450 0 : nRetValue+=j;
451 : }
452 0 : return nRetValue;
453 : }
454 0 : else return 0;
455 : }
456 :
457 0 : bool XPMReader::ImplCompare( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nSize, sal_uLong nMode )
458 : {
459 0 : bool bRet = true;
460 :
461 0 : if ( nMode == XPMCASENONSENSITIVE )
462 : {
463 0 : for ( sal_uLong i = 0; i < nSize; i++ )
464 : {
465 0 : if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
466 : {
467 0 : bRet = false;
468 0 : break;
469 : }
470 : }
471 : }
472 : else
473 : {
474 0 : for ( sal_uLong i = 0; i < nSize; i++ )
475 : {
476 0 : if ( pSource[i] != pDest[i] )
477 : {
478 0 : bRet = false;
479 0 : break;
480 : }
481 : }
482 : }
483 0 : return bRet;
484 : }
485 :
486 : // ImplGetPara tries to retrieve nNumb (0...x) parameters from mpStringBuf.
487 : // Parameters are separated by spaces or tabs.
488 : // If a parameter was found then the return value is TRUE and mpPara + mnParaSize
489 : // are set.
490 :
491 0 : bool XPMReader::ImplGetPara ( sal_uLong nNumb )
492 : {
493 : sal_uInt8 nByte;
494 0 : sal_uLong pSize = 0;
495 0 : sal_uInt8* pPtr = mpStringBuf;
496 0 : sal_uLong nCount = 0;
497 :
498 0 : if ( ( *pPtr != ' ' ) && ( *pPtr != 0x09 ) )
499 : {
500 0 : mpPara = pPtr;
501 0 : mnParaSize = 0;
502 0 : nCount = 0;
503 : }
504 : else
505 : {
506 0 : mpPara = NULL;
507 0 : nCount = 0xffffffff;
508 : }
509 :
510 0 : while ( pSize < mnStringSize )
511 : {
512 0 : nByte = *pPtr;
513 :
514 0 : if ( mpPara )
515 : {
516 0 : if ( ( nByte == ' ' ) || ( nByte == 0x09 ) )
517 : {
518 0 : if ( nCount == nNumb )
519 0 : break;
520 : else
521 0 : mpPara = NULL;
522 : }
523 : else
524 0 : mnParaSize++;
525 : }
526 : else
527 : {
528 0 : if ( ( nByte != ' ' ) && ( nByte != 0x09 ) )
529 : {
530 0 : mpPara = pPtr;
531 0 : mnParaSize = 1;
532 0 : nCount++;
533 : }
534 : }
535 0 : pSize++;
536 0 : pPtr++;
537 : }
538 0 : return ( ( nCount == nNumb ) && ( mpPara ) );
539 : }
540 :
541 : // The next string is read and stored in mpStringBuf (terminated with 0);
542 : // mnStringSize contains the size of the string read.
543 : // Comments like '//' and '/*....*/' are skipped.
544 :
545 0 : bool XPMReader::ImplGetString( void )
546 : {
547 0 : sal_uInt8 sID[] = "/* XPM */";
548 0 : sal_uInt8* pString = mpStringBuf;
549 :
550 0 : mnStringSize = 0;
551 0 : mpStringBuf[0] = 0;
552 :
553 0 : while( mbStatus && ( mnStatus != XPMFINISHED ) )
554 : {
555 0 : if ( mnTempAvail == 0 )
556 : {
557 0 : mnTempAvail = mrIStm.Read( mpTempBuf, XPMTEMPBUFSIZE );
558 0 : if ( mnTempAvail == 0 )
559 0 : break;
560 :
561 0 : mpTempPtr = mpTempBuf;
562 :
563 0 : if ( mnIdentifier == XPMIDENTIFIER )
564 : {
565 0 : if ( mnTempAvail <= 50 )
566 : {
567 0 : mbStatus = false; // file is too short to be a correct XPM format
568 0 : break;
569 : }
570 0 : for ( int i = 0; i < 9; i++ ) // searching for "/* XPM */"
571 0 : if ( *mpTempPtr++ != sID[i] )
572 : {
573 0 : mbStatus = false;
574 0 : break;
575 : }
576 0 : mnTempAvail-=9;
577 0 : mnIdentifier++;
578 : }
579 : }
580 0 : mcLastByte = mcThisByte;
581 0 : mcThisByte = *mpTempPtr++;
582 0 : mnTempAvail--;
583 :
584 0 : if ( mnStatus & XPMDOUBLE )
585 : {
586 0 : if ( mcThisByte == 0x0a )
587 0 : mnStatus &=~XPMDOUBLE;
588 0 : continue;
589 : }
590 0 : if ( mnStatus & XPMREMARK )
591 : {
592 0 : if ( ( mcThisByte == '/' ) && ( mcLastByte == '*' ) )
593 0 : mnStatus &=~XPMREMARK;
594 0 : continue;
595 : }
596 0 : if ( mnStatus & XPMSTRING ) // characters in string
597 : {
598 0 : if ( mcThisByte == '"' )
599 : {
600 0 : mnStatus &=~XPMSTRING; // end of parameter by eol
601 0 : break;
602 : }
603 0 : if ( mnStringSize >= ( XPMSTRINGBUF - 1 ) )
604 : {
605 0 : mbStatus = false;
606 0 : break;
607 : }
608 0 : *pString++ = mcThisByte;
609 0 : pString[0] = 0;
610 0 : mnStringSize++;
611 0 : continue;
612 : }
613 : else
614 : { // characters beside string
615 0 : switch ( mcThisByte )
616 : {
617 : case '*' :
618 0 : if ( mcLastByte == '/' ) mnStatus |= XPMREMARK;
619 0 : break;
620 : case '/' :
621 0 : if ( mcLastByte == '/' ) mnStatus |= XPMDOUBLE;
622 0 : break;
623 0 : case '"' : mnStatus |= XPMSTRING;
624 0 : break;
625 : case '{' :
626 0 : if ( mnIdentifier == XPMDEFINITION )
627 0 : mnIdentifier++;
628 0 : break;
629 : case '}' :
630 0 : if ( mnIdentifier == XPMENDEXT )
631 0 : mnStatus = XPMFINISHED;
632 0 : break;
633 : }
634 : }
635 : }
636 0 : return mbStatus;
637 : }
638 :
639 : // - ImportXPM -
640 :
641 0 : bool ImportXPM( SvStream& rStm, Graphic& rGraphic )
642 : {
643 0 : XPMReader* pXPMReader = (XPMReader*) rGraphic.GetContext();
644 : ReadState eReadState;
645 0 : bool bRet = true;
646 :
647 0 : if( !pXPMReader )
648 0 : pXPMReader = new XPMReader( rStm );
649 :
650 0 : rGraphic.SetContext( NULL );
651 0 : eReadState = pXPMReader->ReadXPM( rGraphic );
652 :
653 0 : if( eReadState == XPMREAD_ERROR )
654 : {
655 0 : bRet = false;
656 0 : delete pXPMReader;
657 : }
658 0 : else if( eReadState == XPMREAD_OK )
659 0 : delete pXPMReader;
660 : else
661 0 : rGraphic.SetContext( pXPMReader );
662 :
663 0 : return bRet;
664 : }
665 :
666 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|