1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
23 #include <comphelper/string.hxx>
24 #include "xbmread.hxx"
30 XBMReader::XBMReader( SvStream
& rStm
) :
33 nLastPos ( rStm
.Tell() ),
38 pHexTable
= new short[ 256 ];
39 maUpperName
= OUString("SVIXBM");
43 // ------------------------------------------------------------------------
45 XBMReader::~XBMReader()
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
)
97 sal_Int32 nPos1
, nPos2
, nPos3
;
103 if( !pInStm
->ReadLine( aRet
) )
108 if( ( nPos1
= aRet
.indexOf( pTok1
) ) != -1 )
116 if( ( ( nPos2
= aRet
.indexOf( pTok2
) ) != -1 ) &&
125 if( ( ( nPos3
= aRet
.indexOf( pTok3
) ) != -1 ) && ( nPos3
> nPos2
) )
138 // ------------------------------------------------------------------------
140 long XBMReader::ParseDefine( const sal_Char
* pDefine
)
143 char* pTmp
= (char*) pDefine
;
146 // bis zum Ende gehen
147 pTmp
+= ( strlen( pDefine
) - 1 );
150 // letzte Ziffer suchen
151 while( pHexTable
[ cTmp
] == -1 )
154 // bis vor die Zahl laufen
155 while( pHexTable
[ cTmp
] != -1 )
158 // auf Anfang der Zahl gehen
162 if( ( pTmp
[0] == '0' ) && ( ( pTmp
[1] == 'X' ) || ( pTmp
[1] == 'x' ) ) )
167 while ( pHexTable
[ cTmp
] != -1 )
169 nRet
= ( nRet
<< 4 ) + pHexTable
[ cTmp
];
177 while( ( cTmp
>= '0' ) && ( cTmp
<= '9' ) )
179 nRet
= nRet
* 10 + ( cTmp
- '0' );
187 // ------------------------------------------------------------------------
189 sal_Bool
XBMReader::ParseData( SvStream
* pInStm
, const OString
& aLastLine
, XBMFormat eFormat
)
194 long nBits
= ( eFormat
== XBM10
) ? 16 : 8;
198 sal_Bool bFirstLine
= sal_True
;
200 while( nRow
< nHeight
)
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
) )
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
;
236 bProcessed
= sal_True
;
238 else if( ( nTable
< 0 ) && nDigits
)
240 bProcessed
= sal_True
;
247 while( ( nCol
< nWidth
) && ( nBit
< nBits
) )
248 pAcc1
->SetPixel( nRow
, nCol
++, ( nValue
& ( 1 << nBit
++ ) ) ? aBlack
: aWhite
);
260 // ------------------------------------------------------------------------
262 ReadState
XBMReader::ReadXBM( Graphic
& rGraphic
)
264 ReadState eReadState
;
267 // sehen, ob wir _alles_ lesen koennen
268 rIStm
.Seek( STREAM_SEEK_TO_END
);
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
);
277 OString aLine
= FindTokenLine( &rIStm
, "#define", "_width" );
282 if ( ( nValue
= (int) ParseDefine( aLine
.getStr() ) ) > 0 )
285 aLine
= FindTokenLine( &rIStm
, "#define", "_height" );
287 // Falls die Hoehe nicht folgt, suchen wir noch
288 // einmal vom Anfang der Datei an
291 rIStm
.Seek( nLastPos
);
292 aLine
= FindTokenLine( &rIStm
, "#define", "_height" );
300 if ( ( nValue
= (int) ParseDefine( aLine
.getStr() ) ) > 0 )
303 aLine
= FindTokenLine( &rIStm
, "static", "_bits" );
307 XBMFormat eFormat
= XBM10
;
309 if (aLine
.indexOf("short") != -1)
311 else if (aLine
.indexOf("char") != -1)
316 if ( bStatus
&& nWidth
&& nHeight
)
318 aBmp1
= Bitmap( Size( nWidth
, nHeight
), 1 );
319 pAcc1
= aBmp1
.AcquireWriteAccess();
323 aWhite
= pAcc1
->GetBestMatchingColor( Color( COL_WHITE
) );
324 aBlack
= pAcc1
->GetBestMatchingColor( Color( COL_BLACK
) );
325 bStatus
= ParseData( &rIStm
, aLine
, eFormat
);
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
;
345 eReadState
= XBMREAD_ERROR
;
350 eReadState
= XBMREAD_NEED_MORE
;
360 sal_Bool
ImportXBM( SvStream
& rStm
, Graphic
& rGraphic
)
362 XBMReader
* pXBMReader
= (XBMReader
*) rGraphic
.GetContext();
363 ReadState eReadState
;
364 sal_Bool bRet
= sal_True
;
367 pXBMReader
= new XBMReader( rStm
);
369 rGraphic
.SetContext( NULL
);
370 eReadState
= pXBMReader
->ReadXBM( rGraphic
);
372 if( eReadState
== XBMREAD_ERROR
)
377 else if( eReadState
== XBMREAD_OK
)
380 rGraphic
.SetContext( pXBMReader
);
385 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */