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_filter.hxx"
26
27 #include <vcl/graph.hxx>
28 #include <vcl/bmpacc.hxx>
29 #include <svtools/fltcall.hxx>
30
31 //============================ XPMWriter ==================================
32
33 class XPMWriter {
34
35 private:
36
37 SvStream* mpOStm; // Die auszugebende XPM-Datei
38 sal_uInt16 mpOStmOldModus;
39
40 sal_Bool mbStatus;
41 sal_Bool mbTrans;
42 BitmapReadAccess* mpAcc;
43 sal_uLong mnWidth, mnHeight; // Bildausmass in Pixeln
44 sal_uInt16 mnColors;
45
46 com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
47
48 void ImplCallback( sal_uInt16 nPercent );
49 sal_Bool ImplWriteHeader();
50 void ImplWritePalette();
51 void ImplWriteColor( sal_uInt16 );
52 void ImplWriteBody();
53 void ImplWriteNumber( sal_Int32 );
54 void ImplWritePixel( sal_uLong );
55
56 public:
57 XPMWriter();
58 ~XPMWriter();
59
60 sal_Bool WriteXPM( const Graphic& rGraphic, SvStream& rXPM, FilterConfigItem* pFilterConfigItem );
61 };
62
63 //=================== Methoden von XPMWriter ==============================
64
XPMWriter()65 XPMWriter::XPMWriter() :
66 mbStatus ( sal_True ),
67 mbTrans ( sal_False ),
68 mpAcc ( NULL )
69 {
70 }
71
72 // ------------------------------------------------------------------------
73
~XPMWriter()74 XPMWriter::~XPMWriter()
75 {
76 }
77
78 // ------------------------------------------------------------------------
79
ImplCallback(sal_uInt16 nPercent)80 void XPMWriter::ImplCallback( sal_uInt16 nPercent )
81 {
82 if ( xStatusIndicator.is() )
83 {
84 if ( nPercent <= 100 )
85 xStatusIndicator->setValue( nPercent );
86 }
87 }
88
89 // ------------------------------------------------------------------------
90
WriteXPM(const Graphic & rGraphic,SvStream & rXPM,FilterConfigItem * pFilterConfigItem)91 sal_Bool XPMWriter::WriteXPM( const Graphic& rGraphic, SvStream& rXPM, FilterConfigItem* pFilterConfigItem)
92 {
93 Bitmap aBmp;
94
95 mpOStm = &rXPM;
96
97 if ( pFilterConfigItem )
98 {
99 xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
100 if ( xStatusIndicator.is() )
101 {
102 rtl::OUString aMsg;
103 xStatusIndicator->start( aMsg, 100 );
104 }
105 }
106
107 BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
108 aBmp = aBmpEx.GetBitmap();
109
110 if ( rGraphic.IsTransparent() ) // event. transparente Farbe erzeugen
111 {
112 mbTrans = sal_True;
113 if ( aBmp.GetBitCount() >= 8 ) // wenn noetig Bild auf 8 bit konvertieren
114 aBmp.Convert( BMP_CONVERSION_8BIT_TRANS );
115 else
116 aBmp.Convert( BMP_CONVERSION_4BIT_TRANS );
117 aBmp.Replace( aBmpEx.GetMask(), BMP_COL_TRANS );
118 }
119 else
120 {
121 if ( aBmp.GetBitCount() > 8 ) // wenn noetig Bild auf 8 bit konvertieren
122 aBmp.Convert( BMP_CONVERSION_8BIT_COLORS );
123 }
124 mpAcc = aBmp.AcquireReadAccess();
125 if ( mpAcc )
126 {
127 mnColors = mpAcc->GetPaletteEntryCount();
128 mpOStmOldModus = mpOStm->GetNumberFormatInt();
129 mpOStm->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
130
131 if ( ImplWriteHeader() )
132 {
133 ImplWritePalette();
134 ImplWriteBody();
135 *mpOStm << "\x22XPMENDEXT\x22\x0a};";
136 }
137 aBmp.ReleaseAccess( mpAcc );
138 }
139 else
140 mbStatus = sal_False;
141
142 mpOStm->SetNumberFormatInt( mpOStmOldModus );
143
144 if ( xStatusIndicator.is() )
145 xStatusIndicator->end();
146
147 return mbStatus;
148 }
149
150 // ------------------------------------------------------------------------
151
ImplWriteHeader()152 sal_Bool XPMWriter::ImplWriteHeader()
153 {
154 mnWidth = mpAcc->Width();
155 mnHeight = mpAcc->Height();
156 if ( mnWidth && mnHeight && mnColors )
157 {
158 *mpOStm << "/* XPM */\x0astatic char * image[] = \x0a{\x0a\x22";
159 ImplWriteNumber( mnWidth );
160 *mpOStm << (sal_uInt8)32;
161 ImplWriteNumber( mnHeight );
162 *mpOStm << (sal_uInt8)32;
163 ImplWriteNumber( mnColors );
164 *mpOStm << (sal_uInt8)32;
165 ImplWriteNumber( ( mnColors > 26 ) ? 2 : 1 );
166 *mpOStm << "\x22,\x0a";
167 }
168 else mbStatus = sal_False;
169 return mbStatus;
170 }
171
172 // ------------------------------------------------------------------------
173
ImplWritePalette()174 void XPMWriter::ImplWritePalette()
175 {
176 sal_uInt16 nTransIndex = 0xffff;
177
178 if ( mbTrans )
179 nTransIndex = mpAcc->GetBestPaletteIndex( BMP_COL_TRANS );
180 for ( sal_uInt16 i = 0; i < mnColors; i++ )
181 {
182 *mpOStm << "\x22";
183 ImplWritePixel( i );
184 *mpOStm << (sal_uInt8)32;
185 if ( nTransIndex != i )
186 {
187 ImplWriteColor( i );
188 *mpOStm << "\x22,\x0a";
189 }
190 else
191 *mpOStm << "c none\x22,\x0a";
192 }
193 }
194
195 // ------------------------------------------------------------------------
196
ImplWriteBody()197 void XPMWriter::ImplWriteBody()
198 {
199 for ( sal_uLong y = 0; y < mnHeight; y++ )
200 {
201 ImplCallback( (sal_uInt16)( ( 100 * y ) / mnHeight ) ); // processing output in percent
202 *mpOStm << (sal_uInt8)0x22;
203 for ( sal_uLong x = 0; x < mnWidth; x++ )
204 {
205 ImplWritePixel( mpAcc->GetPixelIndex( y, x ) );
206 }
207 *mpOStm << "\x22,\x0a";
208 }
209 }
210
211 // ------------------------------------------------------------------------
212 // eine Dezimalzahl im ASCII format wird in den Stream geschrieben
213
ImplWriteNumber(sal_Int32 nNumber)214 void XPMWriter::ImplWriteNumber( sal_Int32 nNumber )
215 {
216 const ByteString aNum( ByteString::CreateFromInt32( nNumber ) );
217
218 for( sal_Int16 n = 0UL, nLen = aNum.Len(); n < nLen; n++ )
219 *mpOStm << aNum.GetChar( n );
220
221 }
222
223 // ------------------------------------------------------------------------
224
ImplWritePixel(sal_uLong nCol)225 void XPMWriter::ImplWritePixel( sal_uLong nCol )
226 {
227 if ( mnColors > 26 )
228 {
229 sal_uInt8 nDiff = (sal_uInt8) ( nCol / 26 );
230 *mpOStm << (sal_uInt8)( nDiff + 'A' );
231 *mpOStm << (sal_uInt8)( nCol - ( nDiff*26 ) + 'A' );
232 }
233 else
234 *mpOStm << (sal_uInt8)( nCol + 'A' );
235 }
236
237 // ------------------------------------------------------------------------
238 // ein Farbwert wird im Hexadezimalzahlformat in den Stream geschrieben
ImplWriteColor(sal_uInt16 nNumber)239 void XPMWriter::ImplWriteColor( sal_uInt16 nNumber )
240 {
241 sal_uLong nTmp;
242 sal_uInt8 j;
243
244 *mpOStm << "c #"; // # zeigt einen folgenden Hexwert an
245 const BitmapColor& rColor = mpAcc->GetPaletteColor( nNumber );
246 nTmp = ( rColor.GetRed() << 16 ) | ( rColor.GetGreen() << 8 ) | rColor.GetBlue();
247 for ( signed char i = 20; i >= 0 ; i-=4 )
248 {
249 if ( ( j = (sal_uInt8)( nTmp >> i ) & 0xf ) > 9 )
250 j += 'A' - 10;
251 else
252 j += '0';
253 *mpOStm << j;
254 }
255 }
256
257 // ------------------------------------------------------------------------
258
259 // ---------------------
260 // - exported function -
261 // ---------------------
262
GraphicExport(SvStream & rStream,Graphic & rGraphic,FilterConfigItem * pFilterConfigItem,sal_Bool)263 extern "C" sal_Bool __LOADONCALLAPI GraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool )
264 {
265 XPMWriter aXPMWriter;
266
267 return aXPMWriter.WriteXPM( rGraphic, rStream, pFilterConfigItem );
268 }
269
270