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