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 <osl/endian.h>
22 #include <tools/stream.hxx>
23 #include <tools/fract.hxx>
24 #include <vcl/gdimtf.hxx>
25 #include <tools/color.hxx>
26 #include <vcl/virdev.hxx>
27 #include "sgffilt.hxx"
28 #include "sgfbram.hxx"
29 #include <boost/scoped_array.hpp>
31 SgfHeader::SgfHeader()
33 memset( this, 0, sizeof( SgfHeader
) );
36 SvStream
& ReadSgfHeader(SvStream
& rIStream
, SgfHeader
& rHead
)
38 rIStream
.Read(&rHead
.Magic
, SgfHeaderSize
);
39 #if defined OSL_BIGENDIAN
40 rHead
.Magic
=OSL_SWAPWORD(rHead
.Magic
);
41 rHead
.Version
=OSL_SWAPWORD(rHead
.Version
);
42 rHead
.Typ
=OSL_SWAPWORD(rHead
.Typ
);
43 rHead
.Xsize
=OSL_SWAPWORD(rHead
.Xsize
);
44 rHead
.Ysize
=OSL_SWAPWORD(rHead
.Ysize
);
45 rHead
.Xoffs
=OSL_SWAPWORD(rHead
.Xoffs
);
46 rHead
.Yoffs
=OSL_SWAPWORD(rHead
.Yoffs
);
47 rHead
.Planes
=OSL_SWAPWORD(rHead
.Planes
);
48 rHead
.SwGrCol
=OSL_SWAPWORD(rHead
.SwGrCol
);
49 rHead
.OfsLo
=OSL_SWAPWORD(rHead
.OfsLo
);
50 rHead
.OfsHi
=OSL_SWAPWORD(rHead
.OfsHi
);
55 bool SgfHeader::ChkMagic()
56 { return Magic
=='J'*256+'J'; }
58 sal_uInt32
SgfHeader::GetOffset()
59 { return sal_uInt32(OfsLo
)+0x00010000*sal_uInt32(OfsHi
); }
63 memset( this, 0, sizeof( SgfEntry
) );
66 SvStream
& ReadSgfEntry(SvStream
& rIStream
, SgfEntry
& rEntr
)
68 rIStream
.Read(&rEntr
.Typ
, SgfEntrySize
);
69 #if defined OSL_BIGENDIAN
70 rEntr
.Typ
=OSL_SWAPWORD(rEntr
.Typ
);
71 rEntr
.iFrei
=OSL_SWAPWORD(rEntr
.iFrei
);
72 rEntr
.lFreiLo
=OSL_SWAPWORD (rEntr
.lFreiLo
);
73 rEntr
.lFreiHi
=OSL_SWAPWORD (rEntr
.lFreiHi
);
74 rEntr
.OfsLo
=OSL_SWAPWORD(rEntr
.OfsLo
);
75 rEntr
.OfsHi
=OSL_SWAPWORD(rEntr
.OfsHi
);
80 sal_uInt32
SgfEntry::GetOffset()
81 { return sal_uInt32(OfsLo
)+0x00010000*sal_uInt32(OfsHi
); }
83 SvStream
& ReadSgfVector(SvStream
& rIStream
, SgfVector
& rVect
)
85 rIStream
.Read(&rVect
, sizeof(rVect
));
86 #if defined OSL_BIGENDIAN
87 rVect
.Flag
=OSL_SWAPWORD(rVect
.Flag
);
88 rVect
.x
=OSL_SWAPWORD(rVect
.x
);
89 rVect
.y
=OSL_SWAPWORD(rVect
.y
);
90 rVect
.OfsLo
=OSL_SWAPDWORD (rVect
.OfsLo
);
91 rVect
.OfsHi
=OSL_SWAPDWORD (rVect
.OfsHi
);
96 SvStream
& WriteBmpFileHeader(SvStream
& rOStream
, BmpFileHeader
& rHead
)
98 #if defined OSL_BIGENDIAN
99 rHead
.Typ
=OSL_SWAPWORD(rHead
.Typ
);
100 rHead
.SizeLo
=OSL_SWAPWORD(rHead
.SizeLo
);
101 rHead
.SizeHi
=OSL_SWAPWORD(rHead
.SizeHi
);
102 rHead
.Reserve1
=OSL_SWAPWORD(rHead
.Reserve1
);
103 rHead
.Reserve2
=OSL_SWAPWORD(rHead
.Reserve2
);
104 rHead
.OfsLo
=OSL_SWAPWORD(rHead
.OfsLo
);
105 rHead
.OfsHi
=OSL_SWAPWORD(rHead
.OfsHi
);
107 rOStream
.Write(&rHead
, sizeof(rHead
));
108 #if defined OSL_BIGENDIAN
109 rHead
.Typ
=OSL_SWAPWORD(rHead
.Typ
);
110 rHead
.SizeLo
=OSL_SWAPWORD(rHead
.SizeLo
);
111 rHead
.SizeHi
=OSL_SWAPWORD(rHead
.SizeHi
);
112 rHead
.Reserve1
=OSL_SWAPWORD(rHead
.Reserve1
);
113 rHead
.Reserve2
=OSL_SWAPWORD(rHead
.Reserve2
);
114 rHead
.OfsLo
=OSL_SWAPWORD(rHead
.OfsLo
);
115 rHead
.OfsHi
=OSL_SWAPWORD(rHead
.OfsHi
);
120 void BmpFileHeader::SetSize(sal_uInt32 Size
)
122 SizeLo
=sal_uInt16(Size
& 0x0000FFFF);
123 SizeHi
=sal_uInt16((Size
& 0xFFFF0000)>>16);
126 void BmpFileHeader::SetOfs(sal_uInt32 Ofs
)
128 OfsLo
=sal_uInt16(Ofs
& 0x0000FFFF);
129 OfsHi
=sal_uInt16((Ofs
& 0xFFFF0000)>>16);
132 sal_uInt32
BmpFileHeader::GetOfs()
134 return sal_uInt32(OfsLo
)+0x00010000*sal_uInt32(OfsHi
);
137 SvStream
& WriteBmpInfoHeader(SvStream
& rOStream
, BmpInfoHeader
& rInfo
)
139 #if defined OSL_BIGENDIAN
140 rInfo
.Size
=OSL_SWAPDWORD (rInfo
.Size
);
141 rInfo
.Width
=OSL_SWAPDWORD (rInfo
.Width
);
142 rInfo
.Hight
=OSL_SWAPDWORD (rInfo
.Hight
);
143 rInfo
.Planes
=OSL_SWAPWORD(rInfo
.Planes
);
144 rInfo
.PixBits
=OSL_SWAPWORD(rInfo
.PixBits
);
145 rInfo
.Compress
=OSL_SWAPDWORD (rInfo
.Compress
);
146 rInfo
.ImgSize
=OSL_SWAPDWORD (rInfo
.ImgSize
);
147 rInfo
.xDpmm
=OSL_SWAPDWORD (rInfo
.xDpmm
);
148 rInfo
.yDpmm
=OSL_SWAPDWORD (rInfo
.yDpmm
);
149 rInfo
.ColUsed
=OSL_SWAPDWORD (rInfo
.ColUsed
);
150 rInfo
.ColMust
=OSL_SWAPDWORD (rInfo
.ColMust
);
152 rOStream
.Write(&rInfo
, sizeof(rInfo
));
153 #if defined OSL_BIGENDIAN
154 rInfo
.Size
=OSL_SWAPDWORD (rInfo
.Size
);
155 rInfo
.Width
=OSL_SWAPDWORD (rInfo
.Width
);
156 rInfo
.Hight
=OSL_SWAPDWORD (rInfo
.Hight
);
157 rInfo
.Planes
=OSL_SWAPWORD(rInfo
.Planes
);
158 rInfo
.PixBits
=OSL_SWAPWORD(rInfo
.PixBits
);
159 rInfo
.Compress
=OSL_SWAPDWORD (rInfo
.Compress
);
160 rInfo
.ImgSize
=OSL_SWAPDWORD (rInfo
.ImgSize
);
161 rInfo
.xDpmm
=OSL_SWAPDWORD (rInfo
.xDpmm
);
162 rInfo
.yDpmm
=OSL_SWAPDWORD (rInfo
.yDpmm
);
163 rInfo
.ColUsed
=OSL_SWAPDWORD (rInfo
.ColUsed
);
164 rInfo
.ColMust
=OSL_SWAPDWORD (rInfo
.ColMust
);
169 SvStream
& WriteRGBQuad(SvStream
& rOStream
, const RGBQuad
& rQuad
)
171 rOStream
.Write(&rQuad
, sizeof(rQuad
));
185 sal_uInt8
GetByte(SvStream
& rInp
);
188 sal_uInt8
PcxExpand::GetByte(SvStream
& rInp
)
194 if ((Data
& 0xC0) == 0xC0) {
195 Count
=(Data
& 0x3F) -1;
202 bool SgfFilterBMap(SvStream
& rInp
, SvStream
& rOut
, SgfHeader
& rHead
, SgfEntry
&)
204 BmpFileHeader aBmpHead
;
205 BmpInfoHeader aBmpInfo
;
206 sal_uInt16 nWdtInp
=(rHead
.Xsize
+7)/8; // width of input bitmap in bytes
207 sal_uInt16 nWdtOut
; // width of output bitmap in bytes
208 sal_uInt16 nColors
; // color count (1, 16, 256)
209 sal_uInt16 nColBits
; // number of bits per pixel (2, 4, 8)
210 sal_uInt16 i
,j
,k
; // column/row/plane counter
211 sal_uInt16 a
,b
; // helper variables
212 sal_uInt8 pl1
= 0; // masks for the planes
213 boost::scoped_array
<sal_uInt8
> pBuf
; // buffer for a pixel row
218 if (rHead
.Planes
<=1) nColBits
=1; else nColBits
=4; if (rHead
.Typ
==4) nColBits
=8;
220 nWdtOut
=((rHead
.Xsize
*nColBits
+31)/32)*4;
221 aBmpHead
.Typ
='B'+'M'*256;
222 aBmpHead
.SetOfs(sizeof(aBmpHead
)+sizeof(aBmpInfo
)+nColors
*4);
223 aBmpHead
.SetSize(aBmpHead
.GetOfs()+nWdtOut
*rHead
.Ysize
);
226 aBmpInfo
.Size
=sizeof(aBmpInfo
);
227 aBmpInfo
.Width
=rHead
.Xsize
;
228 aBmpInfo
.Hight
=rHead
.Ysize
;
230 aBmpInfo
.PixBits
=nColBits
;
237 pBuf
.reset(new sal_uInt8
[nWdtOut
]);
238 if (!pBuf
) return false; // error: no more memory available
239 WriteBmpFileHeader( rOut
, aBmpHead
);
240 WriteBmpInfoHeader( rOut
, aBmpInfo
);
241 memset(pBuf
.get(),0,nWdtOut
); // fill buffer with zeroes
246 WriteRGBQuad( rOut
, RGBQuad(0x00,0x00,0x00) ); // black
247 WriteRGBQuad( rOut
, RGBQuad(0xFF,0xFF,0xFF) ); // white
249 for (j
=0;j
<rHead
.Ysize
;j
++)
250 rOut
.Write(pBuf
.get(), nWdtOut
); // fill file with zeroes
251 for (j
=0;j
<rHead
.Ysize
;j
++) {
252 for(i
=0;i
<nWdtInp
;i
++) {
253 pBuf
[i
]=aPcx
.GetByte(rInp
);
255 for(i
=nWdtInp
;i
<nWdtOut
;i
++) pBuf
[i
]=0; // up to 3 bytes
256 rOut
.Seek(nOfs
+((sal_uLong
)rHead
.Ysize
-j
-1L)*(sal_uLong
)nWdtOut
); // write backwards
257 rOut
.Write(pBuf
.get(), nWdtOut
);
259 } else if (nColors
==16) {
260 sal_uInt8 pl2
= 0; // planes' masks
262 WriteRGBQuad( rOut
, RGBQuad(0x00,0x00,0x00) ); // black
263 WriteRGBQuad( rOut
, RGBQuad(0x24,0x24,0x24) ); // gray 80%
264 WriteRGBQuad( rOut
, RGBQuad(0x49,0x49,0x49) ); // gray 60%
265 WriteRGBQuad( rOut
, RGBQuad(0x92,0x92,0x92) ); // gray 40%
266 WriteRGBQuad( rOut
, RGBQuad(0x6D,0x6D,0x6D) ); // gray 30%
267 WriteRGBQuad( rOut
, RGBQuad(0xB6,0xB6,0xB6) ); // gray 20%
268 WriteRGBQuad( rOut
, RGBQuad(0xDA,0xDA,0xDA) ); // gray 10%
269 WriteRGBQuad( rOut
, RGBQuad(0xFF,0xFF,0xFF) ); // white
270 WriteRGBQuad( rOut
, RGBQuad(0x00,0x00,0x00) ); // black
271 WriteRGBQuad( rOut
, RGBQuad(0xFF,0x00,0x00) ); // red
272 WriteRGBQuad( rOut
, RGBQuad(0x00,0x00,0xFF) ); // blue
273 WriteRGBQuad( rOut
, RGBQuad(0xFF,0x00,0xFF) ); // magenta
274 WriteRGBQuad( rOut
, RGBQuad(0x00,0xFF,0x00) ); // green
275 WriteRGBQuad( rOut
, RGBQuad(0xFF,0xFF,0x00) ); // yellow
276 WriteRGBQuad( rOut
, RGBQuad(0x00,0xFF,0xFF) ); // cyan
277 WriteRGBQuad( rOut
, RGBQuad(0xFF,0xFF,0xFF) ); // white
280 for (j
=0;j
<rHead
.Ysize
;j
++)
281 rOut
.Write(pBuf
.get(), nWdtOut
); // fill file with zeroes
282 for (j
=0;j
<rHead
.Ysize
;j
++) {
283 memset(pBuf
.get(),0,nWdtOut
);
290 for(i
=0;i
<nWdtInp
;i
++) {
292 b
=aPcx
.GetByte(rInp
);
293 if (b
& 0x80) pBuf
[a
]|=pl1
;
294 if (b
& 0x40) pBuf
[a
]|=pl2
;
295 if (b
& 0x20) pBuf
[a
+1]|=pl1
;
296 if (b
& 0x10) pBuf
[a
+1]|=pl2
;
297 if (b
& 0x08) pBuf
[a
+2]|=pl1
;
298 if (b
& 0x04) pBuf
[a
+2]|=pl2
;
299 if (b
& 0x02) pBuf
[a
+3]|=pl1
;
300 if (b
& 0x01) pBuf
[a
+3]|=pl2
;
303 for(i
=nWdtInp
*4;i
<nWdtOut
;i
++) pBuf
[i
]=0; // up to 3 bytes
304 rOut
.Seek(nOfs
+((sal_uLong
)rHead
.Ysize
-j
-1L)*(sal_uLong
)nWdtOut
); // write backwards
305 rOut
.Write(pBuf
.get(), nWdtOut
);
307 } else if (nColors
==256) {
308 cRGB
[3]=0; // fourth palette entry for BMP
309 for (i
=0;i
<256;i
++) { // copy palette
311 pl1
=cRGB
[0]; // switch red and blue
318 for (j
=0;j
<rHead
.Ysize
;j
++)
319 rOut
.Write(pBuf
.get(), nWdtOut
); // fill file with zeroes
320 for (j
=0;j
<rHead
.Ysize
;j
++) {
321 for(i
=0;i
<rHead
.Xsize
;i
++)
322 pBuf
[i
]=aPcx
.GetByte(rInp
);
323 for(i
=rHead
.Xsize
;i
<nWdtOut
;i
++) pBuf
[i
]=0; // up to 3 bytes
324 rOut
.Seek(nOfs
+((sal_uLong
)rHead
.Ysize
-j
-1L)*(sal_uLong
)nWdtOut
); // write backwards
325 rOut
.Write(pBuf
.get(), nWdtOut
);
331 bool SgfBMapFilter(SvStream
& rInp
, SvStream
& rOut
)
333 sal_uLong nFileStart
; // offset of SgfHeaders. Usually 0.
337 bool bRdFlag
=false; // read graphics entry?
338 bool bRet
=false; // return value
340 nFileStart
=rInp
.Tell();
341 ReadSgfHeader( rInp
, aHead
);
342 if (aHead
.ChkMagic() && (aHead
.Typ
==SgfBitImag0
|| aHead
.Typ
==SgfBitImag1
||
343 aHead
.Typ
==SgfBitImag2
|| aHead
.Typ
==SgfBitImgMo
)) {
344 nNext
=aHead
.GetOffset();
345 while (nNext
&& !bRdFlag
&& !rInp
.GetError() && !rOut
.GetError()) {
346 rInp
.Seek(nFileStart
+nNext
);
347 ReadSgfEntry( rInp
, aEntr
);
348 nNext
=aEntr
.GetOffset();
349 if (aEntr
.Typ
==aHead
.Typ
) {
355 case SgfBitImgMo
: bRet
=SgfFilterBMap(rInp
,rOut
,aHead
,aEntr
); break;
360 if (rInp
.GetError()) bRet
=false;
364 // for StarDraw embedded SGF vector
371 bool SgfVectScal
=false;
373 Color
Hpgl2SvFarbe( sal_uInt8 nFarb
)
375 sal_uLong nColor
= COL_BLACK
;
377 switch (nFarb
& 0x07) {
378 case 0: nColor
=COL_WHITE
; break;
379 case 1: nColor
=COL_YELLOW
; break;
380 case 2: nColor
=COL_LIGHTMAGENTA
; break;
381 case 3: nColor
=COL_LIGHTRED
; break;
382 case 4: nColor
=COL_LIGHTCYAN
; break;
383 case 5: nColor
=COL_LIGHTGREEN
; break;
384 case 6: nColor
=COL_LIGHTBLUE
; break;
385 case 7: nColor
=COL_BLACK
; break;
387 Color
aColor( nColor
);
391 bool SgfFilterVect(SvStream
& rInp
, SgfHeader
& rHead
, SgfEntry
&, GDIMetaFile
& rMtf
)
393 ScopedVclPtrInstance
< VirtualDevice
> aOutDev
;
404 rMtf
.Record(aOutDev
.get());
405 aOutDev
->SetLineColor(Color(COL_BLACK
));
406 aOutDev
->SetFillColor(Color(COL_BLACK
));
408 while (!bEoDt
&& !rInp
.GetError()) {
409 ReadSgfVector( rInp
, aVect
); RecNr
++;
410 nFarb
=(sal_uInt8
) (aVect
.Flag
& 0x000F);
411 nLTyp
=(sal_uInt8
)((aVect
.Flag
& 0x00F0) >>4);
412 nOTyp
=(sal_uInt8
)((aVect
.Flag
& 0x0F00) >>8);
413 bEoDt
=(aVect
.Flag
& 0x4000) !=0;
414 bool bPDwn
=(aVect
.Flag
& 0x8000) !=0;
416 long x
=aVect
.x
-rHead
.Xoffs
;
417 long y
=rHead
.Ysize
-(aVect
.y
-rHead
.Yoffs
);
419 if (SgfVectXdiv
==0) SgfVectXdiv
=rHead
.Xsize
;
420 if (SgfVectYdiv
==0) SgfVectYdiv
=rHead
.Ysize
;
421 if (SgfVectXdiv
==0) SgfVectXdiv
=1;
422 if (SgfVectYdiv
==0) SgfVectYdiv
=1;
423 x
=SgfVectXofs
+ x
*SgfVectXmul
/SgfVectXdiv
;
424 y
=SgfVectYofs
+ y
*SgfVectXmul
/SgfVectYdiv
;
427 if (!bEoDt
&& !rInp
.GetError()) {
428 if (bPDwn
&& nLTyp
<=6) {
430 case 1: if (nFarb
!=nFrb0
) {
431 switch(rHead
.SwGrCol
) {
432 case SgfVectFarb
: aOutDev
->SetLineColor(Hpgl2SvFarbe(nFarb
)); break;
433 case SgfVectGray
: break;
434 case SgfVectWdth
: break;
437 aOutDev
->DrawLine(aP0
,aP1
); break; // line
438 case 2: break; // circle
439 case 3: break; // text
440 case 5: aOutDev
->DrawRect(Rectangle(aP0
,aP1
)); break; // rectangle (solid)
449 MapMode
aMap( MAP_10TH_MM
, Point(),
450 Fraction( 1, 4 ), Fraction( 1, 4 ) );
451 rMtf
.SetPrefMapMode( aMap
);
452 rMtf
.SetPrefSize( Size( (short)rHead
.Xsize
, (short)rHead
.Ysize
) );
456 bool SgfVectFilter(SvStream
& rInp
, GDIMetaFile
& rMtf
)
458 sal_uLong nFileStart
; // offset of SgfHeaders. Usually 0.
462 bool bRet
=false; // return value
464 nFileStart
=rInp
.Tell();
465 ReadSgfHeader( rInp
, aHead
);
466 if (aHead
.ChkMagic() && aHead
.Typ
==SGF_SIMPVECT
) {
467 nNext
=aHead
.GetOffset();
468 while (nNext
&& !rInp
.GetError()) {
469 rInp
.Seek(nFileStart
+nNext
);
470 ReadSgfEntry( rInp
, aEntr
);
471 nNext
=aEntr
.GetOffset();
472 if (aEntr
.Typ
==aHead
.Typ
) {
473 bRet
=SgfFilterVect(rInp
,aHead
,aEntr
,rMtf
);
480 /*************************************************************************
484 |* Description determine which kind of SGF/SGV it is
486 *************************************************************************/
487 sal_uInt8
CheckSgfTyp(SvStream
& rInp
, sal_uInt16
& nVersion
)
489 #if OSL_DEBUG_LEVEL > 1 // check record size, new Compiler had different alignment!
490 if (sizeof(SgfHeader
)!=SgfHeaderSize
||
491 sizeof(SgfEntry
) !=SgfEntrySize
||
492 sizeof(SgfVector
)!=SgfVectorSize
||
493 sizeof(BmpFileHeader
)!=BmpFileHeaderSize
||
494 sizeof(BmpInfoHeader
)!=BmpInfoHeaderSize
||
495 sizeof(RGBQuad
)!=RGBQuadSize
) return SGF_DONTKNOW
;
502 ReadSgfHeader( rInp
, aHead
);
504 if (aHead
.ChkMagic()) {
505 nVersion
=aHead
.Version
;
510 case SgfBitImgMo
: return SGF_BITIMAGE
;
511 case SgfSimpVect
: return SGF_SIMPVECT
;
512 case SgfPostScrp
: return SGF_POSTSCRP
;
513 case SgfStarDraw
: return SGF_STARDRAW
;
514 default : return SGF_DONTKNOW
;
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */