Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / source / filter / sgfbram.cxx
blob277e4af3236637f58af5ac9af702876118b9d364
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <string.h>
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 );
51 #endif
52 return rIStream;
55 bool SgfHeader::ChkMagic()
56 { return Magic=='J'*256+'J'; }
58 sal_uInt32 SgfHeader::GetOffset()
59 { return sal_uInt32(OfsLo)+0x00010000*sal_uInt32(OfsHi); }
61 SgfEntry::SgfEntry()
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);
76 #endif
77 return rIStream;
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);
92 #endif
93 return rIStream;
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 );
106 #endif
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 );
116 #endif
117 return rOStream;
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 );
151 #endif
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 );
165 #endif
166 return rOStream;
169 SvStream& WriteRGBQuad(SvStream& rOStream, const RGBQuad& rQuad)
171 rOStream.Write(&rQuad, sizeof(rQuad));
172 return rOStream;
175 class PcxExpand
177 private:
178 sal_uInt16 Count;
179 sal_uInt8 Data;
180 public:
181 PcxExpand()
182 : Count(0)
183 , Data(0)
185 sal_uInt8 GetByte(SvStream& rInp);
188 sal_uInt8 PcxExpand::GetByte(SvStream& rInp)
190 if (Count>0) {
191 Count--;
192 } else {
193 rInp.Read(&Data, 1);
194 if ((Data & 0xC0) == 0xC0) {
195 Count=(Data & 0x3F) -1;
196 rInp.Read(&Data, 1);
199 return Data;
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
214 PcxExpand aPcx;
215 sal_uLong nOfs;
216 sal_uInt8 cRGB[4];
218 if (rHead.Planes<=1) nColBits=1; else nColBits=4; if (rHead.Typ==4) nColBits=8;
219 nColors=1<<nColBits;
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);
224 aBmpHead.Reserve1=0;
225 aBmpHead.Reserve2=0;
226 aBmpInfo.Size=sizeof(aBmpInfo);
227 aBmpInfo.Width=rHead.Xsize;
228 aBmpInfo.Hight=rHead.Ysize;
229 aBmpInfo.Planes=1;
230 aBmpInfo.PixBits=nColBits;
231 aBmpInfo.Compress=0;
232 aBmpInfo.ImgSize=0;
233 aBmpInfo.xDpmm=0;
234 aBmpInfo.yDpmm=0;
235 aBmpInfo.ColUsed=0;
236 aBmpInfo.ColMust=0;
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
243 if (nColors==2)
246 WriteRGBQuad( rOut, RGBQuad(0x00,0x00,0x00) ); // black
247 WriteRGBQuad( rOut, RGBQuad(0xFF,0xFF,0xFF) ); // white
248 nOfs=rOut.Tell();
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
279 nOfs=rOut.Tell();
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);
284 for(k=0;k<4;k++) {
285 if (k==0) {
286 pl1=0x10; pl2=0x01;
287 } else {
288 pl1<<=1; pl2<<=1;
290 for(i=0;i<nWdtInp;i++) {
291 a=i*4;
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
310 rInp.Read(cRGB, 3);
311 pl1=cRGB[0]; // switch red and blue
312 cRGB[0]=cRGB[2];
313 cRGB[2]=pl1;
314 rOut.Write(cRGB, 4);
317 nOfs=rOut.Tell();
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);
328 return true;
331 bool SgfBMapFilter(SvStream& rInp, SvStream& rOut)
333 sal_uLong nFileStart; // offset of SgfHeaders. Usually 0.
334 SgfHeader aHead;
335 SgfEntry aEntr;
336 sal_uLong nNext;
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) {
350 bRdFlag=true;
351 switch(aEntr.Typ) {
352 case SgfBitImag0:
353 case SgfBitImag1:
354 case SgfBitImag2:
355 case SgfBitImgMo: bRet=SgfFilterBMap(rInp,rOut,aHead,aEntr); break;
358 } // while(nNext)
360 if (rInp.GetError()) bRet=false;
361 return bRet;
364 // for StarDraw embedded SGF vector
365 long SgfVectXofs=0;
366 long SgfVectYofs=0;
367 long SgfVectXmul=0;
368 long SgfVectYmul=0;
369 long SgfVectXdiv=0;
370 long SgfVectYdiv=0;
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 );
388 return aColor;
391 bool SgfFilterVect(SvStream& rInp, SgfHeader& rHead, SgfEntry&, GDIMetaFile& rMtf)
393 ScopedVclPtrInstance< VirtualDevice > aOutDev;
394 SgfVector aVect;
395 sal_uInt8 nFarb;
396 sal_uInt8 nFrb0=7;
397 sal_uInt8 nLTyp;
398 sal_uInt8 nOTyp;
399 bool bEoDt=false;
400 Point aP0(0,0);
401 Point aP1(0,0);
402 sal_uInt16 RecNr=0;
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);
418 if (SgfVectScal) {
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;
426 aP1=Point(x,y);
427 if (!bEoDt && !rInp.GetError()) {
428 if (bPDwn && nLTyp<=6) {
429 switch(nOTyp) {
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)
443 aP0=aP1;
444 nFrb0=nFarb;
447 rMtf.Stop();
448 rMtf.WindStart();
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 ) );
453 return true;
456 bool SgfVectFilter(SvStream& rInp, GDIMetaFile& rMtf)
458 sal_uLong nFileStart; // offset of SgfHeaders. Usually 0.
459 SgfHeader aHead;
460 SgfEntry aEntr;
461 sal_uLong nNext;
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);
475 } // while(nNext)
477 return bRet;
480 /*************************************************************************
482 |* CheckSgfTyp()
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;
496 #endif
498 sal_uLong nPos;
499 SgfHeader aHead;
500 nVersion=0;
501 nPos=rInp.Tell();
502 ReadSgfHeader( rInp, aHead );
503 rInp.Seek(nPos);
504 if (aHead.ChkMagic()) {
505 nVersion=aHead.Version;
506 switch(aHead.Typ) {
507 case SgfBitImag0:
508 case SgfBitImag1:
509 case SgfBitImag2:
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;
516 } else {
517 return SGF_DONTKNOW;
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */