1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include "psputil.hxx"
28 
29 #include "printergfx.hxx"
30 #include "vcl/strhelper.hxx"
31 
32 namespace psp {
33 
34 const sal_uInt32 nLineLength = 80;
35 const sal_uInt32 nBufferSize = 16384;
36 
37 /*
38  *
39  * Bitmap compression / Hex encoding / Ascii85 Encoding
40  *
41  */
42 
~PrinterBmp()43 PrinterBmp::~PrinterBmp ()
44 { /* dont need this, but C50 does */ }
45 
46 /* virtual base class */
47 
48 class ByteEncoder
49 {
50 private:
51 
52 public:
53 
54     virtual void    EncodeByte (sal_uInt8 nByte) = 0;
55     virtual         ~ByteEncoder () = 0;
56 };
57 
~ByteEncoder()58 ByteEncoder::~ByteEncoder ()
59 { /* dont need this, but the C50 does */ }
60 
61 /* HexEncoder */
62 
63 class HexEncoder : public ByteEncoder
64 {
65 private:
66 
67     osl::File*      mpFile;
68     sal_uInt32      mnColumn;
69     sal_uInt32      mnOffset;
70     sal_Char        mpFileBuffer[nBufferSize + 16];
71 
72                     HexEncoder (); /* dont use */
73 
74 public:
75 
76     HexEncoder (osl::File* pFile);
77     virtual         ~HexEncoder ();
78     void            WriteAscii (sal_uInt8 nByte);
79     virtual void    EncodeByte (sal_uInt8 nByte);
80     void            FlushLine ();
81 };
82 
HexEncoder(osl::File * pFile)83 HexEncoder::HexEncoder (osl::File* pFile) :
84         mpFile (pFile),
85         mnColumn (0),
86         mnOffset (0)
87 {}
88 
~HexEncoder()89 HexEncoder::~HexEncoder ()
90 {
91     FlushLine ();
92     if (mnColumn > 0)
93         WritePS (mpFile, "\n");
94 }
95 
96 void
WriteAscii(sal_uInt8 nByte)97 HexEncoder::WriteAscii (sal_uInt8 nByte)
98 {
99     sal_uInt32 nOff = psp::getHexValueOf (nByte, mpFileBuffer + mnOffset);
100     mnColumn += nOff;
101     mnOffset += nOff;
102 
103     if (mnColumn >= nLineLength)
104     {
105         mnOffset += psp::appendStr ("\n", mpFileBuffer + mnOffset);
106         mnColumn = 0;
107     }
108     if (mnOffset >= nBufferSize)
109         FlushLine ();
110 }
111 
112 void
EncodeByte(sal_uInt8 nByte)113 HexEncoder::EncodeByte (sal_uInt8 nByte)
114 {
115     WriteAscii (nByte);
116 }
117 
118 void
FlushLine()119 HexEncoder::FlushLine ()
120 {
121     if (mnOffset > 0)
122     {
123         WritePS (mpFile, mpFileBuffer, mnOffset);
124         mnOffset = 0;
125     }
126 }
127 
128 /* Ascii85 encoder, is abi compatible with HexEncoder but writes a ~> to
129    indicate end of data EOD */
130 
131 class Ascii85Encoder : public ByteEncoder
132 {
133 private:
134 
135     osl::File*      mpFile;
136     sal_uInt32      mnByte;
137     sal_uInt8       mpByteBuffer[4];
138 
139     sal_uInt32      mnColumn;
140     sal_uInt32      mnOffset;
141     sal_Char        mpFileBuffer[nBufferSize + 16];
142 
143     Ascii85Encoder (); /* dont use */
144 
145     inline void     PutByte (sal_uInt8 nByte);
146     inline void     PutEOD ();
147     void            ConvertToAscii85 ();
148     void            FlushLine ();
149 
150 public:
151 
152     Ascii85Encoder (osl::File* pFile);
153     virtual         ~Ascii85Encoder ();
154     virtual void    EncodeByte (sal_uInt8 nByte);
155     void            WriteAscii (sal_uInt8 nByte);
156 };
157 
Ascii85Encoder(osl::File * pFile)158 Ascii85Encoder::Ascii85Encoder (osl::File* pFile) :
159         mpFile (pFile),
160         mnByte (0),
161         mnColumn (0),
162         mnOffset (0)
163 {}
164 
165 inline void
PutByte(sal_uInt8 nByte)166 Ascii85Encoder::PutByte (sal_uInt8 nByte)
167 {
168     mpByteBuffer [mnByte++] = nByte;
169 }
170 
171 inline void
PutEOD()172 Ascii85Encoder::PutEOD ()
173 {
174     WritePS (mpFile, "~>\n");
175 }
176 
177 void
ConvertToAscii85()178 Ascii85Encoder::ConvertToAscii85 ()
179 {
180     if (mnByte < 4)
181         std::memset (mpByteBuffer + mnByte, 0, (4 - mnByte) * sizeof(sal_uInt8));
182 
183     sal_uInt32 nByteValue =   mpByteBuffer[0] * 256 * 256 * 256
184         + mpByteBuffer[1] * 256 * 256
185         + mpByteBuffer[2] * 256
186         + mpByteBuffer[3];
187 
188     if (nByteValue == 0 && mnByte == 4)
189     {
190         /* special case of 4 Bytes in row */
191         mpFileBuffer [mnOffset] = 'z';
192 
193         mnOffset += 1;
194         mnColumn += 1;
195     }
196     else
197     {
198         /* real ascii85 encoding */
199         mpFileBuffer [mnOffset + 4] = (nByteValue % 85) + 33;
200         nByteValue /= 85;
201         mpFileBuffer [mnOffset + 3] = (nByteValue % 85) + 33;
202         nByteValue /= 85;
203         mpFileBuffer [mnOffset + 2] = (nByteValue % 85) + 33;
204         nByteValue /= 85;
205         mpFileBuffer [mnOffset + 1] = (nByteValue % 85) + 33;
206         nByteValue /= 85;
207         mpFileBuffer [mnOffset + 0] = (nByteValue % 85) + 33;
208 
209         mnColumn += (mnByte + 1);
210         mnOffset += (mnByte + 1);
211 
212         /* insert a newline if necessary */
213         if (mnColumn > nLineLength)
214         {
215             sal_uInt32 nEolOff = mnColumn - nLineLength;
216             sal_uInt32 nBufOff = mnOffset - nEolOff;
217 
218             std::memmove (mpFileBuffer + nBufOff + 1, mpFileBuffer + nBufOff, nEolOff);
219             mpFileBuffer[ nBufOff ] = '\n';
220 
221             mnOffset++;
222             mnColumn = nEolOff;
223         }
224     }
225 
226     mnByte = 0;
227 }
228 
229 void
WriteAscii(sal_uInt8 nByte)230 Ascii85Encoder::WriteAscii (sal_uInt8 nByte)
231 {
232     PutByte (nByte);
233     if (mnByte == 4)
234         ConvertToAscii85 ();
235 
236     if (mnColumn >= nLineLength)
237     {
238         mnOffset += psp::appendStr ("\n", mpFileBuffer + mnOffset);
239         mnColumn = 0;
240     }
241     if (mnOffset >= nBufferSize)
242         FlushLine ();
243 }
244 
245 void
EncodeByte(sal_uInt8 nByte)246 Ascii85Encoder::EncodeByte (sal_uInt8 nByte)
247 {
248     WriteAscii (nByte);
249 }
250 
251 void
FlushLine()252 Ascii85Encoder::FlushLine ()
253 {
254     if (mnOffset > 0)
255     {
256         WritePS (mpFile, mpFileBuffer, mnOffset);
257         mnOffset = 0;
258     }
259 }
260 
~Ascii85Encoder()261 Ascii85Encoder::~Ascii85Encoder ()
262 {
263     if (mnByte > 0)
264         ConvertToAscii85 ();
265     if (mnOffset > 0)
266         FlushLine ();
267     PutEOD ();
268 }
269 
270 /* LZW encoder */
271 
272 class LZWEncoder : public Ascii85Encoder
273 {
274 private:
275 
276     struct LZWCTreeNode
277     {
278         LZWCTreeNode*   mpBrother;      // next node with same parent
279         LZWCTreeNode*   mpFirstChild;   // first son
280         sal_uInt16      mnCode;         // code for the string
281         sal_uInt16      mnValue;        // pixelvalue
282     };
283 
284     LZWCTreeNode*   mpTable;    // LZW compression data
285     LZWCTreeNode*   mpPrefix;   // the compression is as same as the TIFF compression
286     sal_uInt16      mnDataSize;
287     sal_uInt16      mnClearCode;
288     sal_uInt16      mnEOICode;
289     sal_uInt16      mnTableSize;
290     sal_uInt16      mnCodeSize;
291     sal_uInt32      mnOffset;
292     sal_uInt32      mdwShift;
293 
294     LZWEncoder ();
295     void            WriteBits (sal_uInt16 nCode, sal_uInt16 nCodeLen);
296 
297 public:
298 
299     LZWEncoder (osl::File* pOutputFile);
300     ~LZWEncoder ();
301 
302     virtual void    EncodeByte (sal_uInt8 nByte);
303 };
304 
LZWEncoder(osl::File * pOutputFile)305 LZWEncoder::LZWEncoder(osl::File* pOutputFile) :
306         Ascii85Encoder (pOutputFile)
307 {
308     mnDataSize  = 8;
309 
310     mnClearCode = 1 << mnDataSize;
311     mnEOICode   = mnClearCode + 1;
312     mnTableSize = mnEOICode   + 1;
313     mnCodeSize  = mnDataSize  + 1;
314 
315     mnOffset    = 32;   // free bits in dwShift
316     mdwShift    = 0;
317 
318     mpTable = new LZWCTreeNode[ 4096 ];
319 
320     for (sal_uInt32 i = 0; i < 4096; i++)
321     {
322         mpTable[i].mpBrother    = NULL;
323         mpTable[i].mpFirstChild = NULL;
324         mpTable[i].mnCode       = i;
325         mpTable[i].mnValue      = (sal_uInt8)mpTable[i].mnCode;
326     }
327 
328     mpPrefix = NULL;
329 
330     WriteBits( mnClearCode, mnCodeSize );
331 }
332 
~LZWEncoder()333 LZWEncoder::~LZWEncoder()
334 {
335     if (mpPrefix)
336         WriteBits (mpPrefix->mnCode, mnCodeSize);
337 
338     WriteBits (mnEOICode, mnCodeSize);
339 
340     delete[] mpTable;
341 }
342 
343 void
WriteBits(sal_uInt16 nCode,sal_uInt16 nCodeLen)344 LZWEncoder::WriteBits (sal_uInt16 nCode, sal_uInt16 nCodeLen)
345 {
346     mdwShift |= (nCode << (mnOffset - nCodeLen));
347     mnOffset -= nCodeLen;
348     while (mnOffset < 24)
349     {
350         WriteAscii ((sal_uInt8)(mdwShift >> 24));
351         mdwShift <<= 8;
352         mnOffset += 8;
353     }
354     if (nCode == 257 && mnOffset != 32)
355         WriteAscii ((sal_uInt8)(mdwShift >> 24));
356 }
357 
358 void
EncodeByte(sal_uInt8 nByte)359 LZWEncoder::EncodeByte (sal_uInt8 nByte )
360 {
361     LZWCTreeNode*   p;
362     sal_uInt16      i;
363     sal_uInt8       nV;
364 
365     if (!mpPrefix)
366     {
367         mpPrefix = mpTable + nByte;
368     }
369     else
370     {
371         nV = nByte;
372         for (p = mpPrefix->mpFirstChild; p != NULL; p = p->mpBrother)
373         {
374             if (p->mnValue == nV)
375                 break;
376         }
377 
378         if (p != NULL)
379         {
380             mpPrefix = p;
381         }
382         else
383         {
384             WriteBits (mpPrefix->mnCode, mnCodeSize);
385 
386             if (mnTableSize == 409)
387             {
388                 WriteBits (mnClearCode, mnCodeSize);
389 
390                 for (i = 0; i < mnClearCode; i++)
391                     mpTable[i].mpFirstChild = NULL;
392 
393                 mnCodeSize = mnDataSize + 1;
394                 mnTableSize = mnEOICode + 1;
395             }
396             else
397             {
398                 if(mnTableSize == (sal_uInt16)((1 << mnCodeSize) - 1))
399                     mnCodeSize++;
400 
401                 p = mpTable + (mnTableSize++);
402                 p->mpBrother = mpPrefix->mpFirstChild;
403                 mpPrefix->mpFirstChild = p;
404                 p->mnValue = nV;
405                 p->mpFirstChild = NULL;
406             }
407 
408             mpPrefix = mpTable + nV;
409         }
410     }
411 }
412 
413 /*
414  *
415  * bitmap handling routines
416  *
417  */
418 
419 void
DrawBitmap(const Rectangle & rDest,const Rectangle & rSrc,const PrinterBmp & rBitmap)420 PrinterGfx::DrawBitmap (const Rectangle& rDest, const Rectangle& rSrc,
421                         const PrinterBmp& rBitmap)
422 {
423     double fScaleX = (double)rDest.GetWidth() / (double)rSrc.GetWidth();
424     double fScaleY = (double)rDest.GetHeight() / (double)rSrc.GetHeight();
425 
426     PSGSave ();
427     PSTranslate (rDest.BottomLeft());
428     PSScale (fScaleX, fScaleY);
429 
430     if (mnPSLevel >= 2)
431     {
432         if (rBitmap.GetDepth() == 1)
433         {
434             DrawPS2MonoImage (rBitmap, rSrc);
435         }
436         else
437         if (rBitmap.GetDepth() ==  8 && mbColor)
438         {
439             // if the palette is larger than the image itself print it as a truecolor
440             // image to save diskspace. This is important for printing transparent
441             // bitmaps that are disassembled into small pieces
442             sal_Int32 nImageSz   = rSrc.GetWidth() * rSrc.GetHeight();
443             sal_Int32 nPaletteSz = rBitmap.GetPaletteEntryCount();
444             if ((nImageSz < nPaletteSz) || (nImageSz < 24) )
445         	    DrawPS2TrueColorImage (rBitmap, rSrc);
446             else
447                 DrawPS2PaletteImage (rBitmap, rSrc);
448         }
449         else
450         if (rBitmap.GetDepth() == 24 && mbColor)
451         {
452         	DrawPS2TrueColorImage (rBitmap, rSrc);
453         }
454         else
455         {
456         	DrawPS2GrayImage (rBitmap, rSrc);
457         }
458     }
459     else
460     {
461         DrawPS1GrayImage (rBitmap, rSrc);
462     }
463 
464     PSGRestore ();
465 }
466 
467 /* XXX does not work XXX */
468 void
DrawBitmap(const Rectangle & rDest,const Rectangle & rSrc,const PrinterBmp &,const PrinterBmp &)469 PrinterGfx::DrawBitmap (const Rectangle& rDest, const Rectangle& rSrc,
470                         const PrinterBmp& /*rBitmap*/, const PrinterBmp& /*rTransBitmap*/)
471 {
472     double fScaleX = (double)rDest.GetWidth() / (double)rSrc.GetWidth();
473     double fScaleY = (double)rDest.GetHeight() / (double)rSrc.GetHeight();
474 
475     PSGSave ();
476     PSTranslate (rDest.BottomLeft());
477     PSScale (fScaleX, fScaleY);
478     PSGRestore ();
479 }
480 
481 /* XXX does not work XXX */
482 void
DrawMask(const Rectangle & rDest,const Rectangle & rSrc,const PrinterBmp &,PrinterColor &)483 PrinterGfx::DrawMask   (const Rectangle& rDest, const Rectangle& rSrc,
484                         const PrinterBmp &/*rBitmap*/, PrinterColor& /*rMaskColor*/)
485 {
486     double fScaleX = (double)rDest.GetWidth() / (double)rSrc.GetWidth();
487     double fScaleY = (double)rDest.GetHeight() / (double)rSrc.GetHeight();
488 
489     PSGSave ();
490     PSTranslate (rDest.BottomLeft());
491     PSScale (fScaleX, fScaleY);
492     PSGRestore ();
493 }
494 
495 /*
496  *
497  * Implementation: PS Level 1
498  *
499  */
500 
501 void
DrawPS1GrayImage(const PrinterBmp & rBitmap,const Rectangle & rArea)502 PrinterGfx::DrawPS1GrayImage (const PrinterBmp& rBitmap, const Rectangle& rArea)
503 {
504     sal_uInt32 nWidth  = rArea.GetWidth();
505     sal_uInt32 nHeight = rArea.GetHeight();
506 
507     sal_Char  pGrayImage [512];
508     sal_Int32 nChar = 0;
509 
510     // image header
511     nChar += psp::getValueOf (nWidth,                           pGrayImage + nChar);
512     nChar += psp::appendStr  (" ",                              pGrayImage + nChar);
513     nChar += psp::getValueOf (nHeight,                          pGrayImage + nChar);
514     nChar += psp::appendStr  (" 8 ",                            pGrayImage + nChar);
515     nChar += psp::appendStr  ("[ 1 0 0 1 0 ",                   pGrayImage + nChar);
516     nChar += psp::getValueOf (nHeight,                          pGrayImage + nChar);
517     nChar += psp::appendStr  ("]",                              pGrayImage + nChar);
518     nChar += psp::appendStr  (" {currentfile ",                 pGrayImage + nChar);
519     nChar += psp::getValueOf (nWidth,                           pGrayImage + nChar);
520     nChar += psp::appendStr  (" string readhexstring pop}\n",   pGrayImage + nChar);
521     nChar += psp::appendStr  ("image\n",                        pGrayImage + nChar);
522 
523     WritePS (mpPageBody, pGrayImage);
524 
525     // image body
526     HexEncoder* pEncoder = new HexEncoder (mpPageBody);
527 
528     for (long nRow = rArea.Top(); nRow <= rArea.Bottom(); nRow++)
529     {
530         for (long nColumn = rArea.Left(); nColumn <= rArea.Right(); nColumn++)
531         {
532             sal_uChar nByte = rBitmap.GetPixelGray (nRow, nColumn);
533             pEncoder->EncodeByte (nByte);
534         }
535     }
536 
537     delete pEncoder;
538 
539     WritePS (mpPageBody, "\n");
540 }
541 
542 /*
543  *
544  * Implementation: PS Level 2
545  *
546  */
547 
548 void
writePS2ImageHeader(const Rectangle & rArea,psp::ImageType nType)549 PrinterGfx::writePS2ImageHeader (const Rectangle& rArea, psp::ImageType nType)
550 {
551     sal_Int32 nChar = 0;
552     sal_Char  pImage [512];
553 
554     sal_Int32 nDictType = 0;
555     switch (nType)
556     {
557         case psp::TrueColorImage:  nDictType = 0; break;
558         case psp::PaletteImage:    nDictType = 1; break;
559         case psp::GrayScaleImage:  nDictType = 2; break;
560         case psp::MonochromeImage: nDictType = 3; break;
561         default: break;
562     }
563     sal_Int32 nCompressType = mbCompressBmp ? 1 : 0;
564 
565     nChar += psp::getValueOf (rArea.GetWidth(),  pImage + nChar);
566     nChar += psp::appendStr  (" ",               pImage + nChar);
567     nChar += psp::getValueOf (rArea.GetHeight(), pImage + nChar);
568     nChar += psp::appendStr  (" ",               pImage + nChar);
569     nChar += psp::getValueOf (nDictType,         pImage + nChar);
570     nChar += psp::appendStr  (" ",               pImage + nChar);
571     nChar += psp::getValueOf (nCompressType,     pImage + nChar);
572     nChar += psp::appendStr  (" psp_imagedict image\n", pImage + nChar);
573 
574     WritePS (mpPageBody, pImage);
575 }
576 
577 void
writePS2Colorspace(const PrinterBmp & rBitmap,psp::ImageType nType)578 PrinterGfx::writePS2Colorspace(const PrinterBmp& rBitmap, psp::ImageType nType)
579 {
580     switch (nType)
581     {
582         case psp::GrayScaleImage:
583 
584             WritePS (mpPageBody, "/DeviceGray setcolorspace\n");
585             break;
586 
587         case psp::TrueColorImage:
588 
589             WritePS (mpPageBody, "/DeviceRGB setcolorspace\n");
590             break;
591 
592         case psp::MonochromeImage:
593         case psp::PaletteImage:
594         {
595 
596             sal_Int32 nChar = 0;
597             sal_Char  pImage [4096];
598 
599             const sal_uInt32 nSize = rBitmap.GetPaletteEntryCount();
600 
601             nChar += psp::appendStr ("[/Indexed /DeviceRGB ", pImage + nChar);
602             nChar += psp::getValueOf (nSize - 1, pImage + nChar);
603             if (mbCompressBmp)
604                 nChar += psp::appendStr ("\npsp_lzwstring\n", pImage + nChar);
605             else
606                 nChar += psp::appendStr ("\npsp_ascii85string\n", pImage + nChar);
607             WritePS (mpPageBody, pImage);
608 
609             ByteEncoder* pEncoder = mbCompressBmp ? new LZWEncoder(mpPageBody)
610                                                   : new Ascii85Encoder(mpPageBody);
611             for (sal_uInt32 i = 0; i < nSize; i++)
612             {
613                 PrinterColor aColor = rBitmap.GetPaletteColor(i);
614 
615                 pEncoder->EncodeByte (aColor.GetRed());
616                 pEncoder->EncodeByte (aColor.GetGreen());
617                 pEncoder->EncodeByte (aColor.GetBlue());
618             }
619             delete pEncoder;
620 
621             WritePS (mpPageBody, "pop ] setcolorspace\n");
622         }
623         break;
624         default: break;
625     }
626 }
627 
628 void
DrawPS2GrayImage(const PrinterBmp & rBitmap,const Rectangle & rArea)629 PrinterGfx::DrawPS2GrayImage (const PrinterBmp& rBitmap, const Rectangle& rArea)
630 {
631     writePS2Colorspace(rBitmap, psp::GrayScaleImage);
632     writePS2ImageHeader(rArea, psp::GrayScaleImage);
633 
634     ByteEncoder* pEncoder = mbCompressBmp ? new LZWEncoder(mpPageBody)
635                                           : new Ascii85Encoder(mpPageBody);
636 
637     for (long nRow = rArea.Top(); nRow <= rArea.Bottom(); nRow++)
638     {
639         for (long nColumn = rArea.Left(); nColumn <= rArea.Right(); nColumn++)
640         {
641             sal_uChar nByte = rBitmap.GetPixelGray (nRow, nColumn);
642             pEncoder->EncodeByte (nByte);
643         }
644     }
645 
646     delete pEncoder;
647 }
648 
649 void
DrawPS2MonoImage(const PrinterBmp & rBitmap,const Rectangle & rArea)650 PrinterGfx::DrawPS2MonoImage (const PrinterBmp& rBitmap, const Rectangle& rArea)
651 {
652     writePS2Colorspace(rBitmap, psp::MonochromeImage);
653     writePS2ImageHeader(rArea, psp::MonochromeImage);
654 
655     ByteEncoder* pEncoder = mbCompressBmp ? new LZWEncoder(mpPageBody)
656                                           : new Ascii85Encoder(mpPageBody);
657 
658     for (long nRow = rArea.Top(); nRow <= rArea.Bottom(); nRow++)
659     {
660         long      nBitPos = 0;
661         sal_uChar nBit    = 0;
662         sal_uChar nByte   = 0;
663 
664         for (long nColumn = rArea.Left(); nColumn <= rArea.Right(); nColumn++)
665         {
666             nBit   = rBitmap.GetPixelIdx (nRow, nColumn);
667             nByte |= nBit << (7 - nBitPos);
668 
669             if (++nBitPos == 8)
670             {
671                 pEncoder->EncodeByte (nByte);
672                 nBitPos = 0;
673                 nByte   = 0;
674             }
675         }
676         // keep the row byte aligned
677         if (nBitPos != 0)
678             pEncoder->EncodeByte (nByte);
679     }
680 
681     delete pEncoder;
682 }
683 
684 void
DrawPS2PaletteImage(const PrinterBmp & rBitmap,const Rectangle & rArea)685 PrinterGfx::DrawPS2PaletteImage (const PrinterBmp& rBitmap, const Rectangle& rArea)
686 {
687     writePS2Colorspace(rBitmap, psp::PaletteImage);
688     writePS2ImageHeader(rArea, psp::PaletteImage);
689 
690     ByteEncoder* pEncoder = mbCompressBmp ? new LZWEncoder(mpPageBody)
691                                           : new Ascii85Encoder(mpPageBody);
692 
693     for (long nRow = rArea.Top(); nRow <= rArea.Bottom(); nRow++)
694     {
695         for (long nColumn = rArea.Left(); nColumn <= rArea.Right(); nColumn++)
696         {
697             sal_uChar nByte = rBitmap.GetPixelIdx (nRow, nColumn);
698             pEncoder->EncodeByte (nByte);
699         }
700     }
701 
702     delete pEncoder;
703 }
704 
705 void
DrawPS2TrueColorImage(const PrinterBmp & rBitmap,const Rectangle & rArea)706 PrinterGfx::DrawPS2TrueColorImage (const PrinterBmp& rBitmap, const Rectangle& rArea)
707 {
708     writePS2Colorspace(rBitmap, psp::TrueColorImage);
709     writePS2ImageHeader(rArea, psp::TrueColorImage);
710 
711     ByteEncoder* pEncoder = mbCompressBmp ? new LZWEncoder(mpPageBody)
712                                           : new Ascii85Encoder(mpPageBody);
713 
714     for (long nRow = rArea.Top(); nRow <= rArea.Bottom(); nRow++)
715     {
716         for (long nColumn = rArea.Left(); nColumn <= rArea.Right(); nColumn++)
717         {
718             PrinterColor aColor = rBitmap.GetPixelRGB (nRow, nColumn);
719             pEncoder->EncodeByte (aColor.GetRed());
720             pEncoder->EncodeByte (aColor.GetGreen());
721             pEncoder->EncodeByte (aColor.GetBlue());
722         }
723     }
724 
725     delete pEncoder;
726 }
727 
728 } /* namespace psp */
729