1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bmpcore.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <tools/color.hxx>
35 #include <vcl/bmpacc.hxx>
36 #include <vcl/bitmapex.hxx>
37 #include <vcl/alpha.hxx>
38 #include <vcl/pngread.hxx>
39 #include <vcl/pngwrite.hxx>
40 #include "bmpcore.hxx"
45 #undef WRITE_ALPHA_PNG
47 // -------------------------
48 // - ImplGetSystemFileName -
49 // -------------------------
51 static String
ImplGetSystemFileName( const String
& rFileName
)
53 String
aRet( rFileName
);
54 const sal_Unicode aReplace
= DirEntry::GetAccessDelimiter( FSYS_STYLE_HOST
).GetChar( 0 );
56 aRet
.SearchAndReplaceAll( '/', aReplace
);
57 aRet
.SearchAndReplaceAll( '\\', aReplace
);
66 BmpCreator::BmpCreator()
70 // -----------------------------------------------------------------------------
72 BmpCreator::~BmpCreator()
76 // -----------------------------------------------------------------------------
78 void BmpCreator::Message( const String
&, BYTE
)
82 // -----------------------------------------------------------------------
84 void BmpCreator::ImplCreate( const ::std::vector
< DirEntry
>& rInDirs
,
87 const LangInfo
& rLang
)
89 const sal_uInt32 nOldPos
= pSRS
->Tell();
90 const char* pCollectFile
= getenv( "BMP_COLLECT_FILE" );
91 SvFileStream
* pCollectStm
= pCollectFile
? new SvFileStream( String( pCollectFile
, RTL_TEXTENCODING_ASCII_US
),
92 STREAM_WRITE
) : NULL
;
95 pCollectStm
->Seek( STREAM_SEEK_TO_END
);
100 String aInfo
, aPrefix
, aName( rName
), aString
;
101 SvFileStream aOutStream
;
102 BitmapEx aTotalBmpEx
;
103 DirEntry
aOutFile( rOut
);
104 ::std::vector
< DirEntry
> aInFiles( rInDirs
);
105 ::std::vector
< String
> aNameVector
;
108 for( i
= 0; i
< aInFiles
.size(); i
++ )
109 aInFiles
[ i
] += DirEntry( String( RTL_CONSTASCII_USTRINGPARAM( "xxx.xxx" ) ) );
111 // get prefix for files
112 if( ( aName
.Len() >= 3 ) && ( aName
.GetChar( 2 ) != '_' ) )
113 aPrefix
= String( aName
, 0, 3 );
115 aPrefix
= String( aName
, 0, 2 );
117 String
aNumStr( String::CreateFromAscii( rLang
.maLangDir
)) ;
119 if( aNumStr
.Len() == 1 )
120 aNumStr
.Insert( '0', 0 );
122 aName
= DirEntry( aName
).GetBase();
123 aName
+= String( RTL_CONSTASCII_USTRINGPARAM( ".bmp" ) );
125 // create output file name
126 aOutFile
+= DirEntry( aName
);
128 // get number of bitmaps
129 while( aLine
.Search( '}' ) == STRING_NOTFOUND
)
131 if( !pSRS
->ReadLine( aLine
) )
134 aLine
.EraseLeadingChars( ' ' );
135 aLine
.EraseLeadingChars( '\t' );
136 aLine
.EraseAllChars( ';' );
138 if( aLine
.IsNumericAscii() )
142 if( atoi( aLine
.GetBuffer() ) < 10000 )
143 aString
+= String::CreateFromInt32( 0 );
145 // search for pngs by default
146 String
aPngString( aString
+= String( aLine
.GetBuffer(), RTL_TEXTENCODING_UTF8
) );
147 aNameVector
.push_back( aPngString
+= String( RTL_CONSTASCII_USTRINGPARAM( ".png" ) ) );
151 if( !aNameVector
.size() )
152 Message( String( RTL_CONSTASCII_USTRINGPARAM( "WARNING: No imagelist resource found: " ) ).Append( aString
), EXIT_MISSING_RESOURCE
);
156 aInfo
= String( RTL_CONSTASCII_USTRINGPARAM( "CREATING ImageList for language: " ) );
157 aInfo
+= String( ::rtl::OUString::createFromAscii( rLang
.maLangDir
) );
158 aInfo
+= String( RTL_CONSTASCII_USTRINGPARAM( " [ " ) );
160 for( i
= 0; i
< rInDirs
.size(); i
++ )
161 ( aInfo
+= rInDirs
[ i
].GetFull() ) += String( RTL_CONSTASCII_USTRINGPARAM( "; " ) );
163 aInfo
+= String( RTL_CONSTASCII_USTRINGPARAM( " ]" ) );
166 // create bit vector to hold flags for valid bitmaps
167 ::std::bit_vector
aValidBmpBitVector( aNameVector
.size(), false );
170 for( sal_uInt32 n
= 0; n
< aNameVector
.size(); n
++ )
174 for( i
= 0; i
< aInFiles
.size() && aBmpEx
.IsEmpty(); i
++ )
176 DirEntry
aInFile( aInFiles
[ i
] );
178 aInFile
.SetName( aString
= aNameVector
[ n
] );
179 bool bPNG
= aInFile
.Exists();
183 aInFile
.SetExtension( String( RTL_CONSTASCII_USTRINGPARAM( "bmp" ) ) );
184 aString
= aInFile
.GetName();
187 if( aInFile
.Exists() )
189 const String
aFileName( aInFile
.GetFull() );
190 SvFileStream
aIStm( aFileName
, STREAM_READ
);
194 ::vcl::PNGReader
aPNGReader( aIStm
);
195 aBmpEx
= aPNGReader
.Read();
200 if( pCollectStm
&& !aBmpEx
.IsEmpty() )
202 const ByteString
aCollectString( aFileName
, RTL_TEXTENCODING_ASCII_US
);
203 pCollectStm
->WriteLine( aCollectString
);
208 const Size
aSize( aBmpEx
.GetSizePixel() );
210 if( aBmpEx
.IsEmpty() )
212 Message( String( RTL_CONSTASCII_USTRINGPARAM( "ERROR: graphic is missing: " ) ).Append( aString
), EXIT_MISSING_BITMAP
);
216 if( aTotalBmpEx
.IsEmpty() )
218 // first bitmap determines metrics of total bitmap
219 Size
aTotalSize( aOneSize
= aSize
);
221 aTotalSize
.Width() *= aNameVector
.size();
222 aTotalBmpEx
= Bitmap( aTotalSize
, aBmpEx
.GetBitmap().GetBitCount() );
225 if( ( aSize
.Width() > aOneSize
.Width() ) || ( aSize
.Height() > aOneSize
.Height() ) )
226 Message( String( RTL_CONSTASCII_USTRINGPARAM( "ERROR: Different dimensions in file: " ) ).Append( aString
), EXIT_DIMENSIONERROR
);
230 const Rectangle
aDst( Point( aOneSize
.Width() * n
, 0L ), aSize
);
231 const Rectangle
aSrc( aPoint
, aSize
);
233 if( !aTotalBmpEx
.IsEmpty() && !aBmpEx
.IsEmpty() && !aDst
.IsEmpty() && !aSrc
.IsEmpty() )
235 if( !aTotalBmpEx
.IsTransparent() && aBmpEx
.IsTransparent() )
237 const Bitmap
aTmpBmp( aTotalBmpEx
.GetBitmap() );
238 aTotalBmpEx
= BitmapEx( aTmpBmp
, AlphaMask( aTmpBmp
.CreateMask( COL_LIGHTMAGENTA
) ) );
240 else if( aTotalBmpEx
.IsTransparent() && !aBmpEx
.IsTransparent() )
242 const Bitmap
aTmpBmp( aBmpEx
.GetBitmap() );
243 aBmpEx
= BitmapEx( aTmpBmp
, AlphaMask( aTmpBmp
.CreateMask( COL_LIGHTMAGENTA
) ) );
246 aTotalBmpEx
.CopyPixel( aDst
, aSrc
, &aBmpEx
);
247 aValidBmpBitVector
[ n
] = true;
253 if( !aTotalBmpEx
.IsEmpty() )
255 // do we have invalid bitmaps?
256 if( ::std::find( aValidBmpBitVector
.begin(), aValidBmpBitVector
.end(), false ) != aValidBmpBitVector
.end() )
258 Bitmap
aTmpBmp( aTotalBmpEx
.GetBitmap() );
259 BitmapWriteAccess
* pAcc
= aTmpBmp
.AcquireWriteAccess();
263 pAcc
->SetLineColor( Color( COL_LIGHTGREEN
) );
265 for( sal_uInt32 n
= 0; n
< aValidBmpBitVector
.size(); n
++ )
267 if( !aValidBmpBitVector
[ n
] )
269 const Rectangle
aDst( Point( aOneSize
.Width() * n
, 0L ), aOneSize
);
271 pAcc
->DrawRect( aDst
);
272 pAcc
->DrawLine( aDst
.TopLeft(), aDst
.BottomRight() );
273 pAcc
->DrawLine( aDst
.TopRight(), aDst
.BottomLeft() );
277 aTmpBmp
.ReleaseAccess( pAcc
);
279 if( aTotalBmpEx
.IsAlpha() )
280 aTotalBmpEx
= BitmapEx( aTmpBmp
, aTotalBmpEx
.GetAlpha() );
281 else if( aTotalBmpEx
.IsTransparent() )
282 aTotalBmpEx
= BitmapEx( aTmpBmp
, aTotalBmpEx
.GetMask() );
284 aTotalBmpEx
= aTmpBmp
;
289 const String
aOutFileName( aOutFile
.GetFull() );
291 aOutStream
.Open( aOutFileName
, STREAM_WRITE
| STREAM_TRUNC
);
293 if( !aOutStream
.IsOpen() )
294 Message( String( RTL_CONSTASCII_USTRINGPARAM( "ERROR: Could not open output file: " ) ).Append( aOutFileName
), EXIT_IOERROR
);
297 if( aOutFileName
.Search( String( RTL_CONSTASCII_USTRINGPARAM( ".png" ) ) ) != STRING_NOTFOUND
)
299 ::vcl::PNGWriter
aPNGWriter( aTotalBmpEx
);
300 aPNGWriter
.Write( aOutStream
);
303 aOutStream
<< aTotalBmpEx
;
305 if( aOutStream
.GetError() )
306 Message( String( RTL_CONSTASCII_USTRINGPARAM( "ERROR: Could not write to output file: " ) ).Append( aOutFileName
), EXIT_IOERROR
);
308 Message( String( RTL_CONSTASCII_USTRINGPARAM( "Successfully generated ImageList " ) ).Append( aOutFileName
) );
314 Message( String( RTL_CONSTASCII_USTRINGPARAM( "ERROR: Could not generate " ) ).Append( aOutFile
.GetFull() ), EXIT_COMMONERROR
);
320 Message( String( RTL_CONSTASCII_USTRINGPARAM( "ERROR: SOLARSRC environment variable not set!" ) ), EXIT_MISSING_SOLARSRC_ENV
);
322 pSRS
->Seek( nOldPos
);
326 // -----------------------------------------------------------------------------
328 void BmpCreator::Create( const String
& rSRSName
,
329 const ::std::vector
< String
>& rInDirs
,
330 const String
& rOutName
,
331 const LangInfo
& rLang
)
333 DirEntry
aFileName( ImplGetSystemFileName( rSRSName
) ), aOutDir( ImplGetSystemFileName( rOutName
) );
334 ::std::vector
< DirEntry
> aInDirs
;
340 // create vector of all valid input directories,
341 // including language subdirectories
342 for( sal_uInt32 i
= 0; i
< rInDirs
.size(); i
++ )
344 DirEntry
aInDir( ImplGetSystemFileName( rInDirs
[ i
] ) );
348 if( aInDir
.Exists() )
350 DirEntry
aLangInDir( aInDir
);
352 if( ( aLangInDir
+= DirEntry( ::rtl::OUString::createFromAscii( rLang
.maLangDir
) ) ).Exists() )
353 aInDirs
.push_back( aLangInDir
);
355 aInDirs
.push_back( aInDir
);
359 pSRS
= new SvFileStream ( aFileName
.GetFull(), STREAM_STD_READ
);
361 if( pSRS
->GetError() )
362 Message( String( RTL_CONSTASCII_USTRINGPARAM( "ERROR: Kein SRS file!" ) ), EXIT_NOSRSFILE
);
366 ByteString aByteText
;
367 BOOL bLangDep
= FALSE
;
373 if (!pSRS
->ReadLine(aByteText
))
376 while ( aByteText
.Search( "ImageList" ) == STRING_NOTFOUND
);
380 if (!pSRS
->ReadLine( aByteText
) )
383 while ( aByteText
.Search( "File" ) == STRING_NOTFOUND
);
384 aText
= String::CreateFromAscii( aByteText
.GetBuffer() );
386 const String
aName( aText
.GetToken( 1, '"' ) );
391 aByteText
.Search( "File" ) != STRING_NOTFOUND
&&
392 aByteText
.Search( '[' ) != STRING_NOTFOUND
&&
393 aByteText
.Search( ']' ) != STRING_NOTFOUND
)
398 if (!pSRS
->ReadLine(aByteText
))
401 while (aByteText
.Search( "IdList" ) == STRING_NOTFOUND
);
402 aText
= String::CreateFromAscii( aByteText
.GetBuffer() );
404 // if image list is not language dependent, don't do anything for languages except german
408 ImplCreate( aInDirs
, aOutDir
, aName
, rLang
);
410 /* else if( ( rLang.mnLangNum != 49 ) && !bLangDep )
412 Message( String( RTL_CONSTASCII_USTRINGPARAM( "INFO: ImageList is not language dependent! Nothing to do for this language." ) ) );
416 while ( aText
.Len() );
420 Message( String( RTL_CONSTASCII_USTRINGPARAM( "ERROR: No ImageList found in SRS file!" ) ), EXIT_NOIMGLIST
);