Tizen 2.1 base
[platform/upstream/hplip.git] / prnt / hpcups / Mode9.cpp
1 /*****************************************************************************\
2   Mode9.cpp : implementaiton of Mode9 class
3
4   Copyright (c) 1996 - 2001, Hewlett-Packard Co.
5   All rights reserved.
6
7   Redistribution and use in source and binary forms, with or without
8   modification, are permitted provided that the following conditions
9   are met:
10   1. Redistributions of source code must retain the above copyright
11      notice, this list of conditions and the following disclaimer.
12   2. Redistributions in binary form must reproduce the above copyright
13      notice, this list of conditions and the following disclaimer in the
14      documentation and/or other materials provided with the distribution.
15   3. Neither the name of Hewlett-Packard nor the names of its
16      contributors may be used to endorse or promote products derived
17      from this software without specific prior written permission.
18
19   THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
22   NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24   TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 \*****************************************************************************/
30
31 #include "Mode9.h"
32 #include "Pipeline.h"
33 Mode9::Mode9 (unsigned int RasterSize, bool bPackedBits)
34     : Compressor(RasterSize, true)
35 {
36     if (constructor_error != NO_ERROR)  // if error in base constructor
37         return;
38
39     // Allocate double the RasterSize to accommodate worst case
40     compressBuf = (BYTE*) new BYTE[RasterSize * 2];
41     if (compressBuf == NULL)
42         constructor_error=ALLOCMEM_ERROR;
43
44     memset(compressBuf, 0, RasterSize * 2);
45     memset(SeedRow,0,RasterSize);
46
47     ResetSeedRow = false;
48     m_bPackedBits = bPackedBits;
49 }
50
51 Mode9::~Mode9()
52 { }
53
54 ////////////////////////////////////////////////////////////////////////////
55
56 typedef union {
57     unsigned char comchar;  /* command byte as char */
58     struct
59     {
60 #if defined(APDK_LITTLE_ENDIAN) || defined(LITTLE_ENDIAN_HW)
61         unsigned replace_count:3;   /* replace count 1-7, 8=8+next byte */
62         unsigned roff:4;    /* relative offset 0-14, 15=15+next byte */
63         unsigned type:1;      /* type of replacement: 0=mode0, 1=mode1 */
64 #else
65         unsigned type:1;      /* type of replacement: 0=mode0, 1=mode1 */
66         unsigned roff:4;    /* relative offset 0-14, 15=15+next byte */
67         unsigned replace_count:3;   /* replace count 1-7, 8=8+next byte */
68 #endif
69     } bitf0;
70     struct
71     {
72 #if defined(APDK_LITTLE_ENDIAN) || defined(LITTLE_ENDIAN_HW)
73         unsigned replace_count:5;   /* replace count 2-32, 33=33+next byte */
74         unsigned roff:2;    /* relative offset 0-2, 3=3+next byte */
75         unsigned type:1;      /* type of replacement: 0=mode0, 1=mode1 */
76 #else
77         unsigned type:1;      /* type of replacement: 0=mode0, 1=mode1 */
78         unsigned roff:2;    /* relative offset 0-2, 3=3+next byte */
79         unsigned replace_count:5;   /* replace count 2-32, 33=33+next byte */
80 #endif
81     } bitf1;
82 } Mode9_comtype;
83
84 #ifndef MIN
85 #define MIN(a,b)    (((a)>=(b))?(b):(a))
86 #endif
87
88 #define kPCLMode9           9
89
90 #define MAX_OFFSET0         14      /* Largest unscaled value an offset can have before extra byte is needed. */
91 #define OFFSET_START0       0
92 #define MAX_COUNT0          6       /* Largest unscaled value a count can have before extra byte is needed */
93 #define COUNT_START0        1       /* What a count of zero has a value of. */
94
95 #define MAX_OFFSET1         2
96 #define OFFSET_START1       0
97 #define MAX_COUNT1          30
98 #define COUNT_START1        2
99
100 //*********************************************************
101 // This is based on code that came from Kevin Hudson.
102
103 void Mode9::Flush()
104 {
105     if (!seeded)
106         return;
107
108     compressedsize=0;
109     iRastersReady=0;
110     seeded = false;
111     memset (SeedRow, 0, inputsize);
112 }
113
114 bool Mode9::Process(RASTERDATA* input)
115 // compresses input data,
116 // result in Mode9::compressbuf,
117 // updates compressedsize
118 {
119     if (input==NULL || 
120         (input->rasterdata[COLORTYPE_COLOR]==NULL && input->rasterdata[COLORTYPE_BLACK]==NULL))    // flushing pipeline
121     {
122         Flush();
123         return false;
124     }
125     else
126         seeded = true;
127
128     if (!ResetSeedRow && input->rasterdata[myplane] == 0)
129     {
130         compressedsize=0;
131         iRastersReady=1;
132         return true;
133     }
134
135     memset(compressBuf, 0, inputsize * 2);
136
137     unsigned int originalsize=input->rastersize[myplane];
138     unsigned int size=input->rastersize[myplane];
139     unsigned int layer;
140
141     //  Convert 8 bit per pixel data into 1 bit per pixel data
142     if (myplane == COLORTYPE_BLACK)
143     {
144         if (input->rasterdata[myplane] == 0)
145         {
146             memset(originalKData, 0, inputsize+1);
147             size = originalsize = inputsize;
148         }
149         else
150         {
151             size = originalsize = (input->rastersize[myplane]+7)/8;
152             memset(originalKData, 0, size);
153
154             memcpy(originalKData, input->rasterdata[myplane], size);
155             if (!m_bPackedBits)
156             {
157                 int curBit = 0x80, curByte = 0;
158                 for (int i=0; i<input->rastersize[myplane]; i++)
159                 {
160                     if (input->rasterdata[myplane][i])
161                     {
162                         originalKData[curByte] |= curBit;
163                     }
164                     if (curBit == 0x01)
165                     {
166                         curByte++;
167                         curBit = 0x80;
168                     }
169                     else
170                     {
171                         curBit = curBit >> 1;
172                     }
173                 }
174             }
175             ResetSeedRow = true;
176         }
177     }
178     if ((myphase) && (myphase->prev))       // if in pipeline, as opposed to autonomous call
179     {
180         layer = myphase->prev->Exec->iRastersDelivered;
181     }
182     else layer = 1;
183
184     if (myplane == COLORTYPE_BLACK)
185     {
186         layer = 1;
187     }
188
189     layer--;    // using as offset
190     char *sptr = (char *)(&SeedRow[size*layer]);
191
192     BYTE *nptr;
193     if (myplane == COLORTYPE_BLACK)
194     {
195         nptr = originalKData;
196     }
197     else
198     {
199         nptr = input->rasterdata[myplane];
200     }
201     BYTE *tempPtr;
202     char last_byte;
203     unsigned int    offset,byte_count,rem_count;
204     Mode9_comtype       command;
205     char* dest=    (char*) compressBuf;
206     register char *dptr=dest;
207
208     while ( size > 0 )
209     {
210         offset = 0;
211
212         if (seeded)
213         {
214             /* find a difference between the seed row and this row. */
215             while ((offset < size) && (*sptr++ == *nptr++))
216             {
217                 offset++;
218             }
219             sptr--;
220             nptr--;
221         }
222
223         if ( offset >= size )   /* too far to find diff, bail */
224           goto bail;
225
226         size -= offset;
227
228         if ((*nptr != nptr[1]) || (size < 2))   /************  if doing a mode 0 **********/
229         {
230             command.bitf0.type = 0;
231             last_byte = *nptr++;   /* keep track of the last_byte */
232             sptr++;        /* seed pointer must keep up with nptr */
233             byte_count = 1;
234
235             /* Now find all of the bytes in a row that don't match
236                either a run of mode3 or mode 1.  A slight
237                optimization here would be to not jump out of this
238                run of mode 0 for a single mode 3 or two mode 1
239                bytes if we have to jump right back into mode 0,
240                especially if there are already 7 mode 0 bytes here
241                (we've already spent the extra byte for the
242                byte-count) */
243             while ((*sptr++ != *nptr) && (last_byte != *nptr) && (byte_count < size))
244             {
245                byte_count++;
246                last_byte = *nptr++;
247             }
248             sptr--;
249
250             /* Adjust the count if the last_byte == current_byte.
251                Save these bytes for the upcomming run of mode 1. */
252             if ((byte_count < size) && (last_byte == (char)*nptr))
253             {
254                 nptr--;  /* Now sptr points to first byte in the new run of mode 1. */
255                 sptr--;
256                 byte_count--;
257             }
258
259             size -= byte_count;
260             /* Now output full command.  If offset is over 14 then
261                need optional offset bytes.  If byte count is over 7
262                then need optional byte count. */
263
264             if (offset > (MAX_OFFSET0+OFFSET_START0))
265                 command.bitf0.roff = MAX_OFFSET0+1;
266             else
267                 command.bitf0.roff = offset-OFFSET_START0;
268
269             if (byte_count > (MAX_COUNT0+COUNT_START0))
270                 command.bitf0.replace_count = MAX_COUNT0+1;
271             else
272                 command.bitf0.replace_count = byte_count-COUNT_START0;
273
274             *dptr++ = command.comchar;
275
276             if (offset > (MAX_OFFSET0+OFFSET_START0))
277             {
278                 offset -= (MAX_OFFSET0+OFFSET_START0+1);
279                 if (offset == 0)
280                 {
281                     *dptr++ = 0;
282                 }
283                 else
284                 {
285                      while( offset )
286                      {
287                        *dptr++ = MIN ( offset, 255 );
288
289                        if ( offset == 255 )
290                        *dptr++ = 0;
291
292                         offset -= MIN ( offset, 255 );
293                     }
294                 }
295             }
296
297             if (byte_count > (MAX_COUNT0+COUNT_START0))
298             {
299                 rem_count = byte_count - (MAX_COUNT0+COUNT_START0+1);
300                 if (rem_count == 0)
301                     *dptr++ = 0;
302                 else
303                 {
304                     while( rem_count )
305                     {
306                         *dptr++ = MIN ( rem_count, 255 );
307
308                         if ( rem_count == 255 )
309                         *dptr++ = 0;
310
311                          rem_count -= MIN ( rem_count, 255 );
312                     }
313                 }
314             }
315
316             /* Now output the run of bytes.  First set up a pointer to the first source byte. */
317
318             tempPtr = nptr - byte_count;
319             for(;byte_count;byte_count--)
320             {
321                 *dptr++ = *tempPtr++;
322             }
323
324         } else      /************ If doing a mode 1 *************/
325         {
326             /* mode 1, next two bytes are equal */
327             command.bitf1.type = 1;
328             nptr++;
329             last_byte = *nptr++;
330             byte_count = 2;
331
332             while ((last_byte == *nptr++) && (byte_count < size))
333             {
334                byte_count++;
335             }
336             nptr--;
337             sptr += byte_count;
338             size -= byte_count;
339
340             if (offset > (MAX_OFFSET1+OFFSET_START1))
341                 command.bitf1.roff = MAX_OFFSET1+1;
342             else
343                 command.bitf1.roff = offset-OFFSET_START1;
344
345             if (byte_count > (MAX_COUNT1+COUNT_START1))
346                 command.bitf1.replace_count = MAX_COUNT1+1;
347             else
348                 command.bitf1.replace_count =  byte_count-COUNT_START1;
349
350             *dptr++ = command.comchar;
351
352             if (offset > (MAX_OFFSET1+OFFSET_START1))
353             {
354                 offset -= (MAX_OFFSET1+OFFSET_START1+1);
355                 if (offset == 0)
356                 {
357                  *dptr++ = 0;
358                 }
359                 else
360                 {
361                      while( offset )
362                      {
363                         *dptr++ = MIN ( offset, 255 );
364
365                         if ( offset == 255 )
366                             *dptr++ = 0;
367
368                         offset -= MIN ( offset, 255 );
369                     }
370                 }
371             }  /* if (offset > MAX...  */
372
373             if (byte_count > (MAX_COUNT1+COUNT_START1))
374             {
375                 rem_count = byte_count - (MAX_COUNT1+COUNT_START1+1);
376                 if (rem_count == 0)
377                     *dptr++ = 0;
378                 else
379                 {
380                     while( rem_count )
381                     {
382                         *dptr++ = MIN ( rem_count, 255 );
383
384                         if ( rem_count == 255 )
385                             *dptr++ = 0;
386
387                         rem_count -= MIN ( rem_count, 255 );
388                     }
389                  }
390              }  /* if (byte_count > ... */
391
392              *dptr++ = last_byte;  /* Now output the repeated byte. */
393         }
394     }  /* while (size > 0) */
395
396 bail:
397     size = static_cast<int>((dptr - dest));
398     compressedsize = size;
399     if (myplane == COLORTYPE_BLACK)
400     {
401         memcpy(&(SeedRow[layer*originalsize]), originalKData, originalsize);
402     }
403     else
404     {
405         memcpy(&(SeedRow[layer*originalsize]), input->rasterdata[myplane], originalsize);
406     }
407     seeded = true;
408     iRastersReady=1;
409
410     return true;
411 }
412
413 bool Mode9::NextOutputRaster(RASTERDATA& next_raster)
414 // since we return 1-for-1, just return result first call
415 {
416     if (iRastersReady==0){
417         return false;
418     }
419     iRastersReady=0;
420     if (myplane == COLORTYPE_BLACK)
421     {
422         if (compressedsize != 0)
423         {
424             next_raster.rastersize[COLORTYPE_BLACK] = compressedsize;
425             next_raster.rasterdata[COLORTYPE_BLACK] = compressBuf;
426         }
427         else
428         {
429             next_raster.rastersize[COLORTYPE_BLACK] = 0;
430             next_raster.rasterdata[COLORTYPE_BLACK] = raster.rasterdata[COLORTYPE_BLACK];
431         }
432         next_raster.rastersize[COLORTYPE_COLOR] = raster.rastersize[COLORTYPE_COLOR];
433         next_raster.rasterdata[COLORTYPE_COLOR] = raster.rasterdata[COLORTYPE_COLOR];
434         return true;
435     }
436
437     if (myplane == COLORTYPE_COLOR)
438     {
439         if (compressedsize != 0)
440         {
441             next_raster.rastersize[COLORTYPE_COLOR] = compressedsize;
442             next_raster.rasterdata[COLORTYPE_COLOR] = compressBuf;
443         }
444         else
445         {
446             next_raster.rastersize[COLORTYPE_COLOR] = 0;
447             next_raster.rasterdata[COLORTYPE_COLOR] = raster.rasterdata[COLORTYPE_COLOR];
448         }
449         next_raster.rastersize[COLORTYPE_BLACK] = raster.rastersize[COLORTYPE_BLACK];
450         next_raster.rasterdata[COLORTYPE_BLACK] = raster.rasterdata[COLORTYPE_BLACK];
451     }
452
453     return true;
454 }
455