1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <vcl/graph.hxx>
22 #include <vcl/bmpacc.hxx>
23 #include <vcl/fltcall.hxx>
25 //============================ XPMWriter ==================================
31 SvStream
& m_rOStm
; // the output XPM file
35 BitmapReadAccess
* mpAcc
;
36 sal_uLong mnWidth
, mnHeight
; // size in Pixel
39 com::sun::star::uno::Reference
< com::sun::star::task::XStatusIndicator
> xStatusIndicator
;
41 void ImplCallback( sal_uInt16 nPercent
);
42 bool ImplWriteHeader();
43 void ImplWritePalette();
44 void ImplWriteColor( sal_uInt16
);
46 void ImplWriteNumber( sal_Int32
);
47 void ImplWritePixel( sal_uLong
) const;
50 XPMWriter(SvStream
& rOStm
);
53 bool WriteXPM( const Graphic
& rGraphic
, FilterConfigItem
* pFilterConfigItem
);
56 //=================== Methoden von XPMWriter ==============================
58 XPMWriter::XPMWriter(SvStream
& rOStm
)
71 XPMWriter::~XPMWriter()
77 void XPMWriter::ImplCallback( sal_uInt16 nPercent
)
79 if ( xStatusIndicator
.is() )
81 if ( nPercent
<= 100 )
82 xStatusIndicator
->setValue( nPercent
);
88 bool XPMWriter::WriteXPM( const Graphic
& rGraphic
, FilterConfigItem
* pFilterConfigItem
)
92 if ( pFilterConfigItem
)
94 xStatusIndicator
= pFilterConfigItem
->GetStatusIndicator();
95 if ( xStatusIndicator
.is() )
98 xStatusIndicator
->start( aMsg
, 100 );
102 BitmapEx
aBmpEx( rGraphic
.GetBitmapEx() );
103 aBmp
= aBmpEx
.GetBitmap();
105 if ( rGraphic
.IsTransparent() ) // possibly create transparent color
108 if ( aBmp
.GetBitCount() >= 8 ) // if necessary convert image to 8 bit
109 aBmp
.Convert( BMP_CONVERSION_8BIT_TRANS
);
111 aBmp
.Convert( BMP_CONVERSION_4BIT_TRANS
);
112 aBmp
.Replace( aBmpEx
.GetMask(), BMP_COL_TRANS
);
116 if ( aBmp
.GetBitCount() > 8 ) // if necessary convert image to 8 bit
117 aBmp
.Convert( BMP_CONVERSION_8BIT_COLORS
);
119 mpAcc
= aBmp
.AcquireReadAccess();
122 SvStreamEndian nOStmOldModus
= m_rOStm
.GetEndian();
123 m_rOStm
.SetEndian( SvStreamEndian::BIG
);
125 mnColors
= mpAcc
->GetPaletteEntryCount();
126 if ( ImplWriteHeader() )
130 m_rOStm
.WriteCharPtr( "\x22XPMENDEXT\x22\x0a};" );
133 m_rOStm
.SetEndian(nOStmOldModus
);
135 Bitmap::ReleaseAccess( mpAcc
);
141 if ( xStatusIndicator
.is() )
142 xStatusIndicator
->end();
149 bool XPMWriter::ImplWriteHeader()
151 mnWidth
= mpAcc
->Width();
152 mnHeight
= mpAcc
->Height();
153 if ( mnWidth
&& mnHeight
&& mnColors
)
155 m_rOStm
.WriteCharPtr( "/* XPM */\x0astatic char * image[] = \x0a{\x0a\x22" );
156 ImplWriteNumber( mnWidth
);
157 m_rOStm
.WriteUChar( 32 );
158 ImplWriteNumber( mnHeight
);
159 m_rOStm
.WriteUChar( 32 );
160 ImplWriteNumber( mnColors
);
161 m_rOStm
.WriteUChar( 32 );
162 ImplWriteNumber( ( mnColors
> 26 ) ? 2 : 1 );
163 m_rOStm
.WriteCharPtr( "\x22,\x0a" );
165 else mbStatus
= false;
171 void XPMWriter::ImplWritePalette()
173 sal_uInt16 nTransIndex
= 0xffff;
176 nTransIndex
= mpAcc
->GetBestPaletteIndex( BMP_COL_TRANS
);
177 for ( sal_uInt16 i
= 0; i
< mnColors
; i
++ )
179 m_rOStm
.WriteCharPtr( "\x22" );
181 m_rOStm
.WriteUChar( 32 );
182 if ( nTransIndex
!= i
)
185 m_rOStm
.WriteCharPtr( "\x22,\x0a" );
188 m_rOStm
.WriteCharPtr( "c none\x22,\x0a" );
194 void XPMWriter::ImplWriteBody()
196 for ( sal_uLong y
= 0; y
< mnHeight
; y
++ )
198 ImplCallback( (sal_uInt16
)( ( 100 * y
) / mnHeight
) ); // processing output in percent
199 m_rOStm
.WriteUChar( 0x22 );
200 for ( sal_uLong x
= 0; x
< mnWidth
; x
++ )
202 ImplWritePixel( mpAcc
->GetPixelIndex( y
, x
) );
204 m_rOStm
.WriteCharPtr( "\x22,\x0a" );
209 // write a decimal number in ascii format into the stream
211 void XPMWriter::ImplWriteNumber(sal_Int32 nNumber
)
213 const OString
aNum(OString::number(nNumber
));
214 m_rOStm
.WriteCharPtr( aNum
.getStr() );
219 void XPMWriter::ImplWritePixel( sal_uLong nCol
) const
223 sal_uInt8 nDiff
= (sal_uInt8
) ( nCol
/ 26 );
224 m_rOStm
.WriteUChar( nDiff
+ 'A' );
225 m_rOStm
.WriteUChar( nCol
- ( nDiff
*26 ) + 'A' );
228 m_rOStm
.WriteUChar( nCol
+ 'A' );
232 // write a color value in hex format into the stream
233 void XPMWriter::ImplWriteColor( sal_uInt16 nNumber
)
238 m_rOStm
.WriteCharPtr( "c #" ); // # indicates a following hex value
239 const BitmapColor
& rColor
= mpAcc
->GetPaletteColor( nNumber
);
240 nTmp
= ( rColor
.GetRed() << 16 ) | ( rColor
.GetGreen() << 8 ) | rColor
.GetBlue();
241 for ( signed char i
= 20; i
>= 0 ; i
-=4 )
243 if ( ( j
= (sal_uInt8
)( nTmp
>> i
) & 0xf ) > 9 )
247 m_rOStm
.WriteUChar( j
);
253 // this needs to be kept in sync with
254 // ImpFilterLibCacheEntry::GetImportFunction() from
255 // vcl/source/filter/graphicfilter.cxx
256 #if defined(DISABLE_DYNLOADING)
257 #define GraphicExport expGraphicExport
260 extern "C" SAL_DLLPUBLIC_EXPORT
bool SAL_CALL
261 GraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pFilterConfigItem
)
263 XPMWriter
aXPMWriter(rStream
);
265 return aXPMWriter
.WriteXPM( rGraphic
, pFilterConfigItem
);
269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */