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"
31 SgfHeader::SgfHeader()
33 memset( this, 0, sizeof( SgfHeader
) );
36 SvStream
& ReadSgfHeader(SvStream
& rIStream
, SgfHeader
& rHead
)
39 sal_uInt64
const nOldPos(rIStream
.Tell());
41 rIStream
.ReadUInt16(rHead
.Magic
);
42 rIStream
.ReadUInt16(rHead
.Version
);
43 rIStream
.ReadUInt16(rHead
.Typ
);
44 rIStream
.ReadUInt16(rHead
.Xsize
);
45 rIStream
.ReadUInt16(rHead
.Ysize
);
46 rIStream
.ReadInt16(rHead
.Xoffs
);
47 rIStream
.ReadInt16(rHead
.Yoffs
);
48 rIStream
.ReadUInt16(rHead
.Planes
);
49 rIStream
.ReadUInt16(rHead
.SwGrCol
);
50 rIStream
.ReadBytes(&rHead
.Autor
, 10);
51 rIStream
.ReadBytes(&rHead
.Programm
, 10);
52 rIStream
.ReadUInt16(rHead
.OfsLo
);
53 rIStream
.ReadUInt16(rHead
.OfsHi
);
54 assert(rIStream
.GetError() || rIStream
.Tell() == nOldPos
+ SgfHeaderSize
);
58 bool SgfHeader::ChkMagic()
59 { return Magic
=='J'*256+'J'; }
61 sal_uInt32
SgfHeader::GetOffset()
62 { return sal_uInt32(OfsLo
)+0x00010000*sal_uInt32(OfsHi
); }
66 memset( this, 0, sizeof( SgfEntry
) );
69 SvStream
& ReadSgfEntry(SvStream
& rIStream
, SgfEntry
& rEntr
)
72 sal_uInt64
const nOldPos(rIStream
.Tell());
74 rIStream
.ReadUInt16(rEntr
.Typ
);
75 rIStream
.ReadUInt16(rEntr
.iFrei
);
76 rIStream
.ReadUInt16(rEntr
.lFreiLo
);
77 rIStream
.ReadUInt16(rEntr
.lFreiHi
);
78 rIStream
.ReadBytes(&rEntr
.cFrei
, 10);
79 rIStream
.ReadUInt16(rEntr
.OfsLo
);
80 rIStream
.ReadUInt16(rEntr
.OfsHi
);
81 assert(rIStream
.GetError() || rIStream
.Tell() == nOldPos
+ SgfEntrySize
);
85 sal_uInt32
SgfEntry::GetOffset()
86 { return sal_uInt32(OfsLo
)+0x00010000*sal_uInt32(OfsHi
); }
88 SvStream
& ReadSgfVector(SvStream
& rIStream
, SgfVector
& rVect
)
91 sal_uInt64
const nOldPos(rIStream
.Tell());
93 rIStream
.ReadUInt16(rVect
.Flag
);
94 rIStream
.ReadInt16(rVect
.x
);
95 rIStream
.ReadInt16(rVect
.y
);
96 rIStream
.ReadUInt16(rVect
.OfsLo
);
97 rIStream
.ReadUInt16(rVect
.OfsHi
);
98 assert(rIStream
.GetError() || rIStream
.Tell() == nOldPos
+ SgfVectorSize
);
102 SvStream
& WriteBmpFileHeader(SvStream
& rOStream
, BmpFileHeader
& rHead
)
105 sal_uInt64
const nOldPos(rOStream
.Tell());
107 rOStream
.WriteUInt16(rHead
.Typ
);
108 rOStream
.WriteUInt16(rHead
.SizeLo
);
109 rOStream
.WriteUInt16(rHead
.SizeHi
);
110 rOStream
.WriteUInt16(rHead
.Reserve1
);
111 rOStream
.WriteUInt16(rHead
.Reserve2
);
112 rOStream
.WriteUInt16(rHead
.OfsLo
);
113 rOStream
.WriteUInt16(rHead
.OfsHi
);
114 assert(rOStream
.GetError() || rOStream
.Tell() == nOldPos
+ BmpFileHeaderSize
);
118 void BmpFileHeader::SetSize(sal_uInt32 Size
)
120 SizeLo
=sal_uInt16(Size
& 0x0000FFFF);
121 SizeHi
=sal_uInt16((Size
& 0xFFFF0000)>>16);
124 void BmpFileHeader::SetOfs(sal_uInt32 Ofs
)
126 OfsLo
=sal_uInt16(Ofs
& 0x0000FFFF);
127 OfsHi
=sal_uInt16((Ofs
& 0xFFFF0000)>>16);
130 sal_uInt32
BmpFileHeader::GetOfs()
132 return sal_uInt32(OfsLo
)+0x00010000*sal_uInt32(OfsHi
);
135 SvStream
& WriteBmpInfoHeader(SvStream
& rOStream
, BmpInfoHeader
& rInfo
)
138 sal_uInt64
const nOldPos(rOStream
.Tell());
140 rOStream
.WriteUInt32(rInfo
.Size
);
141 rOStream
.WriteInt32(rInfo
.Width
);
142 rOStream
.WriteInt32(rInfo
.Hight
);
143 rOStream
.WriteUInt16(rInfo
.Planes
);
144 rOStream
.WriteUInt16(rInfo
.PixBits
);
145 rOStream
.WriteUInt32(rInfo
.Compress
);
146 rOStream
.WriteUInt32(rInfo
.ImgSize
);
147 rOStream
.WriteInt32(rInfo
.xDpmm
);
148 rOStream
.WriteInt32(rInfo
.yDpmm
);
149 rOStream
.WriteUInt32(rInfo
.ColUsed
);
150 rOStream
.WriteUInt32(rInfo
.ColMust
);
151 assert(rOStream
.GetError() || rOStream
.Tell() == nOldPos
+ BmpInfoHeaderSize
);
155 SvStream
& WriteRGBQuad(SvStream
& rOStream
, const RGBQuad
& rQuad
)
157 rOStream
.WriteBytes(&rQuad
, sizeof(rQuad
));
171 sal_uInt8
GetByte(SvStream
& rInp
);
174 sal_uInt8
PcxExpand::GetByte(SvStream
& rInp
)
179 rInp
.ReadBytes(&Data
, 1);
180 if ((Data
& 0xC0) == 0xC0) {
181 Count
=(Data
& 0x3F) -1;
182 rInp
.ReadBytes(&Data
, 1);
188 bool SgfFilterBMap(SvStream
& rInp
, SvStream
& rOut
, SgfHeader
& rHead
, SgfEntry
&)
190 BmpFileHeader aBmpHead
;
191 BmpInfoHeader aBmpInfo
;
192 sal_uInt16 nWdtInp
=(rHead
.Xsize
+7)/8; // width of input bitmap in bytes
193 sal_uInt16 nWdtOut
; // width of output bitmap in bytes
194 sal_uInt16 nColors
; // color count (1, 16, 256)
195 sal_uInt16 nColBits
; // number of bits per pixel (2, 4, 8)
196 sal_uInt16 i
,j
,k
; // column/row/plane counter
197 sal_uInt16 a
,b
; // helper variables
198 sal_uInt8 pl1
= 0; // masks for the planes
199 std::unique_ptr
<sal_uInt8
[]> pBuf
; // buffer for a pixel row
204 if (rHead
.Planes
<=1) nColBits
=1; else nColBits
=4; if (rHead
.Typ
==4) nColBits
=8;
206 nWdtOut
=((rHead
.Xsize
*nColBits
+31)/32)*4;
207 aBmpHead
.Typ
='B'+'M'*256;
208 aBmpHead
.SetOfs(sizeof(aBmpHead
)+sizeof(aBmpInfo
)+nColors
*4);
209 aBmpHead
.SetSize(aBmpHead
.GetOfs()+nWdtOut
*rHead
.Ysize
);
212 aBmpInfo
.Size
=sizeof(aBmpInfo
);
213 aBmpInfo
.Width
=rHead
.Xsize
;
214 aBmpInfo
.Hight
=rHead
.Ysize
;
216 aBmpInfo
.PixBits
=nColBits
;
223 pBuf
.reset(new sal_uInt8
[nWdtOut
]);
224 if (!pBuf
) return false; // error: no more memory available
225 WriteBmpFileHeader( rOut
, aBmpHead
);
226 WriteBmpInfoHeader( rOut
, aBmpInfo
);
227 memset(pBuf
.get(),0,nWdtOut
); // fill buffer with zeroes
232 WriteRGBQuad( rOut
, RGBQuad(0x00,0x00,0x00) ); // black
233 WriteRGBQuad( rOut
, RGBQuad(0xFF,0xFF,0xFF) ); // white
235 for (j
=0;j
<rHead
.Ysize
;j
++)
236 rOut
.WriteBytes(pBuf
.get(), nWdtOut
); // fill file with zeroes
237 for (j
=0;j
<rHead
.Ysize
;j
++) {
238 for(i
=0;i
<nWdtInp
;i
++) {
239 pBuf
[i
]=aPcx
.GetByte(rInp
);
241 for(i
=nWdtInp
;i
<nWdtOut
;i
++) pBuf
[i
]=0; // up to 3 bytes
242 rOut
.Seek(nOfs
+((sal_uLong
)rHead
.Ysize
-j
-1L)*(sal_uLong
)nWdtOut
); // write backwards
243 rOut
.WriteBytes(pBuf
.get(), nWdtOut
);
245 } else if (nColors
==16) {
246 sal_uInt8 pl2
= 0; // planes' masks
248 WriteRGBQuad( rOut
, RGBQuad(0x00,0x00,0x00) ); // black
249 WriteRGBQuad( rOut
, RGBQuad(0x24,0x24,0x24) ); // gray 80%
250 WriteRGBQuad( rOut
, RGBQuad(0x49,0x49,0x49) ); // gray 60%
251 WriteRGBQuad( rOut
, RGBQuad(0x92,0x92,0x92) ); // gray 40%
252 WriteRGBQuad( rOut
, RGBQuad(0x6D,0x6D,0x6D) ); // gray 30%
253 WriteRGBQuad( rOut
, RGBQuad(0xB6,0xB6,0xB6) ); // gray 20%
254 WriteRGBQuad( rOut
, RGBQuad(0xDA,0xDA,0xDA) ); // gray 10%
255 WriteRGBQuad( rOut
, RGBQuad(0xFF,0xFF,0xFF) ); // white
256 WriteRGBQuad( rOut
, RGBQuad(0x00,0x00,0x00) ); // black
257 WriteRGBQuad( rOut
, RGBQuad(0xFF,0x00,0x00) ); // red
258 WriteRGBQuad( rOut
, RGBQuad(0x00,0x00,0xFF) ); // blue
259 WriteRGBQuad( rOut
, RGBQuad(0xFF,0x00,0xFF) ); // magenta
260 WriteRGBQuad( rOut
, RGBQuad(0x00,0xFF,0x00) ); // green
261 WriteRGBQuad( rOut
, RGBQuad(0xFF,0xFF,0x00) ); // yellow
262 WriteRGBQuad( rOut
, RGBQuad(0x00,0xFF,0xFF) ); // cyan
263 WriteRGBQuad( rOut
, RGBQuad(0xFF,0xFF,0xFF) ); // white
266 for (j
=0;j
<rHead
.Ysize
;j
++)
267 rOut
.WriteBytes(pBuf
.get(), nWdtOut
); // fill file with zeroes
268 for (j
=0;j
<rHead
.Ysize
;j
++) {
269 memset(pBuf
.get(),0,nWdtOut
);
276 for(i
=0;i
<nWdtInp
;i
++) {
278 b
=aPcx
.GetByte(rInp
);
279 if (b
& 0x80) pBuf
[a
]|=pl1
;
280 if (b
& 0x40) pBuf
[a
]|=pl2
;
281 if (b
& 0x20) pBuf
[a
+1]|=pl1
;
282 if (b
& 0x10) pBuf
[a
+1]|=pl2
;
283 if (b
& 0x08) pBuf
[a
+2]|=pl1
;
284 if (b
& 0x04) pBuf
[a
+2]|=pl2
;
285 if (b
& 0x02) pBuf
[a
+3]|=pl1
;
286 if (b
& 0x01) pBuf
[a
+3]|=pl2
;
289 for(i
=nWdtInp
*4;i
<nWdtOut
;i
++) pBuf
[i
]=0; // up to 3 bytes
290 rOut
.Seek(nOfs
+((sal_uLong
)rHead
.Ysize
-j
-1L)*(sal_uLong
)nWdtOut
); // write backwards
291 rOut
.WriteBytes(pBuf
.get(), nWdtOut
);
293 } else if (nColors
==256) {
294 cRGB
[3]=0; // fourth palette entry for BMP
295 for (i
=0;i
<256;i
++) { // copy palette
296 rInp
.ReadBytes(cRGB
, 3);
297 pl1
=cRGB
[0]; // switch red and blue
300 rOut
.WriteBytes(cRGB
, 4);
304 for (j
=0;j
<rHead
.Ysize
;j
++)
305 rOut
.WriteBytes(pBuf
.get(), nWdtOut
); // fill file with zeroes
306 for (j
=0;j
<rHead
.Ysize
;j
++) {
307 for(i
=0;i
<rHead
.Xsize
;i
++)
308 pBuf
[i
]=aPcx
.GetByte(rInp
);
309 for(i
=rHead
.Xsize
;i
<nWdtOut
;i
++) pBuf
[i
]=0; // up to 3 bytes
310 rOut
.Seek(nOfs
+((sal_uLong
)rHead
.Ysize
-j
-1L)*(sal_uLong
)nWdtOut
); // write backwards
311 rOut
.WriteBytes(pBuf
.get(), nWdtOut
);
317 bool SgfBMapFilter(SvStream
& rInp
, SvStream
& rOut
)
319 sal_uLong nFileStart
; // offset of SgfHeaders. Usually 0.
323 bool bRet
=false; // return value
325 nFileStart
=rInp
.Tell();
326 ReadSgfHeader( rInp
, aHead
);
327 if (aHead
.ChkMagic() && (aHead
.Typ
==SgfBitImag0
|| aHead
.Typ
==SgfBitImag1
||
328 aHead
.Typ
==SgfBitImag2
|| aHead
.Typ
==SgfBitImgMo
))
330 bool bRdFlag
= false; // read graphics entry?
331 nNext
= aHead
.GetOffset();
332 while (nNext
&& !bRdFlag
&& !rInp
.GetError() && !rOut
.GetError()) {
333 rInp
.Seek(nFileStart
+nNext
);
334 ReadSgfEntry( rInp
, aEntr
);
335 nNext
=aEntr
.GetOffset();
336 if (aEntr
.Typ
==aHead
.Typ
) {
342 case SgfBitImgMo
: bRet
=SgfFilterBMap(rInp
,rOut
,aHead
,aEntr
); break;
347 if (rInp
.GetError()) bRet
=false;
351 // for StarDraw embedded SGF vector
358 bool SgfVectScal
=false;
360 Color
Hpgl2SvFarbe( sal_uInt8 nFarb
)
362 sal_uLong nColor
= COL_BLACK
;
364 switch (nFarb
& 0x07) {
365 case 0: nColor
=COL_WHITE
; break;
366 case 1: nColor
=COL_YELLOW
; break;
367 case 2: nColor
=COL_LIGHTMAGENTA
; break;
368 case 3: nColor
=COL_LIGHTRED
; break;
369 case 4: nColor
=COL_LIGHTCYAN
; break;
370 case 5: nColor
=COL_LIGHTGREEN
; break;
371 case 6: nColor
=COL_LIGHTBLUE
; break;
372 case 7: nColor
=COL_BLACK
; break;
374 Color
aColor( nColor
);
378 bool SgfFilterVect(SvStream
& rInp
, SgfHeader
& rHead
, SgfEntry
&, GDIMetaFile
& rMtf
)
380 ScopedVclPtrInstance
< VirtualDevice
> aOutDev
;
391 rMtf
.Record(aOutDev
.get());
392 aOutDev
->SetLineColor(Color(COL_BLACK
));
393 aOutDev
->SetFillColor(Color(COL_BLACK
));
395 while (!bEoDt
&& !rInp
.GetError()) {
396 ReadSgfVector( rInp
, aVect
); RecNr
++;
397 nFarb
=(sal_uInt8
) (aVect
.Flag
& 0x000F);
398 nLTyp
=(sal_uInt8
)((aVect
.Flag
& 0x00F0) >>4);
399 nOTyp
=(sal_uInt8
)((aVect
.Flag
& 0x0F00) >>8);
400 bEoDt
=(aVect
.Flag
& 0x4000) !=0;
401 bool bPDwn
=(aVect
.Flag
& 0x8000) !=0;
403 long x
=aVect
.x
-rHead
.Xoffs
;
404 long y
=rHead
.Ysize
-(aVect
.y
-rHead
.Yoffs
);
406 if (SgfVectXdiv
==0) SgfVectXdiv
=rHead
.Xsize
;
407 if (SgfVectYdiv
==0) SgfVectYdiv
=rHead
.Ysize
;
408 if (SgfVectXdiv
==0) SgfVectXdiv
=1;
409 if (SgfVectYdiv
==0) SgfVectYdiv
=1;
410 x
=SgfVectXofs
+ x
*SgfVectXmul
/SgfVectXdiv
;
411 y
=SgfVectYofs
+ y
*SgfVectXmul
/SgfVectYdiv
;
414 if (!bEoDt
&& !rInp
.GetError()) {
415 if (bPDwn
&& nLTyp
<=6) {
417 case 1: if (nFarb
!=nFrb0
) {
418 switch(rHead
.SwGrCol
) {
419 case SgfVectFarb
: aOutDev
->SetLineColor(Hpgl2SvFarbe(nFarb
)); break;
420 case SgfVectGray
: break;
421 case SgfVectWdth
: break;
424 aOutDev
->DrawLine(aP0
,aP1
); break; // line
425 case 2: break; // circle
426 case 3: break; // text
427 case 5: aOutDev
->DrawRect(Rectangle(aP0
,aP1
)); break; // rectangle (solid)
436 MapMode
aMap( MapUnit::Map10thMM
, Point(),
437 Fraction( 1, 4 ), Fraction( 1, 4 ) );
438 rMtf
.SetPrefMapMode( aMap
);
439 rMtf
.SetPrefSize( Size( (short)rHead
.Xsize
, (short)rHead
.Ysize
) );
443 bool SgfVectFilter(SvStream
& rInp
, GDIMetaFile
& rMtf
)
445 sal_uLong nFileStart
; // offset of SgfHeaders. Usually 0.
449 bool bRet
=false; // return value
451 nFileStart
=rInp
.Tell();
452 ReadSgfHeader( rInp
, aHead
);
453 if (aHead
.ChkMagic() && aHead
.Typ
==SGF_SIMPVECT
) {
454 nNext
=aHead
.GetOffset();
455 while (nNext
&& !rInp
.GetError()) {
456 rInp
.Seek(nFileStart
+nNext
);
457 ReadSgfEntry( rInp
, aEntr
);
458 nNext
=aEntr
.GetOffset();
459 if (aEntr
.Typ
==aHead
.Typ
) {
460 bRet
=SgfFilterVect(rInp
,aHead
,aEntr
,rMtf
);
467 /*************************************************************************
471 |* Description determine which kind of SGF/SGV it is
473 *************************************************************************/
474 sal_uInt8
CheckSgfTyp(SvStream
& rInp
, sal_uInt16
& nVersion
)
476 #if OSL_DEBUG_LEVEL > 1 // check record size, new Compiler had different alignment!
477 if (sizeof(SgfHeader
)!=SgfHeaderSize
||
478 sizeof(SgfEntry
) !=SgfEntrySize
||
479 sizeof(SgfVector
)!=SgfVectorSize
||
480 sizeof(BmpFileHeader
)!=BmpFileHeaderSize
||
481 sizeof(BmpInfoHeader
)!=BmpInfoHeaderSize
||
482 sizeof(RGBQuad
)!=RGBQuadSize
) return SGF_DONTKNOW
;
489 ReadSgfHeader( rInp
, aHead
);
491 if (aHead
.ChkMagic()) {
492 nVersion
=aHead
.Version
;
497 case SgfBitImgMo
: return SGF_BITIMAGE
;
498 case SgfSimpVect
: return SGF_SIMPVECT
;
499 case SgfPostScrp
: return SGF_POSTSCRP
;
500 case SgfStarDraw
: return SGF_STARDRAW
;
501 default : return SGF_DONTKNOW
;
508 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */