1/***********************************************************************
2 *                                                                     *
3 * $Id: hpgspcl.c 367 2006-10-25 06:45:31Z softadm $
4 *                                                                     *
5 * hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript   *
6 *        API for rendering a scene and thus renders to a variety of   *
7 *        devices and fileformats.                                     *
8 *                                                                     *
9 * (C) 2004-2006 ev-i Informationstechnologie GmbH  http://www.ev-i.at *
10 *                                                                     *
11 * Author: Wolfgang Glas                                               *
12 *                                                                     *
13 *  hpgs is free software; you can redistribute it and/or              *
14 * modify it under the terms of the GNU Lesser General Public          *
15 * License as published by the Free Software Foundation; either        *
16 * version 2.1 of the License, or (at your option) any later version.  *
17 *                                                                     *
18 * hpgs is distributed in the hope that it will be useful,             *
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of      *
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   *
21 * Lesser General Public License for more details.                     *
22 *                                                                     *
23 * You should have received a copy of the GNU Lesser General Public    *
24 * License along with this library; if not, write to the               *
25 * Free Software  Foundation, Inc., 59 Temple Place, Suite 330,        *
26 * Boston, MA  02111-1307  USA                                         *
27 *                                                                     *
28 ***********************************************************************
29 *                                                                     *
30 * The implementation of the PCL interpreter.                          *
31 *                                                                     *
32 ***********************************************************************/
33
34#include <hpgsreader.h>
35#include <math.h>
36#include <string.h>
37#include <ctype.h>
38#include <errno.h>
39#if defined ( __MINGW32__ ) || defined ( _MSC_VER )
40#include<malloc.h>
41#else
42#include<alloca.h>
43#endif
44
45//#define HPGS_PCL_DEBUG
46
47#define MK_PCL_CMD(a,b,c) ((a)<<16 | (b)<<8 | (c))
48
49#define PCL_RASTER_CLEAR_FORCE   2
50#define PCL_RASTER_CLEAR_IMAGE   1
51#define PCL_RASTER_CLEAR_PARTIAL 0
52
53static void pcl_clear_raster_data(hpgs_reader *reader, int mode)
54{
55  int i;
56
57  switch (mode)
58    {
59    case PCL_RASTER_CLEAR_FORCE:
60      reader->pcl_raster_presentation = 0;
61      reader->pcl_raster_src_width = 0;
62      reader->pcl_raster_src_height = 0;
63      reader->pcl_raster_dest_width = 0;
64      reader->pcl_raster_dest_height = 0;
65      reader->pcl_raster_planes = 1;
66
67    case PCL_RASTER_CLEAR_IMAGE:
68      reader->pcl_raster_mode = -1;
69      reader->pcl_raster_compression  = 0;
70    }
71
72  reader->pcl_raster_y_offset  = 0;
73  reader->pcl_raster_plane  = 0;
74  reader->pcl_raster_line = 0;
75
76  for (i=0;i<8;++i)
77    if (reader->pcl_raster_data[i])
78      {
79        free(reader->pcl_raster_data[i]);
80        reader->pcl_raster_data[i]=0;
81      }
82
83  reader->pcl_raster_data_size = 0;
84
85  if (reader->pcl_image)
86    hpgs_image_destroy(reader->pcl_image);
87
88  reader->pcl_image=0;
89}
90
91static hpgs_bool is_pcl_compression_supported (int compression)
92{
93  return
94    compression == 0 ||
95    compression == 1 ||
96    compression == 2 ||
97    compression == 3 ||
98    compression == 9;
99}
100
101// uncompressed raster line.
102static int pcl_ignore_raster_data(hpgs_reader *reader,int data_len)
103{
104  int i;
105
106  for (i=0;i<data_len;++i)
107    {
108      reader->last_byte = hpgs_getc(reader->in);
109      if (reader->last_byte == EOF)
110	return -1;
111    }
112
113  return 0;
114}
115
116// uncompressed raster line.
117static int pcl_read_raster_0(hpgs_reader *reader,int data_len)
118{
119  unsigned char *data = reader->pcl_raster_data[reader->pcl_raster_plane];
120  int i;
121
122  for (i=0;i<data_len;++i)
123    {
124      reader->last_byte = hpgs_getc(reader->in);
125      if (reader->last_byte == EOF)
126	return -1;
127
128      if (i<reader->pcl_raster_data_size)
129        data[i] = reader->last_byte;
130    }
131
132  if (data_len < reader->pcl_raster_data_size)
133    memset(data+data_len,0,reader->pcl_raster_data_size-data_len);
134
135  return 0;
136}
137
138// run length encoding.
139static int pcl_read_raster_1(hpgs_reader *reader,int data_len)
140{
141  unsigned char *data = reader->pcl_raster_data[reader->pcl_raster_plane];
142  int i_in=0,i=0;
143
144  while (i_in < data_len)
145    {
146      int count;
147      reader->last_byte = hpgs_getc(reader->in);
148      if (reader->last_byte == EOF)
149	return -1;
150
151      if (++i_in >= data_len) break;
152      count = reader->last_byte + 1;
153
154      reader->last_byte = hpgs_getc(reader->in);
155      if (reader->last_byte == EOF)
156	return -1;
157
158      ++i_in;
159
160      if (i+count > reader->pcl_raster_data_size)
161        count = reader->pcl_raster_data_size-i;
162
163      if (count > 0)
164        {
165          memset(data+i,reader->last_byte,count);
166          i+=count;
167        }
168    }
169
170  if (i < reader->pcl_raster_data_size)
171    memset(data+i,0,reader->pcl_raster_data_size-i);
172
173  return 0;
174}
175
176// tiff v4.0.
177static int pcl_read_raster_2(hpgs_reader *reader,int data_len)
178{
179  unsigned char *data = reader->pcl_raster_data[reader->pcl_raster_plane];
180  int i_in=0,i=0;
181
182  while (i_in < data_len)
183    {
184      int control;
185      reader->last_byte = hpgs_getc(reader->in);
186      if (reader->last_byte == EOF)
187	return -1;
188
189      if (++i_in >= data_len) break;
190      control = reader->last_byte;
191
192      if (control < 128)
193        {
194          while (control >= 0 && i_in < data_len)
195            {
196              reader->last_byte = hpgs_getc(reader->in);
197              if (reader->last_byte == EOF)
198                return -1;
199
200              --control;
201              if (i < reader->pcl_raster_data_size)
202                data[i] = reader->last_byte;
203              ++i;
204              ++i_in;
205            }
206        }
207      else if (control > 128)
208        {
209          int count = 257 - control;
210
211          reader->last_byte = hpgs_getc(reader->in);
212          if (reader->last_byte == EOF)
213            return -1;
214
215          ++i_in;
216
217          if (i+count > reader->pcl_raster_data_size)
218            count = reader->pcl_raster_data_size-i;
219
220          if (count > 0)
221            {
222              memset(data+i,reader->last_byte,count);
223              i+=count;
224            }
225        }
226    }
227
228  if (i < reader->pcl_raster_data_size)
229    memset(data+i,0,reader->pcl_raster_data_size-i);
230
231  return 0;
232}
233
234// delta row
235static int pcl_read_raster_3(hpgs_reader *reader,int data_len)
236{
237  unsigned char *data = reader->pcl_raster_data[reader->pcl_raster_plane];
238  int i_in=0,i=0;
239
240  while (i_in < data_len)
241    {
242      int count;
243      int offset;
244
245      reader->last_byte = hpgs_getc(reader->in);
246      if (reader->last_byte == EOF)
247	return -1;
248
249      if (++i_in >= data_len) break;
250      count = (reader->last_byte >> 5) + 1;
251      offset = reader->last_byte & 0x1f;
252
253      if (offset == 0x1f)
254        {
255          do
256            {
257              reader->last_byte = hpgs_getc(reader->in);
258              if (reader->last_byte == EOF)
259                return -1;
260
261              ++i_in;
262              offset += reader->last_byte;
263            }
264          while (reader->last_byte == 0xff && i_in < data_len);
265
266          if (i_in >= data_len) break;
267        }
268
269      i += offset;
270
271      do
272        {
273          reader->last_byte = hpgs_getc(reader->in);
274          if (reader->last_byte == EOF)
275            return -1;
276
277          ++i_in;
278
279          if (i < reader->pcl_raster_data_size)
280            data[i] = reader->last_byte;
281
282          ++i;
283          --count;
284        }
285      while (count && i_in < data_len);
286    }
287
288  return 0;
289}
290
291// modified delta row - compression mode 9
292static int pcl_read_raster_9(hpgs_reader *reader,int data_len)
293{
294  unsigned char *data = reader->pcl_raster_data[reader->pcl_raster_plane];
295  int i_in=0,i=0;
296
297  while (i_in < data_len)
298    {
299      int count;
300      hpgs_bool more_count;
301      int offset;
302      hpgs_bool more_offset;
303      hpgs_bool comp;
304
305      reader->last_byte = hpgs_getc(reader->in);
306      if (reader->last_byte == EOF)
307	return -1;
308
309      if (++i_in >= data_len) break;
310
311      comp = (reader->last_byte & 0x80) != 0;
312
313      if (comp)
314        {
315          offset = (reader->last_byte >> 5) & 0x03;
316          more_offset = (offset == 0x03);
317          count = (reader->last_byte & 0x1f) + 1;
318          more_count = (count == 0x20);
319        }
320      else
321        {
322          offset = (reader->last_byte >> 3) & 0x0f;
323          more_offset = (offset == 0x0f);
324          count = (reader->last_byte & 0x07) + 1;
325          more_count = (count == 0x08);
326        }
327
328      while (more_offset && i_in < data_len)
329        {
330          reader->last_byte = hpgs_getc(reader->in);
331          if (reader->last_byte == EOF)
332            return -1;
333
334          offset += reader->last_byte;
335          more_offset = (reader->last_byte == 0xff);
336
337          if (++i_in >= data_len) return 0;
338        }
339
340      while (more_count && i_in < data_len)
341        {
342          reader->last_byte = hpgs_getc(reader->in);
343          if (reader->last_byte == EOF)
344            return -1;
345
346          count += reader->last_byte;
347          more_count = (reader->last_byte == 0xff);
348
349          if (++i_in >= data_len) return 0;
350        }
351
352      i += offset;
353
354      if (i >= reader->pcl_raster_data_size) break;
355
356      if (comp)
357        {
358          // run-length encoded replacement.
359          int i_rep = 0;
360
361          while (i_rep < count)
362            {
363              reader->last_byte = hpgs_getc(reader->in);
364              if (reader->last_byte == EOF)
365                return -1;
366
367              if (++i_in >= data_len) return 0;
368
369              int rep_cnt =  reader->last_byte+1;
370
371              reader->last_byte = hpgs_getc(reader->in);
372              if (reader->last_byte == EOF)
373                return -1;
374
375              ++i_in;
376
377              int rep_val =  reader->last_byte;
378
379              while (rep_cnt-- > 0 && i_rep < count)
380                {
381                  if (i < reader->pcl_raster_data_size)
382                    data[i] = rep_val;
383
384                  ++i;
385                  ++i_rep;
386                }
387            }
388        }
389      else
390        {
391          // uncompressed replacement.
392          while (count > 0 && i_in < data_len)
393            {
394              reader->last_byte = hpgs_getc(reader->in);
395              if (reader->last_byte == EOF)
396                return -1;
397
398              if (i < reader->pcl_raster_data_size)
399                data[i] = reader->last_byte;
400
401              ++i_in;
402              ++i;
403              --count;
404            }
405        }
406    }
407
408  return 0;
409}
410
411static int pcl_read_raster_row(hpgs_reader *reader,int data_len)
412{
413  if (!is_pcl_compression_supported(reader->pcl_raster_compression))
414    // simply ignore unknown compression modes.
415    return pcl_ignore_raster_data(reader,data_len);
416
417  if (!reader->pcl_raster_data[reader->pcl_raster_plane])
418    {
419      if (reader->pcl_raster_src_width <= 0)
420        {
421          reader->pcl_raster_src_width = (int)
422            (reader->pcl_raster_presentation ? reader->x_size : reader->y_size)
423            * HP_TO_PT  * reader->pcl_raster_res / 72.0;
424
425          if (reader->verbosity)
426            hpgs_log(hpgs_i18n("Estimated PCL src width = %d.\n"),
427                     reader->pcl_raster_src_width);
428
429          reader->pcl_raster_mode = 1;
430
431          if (reader->pcl_raster_src_height <= 0)
432            {
433              reader->pcl_raster_src_height = (int)
434                (reader->pcl_raster_presentation ? reader->y_size : reader->x_size)
435                * HP_TO_PT  * reader->pcl_raster_res / 72.0;
436
437              while (reader->pcl_raster_src_width * reader->pcl_raster_src_height
438                     > 1024*16384)
439                reader->pcl_raster_src_height /= 2;
440
441              if (reader->verbosity)
442                hpgs_log(hpgs_i18n("Estimated PCL src height = %d.\n"),
443                         reader->pcl_raster_src_height);
444            }
445        }
446
447      if (reader->pcl_raster_data_size <= 0)
448        {
449          reader->pcl_raster_data_size = reader->pcl_raster_src_width;
450
451          if (reader->pcl_palettes[reader->pcl_i_palette]->cid_enc == 3) // direct by pixel
452            reader->pcl_raster_data_size *= 3;
453        }
454
455      reader->pcl_raster_data[reader->pcl_raster_plane] =
456        (unsigned char *)malloc(reader->pcl_raster_data_size);
457
458      if (!reader->pcl_raster_data[reader->pcl_raster_plane])
459        return hpgs_set_error(hpgs_i18n("Out of memory allocating %d bytes of raster bata buffer."),reader->pcl_raster_data_size);
460
461      memset(reader->pcl_raster_data[reader->pcl_raster_plane],
462             0,reader->pcl_raster_data_size);
463    }
464
465  switch (reader->pcl_raster_compression)
466    {
467    case 0:
468      if (pcl_read_raster_0(reader,data_len))
469        return -1;
470      break;
471
472    case 1:
473      if (pcl_read_raster_1(reader,data_len))
474        return -1;
475      break;
476
477    case 2:
478      if (pcl_read_raster_2(reader,data_len))
479        return -1;
480      break;
481
482    case 3:
483      if (pcl_read_raster_3(reader,data_len))
484        return -1;
485      break;
486
487    case 9:
488      if (pcl_read_raster_9(reader,data_len))
489        return -1;
490      break;
491
492    default:
493      return -1;
494    }
495
496  return 0;
497}
498
499static int pcl_fill_scanline(hpgs_reader *reader)
500{
501  int i;
502  hpgs_paint_color c;
503
504  if (!reader->pcl_image)
505    {
506      if (reader->pcl_raster_src_width <= 0)
507        return hpgs_set_error(hpgs_i18n("No PCL source raster width specified."));
508
509      if (reader->pcl_raster_src_height <= 0)
510        return hpgs_set_error(hpgs_i18n("No PCL source raster height specified."));
511
512      if (reader->verbosity > 1)
513        hpgs_log(hpgs_i18n("Creating %dx%d PCL image.\n"),
514                 reader->pcl_raster_src_width,
515                 reader->pcl_raster_src_height);
516
517      // set up image, if not done yet.
518      switch (reader->pcl_palettes[reader->pcl_i_palette]->cid_enc)
519        {
520        case 0: // indexed by plane.
521        case 1: // indexed by pixel.
522          reader->pcl_image = (hpgs_image *)
523            hpgs_new_png_image(reader->pcl_raster_src_width,
524                               reader->pcl_raster_src_height,
525                               8,HPGS_TRUE,HPGS_FALSE);
526
527          // pull in palette
528          if (reader->pcl_image &&
529              hpgs_image_set_palette(reader->pcl_image,
530                                     reader->pcl_palettes[reader->pcl_i_palette]->colors,256))
531            return -1;
532
533          break;
534
535        case 2: // direct by plane.
536          reader->pcl_image = (hpgs_image *)
537            hpgs_new_png_image(reader->pcl_raster_src_width,
538                               reader->pcl_raster_src_height,
539                               8,HPGS_TRUE,HPGS_FALSE);
540          // set palette
541          if (reader->pcl_image)
542            {
543              hpgs_palette_color palette[8];
544
545              for (i=0; i<8; ++i)
546                {
547                  palette[i].r = (i&1)*255;
548                  palette[i].g = ((i>>1)&1)*255;
549                  palette[i].b = ((i>>2)&1)*255;
550                }
551
552              hpgs_image_set_palette(reader->pcl_image,palette,8);
553            }
554          break;
555
556        case 3:
557          reader->pcl_image = (hpgs_image *)
558            hpgs_new_png_image(reader->pcl_raster_src_width,
559                               reader->pcl_raster_src_height,
560                               24,HPGS_FALSE,HPGS_FALSE);
561          break;
562
563        default:
564          return hpgs_set_error(hpgs_i18n("Invalid PCL Pixel Encoding Mode %d."),
565                                reader->pcl_palettes[reader->pcl_i_palette]->cid_enc);
566        }
567
568      if (!reader->pcl_image)
569        return hpgs_set_error(hpgs_i18n("Out of memory creating PCL image."));
570    }
571
572  if (reader->pcl_raster_line >= reader->pcl_raster_src_height)
573    {
574      if (reader->verbosity)
575        hpgs_log(hpgs_i18n("PCL raster line %d is out of range (%dx%d).\n"),
576                 reader->pcl_raster_line,
577                 reader->pcl_raster_src_width,
578                 reader->pcl_raster_src_height);
579
580      return 0;
581    }
582
583  switch (reader->pcl_palettes[reader->pcl_i_palette]->cid_enc)
584    {
585    case 0: // indexed by plane.
586      {
587        int p;
588
589        for (p=0;p<reader->pcl_raster_planes;++p)
590          if (!reader->pcl_raster_data[p])
591            return hpgs_set_error("No raster data.");
592
593        for (i=0; i<reader->pcl_raster_src_width;)
594          {
595            int mask = 0x80;
596
597            int v[8];
598
599            for (p=0;p<reader->pcl_raster_planes;++p)
600              v[p]  = reader->pcl_raster_data[p][i>>3];
601
602            for (; i<reader->pcl_raster_src_width && mask; ++i, mask>>=1)
603              {
604                int bit;
605                c.index = 0;
606
607                for (p=0,bit=1;p<reader->pcl_raster_planes;++p,bit<<=1)
608                  if (v[p] & mask) c.index |= bit;
609
610                if (hpgs_image_put_pixel (reader->pcl_image,i,
611                                          reader->pcl_raster_line,&c,1.0))
612                  return -1;
613              }
614          }
615      }
616      break;
617
618    case 1: // indexed by pixel.
619      if (!reader->pcl_raster_data[0])
620        return hpgs_set_error(hpgs_i18n("No raster data."));
621
622      switch (reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi)
623        {
624        case 1:
625          for (i=0; i<(reader->pcl_raster_src_width+7)/8;++i)
626            {
627              int bit = 0x80;
628              int j;
629
630              for (j=0;j<8 && 8*i+j < reader->pcl_raster_src_width;++j,bit>>=1)
631                {
632                  c.index = (reader->pcl_raster_data[0][i] & bit) ? 1 : 0;
633
634                  if (hpgs_image_put_pixel (reader->pcl_image,8*i+j,
635                                            reader->pcl_raster_line,&c,1.0))
636                    return -1;
637                }
638            }
639          break;
640
641        case 2:
642          for (i=0; i<(reader->pcl_raster_src_width+3)/4;++i)
643            {
644              c.index = reader->pcl_raster_data[0][i] >> 6;
645
646              if (hpgs_image_put_pixel (reader->pcl_image,4*i,
647                                        reader->pcl_raster_line,&c,1.0))
648                return -1;
649
650              c.index = (reader->pcl_raster_data[0][i] >> 4) & 0x03;
651
652              if (4*i+1 >= reader->pcl_raster_src_width) break;
653
654              if (hpgs_image_put_pixel (reader->pcl_image,4*i+1,
655                                        reader->pcl_raster_line,&c,1.0))
656                return -1;
657
658              c.index = (reader->pcl_raster_data[0][i] >> 2) & 0x03;
659
660              if (4*i+2 >= reader->pcl_raster_src_width) break;
661
662              if (hpgs_image_put_pixel (reader->pcl_image,4*i+2,
663                                        reader->pcl_raster_line,&c,1.0))
664                return -1;
665
666              c.index = reader->pcl_raster_data[0][i] & 0x03;
667
668              if (4*i+3 >= reader->pcl_raster_src_width) break;
669
670              if (hpgs_image_put_pixel (reader->pcl_image,4*i+3,
671                                        reader->pcl_raster_line,&c,1.0))
672                return -1;
673            }
674          break;
675
676        case 4:
677          for (i=0; i<(reader->pcl_raster_src_width+1)/2;++i)
678            {
679              c.index = reader->pcl_raster_data[0][i] >> 4;
680
681              if (hpgs_image_put_pixel (reader->pcl_image,2*i,
682                                        reader->pcl_raster_line,&c,1.0))
683                return -1;
684
685
686              c.index = reader->pcl_raster_data[0][i] & 0x0f;
687
688              if (2*i+1 >= reader->pcl_raster_src_width) break;
689
690              if (hpgs_image_put_pixel (reader->pcl_image,2*i+1,
691                                        reader->pcl_raster_line,&c,1.0))
692                return -1;
693            }
694          break;
695
696        case 8:
697          for (i=0; i<reader->pcl_raster_src_width;++i)
698            {
699              c.index = reader->pcl_raster_data[0][i];
700
701              if (hpgs_image_put_pixel (reader->pcl_image,i,
702                                        reader->pcl_raster_line,&c,1.0))
703                return -1;
704            }
705          break;
706
707        default:
708          return hpgs_set_error(hpgs_i18n("Invalid bpi %d."),
709                                (int)reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi);
710        }
711      break;
712
713    case 2: // direct by plane.
714      if (!reader->pcl_raster_data[0] ||
715          !reader->pcl_raster_data[1] ||
716          !reader->pcl_raster_data[2]   )
717        return hpgs_set_error(hpgs_i18n("No raster data."));
718
719      for (i=0; i<reader->pcl_raster_src_width;)
720        {
721          int mask = 0x80;
722
723          int v0 = reader->pcl_raster_data[0][i>>3];
724          int v1 = reader->pcl_raster_data[1][i>>3];
725          int v2 = reader->pcl_raster_data[2][i>>3];
726
727          for (; i<reader->pcl_raster_src_width && mask; ++i, mask>>=1)
728            {
729              c.r = (v0 & mask) ? 255 : 0;
730              c.g = (v1 & mask) ? 255 : 0;
731              c.b = (v2 & mask) ? 255 : 0;
732
733              if (hpgs_image_define_color (reader->pcl_image,&c))
734                return -1;
735
736              if (hpgs_image_put_pixel (reader->pcl_image,i,
737                                        reader->pcl_raster_line,&c,1.0))
738                return -1;
739            }
740        }
741      break;
742
743    case 3:
744      if (!reader->pcl_raster_data[0])
745        return hpgs_set_error(hpgs_i18n("No raster data."));
746
747
748      for (i=0; i<reader->pcl_raster_src_width;++i)
749        {
750          c.r = reader->pcl_raster_data[0][3*i  ];
751          c.g = reader->pcl_raster_data[0][3*i+1];
752          c.b = reader->pcl_raster_data[0][3*i+2];
753
754          if (hpgs_image_put_pixel (reader->pcl_image,i,
755                                    reader->pcl_raster_line,&c,1.0))
756            return -1;
757        }
758      break;
759
760    default:
761      return hpgs_set_error(hpgs_i18n("Invalid PCL Pixel Encoding Mode %d."),reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi);
762    }
763
764  return 0;
765}
766
767static int pcl_put_image(hpgs_reader *reader)
768{
769  // setup image placement
770  double w,h;
771  hpgs_point ll,lr,ur;
772
773  double x0;
774  double y0;
775
776  int angle;
777
778  if (reader->pcl_raster_line <= 0 ||
779      reader->pcl_raster_src_width  <= 0 ||
780      reader->pcl_raster_src_height  <= 0  )
781    // don't process any further, if we don't have an image size.
782    // An image size is needed for correct cursor positioning.
783    return 0;
784
785  if (reader->pcl_raster_line < reader->pcl_raster_src_height)
786    {
787      if (reader->pcl_image &&
788          hpgs_image_resize(reader->pcl_image,reader->pcl_raster_src_width,reader->pcl_raster_line))
789        return hpgs_set_error(hpgs_i18n("Error downsizing PCL image."));
790
791      reader->pcl_raster_src_height = reader->pcl_raster_line;
792    }
793
794  angle = (reader->pcl_raster_presentation != 0) ? 0 : 90;
795
796#ifdef HPGS_PCL_DEBUG
797  hpgs_log("raster_pres,x_size,y_size,rot,angle=%d,%lg,%lg,%d,%d.\n",
798           reader->pcl_raster_presentation,reader->x_size,reader->y_size,
799           reader->rotation, angle);
800#endif
801
802  if (reader->pcl_raster_mode & 1)
803    {
804      x0 = reader->pcl_point.x;
805      y0 = reader->pcl_point.y;
806    }
807  else
808    if (reader->y_size >= reader->x_size)
809      {
810        x0 = 0.0;
811        y0 = reader->pcl_point.y;
812      }
813    else
814      {
815        x0 = reader->pcl_point.x;
816        y0 = 0.0;
817      }
818
819  // PCL coordinates
820  //
821  // y  (w,0)-------------(w,h)
822  // ^    |                 |
823  // |    |                 |
824  // |    |                 |
825  // |    |                 |
826  // |  (0,0)-------------(0,h)
827  // +-----------> x
828
829#ifdef HPGS_PCL_DEBUG
830  hpgs_log("src:w,h=%d,%d.\n",reader->pcl_raster_src_width,reader->pcl_raster_src_height);
831#endif
832  if (reader->pcl_raster_mode & 2)
833    {
834      w = 0.1*reader->pcl_raster_dest_width;
835      h = 0.1*reader->pcl_raster_dest_height;
836    }
837  else
838    {
839#ifdef HPGS_PCL_DEBUG
840  hpgs_log("raster_res=%d.\n",reader->pcl_raster_res);
841#endif
842      w = reader->pcl_raster_src_width * 72.0 / reader->pcl_raster_res;
843      h = reader->pcl_raster_src_height * 72.0 / reader->pcl_raster_res;
844    }
845
846#ifdef HPGS_PCL_DEBUG
847  hpgs_log("w,h=%lg,%lg.\n",w,h);
848#endif
849
850  // 2005-06-13:
851  // Well, the code below is completely based on my experience
852  // with the testsuite, which is available to me.
853  // Up to now, I did not find a consistent description of
854  // the PCL coordinate setup in HP's docs. If you have any problems
855  // with PCL image placement, please send me an e-mail:
856  //
857  // wolfgang.glas@ev-i.at
858  //
859  switch (angle % 360)
860    {
861    case 90:
862    case 270:
863      ur.x =  x0 +
864        h * reader->pcl_raster_y_offset/(double)reader->pcl_raster_src_height;
865
866      ur.y = lr.y = y0 + w;
867      ll.y = y0;
868      ll.x = lr.x = ur.x + h;
869      break;
870
871    default: /* case 0, 180: */
872      ur.x = lr.x = x0 + w;
873
874      ur.y = y0 -
875        h * reader->pcl_raster_y_offset/(double)reader->pcl_raster_src_height;
876
877      ll.x = x0;
878      ll.y = lr.y = ur.y - h;
879      break;
880    }
881
882#ifdef HPGS_PCL_DEBUG
883  hpgs_log("raster_pres,x_s,y_s=%d,%lg,%lg.\n",
884           reader->pcl_raster_presentation,reader->x_size,reader->y_size);
885
886  hpgs_log("ll,lr,ur=(%lg,%lg),(%lg,%lg),(%lg,%lg).\n",
887           ll.x,ll.y,lr.x,lr.y,ur.x,ur.y);
888#endif
889
890  // save inline images, if specified.
891  if (reader->pcl_image && reader->png_dump_filename)
892    {
893      int l = strlen(reader->png_dump_filename)+16;
894      char *fn = hpgs_alloca(l);
895
896      ++reader->png_dump_count;
897      snprintf(fn,l,"%s%04d.png",reader->png_dump_filename,reader->png_dump_count);
898
899      if (reader->verbosity)
900        hpgs_log(hpgs_i18n("Dumping inline PCL image to file <%s>.\n"),fn);
901
902      int ret = hpgs_image_write(reader->pcl_image,fn);
903
904      if (ret) return -1;
905    }
906
907  // check for discarded image data of unknown compression modes,
908  // if the device is unable to process null images.
909  // (only plotsize devices normally can process null images...)
910  if ((hpgs_device_capabilities(reader->device) & HPGS_DEVICE_CAP_NULLIMAGE) ||
911      reader->pcl_image)
912    {
913      hpgs_point ll_p;
914      hpgs_point lr_p;
915      hpgs_point ur_p;
916
917      hpgs_matrix_xform(&ll_p,&reader->page_matrix,&ll);
918      hpgs_matrix_xform(&lr_p,&reader->page_matrix,&lr);
919      hpgs_matrix_xform(&ur_p,&reader->page_matrix,&ur);
920
921      // draw image
922      if (hpgs_drawimage(reader->device,reader->pcl_image,&ll_p,&lr_p,&ur_p))
923        return -1;
924    }
925
926  // set the cursor position.
927  reader->pcl_point = ll;
928
929  return 0;
930}
931
932static int pcl_do_cmd(hpgs_reader *reader, int cmd, int arg, int arg_sign,
933                      hpgs_bool have_arg)
934{
935  if (reader->verbosity>1)
936    hpgs_log(hpgs_i18n("PCL command %c%c%d%c found.\n"),
937             (char)(cmd >> 16),(char)(cmd >> 8),arg,(char)(cmd&0xff));
938
939  switch (cmd)
940    {
941    case MK_PCL_CMD('%',' ','B'):
942      if (!have_arg) return -1;
943#ifdef HPGS_PCL_DEBUG
944      hpgs_log("leave PCL: arg,pcl_point,hpgl_point=%d,(%lg,%lg),(%lg,%lg).\n",
945               arg,
946               reader->pcl_point.x,
947               reader->pcl_point.y,
948               reader->current_point.x,
949               reader->current_point.y );
950#endif
951      if (arg & 1)
952        {
953          hpgs_point tmp;
954          hpgs_matrix_xform(&tmp,&reader->page_matrix,&reader->pcl_point);
955          if (hpgs_reader_moveto(reader,&tmp)) return -1;
956        }
957
958      pcl_clear_raster_data(reader,PCL_RASTER_CLEAR_IMAGE);
959      return 1;
960
961    case MK_PCL_CMD('%',' ','X'):
962      if (!have_arg) return -1;
963      pcl_clear_raster_data(reader,PCL_RASTER_CLEAR_IMAGE);
964      return 2;
965
966    case MK_PCL_CMD('*','v','N'): // Source Transparency Mode.
967      if (!have_arg) return -1;
968      reader->src_transparency = (arg == 0);
969
970#ifdef HPGS_PCL_DEBUG
971      hpgs_log("src transp. %d,%d.\n",arg,reader->src_transparency);
972#endif
973      if (hpgs_setrop3(reader->device,reader->rop3,
974                       reader->src_transparency,
975                       reader->pattern_transparency ))
976          return -1;
977      break;
978
979    case MK_PCL_CMD('*','v','O'): // Pattern Transparency Mode.
980      if (!have_arg) return -1;
981      reader->pattern_transparency = (arg == 0);
982
983#ifdef HPGS_PCL_DEBUG
984      hpgs_log("pat transp. %d,%d.\n",arg,reader->pattern_transparency);
985#endif
986      if (hpgs_setrop3(reader->device,reader->rop3,
987                       reader->src_transparency,
988                       reader->pattern_transparency ))
989          return -1;
990      break;
991
992    case MK_PCL_CMD('*','v','T'): // Set Current Pattern.
993      if (!have_arg) return -1;
994
995      {
996        hpgs_color patcol;
997
998        patcol.r = patcol.g = patcol.b = arg ? (arg == 1 ? 1.0 : 0.5) : 0.0;
999
1000        if (reader->verbosity && (arg < 0 || arg > 1))
1001          hpgs_log(hpgs_i18n("Warning: Invalid pattern %d specified setting pattern to 50%% grey.\n"),arg);
1002
1003        if (hpgs_setpatcol(reader->device,&patcol))
1004          return -1;
1005      }
1006      break;
1007
1008    case MK_PCL_CMD('*','l','O'): // Logical operation.
1009      if (!have_arg) return -1;
1010      reader->rop3 = arg;
1011
1012      if (hpgs_setrop3(reader->device,reader->rop3,
1013                       reader->src_transparency,
1014                       reader->pattern_transparency ))
1015          return -1;
1016      break;
1017
1018    case MK_PCL_CMD('*','p','P'): // Push/Pop palette.
1019      if (!have_arg) return -1;
1020      if (arg < 0 || arg > 1)
1021        return hpgs_set_error(hpgs_i18n("PCL push/pop palette arg %d invalid."),arg);
1022
1023      if (arg)
1024        {
1025          if (hpgs_reader_pop_pcl_palette(reader)) return -1;
1026        }
1027      else
1028        {
1029          if (hpgs_reader_push_pcl_palette(reader)) return -1;
1030        }
1031      break;
1032
1033    case MK_PCL_CMD('&','u','D'): // PCL unit
1034      if (!have_arg) return -1;
1035      reader->pcl_scale = 72.0/(double)arg;
1036      break;
1037
1038    case MK_PCL_CMD('&','k','H'): // horizontal motion index
1039      if (!have_arg) return -1;
1040      reader->pcl_hmi = (double)arg*72.0/120.0;
1041      break;
1042
1043    case MK_PCL_CMD('&','l','C'):// vertical motion index
1044      if (!have_arg) return -1;
1045      reader->pcl_vmi = (double)arg*72.0/48.0;
1046      break;
1047
1048    case MK_PCL_CMD('&','a','C'): // horiz. position in columns.
1049      if (!have_arg) return -1;
1050      if (arg_sign)
1051        reader->pcl_point.y += arg * reader->pcl_hmi;
1052      else
1053        reader->pcl_point.y = reader->frame_y + arg * reader->pcl_hmi;
1054      break;
1055
1056    case MK_PCL_CMD('&','a','H'): // horiz. position in decipoints.
1057      if (!have_arg) return -1;
1058      if (arg_sign)
1059        reader->pcl_point.y += arg * 0.1;
1060      else
1061        reader->pcl_point.y = reader->frame_y + arg * 0.1;
1062      break;
1063
1064    case MK_PCL_CMD('*','p','X'): // horiz. position in PCL units.
1065      if (!have_arg) return -1;
1066      if (arg_sign)
1067        reader->pcl_point.y += arg * reader->pcl_scale;
1068      else
1069        reader->pcl_point.y = reader->frame_y + arg * reader->pcl_scale;
1070      break;
1071
1072    case MK_PCL_CMD('&','a','R'): // vert. position in columns.
1073      if (!have_arg) return -1;
1074      if (arg_sign)
1075        reader->pcl_point.x += arg * reader->pcl_vmi;
1076      else
1077        reader->pcl_point.x = reader->frame_x + arg * reader->pcl_vmi;
1078      break;
1079
1080    case MK_PCL_CMD('&','a','V'): // vert. position in decipoints.
1081      if (!have_arg) return -1;
1082      if (arg_sign)
1083        reader->pcl_point.x += arg * 0.1;
1084      else
1085        reader->pcl_point.x = reader->frame_x + arg * 0.1;
1086      break;
1087
1088    case MK_PCL_CMD('*','p','Y'): // vert. position in PCL units.
1089      if (!have_arg) return -1;
1090      if (arg_sign)
1091        reader->pcl_point.x += arg * reader->pcl_scale;
1092      else
1093        reader->pcl_point.x = reader->frame_x + arg * reader->pcl_scale;
1094      break;
1095
1096    case MK_PCL_CMD('*','v','W'): // configure image data
1097      if (!have_arg) return -1;
1098      if (reader->pcl_raster_data[reader->pcl_raster_plane])
1099        return hpgs_set_error(hpgs_i18n("PCL CID command after image data."));
1100
1101      reader->pcl_palettes[reader->pcl_i_palette]->cid_space = hpgs_getc(reader->in);
1102      if (reader->pcl_palettes[reader->pcl_i_palette]->cid_space == EOF) return -1;
1103      reader->pcl_palettes[reader->pcl_i_palette]->cid_enc = hpgs_getc(reader->in);
1104      if (reader->pcl_palettes[reader->pcl_i_palette]->cid_enc == EOF) return -1;
1105      reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi = hpgs_getc(reader->in);
1106      if (reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi == EOF) return -1;
1107      reader->pcl_palettes[reader->pcl_i_palette]->cid_bpc[0] = hpgs_getc(reader->in);
1108      if (reader->pcl_palettes[reader->pcl_i_palette]->cid_bpc[0] == EOF) return -1;
1109      reader->pcl_palettes[reader->pcl_i_palette]->cid_bpc[1] = hpgs_getc(reader->in);
1110      if (reader->pcl_palettes[reader->pcl_i_palette]->cid_bpc[1] == EOF) return -1;
1111      reader->pcl_palettes[reader->pcl_i_palette]->cid_bpc[2] = hpgs_getc(reader->in);
1112      if (reader->pcl_palettes[reader->pcl_i_palette]->cid_bpc[2] == EOF) return -1;
1113
1114      if (arg == 18)
1115        {
1116          // basic interpretation of long form of CID command.
1117          unsigned char ref_data[12];
1118          // this is the only form of the CID 18 header we are currently recognizig.
1119          unsigned char impl_ref_data[12] = { 0,255,0,255,0,255,0,0,0,0,0,0 };
1120
1121          if (hpgs_istream_read(ref_data,1,sizeof(ref_data),reader->in) != sizeof(ref_data)) return -1;
1122
1123          if (memcmp(ref_data,impl_ref_data,sizeof(ref_data)) != 0)
1124            return hpgs_set_error(hpgs_i18n("PCL CID command with arg==18 and non-trivial colorspace is unimplemented."));
1125        }
1126      else if (arg!=6)
1127        return hpgs_set_error(hpgs_i18n("PCL CID command with arg!=6 and arg !=18 is unimplemented."));
1128
1129#ifdef HPGS_PCL_DEBUG
1130      hpgs_log("CID: %d %d %d %d %d %d.\n",
1131               reader->pcl_palettes[reader->pcl_i_palette]->cid_space,
1132               reader->pcl_palettes[reader->pcl_i_palette]->cid_enc,
1133               reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi,
1134               reader->pcl_palettes[reader->pcl_i_palette]->cid_bpc[0],
1135               reader->pcl_palettes[reader->pcl_i_palette]->cid_bpc[1],
1136               reader->pcl_palettes[reader->pcl_i_palette]->cid_bpc[2] );
1137#endif
1138
1139      if (reader->pcl_palettes[reader->pcl_i_palette]->cid_enc == 0 &&
1140          (reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi < 1 || reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi > 8))
1141        return hpgs_set_error(hpgs_i18n("Invalid bits per index %d for PCL CID encoding 0."),reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi);
1142
1143      if (reader->pcl_palettes[reader->pcl_i_palette]->cid_enc == 1 &&
1144          (reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi != 1 &&
1145           reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi != 2 &&
1146           reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi != 4 &&
1147           reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi != 8   ))
1148        return hpgs_set_error(hpgs_i18n("Inavlid bits per index %d for PCL CID encoding 1."),reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi);
1149
1150      if (reader->pcl_palettes[reader->pcl_i_palette]->cid_enc == 2)
1151        reader->pcl_raster_planes = 3;
1152      else if (reader->pcl_palettes[reader->pcl_i_palette]->cid_enc == 0)
1153        reader->pcl_raster_planes = reader->pcl_palettes[reader->pcl_i_palette]->cid_bpi;
1154      else
1155        reader->pcl_raster_planes = 1;
1156
1157      break;
1158
1159    case MK_PCL_CMD('*','v','A'): // color component #1
1160      if (!have_arg) return -1;
1161      reader->pcl_palettes[reader->pcl_i_palette]->last_color.r = arg;
1162      break;
1163
1164    case MK_PCL_CMD('*','v','B'): // color component #2
1165      if (!have_arg) return -1;
1166      reader->pcl_palettes[reader->pcl_i_palette]->last_color.g = arg;
1167      break;
1168
1169    case MK_PCL_CMD('*','v','C'): // color component #3
1170      if (!have_arg) return -1;
1171      reader->pcl_palettes[reader->pcl_i_palette]->last_color.b = arg;
1172      break;
1173
1174    case MK_PCL_CMD('*','v','I'): // assign color index
1175      if (!have_arg) return -1;
1176      if (arg < 0 || arg >= 256)
1177        return hpgs_set_error(hpgs_i18n("PCL Color index %d is out of bounds."),arg);
1178
1179      reader->pcl_palettes[reader->pcl_i_palette]->colors[arg] = reader->pcl_palettes[reader->pcl_i_palette]->last_color;
1180
1181      reader->pcl_palettes[reader->pcl_i_palette]->last_color.r = 0;
1182      reader->pcl_palettes[reader->pcl_i_palette]->last_color.g = 0;
1183      reader->pcl_palettes[reader->pcl_i_palette]->last_color.b = 0;
1184      break;
1185
1186    case MK_PCL_CMD('*','r','A'): // start raster graphics
1187      if (!have_arg) return -1;
1188      //      if (reader->pcl_raster_mode >= 0)
1189      //  return hpgs_set_error(hpgs_i18n("Nested PCL start raster graphics commands."));
1190
1191      reader->pcl_raster_mode = arg;
1192      break;
1193
1194    case MK_PCL_CMD('*','r','F'): // Raster Presentation Mode
1195      if (!have_arg) return -1;
1196      if (arg != 0 && arg != 3)
1197        return hpgs_set_error(hpgs_i18n("PCL Raster Presentation Mode %d is invalid."),arg);
1198
1199      reader->pcl_raster_presentation = arg;
1200      break;
1201
1202    case MK_PCL_CMD('*','t','R'): // Raster Resolution
1203      if (!have_arg) return -1;
1204      if (arg < 75 || arg > 2400)
1205        return hpgs_set_error(hpgs_i18n("PCL Raster Resolution %d is out of bounds."),arg);
1206
1207      reader->pcl_raster_res = arg;
1208      break;
1209
1210    case MK_PCL_CMD('*','r','S'): // source Raster Width
1211      if (!have_arg) return -1;
1212
1213      if (reader->pcl_raster_data[0])
1214        return hpgs_set_error(hpgs_i18n("PCL Source raster width command after image data."));
1215
1216      // if (reader->pcl_raster_src_width > 0)
1217      //   return hpgs_set_error("Repeated occurrence of PCL Source raster width.");
1218
1219      if (arg < 0 || arg > 32767)
1220        return hpgs_set_error(hpgs_i18n("PCL Source raster width %d is out of bounds."),arg);
1221
1222      reader->pcl_raster_src_width = arg;
1223      break;
1224
1225    case MK_PCL_CMD('*','r','T'): // source Raster Height
1226      if (!have_arg) return -1;
1227
1228      if (reader->pcl_raster_data[0])
1229        return hpgs_set_error(hpgs_i18n("PCL Source raster height command after image data."));
1230
1231      // if (reader->pcl_raster_src_height > 0)
1232      //   return hpgs_set_error("Repeated occurrence of PCL Source raster height.");
1233
1234      if (arg < 0 || arg > 32767)
1235        return hpgs_set_error(hpgs_i18n("PCL Source raster height %d is out of bounds."),arg);
1236
1237      reader->pcl_raster_src_height = arg;
1238      break;
1239
1240    case MK_PCL_CMD('*','t','H'): // destination Raster Width
1241      if (!have_arg) return -1;
1242      if (arg < 0 || arg > 65535)
1243        return hpgs_set_error(hpgs_i18n("PCL Destination raster width %d is out of bounds."),arg);
1244
1245      reader->pcl_raster_dest_width = arg;
1246      break;
1247
1248    case MK_PCL_CMD('*','t','V'): // destination Raster Height
1249      if (!have_arg) return -1;
1250      if (arg < 0 || arg > 65535)
1251        return hpgs_set_error(hpgs_i18n("PCL Destination raster height %d is out of bounds."),arg);
1252
1253      reader->pcl_raster_dest_height = arg;
1254      break;
1255
1256    case MK_PCL_CMD('*','b','Y'): // raster Y offset
1257      if (!have_arg) return -1;
1258      reader->pcl_raster_y_offset = arg;
1259      break;
1260
1261    case MK_PCL_CMD('*','b','M'): // Raster Compression Mode
1262      if (!have_arg) return -1;
1263
1264      if (!is_pcl_compression_supported(arg) && reader->verbosity > 0)
1265        hpgs_log(hpgs_i18n("Warning: Ignoring image data in PCL Raster Compression Mode %d.\n"),arg);
1266
1267      reader->pcl_raster_compression = arg;
1268      break;
1269
1270    case MK_PCL_CMD('*','b','V'): // Transfer Raster Data by Plane
1271      if (!have_arg) return -1;
1272      if (arg < 0)
1273        return hpgs_set_error(hpgs_i18n("PCL Raster Row length %d is invalid."),arg);
1274
1275      if (pcl_read_raster_row(reader,arg)) return -1;
1276      reader->pcl_raster_plane = (reader->pcl_raster_plane+1)%reader->pcl_raster_planes;
1277      break;
1278
1279    case MK_PCL_CMD('*','b','W'): // Transfer Raster Data by Row
1280      if (!have_arg) return -1;
1281      if (arg < 0)
1282        return hpgs_set_error(hpgs_i18n("PCL Raster Row length %d is invalid."),arg);
1283
1284      if (pcl_read_raster_row(reader,arg)) return -1;
1285      reader->pcl_raster_plane = 0;
1286
1287      // For the sake of performance, only process image data
1288      // for real drawing devices, not for the plotsize device.
1289      // Additionally, ignore unknown raster compression modes.
1290      if ((hpgs_device_capabilities(reader->device) & HPGS_DEVICE_CAP_PLOTSIZE) == 0 &&
1291          is_pcl_compression_supported(reader->pcl_raster_compression) &&
1292          reader->pcl_raster_src_width > 0 &&
1293          pcl_fill_scanline(reader))
1294        return -1;
1295
1296      ++reader->pcl_raster_line;
1297
1298      // emit partial images.
1299      if (reader->pcl_raster_src_height > 1 &&
1300          reader->pcl_raster_line >= reader->pcl_raster_src_height)
1301        {
1302          if (pcl_put_image(reader)) return -1;
1303          pcl_clear_raster_data(reader,PCL_RASTER_CLEAR_PARTIAL);
1304        }
1305
1306      break;
1307
1308    case MK_PCL_CMD('*','r','B'): // End Raster Graphics
1309    case MK_PCL_CMD('*','r','C'): // End Raster Graphics
1310        if (have_arg) return -1;
1311        if (pcl_put_image(reader)) return -1;
1312        pcl_clear_raster_data(reader,PCL_RASTER_CLEAR_IMAGE);
1313        break;
1314
1315    default:
1316      if (reader->verbosity)
1317        hpgs_log(hpgs_i18n("Unknown PCL command %c%c%d%c found.\n"),
1318                 (char)(cmd >> 16),(char)(cmd >> 8),arg,(char)(cmd&0xff));
1319    }
1320#ifdef HPGS_PCL_DEBUG
1321  if ((cmd >> 16) == '&' || cmd == MK_PCL_CMD('*','p','X') || cmd == MK_PCL_CMD('*','p','Y'))
1322    hpgs_log("%c%c%d%c: pcl_point=(%lg,%lg).\n",
1323             (char)(cmd >> 16),(char)(cmd >> 8),arg,(char)(cmd&0xff),
1324             reader->pcl_point.x,
1325             reader->pcl_point.y);
1326#endif
1327
1328  return 0;
1329}
1330
1331/*!
1332  Read a PCL block of the file.
1333
1334  Return values:
1335   \li -1 Error, unexpected EOF.
1336   \li 0 Success, return to HPGL context.
1337   \li 1 Success, return to PJL context.
1338   \li 2 Success, EOF reached.
1339*/
1340int hpgs_reader_do_PCL(hpgs_reader *reader, hpgs_bool take_pos)
1341{
1342  int cmd1,cmd2;
1343  reader->bytes_ignored = 0;
1344  reader->eoc = 0;
1345  int ret = -1;
1346
1347#ifdef HPGS_PCL_DEBUG
1348      hpgs_log("enter PCL: arg,pcl_point,hpgl_point=%d,(%lg,%lg),(%lg,%lg).\n",
1349               take_pos,
1350               reader->pcl_point.x,
1351               reader->pcl_point.y,
1352               reader->current_point.x,
1353               reader->current_point.y );
1354#endif
1355
1356  if (take_pos)
1357    {
1358      reader->pcl_point.x = reader->current_point.x;
1359      reader->pcl_point.y = reader->current_point.y;
1360    }
1361  else
1362    if (reader->y_size >= reader->x_size)
1363      {
1364        reader->pcl_point.x = 0.0;
1365        reader->pcl_point.y = HP_TO_PT * reader->y_size;
1366      }
1367    else
1368      {
1369        reader->pcl_point.x = 0.0;
1370        reader->pcl_point.y = 0.0;
1371      }
1372
1373  hpgs_matrix_ixform(&reader->pcl_point,&reader->pcl_point,&reader->page_matrix);
1374
1375  while ((reader->last_byte = hpgs_getc(reader->in)) != EOF)
1376    {
1377      if (reader->interrupted) goto interrupted_escape;
1378
1379      if (reader->last_byte != HPGS_ESC) continue;
1380
1381      reader->last_byte = hpgs_getc(reader->in);
1382
1383      if (reader->last_byte == EOF) break;
1384
1385      cmd1 = reader->last_byte;
1386      cmd2 = ' ';
1387
1388      switch (cmd1)
1389	{
1390	case 'E':
1391          hpgs_reader_set_default_state (reader);
1392	  break;
1393	case '&':
1394	case '*':
1395         reader->last_byte = hpgs_getc(reader->in);
1396         if (reader->last_byte == EOF) goto unexpected_eof;
1397         // invalid group character ?
1398         if (reader->last_byte < 96 || reader->last_byte >126) break;
1399         cmd2 = reader->last_byte;
1400	case '%':
1401          {
1402            hpgs_bool do_continue;
1403            do
1404              {
1405                int cmd = 0;
1406                int arg,arg_sign;
1407                int have_arg = hpgs_reader_read_pcl_int(reader,&arg,&arg_sign);
1408
1409                // check for an ESC charcter here
1410                // (which has already put back by ungetc() in pcl_read_int)
1411                // and continue with command parsing from the beginning.
1412                // This fixes some broken PCL files.
1413                if (reader->last_byte == HPGS_ESC) break;
1414
1415                do_continue = HPGS_FALSE;
1416
1417                if (have_arg < 0)
1418                  goto unexpected_eof;
1419
1420                reader->last_byte = hpgs_getc(reader->in);
1421
1422                if (reader->last_byte == EOF) goto unexpected_eof;
1423
1424                if (reader->last_byte >= 'a' && reader->last_byte <= 'z')
1425                  {
1426                    cmd = MK_PCL_CMD(cmd1,cmd2,reader->last_byte + ('A' - 'a'));
1427                    do_continue = HPGS_TRUE;
1428                  }
1429                else if (reader->last_byte >= 'A' && reader->last_byte <= 'Z')
1430                  cmd = MK_PCL_CMD(cmd1,cmd2,reader->last_byte);
1431
1432                if (cmd)
1433                  switch (pcl_do_cmd(reader,cmd,arg,arg_sign,have_arg))
1434                    {
1435                    case 1:
1436                      return 0;
1437                    case 2:
1438                      return 1;
1439                    case 0:
1440                      break;
1441                    default:
1442                      goto unexpected_eof;
1443                    }
1444              }
1445            while (do_continue);
1446          }
1447	  break;
1448	}
1449    }
1450
1451  ret = 2;
1452
1453 unexpected_eof:
1454
1455  if (reader->pcl_image)
1456    ret = hpgs_error_ctxt("Error in PCL image");
1457
1458 interrupted_escape:
1459  pcl_clear_raster_data(reader,PCL_RASTER_CLEAR_FORCE);
1460  return ret;
1461}
1462