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