xref: /aoo41x/main/editeng/source/rtf/rtfgrf.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_editeng.hxx"
30 
31 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
32 #include <osl/endian.h>
33 #include <tools/cachestr.hxx>
34 #include <vcl/graph.hxx>
35 #include <vcl/svapp.hxx>
36 #include <svtools/rtfkeywd.hxx>
37 #include <svtools/rtftoken.h>
38 #include <svtools/filter.hxx>
39 
40 #include <editeng/svxrtf.hxx>
41 
42 using namespace ::rtl;
43 
44 #ifndef DBG_UTIL
45 #undef DEBUG_JP
46 #endif
47 
48 #ifdef DEBUG_JP
49 
50 #include <tools/fsys.hxx>
51 
52 class GrfWindow : public WorkWindow
53 {
54 	Graphic aGrf;
55 public:
56 	GrfWindow( const Graphic& rGrf );
57 	virtual void    Paint( const Rectangle& rRect );
58 };
59 
60 GrfWindow::GrfWindow( const Graphic& rGrf )
61 	: WorkWindow( NULL ),
62 	aGrf( rGrf )
63 {
64 	SetPosSizePixel( Point( 100, 0 ), Size( 300, 300 ));
65 	Show();
66 	Invalidate();
67 	Update();
68 }
69 
70 void GrfWindow::Paint( const Rectangle& )
71 {
72 	aGrf.Draw( this, Point(0,0), GetSizePixel() );
73 }
74 #endif
75 
76 static sal_uInt8 __FAR_DATA aPal1[ 2 * 4 ] = {
77 		0x00, 0x00, 0x00, 0x00,				// Schwarz
78 		0xFF, 0xFF, 0xFF, 0x00				// Weiss
79 };
80 
81 static sal_uInt8 __FAR_DATA aPal4[ 16 * 4 ] = {
82 		0x00, 0x00, 0x00, 0x00,
83 		0x80, 0x00, 0x00, 0x00,
84 		0x00, 0x80, 0x00, 0x00,
85 		0x80, 0x80, 0x00, 0x00,
86 		0x00, 0x00, 0x80, 0x00,
87 		0x80, 0x00, 0x80, 0x00,
88 		0x00, 0x80, 0x80, 0x00,
89 		0x80, 0x80, 0x80, 0x00,
90 		0xC0, 0xC0, 0xC0, 0x00,
91 		0xFF, 0x00, 0x00, 0x00,
92 		0x00, 0xFF, 0x00, 0x00,
93 		0xFF, 0xFF, 0x00, 0x00,
94 		0x00, 0x00, 0xFF, 0x00,
95 		0xFF, 0x00, 0xFF, 0x00,
96 		0x00, 0xFF, 0xFF, 0x00,
97 		0xFF, 0xFF, 0xFF, 0x00
98 };
99 
100 static sal_uInt8 __FAR_DATA aPal8[ 256 * 4 ] =
101 {
102 0x00, 0x00, 0x00, 0x00,   0x80, 0x00, 0x00, 0x00,   0x00, 0x92, 0x00, 0x00,
103 0x80, 0x92, 0x00, 0x00,   0x00, 0x00, 0xAA, 0x00,   0x80, 0x00, 0xAA, 0x00,
104 0x00, 0x92, 0xAA, 0x00,   0xC1, 0xC1, 0xC1, 0x00,   0xC9, 0xC9, 0xC9, 0x00,
105 0xAA, 0xDB, 0xFF, 0x00,   0x00, 0x49, 0xAA, 0x00,   0x00, 0x49, 0xFF, 0x00,
106 0x00, 0x6D, 0x00, 0x00,   0x00, 0x6D, 0x55, 0x00,   0x00, 0x6D, 0xAA, 0x00,
107 0x00, 0x6D, 0xFF, 0x00,   0x00, 0x24, 0x00, 0x00,   0x00, 0x92, 0x55, 0x00,
108 0x00, 0x24, 0xAA, 0x00,   0x00, 0x92, 0xFF, 0x00,   0x00, 0xB6, 0x00, 0x00,
109 0x00, 0xB6, 0x55, 0x00,   0x00, 0xB6, 0xAA, 0x00,   0x00, 0xB6, 0xFF, 0x00,
110 0x00, 0xDB, 0x00, 0x00,   0x00, 0xDB, 0x55, 0x00,   0x00, 0xDB, 0xAA, 0x00,
111 0x00, 0xDB, 0xFF, 0x00,   0xFF, 0xDB, 0xAA, 0x00,   0x00, 0xFF, 0x55, 0x00,
112 0x00, 0xFF, 0xAA, 0x00,   0xFF, 0xFF, 0xAA, 0x00,   0x2B, 0x00, 0x00, 0x00,
113 0x2B, 0x00, 0x55, 0x00,   0x2B, 0x00, 0xAA, 0x00,   0x2B, 0x00, 0xFF, 0x00,
114 0x2B, 0x24, 0x00, 0x00,   0x2B, 0x24, 0x55, 0x00,   0x2B, 0x24, 0xAA, 0x00,
115 0x2B, 0x24, 0xFF, 0x00,   0x2B, 0x49, 0x00, 0x00,   0x2B, 0x49, 0x55, 0x00,
116 0x2B, 0x49, 0xAA, 0x00,   0x2B, 0x49, 0xFF, 0x00,   0x2B, 0x6D, 0x00, 0x00,
117 0x2B, 0x6D, 0x55, 0x00,   0x2B, 0x6D, 0xAA, 0x00,   0x2B, 0x6D, 0xFF, 0x00,
118 0x2B, 0x92, 0x00, 0x00,   0x2B, 0x92, 0x55, 0x00,   0x2B, 0x92, 0xAA, 0x00,
119 0x2B, 0x92, 0xFF, 0x00,   0x2B, 0xB6, 0x00, 0x00,   0x2B, 0xB6, 0x55, 0x00,
120 0x2B, 0xB6, 0xAA, 0x00,   0x2B, 0xB6, 0xFF, 0x00,   0x2B, 0xDB, 0x00, 0x00,
121 0x2B, 0xDB, 0x55, 0x00,   0x2B, 0xDB, 0xAA, 0x00,   0x2B, 0xDB, 0xFF, 0x00,
122 0x2B, 0xFF, 0x00, 0x00,   0x2B, 0xFF, 0x55, 0x00,   0x2B, 0xFF, 0xAA, 0x00,
123 0x2B, 0xFF, 0xFF, 0x00,   0x55, 0x00, 0x00, 0x00,   0x55, 0x00, 0x55, 0x00,
124 0x55, 0x00, 0xAA, 0x00,   0x55, 0x00, 0xFF, 0x00,   0x55, 0x24, 0x00, 0x00,
125 0x55, 0x24, 0x55, 0x00,   0x55, 0x24, 0xAA, 0x00,   0x55, 0x24, 0xFF, 0x00,
126 0x55, 0x49, 0x00, 0x00,   0x55, 0x49, 0x55, 0x00,   0x55, 0x49, 0xAA, 0x00,
127 0x55, 0x49, 0xFF, 0x00,   0x55, 0x6D, 0x00, 0x00,   0x55, 0x6D, 0x55, 0x00,
128 0x55, 0x6D, 0xAA, 0x00,   0x55, 0x6D, 0xFF, 0x00,   0x55, 0x92, 0x00, 0x00,
129 0x55, 0x92, 0x55, 0x00,   0x55, 0x92, 0xAA, 0x00,   0x55, 0x92, 0xFF, 0x00,
130 0x55, 0xB6, 0x00, 0x00,   0x55, 0xB6, 0x55, 0x00,   0x55, 0xB6, 0xAA, 0x00,
131 0x55, 0xB6, 0xFF, 0x00,   0x55, 0xDB, 0x00, 0x00,   0x55, 0xDB, 0x55, 0x00,
132 0x55, 0xDB, 0xAA, 0x00,   0x55, 0xDB, 0xFF, 0x00,   0x55, 0xFF, 0x00, 0x00,
133 0x55, 0xFF, 0x55, 0x00,   0x55, 0xFF, 0xAA, 0x00,   0x55, 0xFF, 0xFF, 0x00,
134 0x00, 0x00, 0x55, 0x00,   0x80, 0x00, 0x55, 0x00,   0x00, 0x24, 0x55, 0x00,
135 0x80, 0x00, 0xFF, 0x00,   0x80, 0x24, 0x00, 0x00,   0x80, 0x24, 0x55, 0x00,
136 0x80, 0x24, 0xAA, 0x00,   0x80, 0x24, 0xFF, 0x00,   0x80, 0x49, 0x00, 0x00,
137 0x80, 0x49, 0x55, 0x00,   0x80, 0x49, 0xAA, 0x00,   0x80, 0x49, 0xFF, 0x00,
138 0x80, 0x6D, 0x00, 0x00,   0x80, 0x6D, 0x55, 0x00,   0x80, 0x6D, 0xAA, 0x00,
139 0x80, 0x6D, 0xFF, 0x00,   0x08, 0x08, 0x08, 0x00,   0x0F, 0x0F, 0x0F, 0x00,
140 0x17, 0x17, 0x17, 0x00,   0x1F, 0x1F, 0x1F, 0x00,   0x27, 0x27, 0x27, 0x00,
141 0x2E, 0x2E, 0x2E, 0x00,   0x36, 0x36, 0x36, 0x00,   0x3E, 0x3E, 0x3E, 0x00,
142 0x46, 0x46, 0x46, 0x00,   0x4D, 0x4D, 0x4D, 0x00,   0x55, 0x55, 0x55, 0x00,
143 0x5D, 0x5D, 0x5D, 0x00,   0x64, 0x64, 0x64, 0x00,   0x6C, 0x6C, 0x6C, 0x00,
144 0x74, 0x74, 0x74, 0x00,   0x7C, 0x7C, 0x7C, 0x00,   0xFF, 0xDB, 0x00, 0x00,
145 0x8B, 0x8B, 0x8B, 0x00,   0x93, 0x93, 0x93, 0x00,   0x9B, 0x9B, 0x9B, 0x00,
146 0xFF, 0xB6, 0xFF, 0x00,   0xAA, 0xAA, 0xAA, 0x00,   0xB2, 0xB2, 0xB2, 0x00,
147 0xB9, 0xB9, 0xB9, 0x00,   0x00, 0x24, 0xFF, 0x00,   0x00, 0x49, 0x00, 0x00,
148 0xD1, 0xD1, 0xD1, 0x00,   0xD8, 0xD8, 0xD8, 0x00,   0xE0, 0xE0, 0xE0, 0x00,
149 0xE8, 0xE8, 0xE8, 0x00,   0xF0, 0xF0, 0xF0, 0x00,   0xFF, 0xB6, 0xAA, 0x00,
150 0xFF, 0xDB, 0xFF, 0x00,   0x80, 0x92, 0x55, 0x00,   0x80, 0x92, 0xAA, 0x00,
151 0x80, 0x92, 0xFF, 0x00,   0x80, 0xB6, 0x00, 0x00,   0x80, 0xB6, 0x55, 0x00,
152 0x80, 0xB6, 0xAA, 0x00,   0x80, 0xB6, 0xFF, 0x00,   0x80, 0xDB, 0x00, 0x00,
153 0x80, 0xDB, 0x55, 0x00,   0x80, 0xDB, 0xAA, 0x00,   0x80, 0xDB, 0xFF, 0x00,
154 0x80, 0xFF, 0x00, 0x00,   0x80, 0xFF, 0x55, 0x00,   0x80, 0xFF, 0xAA, 0x00,
155 0x80, 0xFF, 0xFF, 0x00,   0xAA, 0x00, 0x00, 0x00,   0xAA, 0x00, 0x55, 0x00,
156 0xAA, 0x00, 0xAA, 0x00,   0xAA, 0x00, 0xFF, 0x00,   0xAA, 0x24, 0x00, 0x00,
157 0xAA, 0x24, 0x55, 0x00,   0xAA, 0x24, 0xAA, 0x00,   0xAA, 0x24, 0xFF, 0x00,
158 0xAA, 0x49, 0x00, 0x00,   0xAA, 0x49, 0x55, 0x00,   0xAA, 0x49, 0xAA, 0x00,
159 0xAA, 0x49, 0xFF, 0x00,   0xAA, 0x6D, 0x00, 0x00,   0xAA, 0x6D, 0x55, 0x00,
160 0xAA, 0x6D, 0xAA, 0x00,   0xAA, 0x6D, 0xFF, 0x00,   0xAA, 0x92, 0x00, 0x00,
161 0xAA, 0x92, 0x55, 0x00,   0xAA, 0x92, 0xAA, 0x00,   0xAA, 0x92, 0xFF, 0x00,
162 0xAA, 0xB6, 0x00, 0x00,   0xAA, 0xB6, 0x55, 0x00,   0xAA, 0xB6, 0xAA, 0x00,
163 0xAA, 0xB6, 0xFF, 0x00,   0xAA, 0xDB, 0x00, 0x00,   0xAA, 0xDB, 0x55, 0x00,
164 0xAA, 0xDB, 0xAA, 0x00,   0x00, 0x49, 0x55, 0x00,   0xAA, 0xFF, 0x00, 0x00,
165 0xAA, 0xFF, 0x55, 0x00,   0xAA, 0xFF, 0xAA, 0x00,   0xAA, 0xFF, 0xFF, 0x00,
166 0xD5, 0x00, 0x00, 0x00,   0xD5, 0x00, 0x55, 0x00,   0xD5, 0x00, 0xAA, 0x00,
167 0xD5, 0x00, 0xFF, 0x00,   0xD5, 0x24, 0x00, 0x00,   0xD5, 0x24, 0x55, 0x00,
168 0xD5, 0x24, 0xAA, 0x00,   0xD5, 0x24, 0xFF, 0x00,   0xD5, 0x49, 0x00, 0x00,
169 0xD5, 0x49, 0x55, 0x00,   0xD5, 0x49, 0xAA, 0x00,   0xD5, 0x49, 0xFF, 0x00,
170 0xD5, 0x6D, 0x00, 0x00,   0xD5, 0x6D, 0x55, 0x00,   0xD5, 0x6D, 0xAA, 0x00,
171 0xD5, 0x6D, 0xFF, 0x00,   0xD5, 0x92, 0x00, 0x00,   0xD5, 0x92, 0x55, 0x00,
172 0xD5, 0x92, 0xAA, 0x00,   0xD5, 0x92, 0xFF, 0x00,   0xD5, 0xB6, 0x00, 0x00,
173 0xD5, 0xB6, 0x55, 0x00,   0xD5, 0xB6, 0xAA, 0x00,   0xD5, 0xB6, 0xFF, 0x00,
174 0xD5, 0xDB, 0x00, 0x00,   0xD5, 0xDB, 0x55, 0x00,   0xD5, 0xDB, 0xAA, 0x00,
175 0xD5, 0xDB, 0xFF, 0x00,   0xD5, 0xFF, 0x00, 0x00,   0xD5, 0xFF, 0x55, 0x00,
176 0xD5, 0xFF, 0xAA, 0x00,   0xD5, 0xFF, 0xFF, 0x00,   0xFF, 0xDB, 0x55, 0x00,
177 0xFF, 0x00, 0x55, 0x00,   0xFF, 0x00, 0xAA, 0x00,   0xFF, 0xFF, 0x55, 0x00,
178 0xFF, 0x24, 0x00, 0x00,   0xFF, 0x24, 0x55, 0x00,   0xFF, 0x24, 0xAA, 0x00,
179 0xFF, 0x24, 0xFF, 0x00,   0xFF, 0x49, 0x00, 0x00,   0xFF, 0x49, 0x55, 0x00,
180 0xFF, 0x49, 0xAA, 0x00,   0xFF, 0x49, 0xFF, 0x00,   0xFF, 0x6D, 0x00, 0x00,
181 0xFF, 0x6D, 0x55, 0x00,   0xFF, 0x6D, 0xAA, 0x00,   0xFF, 0x6D, 0xFF, 0x00,
182 0xFF, 0x92, 0x00, 0x00,   0xFF, 0x92, 0x55, 0x00,   0xFF, 0x92, 0xAA, 0x00,
183 0xFF, 0x92, 0xFF, 0x00,   0xFF, 0xB6, 0x00, 0x00,   0xFF, 0xB6, 0x55, 0x00,
184 0xF7, 0xF7, 0xF7, 0x00,   0xA2, 0xA2, 0xA2, 0x00,   0x83, 0x83, 0x83, 0x00,
185 0xFF, 0x00, 0x00, 0x00,   0x00, 0xFF, 0x00, 0x00,   0xFF, 0xFF, 0x00, 0x00,
186 0x00, 0x00, 0xFF, 0x00,   0xFF, 0x00, 0xFF, 0x00,   0x00, 0xFF, 0xFF, 0x00,
187 0xFF, 0xFF, 0xFF, 0x00
188 };
189 
190 
191 /*  */
192 
193 
194 inline long SwapLong( long n )
195 {
196 #ifndef OSL_LITENDIAN
197 	return SWAPLONG( n );
198 #else
199 	return n;
200 #endif
201 }
202 
203 inline short SwapShort( short n )
204 {
205 #ifndef OSL_LITENDIAN
206 	return SWAPSHORT( n );
207 #else
208 	return n;
209 #endif
210 }
211 
212 
213 static void WriteBMPHeader( SvStream& rStream,
214 							const SvxRTFPictureType& rPicType )
215 {
216 	sal_uInt32 n4Width = rPicType.nWidth;
217 	sal_uInt32 n4Height = rPicType.nHeight;
218 	sal_uInt16 n4ColBits = rPicType.nBitsPerPixel;
219 
220 	sal_uInt16 nColors = (1 << n4ColBits);	// Anzahl der Farben ( 1, 16, 256 )
221 	sal_uInt16 nWdtOut = rPicType.nWidthBytes;
222 	if( !nWdtOut )
223 		nWdtOut = (sal_uInt16)((( n4Width * n4ColBits + 31 ) / 32 ) * 4 );
224 
225 	long nOffset = 14 + 40; 	// BMP_FILE_HD_SIZ + sizeof(*pBmpInfo);
226 	if( 256 >= nColors )
227 		nOffset += nColors * 4;
228 	long nSize = nOffset + nWdtOut * n4Height;
229 	rStream << "BM"						// = "BM"
230 			<< SwapLong(nSize)          // Filesize in Bytes
231 			<< SwapShort(0)             // Reserviert
232 			<< SwapShort(0)             // Reserviert
233 			<< SwapLong(nOffset);       // Offset?
234 
235 	rStream	<< SwapLong(40)				// sizeof( BmpInfo )
236 			<< SwapLong(n4Width)
237 			<< SwapLong(n4Height)
238 			<< (sal_uInt16)1
239 			<< n4ColBits
240 			<< SwapLong(0)
241 			<< SwapLong(0)
242 			<< SwapLong( rPicType.nGoalWidth
243 						? rPicType.nGoalWidth * 1000L / 254L
244 						: 0 )	      // DPI in Pixel per Meter
245 			<< SwapLong( rPicType.nGoalHeight
246 						? rPicType.nGoalHeight * 1000L / 254L      // dito
247 						: 0 )
248 			<< SwapLong(0)
249 			<< SwapLong(0);
250 
251 
252 	switch( rPicType.nBitsPerPixel )
253 	{
254 	case 1:		rStream.Write( aPal1, sizeof( aPal1 ));	break;
255 	case 4:		rStream.Write( aPal4, sizeof( aPal4 ));	break;
256 	case 8:		rStream.Write( aPal8, sizeof( aPal8 ));	break;
257 	}
258 }
259 
260 /*  */
261 
262 		// wandel die ASCII-HexCodes in binaere Zeichen um. Werden
263 		// ungueltige Daten gefunden (Zeichen ausser 0-9|a-f|A-F, so
264 		// wird USHRT_MAX returnt, ansonsten die Anzahl der umgewandelten Ze.
265 xub_StrLen SvxRTFParser::HexToBin( String& rToken )
266 {
267 	// dann mache aus den Hex-Werten mal "Binare Daten"
268 	// (missbrauche den String als temp Buffer)
269 	if( rToken.Len() & 1 )		// ungerade Anzahl, mit 0 auffuellen
270 		rToken += '0';
271 
272 	xub_StrLen n, nLen;
273 	sal_Unicode nVal;
274 	sal_Bool bValidData = sal_True;
275 	const sal_Unicode* pStr = rToken.GetBufferAccess();
276 	sal_Char* pData = (sal_Char*)pStr;
277 	for( n = 0, nLen = rToken.Len(); n < nLen; ++n, ++pStr )
278 	{
279 		if( ((nVal = *pStr) >= '0') && ( nVal <= '9') )
280 			nVal -= '0';
281 		else if( (nVal >= 'A') && (nVal <= 'F') )
282 			nVal -= 'A' - 10;
283 		else if( (nVal >= 'a') && (nVal <= 'f') )
284 			nVal -= 'a' - 10;
285 		else
286 		{
287 			DBG_ASSERT( !this, "ungueltiger Hex-Wert" );
288 			bValidData = sal_False;
289 			break;
290 		}
291 
292 		if( n & 1 )
293 			*(pData++) |= nVal & 0x0f;
294 		else
295 			*(pData) = sal::static_int_cast< char >( ( nVal << 4 ) & 0xf0 );
296 	}
297 	// the len div 2, because 2 character are one byte
298 	return bValidData ? nLen / 2  : STRING_NOTFOUND;
299 }
300 
301 sal_Bool SvxRTFParser::ReadBmpData( Graphic& rGrf, SvxRTFPictureType& rPicType )
302 {
303 	// die alten Daten loeschen
304 	rGrf.Clear();
305 //	sal_uInt32 nBmpSize = 0;
306 
307 	rtl_TextEncoding eOldEnc = GetSrcEncoding();
308 	SetSrcEncoding( RTL_TEXTENCODING_MS_1252 );
309 
310 	const sal_Char* pFilterNm = 0;
311 	SvCacheStream* pTmpFile = 0;
312 
313 	int nToken = 0;
314     bool bValidBmp = true, bFirstTextToken = true;
315 	int _nOpenBrakets = 1,		// die erste wurde schon vorher erkannt !!
316 		nValidDataBraket = 1;
317 
318 	if( RTF_SHPPICT == GetStackPtr(0)->nTokenId )
319 		++nValidDataBraket;
320     OUString sShapePropertyName, sShapePropertyValue;
321     int nShapePropertyBracket = -1;
322 	while( _nOpenBrakets && IsParserWorking() && bValidBmp )
323 	{
324 		nToken = GetNextToken();
325 		sal_uInt16 nVal = sal_uInt16( nTokenValue );
326 		switch( nToken )
327 		{
328         case '}':
329             --_nOpenBrakets;
330             if( nShapePropertyBracket > 0 && nShapePropertyBracket > _nOpenBrakets )
331             {
332                 nShapePropertyBracket = -1;
333                 if( sShapePropertyName.getLength() )
334                 {
335                     rPicType.aPropertyPairs.push_back( ::std::pair< OUString, OUString >( sShapePropertyName, sShapePropertyValue ) );
336                     sShapePropertyName = sShapePropertyValue = ::rtl::OUString();
337                 }
338             }
339         break;
340 		case '{':
341 			{
342 				if( RTF_IGNOREFLAG != GetNextToken() )
343 					nToken = SkipToken( -1 );
344 				else if( RTF_UNKNOWNCONTROL != GetNextToken() )
345 					nToken = SkipToken( -2 );
346 				else
347 				{
348 					// gleich herausfiltern
349 					ReadUnknownData();
350 					nToken = GetNextToken();
351 					if( '}' != nToken )
352 						eState = SVPAR_ERROR;
353 					break;
354 				}
355 				++_nOpenBrakets;
356 			}
357 			break;
358 
359 		case RTF_MACPICT:
360 			{
361 				rPicType.eStyle = SvxRTFPictureType::MAC_QUICKDRAW;
362 				// Mac-Pict bekommt einen leeren Header voran
363 				pTmpFile = new SvCacheStream;
364 				ByteString aStr;
365 				aStr.Fill( 512, '\0' );
366 				pTmpFile->Write( aStr.GetBuffer(), aStr.Len() );
367 				pFilterNm = "PCT";
368 			}
369 			break;
370 
371 		case RTF_EMFBLIP:
372 		case RTF_WMETAFILE:
373 		case RTF_PNGBLIP:
374 		case RTF_JPEGBLIP:
375 		case RTF_WBITMAP:
376 		case RTF_OSMETAFILE:
377 		case RTF_DIBITMAP:
378 			{
379 				switch( nToken )
380 				{
381 				case RTF_EMFBLIP:
382 					rPicType.eStyle = SvxRTFPictureType::ENHANCED_MF;
383 					pFilterNm = "EMF";
384 					break;
385 				case RTF_WMETAFILE:
386 					rPicType.eStyle = SvxRTFPictureType::WIN_METAFILE;
387 					pFilterNm = "WMF";
388 					break;
389 				case RTF_PNGBLIP:
390 					rPicType.eStyle = SvxRTFPictureType::RTF_PNG;
391 					pFilterNm = "PNG";
392 					break;
393 				case RTF_JPEGBLIP:
394 					rPicType.eStyle = SvxRTFPictureType::RTF_JPG;
395 					pFilterNm = "JPG";
396 					break;
397 
398 				case RTF_WBITMAP:
399 					rPicType.eStyle = SvxRTFPictureType::RTF_BITMAP;
400 					break;
401 				case RTF_OSMETAFILE:
402 					rPicType.eStyle = SvxRTFPictureType::OS2_METAFILE;
403 					break;
404 				case RTF_DIBITMAP:
405 					rPicType.eStyle = SvxRTFPictureType::RTF_DI_BMP;
406 					break;
407 				}
408 
409 				rPicType.nType = nVal;
410 				pTmpFile = new SvCacheStream;
411 			}
412 			break;
413 
414 		case RTF_PICW:				rPicType.nWidth = nVal; break;
415 		case RTF_PICH:				rPicType.nHeight = nVal; break;
416 		case RTF_WBMBITSPIXEL:		rPicType.nBitsPerPixel = nVal; break;
417 		case RTF_WBMPLANES: 		rPicType.nPlanes = nVal; break;
418 		case RTF_WBMWIDTHBYTES:		rPicType.nWidthBytes = nVal; break;
419 		case RTF_PICWGOAL:			rPicType.nGoalWidth = nVal; break;
420 		case RTF_PICHGOAL:			rPicType.nGoalHeight = nVal; break;
421 		case RTF_BIN:
422             rPicType.nMode = SvxRTFPictureType::BINARY_MODE;
423 			rPicType.uPicLen = nTokenValue;
424             if (rPicType.uPicLen)
425             {
426                 sal_uInt32 nPos = rStrm.Tell();
427                 nPos = nPos;
428                 rStrm.SeekRel(-1);
429                 sal_uInt8 aData[4096];
430                 sal_uInt32 nSize = sizeof(aData);
431 
432                 while (rPicType.uPicLen > 0)
433                 {
434                     if (rPicType.uPicLen < nSize)
435                         nSize = rPicType.uPicLen;
436 
437                     rStrm.Read(aData, nSize);
438                     pTmpFile->Write(aData, nSize);
439                     rPicType.uPicLen -= nSize;
440                 }
441                 nNextCh = GetNextChar();
442                 bValidBmp = !pTmpFile->GetError();
443                 nPos = rStrm.Tell();
444                 nPos = nPos;
445             }
446             break;
447 		case RTF_PICSCALEX:			rPicType.nScalX = nVal; break;
448 		case RTF_PICSCALEY:			rPicType.nScalY = nVal; break;
449 		case RTF_PICSCALED: 		break;
450 
451 		case RTF_PICCROPT:			rPicType.nCropT = (short)nTokenValue; break;
452 		case RTF_PICCROPB:			rPicType.nCropB = (short)nTokenValue; break;
453 		case RTF_PICCROPL:			rPicType.nCropL = (short)nTokenValue; break;
454 		case RTF_PICCROPR:			rPicType.nCropR = (short)nTokenValue; break;
455         case RTF_SP:
456             //read pairs of {\sn Name}{\sv Value}
457             nShapePropertyBracket = _nOpenBrakets;
458         break;
459         case RTF_SN:
460             nToken = GetNextToken();
461             if( nToken != '}' )
462                 sShapePropertyName = aToken;
463             else
464                 nToken = SkipToken( -1 );
465         break;
466         case RTF_SV:
467             nToken = GetNextToken();
468             if( nToken != '}' )
469                 sShapePropertyValue = aToken;
470             else
471                 nToken = SkipToken( -1 );
472         break;
473 		case RTF_TEXTTOKEN:
474 			// JP 26.06.98: Bug #51719# - nur TextToken auf 1. Ebene
475 			//				auswerten. Alle anderen sind irgendwelche
476 			//				nicht auszuwertende Daten
477 			if( nValidDataBraket != _nOpenBrakets )
478 				break;
479 
480 			if( bFirstTextToken )
481 			{
482 				switch( rPicType.eStyle )
483 				{
484 				case SvxRTFPictureType::RTF_BITMAP:
485 					// erstmal die Header und Info-Struktur schreiben
486 					if( pTmpFile )
487 						::WriteBMPHeader( *pTmpFile, rPicType );
488 					break;
489 				default:
490 					break;
491 				}
492 				bFirstTextToken = sal_False;
493 			}
494 
495 			if( pTmpFile && SvxRTFPictureType::HEX_MODE == rPicType.nMode )
496 			{
497 				xub_StrLen nTokenLen = HexToBin( aToken );
498 				if( STRING_NOTFOUND == nTokenLen )
499 					bValidBmp = sal_False;
500 				else
501 				{
502 					pTmpFile->Write( (sal_Char*)aToken.GetBuffer(),
503 										nTokenLen );
504 					bValidBmp = 0 == pTmpFile->GetError();
505 				}
506 			}
507 			break;
508 		}
509 	}
510 
511 	if (pTmpFile)
512 	{
513         //#i20775#
514         if (pTmpFile->Tell() == 0)
515             bValidBmp = false;
516 
517 		if( bValidBmp )
518 		{
519 			GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
520 			sal_uInt16 nImportFilter = GRFILTER_FORMAT_DONTKNOW;
521 
522 			if( pFilterNm )
523 			{
524 				String sTmp;
525 				for( sal_uInt16 n = pGF->GetImportFormatCount(); n; )
526 				{
527 					sTmp = pGF->GetImportFormatShortName( --n );
528 					if( sTmp.EqualsAscii( pFilterNm ))
529 					{
530 						nImportFilter = n;
531 						break;
532 					}
533 				}
534 			}
535 
536 			String sTmpStr;
537 			pTmpFile->Seek( STREAM_SEEK_TO_BEGIN );
538 			bValidBmp = 0 == pGF->ImportGraphic( rGrf, sTmpStr, *pTmpFile,
539 												nImportFilter );
540 		}
541 		delete pTmpFile;
542 	}
543 
544 	if( !bValidBmp )
545 	{
546 		rGrf.Clear();
547         //TODO  If nToken were not initialized to 0 above, it would potentially
548         // be used uninitialized here (if IsParserWorking() is false at the
549         // start of the while loop above):
550 		if( '}' != nToken )
551 			SkipGroup();
552 	}
553 	else
554 	{
555 		switch( rPicType.eStyle )
556 		{
557 //??		ENHANCED_MF,		// in den Pict.Daten steht ein Enhanced-Metafile
558 		case SvxRTFPictureType::RTF_PNG:
559 		case SvxRTFPictureType::RTF_JPG:
560 			{
561 				const MapMode aMap( MAP_100TH_MM );
562 			 	Size aSize( rGrf.GetPrefSize() );
563 				if( MAP_PIXEL == rGrf.GetPrefMapMode().GetMapUnit() )
564 					aSize = Application::GetDefaultDevice()->PixelToLogic(
565 										aSize, aMap );
566 				else
567 					aSize = OutputDevice::LogicToLogic( aSize,
568 										rGrf.GetPrefMapMode(), aMap );
569 				rPicType.nWidth = sal::static_int_cast< sal_uInt16 >(aSize.Width());
570 				rPicType.nHeight = sal::static_int_cast< sal_uInt16 >(
571                     aSize.Height());
572 			}
573 			break;
574 		default:
575 			break;
576 		}
577 
578 #ifdef DEBUG_JP
579 		new GrfWindow( rGrf );
580 #endif
581 	}
582 	SetSrcEncoding( eOldEnc );
583 
584 	SkipToken( -1 );		// die schliesende Klammer wird "oben" ausgewertet
585 	return bValidBmp;
586 }
587 
588 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
589