Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #define _XBMPRIVATE
31 : : #include <ctype.h>
32 : : #include <comphelper/string.hxx>
33 : : #include "xbmread.hxx"
34 : :
35 : : // -------------
36 : : // - XBMReader -
37 : : // -------------
38 : :
39 : 0 : XBMReader::XBMReader( SvStream& rStm ) :
40 : : rIStm ( rStm ),
41 : : pAcc1 ( NULL ),
42 : 0 : nLastPos ( rStm.Tell() ),
43 : : nWidth ( 0 ),
44 : : nHeight ( 0 ),
45 [ # # ]: 0 : bStatus ( sal_True )
46 : : {
47 [ # # ]: 0 : pHexTable = new short[ 256 ];
48 [ # # ]: 0 : maUpperName = rtl::OUString("SVIXBM");
49 : 0 : InitTable();
50 : 0 : }
51 : :
52 : : // ------------------------------------------------------------------------
53 : :
54 [ # # ]: 0 : XBMReader::~XBMReader()
55 : : {
56 [ # # ]: 0 : delete[] pHexTable;
57 : :
58 [ # # ]: 0 : if( pAcc1 )
59 [ # # ]: 0 : aBmp1.ReleaseAccess( pAcc1 );
60 [ # # ]: 0 : }
61 : :
62 : : // ------------------------------------------------------------------------
63 : :
64 : 0 : void XBMReader::InitTable()
65 : : {
66 : 0 : memset( pHexTable, 0, sizeof( short ) * 256 );
67 : :
68 : 0 : pHexTable[(int)'0'] = 0;
69 : 0 : pHexTable[(int)'1'] = 1;
70 : 0 : pHexTable[(int)'2'] = 2;
71 : 0 : pHexTable[(int)'3'] = 3;
72 : 0 : pHexTable[(int)'4'] = 4;
73 : 0 : pHexTable[(int)'5'] = 5;
74 : 0 : pHexTable[(int)'6'] = 6;
75 : 0 : pHexTable[(int)'7'] = 7;
76 : 0 : pHexTable[(int)'8'] = 8;
77 : 0 : pHexTable[(int)'9'] = 9;
78 : 0 : pHexTable[(int)'A'] = 10;
79 : 0 : pHexTable[(int)'B'] = 11;
80 : 0 : pHexTable[(int)'C'] = 12;
81 : 0 : pHexTable[(int)'D'] = 13;
82 : 0 : pHexTable[(int)'E'] = 14;
83 : 0 : pHexTable[(int)'F'] = 15;
84 : 0 : pHexTable[(int)'X'] = 0;
85 : 0 : pHexTable[(int)'a'] = 10;
86 : 0 : pHexTable[(int)'b'] = 11;
87 : 0 : pHexTable[(int)'c'] = 12;
88 : 0 : pHexTable[(int)'d'] = 13;
89 : 0 : pHexTable[(int)'e'] = 14;
90 : 0 : pHexTable[(int)'f'] = 15;
91 : 0 : pHexTable[(int)'x'] = 0;
92 : 0 : pHexTable[(int)' '] = -1;
93 : 0 : pHexTable[(int)','] = -1;
94 : 0 : pHexTable[(int)'}'] = -1;
95 : 0 : pHexTable[(int)'\n'] = -1;
96 : 0 : pHexTable[(int)'\t'] = -1;
97 : 0 : pHexTable[(int)'\0'] = -1;
98 : 0 : }
99 : :
100 : : // ------------------------------------------------------------------------
101 : :
102 : 0 : rtl::OString XBMReader::FindTokenLine( SvStream* pInStm, const char* pTok1,
103 : : const char* pTok2, const char* pTok3 )
104 : : {
105 : 0 : rtl::OString aRet;
106 : : sal_Int32 nPos1, nPos2, nPos3;
107 : :
108 : 0 : bStatus = sal_False;
109 : :
110 [ # # ]: 0 : do
111 : : {
112 [ # # ][ # # ]: 0 : if( !pInStm->ReadLine( aRet ) )
113 : 0 : break;
114 : :
115 [ # # ]: 0 : if( pTok1 )
116 : : {
117 [ # # ]: 0 : if( ( nPos1 = aRet.indexOf( pTok1 ) ) != -1 )
118 : : {
119 : 0 : bStatus = sal_True;
120 : :
121 [ # # ]: 0 : if( pTok2 )
122 : : {
123 : 0 : bStatus = sal_False;
124 : :
125 [ # # ][ # # ]: 0 : if( ( ( nPos2 = aRet.indexOf( pTok2 ) ) != -1 ) &&
[ # # ][ # # ]
[ # # ]
126 : : ( nPos2 > nPos1 ) )
127 : : {
128 : 0 : bStatus = sal_True;
129 : :
130 [ # # ]: 0 : if( pTok3 )
131 : : {
132 : 0 : bStatus = sal_False;
133 : :
134 [ # # ][ # # ]: 0 : if( ( ( nPos3 = aRet.indexOf( pTok3 ) ) != -1 ) && ( nPos3 > nPos2 ) )
[ # # ][ # # ]
[ # # ]
135 : 0 : bStatus = sal_True;
136 : : }
137 : : }
138 : : }
139 : : }
140 : : }
141 : : }
142 : 0 : while( !bStatus );
143 : :
144 : 0 : return aRet;
145 : : }
146 : :
147 : : // ------------------------------------------------------------------------
148 : :
149 : 0 : long XBMReader::ParseDefine( const sal_Char* pDefine )
150 : : {
151 : 0 : long nRet = 0;
152 : 0 : char* pTmp = (char*) pDefine;
153 : : unsigned char cTmp;
154 : :
155 : : // bis zum Ende gehen
156 : 0 : pTmp += ( strlen( pDefine ) - 1 );
157 : 0 : cTmp = *pTmp--;
158 : :
159 : : // letzte Ziffer suchen
160 [ # # ]: 0 : while( pHexTable[ cTmp ] == -1 )
161 : 0 : cTmp = *pTmp--;
162 : :
163 : : // bis vor die Zahl laufen
164 [ # # ]: 0 : while( pHexTable[ cTmp ] != -1 )
165 : 0 : cTmp = *pTmp--;
166 : :
167 : : // auf Anfang der Zahl gehen
168 : 0 : pTmp += 2;
169 : :
170 : : // Hex lesen
171 [ # # ][ # # ]: 0 : if( ( pTmp[0] == '0' ) && ( ( pTmp[1] == 'X' ) || ( pTmp[1] == 'x' ) ) )
[ # # ]
172 : : {
173 : 0 : pTmp += 2;
174 : 0 : cTmp = *pTmp++;
175 : :
176 [ # # ]: 0 : while ( pHexTable[ cTmp ] != -1 )
177 : : {
178 : 0 : nRet = ( nRet << 4 ) + pHexTable[ cTmp ];
179 : 0 : cTmp = *pTmp++;
180 : : }
181 : : }
182 : : // Dezimal lesen
183 : : else
184 : : {
185 : 0 : cTmp = *pTmp++;
186 [ # # ][ # # ]: 0 : while( ( cTmp >= '0' ) && ( cTmp <= '9' ) )
[ # # ]
187 : : {
188 : 0 : nRet = nRet * 10 + ( cTmp - '0' );
189 : 0 : cTmp = *pTmp++;
190 : : }
191 : : }
192 : :
193 : 0 : return nRet;
194 : : }
195 : :
196 : : // ------------------------------------------------------------------------
197 : :
198 : 0 : sal_Bool XBMReader::ParseData( SvStream* pInStm, const rtl::OString& aLastLine, XBMFormat eFormat )
199 : : {
200 : 0 : rtl::OString aLine;
201 : 0 : long nRow = 0;
202 : 0 : long nCol = 0;
203 [ # # ]: 0 : long nBits = ( eFormat == XBM10 ) ? 16 : 8;
204 : : long nBit;
205 : : sal_uInt16 nValue;
206 : : sal_uInt16 nDigits;
207 : 0 : sal_Bool bFirstLine = sal_True;
208 : :
209 [ # # ]: 0 : while( nRow < nHeight )
210 : : {
211 [ # # ]: 0 : if( bFirstLine )
212 : : {
213 : : sal_Int32 nPos;
214 : :
215 : : // einfuehrende geschweifte Klammer loeschen
216 [ # # ]: 0 : if( (nPos = ( aLine = aLastLine ).indexOf('{') ) != -1 )
217 : 0 : aLine = aLine.copy(nPos + 1);
218 : :
219 : 0 : bFirstLine = sal_False;
220 : : }
221 [ # # ][ # # ]: 0 : else if( !pInStm->ReadLine( aLine ) )
222 : 0 : break;
223 : :
224 [ # # ]: 0 : if (!aLine.isEmpty())
225 : : {
226 [ # # ]: 0 : const sal_Int32 nCount = comphelper::string::getTokenCount(aLine, ',');
227 : :
228 [ # # ][ # # ]: 0 : for( sal_Int32 i = 0; ( i < nCount ) && ( nRow < nHeight ); ++i )
[ # # ]
229 : : {
230 : 0 : const rtl::OString aToken(comphelper::string::getToken(aLine,i, ','));
231 : 0 : const sal_Int32 nLen = aToken.getLength();
232 : 0 : sal_Bool bProcessed = sal_False;
233 : :
234 : 0 : nBit = nDigits = nValue = 0;
235 : :
236 [ # # ]: 0 : for (sal_Int32 n = 0; n < nLen; ++n)
237 : : {
238 : 0 : const unsigned char cChar = aToken[n];
239 : 0 : const short nTable = pHexTable[ cChar ];
240 : :
241 [ # # ][ # # ]: 0 : if( isxdigit( cChar ) || !nTable )
242 : : {
243 : 0 : nValue = ( nValue << 4 ) + nTable;
244 : 0 : nDigits++;
245 : 0 : bProcessed = sal_True;
246 : : }
247 [ # # ][ # # ]: 0 : else if( ( nTable < 0 ) && nDigits )
248 : : {
249 : 0 : bProcessed = sal_True;
250 : 0 : break;
251 : : }
252 : : }
253 : :
254 [ # # ]: 0 : if( bProcessed )
255 : : {
256 [ # # ][ # # ]: 0 : while( ( nCol < nWidth ) && ( nBit < nBits ) )
[ # # ]
257 [ # # ][ # # ]: 0 : pAcc1->SetPixel( nRow, nCol++, ( nValue & ( 1 << nBit++ ) ) ? aBlack : aWhite );
258 : :
259 [ # # ]: 0 : if( nCol == nWidth )
260 : 0 : nCol = 0, nRow++;
261 : : }
262 : 0 : }
263 : : }
264 : : }
265 : :
266 : 0 : return sal_True;
267 : : }
268 : :
269 : : // ------------------------------------------------------------------------
270 : :
271 : 0 : ReadState XBMReader::ReadXBM( Graphic& rGraphic )
272 : : {
273 : : ReadState eReadState;
274 : : sal_uInt8 cDummy;
275 : :
276 : : // sehen, ob wir _alles_ lesen koennen
277 [ # # ]: 0 : rIStm.Seek( STREAM_SEEK_TO_END );
278 [ # # ]: 0 : rIStm >> cDummy;
279 : :
280 : : // falls wir nicht alles lesen koennen
281 : : // kehren wir zurueck und warten auf neue Daten
282 [ # # ]: 0 : if ( rIStm.GetError() != ERRCODE_IO_PENDING )
283 : : {
284 [ # # ]: 0 : rIStm.Seek( nLastPos );
285 : 0 : bStatus = sal_False;
286 [ # # ]: 0 : rtl::OString aLine = FindTokenLine( &rIStm, "#define", "_width" );
287 : :
288 [ # # ]: 0 : if ( bStatus )
289 : : {
290 : : int nValue;
291 [ # # ]: 0 : if ( ( nValue = (int) ParseDefine( aLine.getStr() ) ) > 0 )
292 : : {
293 : 0 : nWidth = nValue;
294 [ # # ]: 0 : aLine = FindTokenLine( &rIStm, "#define", "_height" );
295 : :
296 : : // Falls die Hoehe nicht folgt, suchen wir noch
297 : : // einmal vom Anfang der Datei an
298 [ # # ]: 0 : if ( !bStatus )
299 : : {
300 [ # # ]: 0 : rIStm.Seek( nLastPos );
301 [ # # ]: 0 : aLine = FindTokenLine( &rIStm, "#define", "_height" );
302 : : }
303 : : }
304 : : else
305 : 0 : bStatus = sal_False;
306 : :
307 [ # # ]: 0 : if ( bStatus )
308 : : {
309 [ # # ]: 0 : if ( ( nValue = (int) ParseDefine( aLine.getStr() ) ) > 0 )
310 : : {
311 : 0 : nHeight = nValue;
312 [ # # ]: 0 : aLine = FindTokenLine( &rIStm, "static", "_bits" );
313 : :
314 [ # # ]: 0 : if ( bStatus )
315 : : {
316 : 0 : XBMFormat eFormat = XBM10;
317 : :
318 [ # # ]: 0 : if (aLine.indexOfL(RTL_CONSTASCII_STRINGPARAM("short")) != -1)
319 : 0 : eFormat = XBM10;
320 [ # # ]: 0 : else if (aLine.indexOfL(RTL_CONSTASCII_STRINGPARAM("char")) != -1)
321 : 0 : eFormat = XBM11;
322 : : else
323 : 0 : bStatus = sal_False;
324 : :
325 [ # # ][ # # ]: 0 : if ( bStatus && nWidth && nHeight )
[ # # ]
326 : : {
327 [ # # ][ # # ]: 0 : aBmp1 = Bitmap( Size( nWidth, nHeight ), 1 );
[ # # ]
328 [ # # ]: 0 : pAcc1 = aBmp1.AcquireWriteAccess();
329 : :
330 [ # # ]: 0 : if( pAcc1 )
331 : : {
332 [ # # ]: 0 : aWhite = pAcc1->GetBestMatchingColor( Color( COL_WHITE ) );
333 [ # # ]: 0 : aBlack = pAcc1->GetBestMatchingColor( Color( COL_BLACK ) );
334 [ # # ]: 0 : bStatus = ParseData( &rIStm, aLine, eFormat );
335 : : }
336 : : else
337 : 0 : bStatus = sal_False;
338 : : }
339 : : }
340 : : }
341 : : }
342 : : }
343 : :
344 [ # # ]: 0 : if( bStatus )
345 : : {
346 [ # # ]: 0 : Bitmap aBlackBmp( Size( pAcc1->Width(), pAcc1->Height() ), 1 );
347 : :
348 [ # # ]: 0 : aBmp1.ReleaseAccess( pAcc1 ), pAcc1 = NULL;
349 [ # # ]: 0 : aBlackBmp.Erase( Color( COL_BLACK ) );
350 [ # # ][ # # ]: 0 : rGraphic = BitmapEx( aBlackBmp, aBmp1 );
[ # # ][ # # ]
[ # # ]
351 [ # # ]: 0 : eReadState = XBMREAD_OK;
352 : : }
353 : : else
354 : 0 : eReadState = XBMREAD_ERROR;
355 : : }
356 : : else
357 : : {
358 [ # # ]: 0 : rIStm.ResetError();
359 : 0 : eReadState = XBMREAD_NEED_MORE;
360 : : }
361 : :
362 : 0 : return eReadState;
363 : : }
364 : :
365 : : // -------------
366 : : // - ImportXBM -
367 : : // -------------
368 : :
369 : 0 : sal_Bool ImportXBM( SvStream& rStm, Graphic& rGraphic )
370 : : {
371 : 0 : XBMReader* pXBMReader = (XBMReader*) rGraphic.GetContext();
372 : : ReadState eReadState;
373 : 0 : sal_Bool bRet = sal_True;
374 : :
375 [ # # ]: 0 : if( !pXBMReader )
376 [ # # ]: 0 : pXBMReader = new XBMReader( rStm );
377 : :
378 : 0 : rGraphic.SetContext( NULL );
379 : 0 : eReadState = pXBMReader->ReadXBM( rGraphic );
380 : :
381 [ # # ]: 0 : if( eReadState == XBMREAD_ERROR )
382 : : {
383 : 0 : bRet = sal_False;
384 [ # # ]: 0 : delete pXBMReader;
385 : : }
386 [ # # ]: 0 : else if( eReadState == XBMREAD_OK )
387 [ # # ]: 0 : delete pXBMReader;
388 : : else
389 : 0 : rGraphic.SetContext( pXBMReader );
390 : :
391 : 0 : return bRet;
392 : : }
393 : :
394 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|