xref: /AOO41X/main/svtools/source/filter/ixbm/xbmread.cxx (revision 5900e8ec128faec89519683efce668ccd8cc6084)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 
27 #define XBMMINREAD 512
28 
29 #define _XBMPRIVATE
30 #include <ctype.h>
31 #include "xbmread.hxx"
32 
33 // -------------
34 // - XBMReader -
35 // -------------
36 
XBMReader(SvStream & rStm)37 XBMReader::XBMReader( SvStream& rStm ) :
38             rIStm           ( rStm ),
39             pAcc1           ( NULL ),
40             nLastPos        ( rStm.Tell() ),
41             nWidth          ( 0 ),
42             nHeight         ( 0 ),
43             bStatus         ( sal_True )
44 {
45     pHexTable = new short[ 256 ];
46     maUpperName = String::CreateFromAscii( "SVIXBM", 6 );
47     InitTable();
48 }
49 
50 // ------------------------------------------------------------------------
51 
~XBMReader()52 XBMReader::~XBMReader()
53 {
54     delete[] pHexTable;
55 
56     if( pAcc1 )
57         aBmp1.ReleaseAccess( pAcc1 );
58 }
59 
60 // ------------------------------------------------------------------------
61 
InitTable()62 void XBMReader::InitTable()
63 {
64     memset( pHexTable, 0, sizeof( short ) );
65 
66     pHexTable['0'] = 0;
67     pHexTable['1'] = 1;
68     pHexTable['2'] = 2;
69     pHexTable['3'] = 3;
70     pHexTable['4'] = 4;
71     pHexTable['5'] = 5;
72     pHexTable['6'] = 6;
73     pHexTable['7'] = 7;
74     pHexTable['8'] = 8;
75     pHexTable['9'] = 9;
76     pHexTable['A'] = 10;
77     pHexTable['B'] = 11;
78     pHexTable['C'] = 12;
79     pHexTable['D'] = 13;
80     pHexTable['E'] = 14;
81     pHexTable['F'] = 15;
82     pHexTable['X'] = 0;
83     pHexTable['a'] = 10;
84     pHexTable['b'] = 11;
85     pHexTable['c'] = 12;
86     pHexTable['d'] = 13;
87     pHexTable['e'] = 14;
88     pHexTable['f'] = 15;
89     pHexTable['x'] = 0;
90     pHexTable[' '] =     -1;
91     pHexTable[','] = -1;
92     pHexTable['}'] = -1;
93     pHexTable['\n'] = -1;
94     pHexTable['\t'] = -1;
95     pHexTable['\0'] = -1;
96 }
97 
98 // ------------------------------------------------------------------------
99 
FindTokenLine(SvStream * pInStm,const char * pTok1,const char * pTok2,const char * pTok3)100 ByteString XBMReader::FindTokenLine( SvStream* pInStm, const char* pTok1,
101                                  const char* pTok2, const char* pTok3 )
102 {
103     ByteString  aRet;
104     long        nPos1;
105     long        nPos2;
106     long        nPos3;
107 
108     bStatus = sal_False;
109 
110     do
111     {
112         if( !pInStm->ReadLine( aRet ) )
113             break;
114 
115         if( pTok1 )
116         {
117             if( ( nPos1 = aRet.Search( pTok1 ) ) != STRING_NOTFOUND )
118             {
119                 bStatus = sal_True;
120 
121                 if( pTok2 )
122                 {
123                     bStatus = sal_False;
124 
125                     if( ( ( nPos2 = aRet.Search( pTok2 ) ) != STRING_NOTFOUND ) &&
126                          ( nPos2 > nPos1 ) )
127                     {
128                         bStatus = sal_True;
129 
130                         if( pTok3 )
131                         {
132                             bStatus = sal_False;
133 
134                             if( ( ( nPos3 = aRet.Search( pTok3 ) ) != STRING_NOTFOUND ) && ( nPos3 > nPos2 ) )
135                                 bStatus = sal_True;
136                         }
137                     }
138                 }
139             }
140         }
141     }
142     while( !bStatus );
143 
144     return aRet;
145 }
146 
147 // ------------------------------------------------------------------------
148 
ParseDefine(const sal_Char * pDefine)149 long XBMReader::ParseDefine( const sal_Char* pDefine )
150 {
151     long    nRet = 0;
152     char*   pTmp = (char*) pDefine;
153     unsigned char   cTmp;
154 
155     // bis zum Ende gehen
156     pTmp += ( strlen( pDefine ) - 1 );
157     cTmp = *pTmp--;
158 
159     // letzte Ziffer suchen
160     while( pHexTable[ cTmp ] == -1 )
161         cTmp = *pTmp--;
162 
163     // bis vor die Zahl laufen
164     while( pHexTable[ cTmp ] != -1 )
165         cTmp = *pTmp--;
166 
167     // auf Anfang der Zahl gehen
168     pTmp += 2;
169 
170     // Hex lesen
171     if( ( pTmp[0] == '0' ) && ( ( pTmp[1] == 'X' ) || ( pTmp[1] == 'x' ) ) )
172     {
173         pTmp += 2;
174         cTmp = *pTmp++;
175 
176         while ( pHexTable[ cTmp ] != -1 )
177         {
178             nRet = ( nRet << 4 ) + pHexTable[ cTmp ];
179             cTmp = *pTmp++;
180         }
181     }
182     // Dezimal lesen
183     else
184     {
185         cTmp = *pTmp++;
186         while( ( cTmp >= '0' ) && ( cTmp <= '9' ) )
187         {
188             nRet = nRet * 10 + ( cTmp - '0' );
189             cTmp = *pTmp++;
190         }
191     }
192 
193     return nRet;
194 }
195 
196 // ------------------------------------------------------------------------
197 
ParseData(SvStream * pInStm,const ByteString & aLastLine,XBMFormat eFormat)198 sal_Bool XBMReader::ParseData( SvStream* pInStm, const ByteString& aLastLine, XBMFormat eFormat )
199 {
200     ByteString      aLine;
201     long            nRow = 0;
202     long            nCol = 0;
203     long            nBits = ( eFormat == XBM10 ) ? 16 : 8;
204     long            nBit;
205     sal_uInt16          nValue;
206     sal_uInt16          nDigits;
207     sal_Bool            bFirstLine = sal_True;
208 
209     while( nRow < nHeight )
210     {
211         if( bFirstLine )
212         {
213             xub_StrLen nPos;
214 
215             // einfuehrende geschweifte Klammer loeschen
216             if( (nPos = ( aLine = aLastLine ).Search( '{' ) ) != STRING_NOTFOUND )
217                 aLine.Erase( 0, nPos + 1 );
218 
219             bFirstLine = sal_False;
220         }
221         else if( !pInStm->ReadLine( aLine ) )
222             break;
223 
224         if( aLine.Len() )
225         {
226             const sal_uInt16 nCount = aLine.GetTokenCount( ',' );
227 
228             for( sal_uInt16 i = 0; ( i < nCount ) && ( nRow < nHeight ); i++ )
229             {
230                 const ByteString    aToken( aLine.GetToken( i, ',' ) );
231                 const xub_StrLen nLen = aToken.Len();
232                 sal_Bool                bProcessed = sal_False;
233 
234                 nBit = nDigits = nValue = 0;
235 
236                 for( xub_StrLen n = 0UL; n < nLen; n++ )
237                 {
238                     const unsigned char cChar = aToken.GetChar( n );
239                     const short         nTable = pHexTable[ cChar ];
240 
241                     if( isxdigit( cChar ) || !nTable )
242                     {
243                         nValue = ( nValue << 4 ) + nTable;
244                         nDigits++;
245                         bProcessed = sal_True;
246                     }
247                     else if( ( nTable < 0 ) && nDigits )
248                     {
249                         bProcessed = sal_True;
250                         break;
251                     }
252                 }
253 
254                 if( bProcessed )
255                 {
256                     while( ( nCol < nWidth ) && ( nBit < nBits ) )
257                         pAcc1->SetPixel( nRow, nCol++, ( nValue & ( 1 << nBit++ ) ) ? aBlack : aWhite );
258 
259                     if( nCol == nWidth )
260                         nCol = 0, nRow++;
261                 }
262             }
263         }
264     }
265 
266     return sal_True;
267 }
268 
269 // ------------------------------------------------------------------------
270 
ReadXBM(Graphic & rGraphic)271 ReadState XBMReader::ReadXBM( Graphic& rGraphic )
272 {
273     ReadState   eReadState;
274     sal_uInt8       cDummy;
275 
276     // sehen, ob wir _alles_ lesen koennen
277     rIStm.Seek( STREAM_SEEK_TO_END );
278     rIStm >> cDummy;
279 
280     // falls wir nicht alles lesen koennen
281     // kehren wir zurueck und warten auf neue Daten
282     if ( rIStm.GetError() != ERRCODE_IO_PENDING )
283     {
284         ByteString  aLine;
285         int         nValue;
286 
287         rIStm.Seek( nLastPos );
288         bStatus = sal_False;
289         aLine = FindTokenLine( &rIStm, "#define", "_width" );
290 
291         if ( bStatus )
292         {
293             if ( ( nValue = (int) ParseDefine( aLine.GetBuffer() ) ) > 0 )
294             {
295                 nWidth = nValue;
296                 aLine = FindTokenLine( &rIStm, "#define", "_height" );
297 
298                 // Falls die Hoehe nicht folgt, suchen wir noch
299                 // einmal vom Anfang der Datei an
300                 if ( !bStatus )
301                 {
302                     rIStm.Seek( nLastPos );
303                     aLine = FindTokenLine( &rIStm, "#define", "_height" );
304                 }
305             }
306             else
307                 bStatus = sal_False;
308 
309             if ( bStatus )
310             {
311                 if ( ( nValue = (int) ParseDefine( aLine.GetBuffer() ) ) > 0 )
312                 {
313                     nHeight = nValue;
314                     aLine = FindTokenLine( &rIStm, "static", "_bits" );
315 
316                     if ( bStatus )
317                     {
318                         XBMFormat eFormat = XBM10;
319 
320                         if ( aLine.Search( "short" ) != STRING_NOTFOUND )
321                             eFormat = XBM10;
322                         else if ( aLine.Search( "char" ) != STRING_NOTFOUND )
323                             eFormat = XBM11;
324                         else
325                             bStatus = sal_False;
326 
327                         if ( bStatus && nWidth && nHeight )
328                         {
329                             aBmp1 = Bitmap( Size( nWidth, nHeight ), 1 );
330                             pAcc1 = aBmp1.AcquireWriteAccess();
331 
332                             if( pAcc1 )
333                             {
334                                 aWhite = pAcc1->GetBestMatchingColor( Color( COL_WHITE ) );
335                                 aBlack = pAcc1->GetBestMatchingColor( Color( COL_BLACK ) );
336                                 bStatus = ParseData( &rIStm, aLine, eFormat );
337                             }
338                             else
339                                 bStatus = sal_False;
340                         }
341                     }
342                 }
343             }
344         }
345 
346         if( bStatus )
347         {
348             Bitmap aBlackBmp( Size( pAcc1->Width(), pAcc1->Height() ), 1 );
349 
350             aBmp1.ReleaseAccess( pAcc1 ), pAcc1 = NULL;
351             aBlackBmp.Erase( Color( COL_BLACK ) );
352             rGraphic = BitmapEx( aBlackBmp, aBmp1 );
353             eReadState = XBMREAD_OK;
354         }
355         else
356             eReadState = XBMREAD_ERROR;
357     }
358     else
359     {
360         rIStm.ResetError();
361         eReadState = XBMREAD_NEED_MORE;
362     }
363 
364     return eReadState;
365 }
366 
367 // -------------
368 // - ImportXBM -
369 // -------------
370 
ImportXBM(SvStream & rStm,Graphic & rGraphic)371 sal_Bool ImportXBM( SvStream& rStm, Graphic& rGraphic )
372 {
373     XBMReader*  pXBMReader = (XBMReader*) rGraphic.GetContext();
374     ReadState   eReadState;
375     sal_Bool        bRet = sal_True;
376 
377     if( !pXBMReader )
378         pXBMReader = new XBMReader( rStm );
379 
380     rGraphic.SetContext( NULL );
381     eReadState = pXBMReader->ReadXBM( rGraphic );
382 
383     if( eReadState == XBMREAD_ERROR )
384     {
385         bRet = sal_False;
386         delete pXBMReader;
387     }
388     else if( eReadState == XBMREAD_OK )
389         delete pXBMReader;
390     else
391         rGraphic.SetContext( pXBMReader );
392 
393     return bRet;
394 }
395