update credits
[LibreOffice.git] / vcl / source / filter / ixbm / xbmread.cxx
blobfc725f00b09632f846f55438927b9580470c55e2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #define _XBMPRIVATE
22 #include <ctype.h>
23 #include <comphelper/string.hxx>
24 #include "xbmread.hxx"
26 // -------------
27 // - XBMReader -
28 // -------------
30 XBMReader::XBMReader( SvStream& rStm ) :
31 rIStm ( rStm ),
32 pAcc1 ( NULL ),
33 nLastPos ( rStm.Tell() ),
34 nWidth ( 0 ),
35 nHeight ( 0 ),
36 bStatus ( sal_True )
38 pHexTable = new short[ 256 ];
39 maUpperName = OUString("SVIXBM");
40 InitTable();
43 // ------------------------------------------------------------------------
45 XBMReader::~XBMReader()
47 delete[] pHexTable;
49 if( pAcc1 )
50 aBmp1.ReleaseAccess( pAcc1 );
53 // ------------------------------------------------------------------------
55 void XBMReader::InitTable()
57 memset( pHexTable, 0, sizeof( short ) * 256 );
59 pHexTable[(int)'0'] = 0;
60 pHexTable[(int)'1'] = 1;
61 pHexTable[(int)'2'] = 2;
62 pHexTable[(int)'3'] = 3;
63 pHexTable[(int)'4'] = 4;
64 pHexTable[(int)'5'] = 5;
65 pHexTable[(int)'6'] = 6;
66 pHexTable[(int)'7'] = 7;
67 pHexTable[(int)'8'] = 8;
68 pHexTable[(int)'9'] = 9;
69 pHexTable[(int)'A'] = 10;
70 pHexTable[(int)'B'] = 11;
71 pHexTable[(int)'C'] = 12;
72 pHexTable[(int)'D'] = 13;
73 pHexTable[(int)'E'] = 14;
74 pHexTable[(int)'F'] = 15;
75 pHexTable[(int)'X'] = 0;
76 pHexTable[(int)'a'] = 10;
77 pHexTable[(int)'b'] = 11;
78 pHexTable[(int)'c'] = 12;
79 pHexTable[(int)'d'] = 13;
80 pHexTable[(int)'e'] = 14;
81 pHexTable[(int)'f'] = 15;
82 pHexTable[(int)'x'] = 0;
83 pHexTable[(int)' '] = -1;
84 pHexTable[(int)','] = -1;
85 pHexTable[(int)'}'] = -1;
86 pHexTable[(int)'\n'] = -1;
87 pHexTable[(int)'\t'] = -1;
88 pHexTable[(int)'\0'] = -1;
91 // ------------------------------------------------------------------------
93 OString XBMReader::FindTokenLine( SvStream* pInStm, const char* pTok1,
94 const char* pTok2, const char* pTok3 )
96 OString aRet;
97 sal_Int32 nPos1, nPos2, nPos3;
99 bStatus = sal_False;
103 if( !pInStm->ReadLine( aRet ) )
104 break;
106 if( pTok1 )
108 if( ( nPos1 = aRet.indexOf( pTok1 ) ) != -1 )
110 bStatus = sal_True;
112 if( pTok2 )
114 bStatus = sal_False;
116 if( ( ( nPos2 = aRet.indexOf( pTok2 ) ) != -1 ) &&
117 ( nPos2 > nPos1 ) )
119 bStatus = sal_True;
121 if( pTok3 )
123 bStatus = sal_False;
125 if( ( ( nPos3 = aRet.indexOf( pTok3 ) ) != -1 ) && ( nPos3 > nPos2 ) )
126 bStatus = sal_True;
133 while( !bStatus );
135 return aRet;
138 // ------------------------------------------------------------------------
140 long XBMReader::ParseDefine( const sal_Char* pDefine )
142 long nRet = 0;
143 char* pTmp = (char*) pDefine;
144 unsigned char cTmp;
146 // bis zum Ende gehen
147 pTmp += ( strlen( pDefine ) - 1 );
148 cTmp = *pTmp--;
150 // letzte Ziffer suchen
151 while( pHexTable[ cTmp ] == -1 )
152 cTmp = *pTmp--;
154 // bis vor die Zahl laufen
155 while( pHexTable[ cTmp ] != -1 )
156 cTmp = *pTmp--;
158 // auf Anfang der Zahl gehen
159 pTmp += 2;
161 // Hex lesen
162 if( ( pTmp[0] == '0' ) && ( ( pTmp[1] == 'X' ) || ( pTmp[1] == 'x' ) ) )
164 pTmp += 2;
165 cTmp = *pTmp++;
167 while ( pHexTable[ cTmp ] != -1 )
169 nRet = ( nRet << 4 ) + pHexTable[ cTmp ];
170 cTmp = *pTmp++;
173 // Dezimal lesen
174 else
176 cTmp = *pTmp++;
177 while( ( cTmp >= '0' ) && ( cTmp <= '9' ) )
179 nRet = nRet * 10 + ( cTmp - '0' );
180 cTmp = *pTmp++;
184 return nRet;
187 // ------------------------------------------------------------------------
189 sal_Bool XBMReader::ParseData( SvStream* pInStm, const OString& aLastLine, XBMFormat eFormat )
191 OString aLine;
192 long nRow = 0;
193 long nCol = 0;
194 long nBits = ( eFormat == XBM10 ) ? 16 : 8;
195 long nBit;
196 sal_uInt16 nValue;
197 sal_uInt16 nDigits;
198 sal_Bool bFirstLine = sal_True;
200 while( nRow < nHeight )
202 if( bFirstLine )
204 sal_Int32 nPos;
206 // einfuehrende geschweifte Klammer loeschen
207 if( (nPos = ( aLine = aLastLine ).indexOf('{') ) != -1 )
208 aLine = aLine.copy(nPos + 1);
210 bFirstLine = sal_False;
212 else if( !pInStm->ReadLine( aLine ) )
213 break;
215 if (!aLine.isEmpty())
217 const sal_Int32 nCount = comphelper::string::getTokenCount(aLine, ',');
219 for( sal_Int32 i = 0; ( i < nCount ) && ( nRow < nHeight ); ++i )
221 const OString aToken(comphelper::string::getToken(aLine,i, ','));
222 const sal_Int32 nLen = aToken.getLength();
223 sal_Bool bProcessed = sal_False;
225 nBit = nDigits = nValue = 0;
227 for (sal_Int32 n = 0; n < nLen; ++n)
229 const unsigned char cChar = aToken[n];
230 const short nTable = pHexTable[ cChar ];
232 if( isxdigit( cChar ) || !nTable )
234 nValue = ( nValue << 4 ) + nTable;
235 nDigits++;
236 bProcessed = sal_True;
238 else if( ( nTable < 0 ) && nDigits )
240 bProcessed = sal_True;
241 break;
245 if( bProcessed )
247 while( ( nCol < nWidth ) && ( nBit < nBits ) )
248 pAcc1->SetPixel( nRow, nCol++, ( nValue & ( 1 << nBit++ ) ) ? aBlack : aWhite );
250 if( nCol == nWidth )
251 nCol = 0, nRow++;
257 return sal_True;
260 // ------------------------------------------------------------------------
262 ReadState XBMReader::ReadXBM( Graphic& rGraphic )
264 ReadState eReadState;
265 sal_uInt8 cDummy;
267 // sehen, ob wir _alles_ lesen koennen
268 rIStm.Seek( STREAM_SEEK_TO_END );
269 rIStm >> cDummy;
271 // falls wir nicht alles lesen koennen
272 // kehren wir zurueck und warten auf neue Daten
273 if ( rIStm.GetError() != ERRCODE_IO_PENDING )
275 rIStm.Seek( nLastPos );
276 bStatus = sal_False;
277 OString aLine = FindTokenLine( &rIStm, "#define", "_width" );
279 if ( bStatus )
281 int nValue;
282 if ( ( nValue = (int) ParseDefine( aLine.getStr() ) ) > 0 )
284 nWidth = nValue;
285 aLine = FindTokenLine( &rIStm, "#define", "_height" );
287 // Falls die Hoehe nicht folgt, suchen wir noch
288 // einmal vom Anfang der Datei an
289 if ( !bStatus )
291 rIStm.Seek( nLastPos );
292 aLine = FindTokenLine( &rIStm, "#define", "_height" );
295 else
296 bStatus = sal_False;
298 if ( bStatus )
300 if ( ( nValue = (int) ParseDefine( aLine.getStr() ) ) > 0 )
302 nHeight = nValue;
303 aLine = FindTokenLine( &rIStm, "static", "_bits" );
305 if ( bStatus )
307 XBMFormat eFormat = XBM10;
309 if (aLine.indexOf("short") != -1)
310 eFormat = XBM10;
311 else if (aLine.indexOf("char") != -1)
312 eFormat = XBM11;
313 else
314 bStatus = sal_False;
316 if ( bStatus && nWidth && nHeight )
318 aBmp1 = Bitmap( Size( nWidth, nHeight ), 1 );
319 pAcc1 = aBmp1.AcquireWriteAccess();
321 if( pAcc1 )
323 aWhite = pAcc1->GetBestMatchingColor( Color( COL_WHITE ) );
324 aBlack = pAcc1->GetBestMatchingColor( Color( COL_BLACK ) );
325 bStatus = ParseData( &rIStm, aLine, eFormat );
327 else
328 bStatus = sal_False;
335 if( bStatus )
337 Bitmap aBlackBmp( Size( pAcc1->Width(), pAcc1->Height() ), 1 );
339 aBmp1.ReleaseAccess( pAcc1 ), pAcc1 = NULL;
340 aBlackBmp.Erase( Color( COL_BLACK ) );
341 rGraphic = BitmapEx( aBlackBmp, aBmp1 );
342 eReadState = XBMREAD_OK;
344 else
345 eReadState = XBMREAD_ERROR;
347 else
349 rIStm.ResetError();
350 eReadState = XBMREAD_NEED_MORE;
353 return eReadState;
356 // -------------
357 // - ImportXBM -
358 // -------------
360 sal_Bool ImportXBM( SvStream& rStm, Graphic& rGraphic )
362 XBMReader* pXBMReader = (XBMReader*) rGraphic.GetContext();
363 ReadState eReadState;
364 sal_Bool bRet = sal_True;
366 if( !pXBMReader )
367 pXBMReader = new XBMReader( rStm );
369 rGraphic.SetContext( NULL );
370 eReadState = pXBMReader->ReadXBM( rGraphic );
372 if( eReadState == XBMREAD_ERROR )
374 bRet = sal_False;
375 delete pXBMReader;
377 else if( eReadState == XBMREAD_OK )
378 delete pXBMReader;
379 else
380 rGraphic.SetContext( pXBMReader );
382 return bRet;
385 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */