Coverage Report

Created: 2025-04-22 06:20

/src/libspectre/ghostscript/devices/gdevccr.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2020 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
/* CalComp Raster Format driver */
17
#include "gdevprn.h"
18
19
/*
20
 * Please contact the author, Ernst Muellner (ernst.muellner@oenzl.siemens.de),
21
 * if you have any questions about this driver.
22
 */
23
24
0
#define CCFILESTART(p) gp_fputc(0x02, p)
25
0
#define CCFILEEND(p) gp_fputc(0x04, p)
26
0
#define CCNEWPASS(p) gp_fputc(0x0c, p)
27
0
#define CCEMPTYLINE(p) gp_fputc(0x0a, p)
28
0
#define CCLINESTART(len,p) do{ gp_fputc(0x1b,p);gp_fputc(0x4b,p);gp_fputc(len>>8,p); \
29
0
                               gp_fputc(len&0xff,p);} while(0)
30
31
0
#define CPASS (0)
32
0
#define MPASS (1)
33
0
#define YPASS (2)
34
#define NPASS (3)
35
36
typedef struct cmyrow_s
37
          {
38
            int current;
39
            int _cmylen[NPASS];
40
            int is_used;
41
            char cname[4];
42
            char mname[4];
43
            char yname[4];
44
            unsigned char *_cmybuf[NPASS];
45
          } cmyrow;
46
47
0
#define clen _cmylen[CPASS]
48
0
#define mlen _cmylen[MPASS]
49
0
#define ylen _cmylen[YPASS]
50
0
#define cmylen _cmylen
51
52
0
#define cbuf _cmybuf[CPASS]
53
0
#define mbuf _cmybuf[MPASS]
54
0
#define ybuf _cmybuf[YPASS]
55
0
#define cmybuf _cmybuf
56
57
static int alloc_rb( gs_memory_t *mem, cmyrow **rb, int rows);
58
static int alloc_line( gs_memory_t *mem, cmyrow *row, int cols);
59
static void add_cmy8(cmyrow *rb, char c, char m, char y);
60
static void write_cpass(cmyrow *buf, int rows, int pass, gp_file * pstream);
61
static void free_rb_line( gs_memory_t *mem, cmyrow *rbuf, int rows, int cols);
62
63
struct gx_device_ccr_s {
64
        gx_device_common;
65
        gx_prn_device_common;
66
        /* optional parameters */
67
};
68
typedef struct gx_device_ccr_s gx_device_ccr;
69
70
#define bdev ((gx_device_ccr *)pdev)
71
72
/* ------ The device descriptors ------ */
73
74
/*
75
 * Default X and Y resolution.
76
 */
77
#define X_DPI 300
78
#define Y_DPI 300
79
#define DEFAULT_WIDTH_10THS_A3 117
80
#define DEFAULT_HEIGHT_10THS_A3 165
81
82
/* Macro for generating ccr device descriptors. */
83
#define ccr_prn_device(procs, dev_name, margin, num_comp, depth, max_gray, max_rgb, print_page)\
84
{ prn_device_body(gx_device_ccr, procs, dev_name,\
85
          DEFAULT_WIDTH_10THS_A3, DEFAULT_HEIGHT_10THS_A3, X_DPI, Y_DPI,\
86
          margin, margin, margin, margin,\
87
          num_comp, depth, max_gray, max_rgb, max_gray + 1, max_rgb + 1,\
88
          print_page)\
89
}
90
91
/* For CCR, we need our own color mapping procedures. */
92
static dev_proc_map_rgb_color(ccr_map_rgb_color);
93
static dev_proc_map_color_rgb(ccr_map_color_rgb);
94
95
/* And of course we need our own print-page routine. */
96
static dev_proc_print_page(ccr_print_page);
97
98
/* The device procedures */
99
/* Since the print_page doesn't alter the device, this device can print in the background */
100
static gx_device_procs ccr_procs =
101
    prn_color_procs(gdev_prn_open, gdev_prn_bg_output_page, gdev_prn_close,
102
                    ccr_map_rgb_color, ccr_map_color_rgb);
103
104
/* The device descriptors themselves */
105
gx_device_ccr far_data gs_ccr_device =
106
  ccr_prn_device(ccr_procs, "ccr", 0.2, 3, 8, 1, 1,
107
                 ccr_print_page);
108
109
/* ------ Color mapping routines ------ */
110
/* map an rgb color to a ccr cmy bitmap */
111
static gx_color_index
112
ccr_map_rgb_color(gx_device *pdev, const ushort cv[])
113
0
{
114
0
  ushort r, g, b;
115
0
  register int shift = gx_color_value_bits - 1;
116
117
0
  r = cv[0]; g = cv[1]; b = cv[2];
118
0
  r>>=shift;
119
0
  g>>=shift;
120
0
  b>>=shift;
121
122
0
  r=1-r; g=1-g; b=1-b; /* rgb -> cmy */
123
0
  return r<<2 | g<<1 | b;
124
0
}
125
126
/* map an ccr cmy bitmap to a rgb color */
127
static int
128
ccr_map_color_rgb(gx_device *pdev, gx_color_index color, ushort rgb[3])
129
0
{
130
0
  rgb[2]=(1-(color >>2))*gx_max_color_value; /* r */
131
0
  rgb[1]=(1-( (color & 0x2) >> 1))*gx_max_color_value; /* g */
132
0
  rgb[0]=(1-(color & 0x1))*gx_max_color_value; /* b */
133
0
  return 0;
134
0
}
135
/* ------ print page routine ------ */
136
137
static int
138
ccr_print_page(gx_device_printer *pdev, gp_file *pstream)
139
0
{
140
0
  cmyrow *linebuf;
141
0
  int line_size = gdev_prn_raster((gx_device *)pdev);
142
0
  int pixnum = pdev->width;
143
0
  int lnum = pdev->height;
144
0
  int l, p, b;
145
0
  int cmy, c, m, y;
146
0
  byte *in;
147
0
  byte *data;
148
0
  int code = 0;
149
150
0
  if((in = (byte *)gs_malloc(pdev->memory, line_size, 1, "gsline")) == NULL)
151
0
     return_error(gs_error_VMerror);
152
153
0
  if(alloc_rb( pdev->memory, &linebuf, lnum))
154
0
    {
155
0
      gs_free(pdev->memory, in, line_size, 1, "gsline");
156
0
      return_error(gs_error_VMerror);
157
0
    }
158
159
0
  for ( l = 0; l < lnum; l++ )
160
0
     {  code = gdev_prn_get_bits(pdev, l, in, &data);
161
0
        if (code < 0)
162
0
            goto xit;
163
0
        if(alloc_line(pdev->memory, &linebuf[l], pixnum))
164
0
          {
165
0
            gs_free(pdev->memory, in, line_size, 1, "gsline");
166
0
            free_rb_line( pdev->memory, linebuf, lnum, pixnum );
167
0
            return_error(gs_error_VMerror);
168
0
          }
169
0
        for ( p=0; p< pixnum; p+=8)
170
0
          {
171
0
            c=m=y=0;
172
0
            for(b=0; b<8; b++)
173
0
            {
174
0
              c <<= 1; m <<= 1; y <<= 1;
175
0
              if(p+b < pixnum)
176
0
                cmy = *data;
177
0
              else
178
0
                cmy = 0;
179
180
0
              c |= cmy>>2;
181
0
              m |= (cmy>>1) & 0x1;
182
0
              y |= cmy & 0x1;
183
0
              data++;
184
0
            }
185
0
            add_cmy8(&linebuf[l], c, m, y);
186
0
          }
187
0
      }
188
0
CCFILESTART(pstream);
189
0
write_cpass(linebuf, lnum, YPASS, pstream);
190
0
CCNEWPASS(pstream);
191
0
write_cpass(linebuf, lnum, MPASS, pstream);
192
0
CCNEWPASS(pstream);
193
0
write_cpass(linebuf, lnum, CPASS, pstream);
194
0
CCFILEEND(pstream);
195
196
/* clean up */
197
0
xit:
198
0
gs_free(pdev->memory, in, line_size, 1, "gsline");
199
0
free_rb_line( pdev->memory, linebuf, lnum, pixnum );
200
0
return code;
201
0
}
202
203
/* ------ Internal routines ------ */
204
205
static int alloc_rb( gs_memory_t *mem, cmyrow **rb, int rows)
206
0
  {
207
0
  *rb = (cmyrow*) gs_malloc(mem, rows, sizeof(cmyrow), "rb");
208
0
  if( *rb == 0)
209
0
    return_error(gs_error_VMerror);
210
0
  else
211
0
    {
212
0
      int r;
213
0
      for(r=0; r<rows; r++)
214
0
        {
215
0
          gs_sprintf((*rb)[r].cname, "C%02x", r);
216
0
          gs_sprintf((*rb)[r].mname, "M%02x", r);
217
0
          gs_sprintf((*rb)[r].yname, "Y%02x", r);
218
0
          (*rb)[r].is_used=0;
219
0
        }
220
0
      return 0;
221
0
    }
222
0
}
223
224
static int alloc_line( gs_memory_t *mem, cmyrow *row, int cols)
225
0
{
226
0
  int suc;
227
0
  suc=((row->cbuf = (unsigned char *) gs_malloc(mem, cols,1, row->cname)) &&
228
0
       (row->mbuf = (unsigned char *) gs_malloc(mem, cols,1, row->mname)) &&
229
0
       (row->ybuf = (unsigned char *) gs_malloc(mem, cols,1, row->yname)));
230
0
  if(suc == 0)
231
0
       {
232
0
       gs_free(mem, row->cbuf, cols,1, row->cname);
233
0
       gs_free(mem, row->mbuf, cols,1, row->mname);
234
0
       gs_free(mem, row->ybuf, cols,1, row->yname);
235
236
0
       return_error(gs_error_VMerror);
237
0
     }
238
0
  row->is_used = 1;
239
0
  row->current = row->clen = row->mlen = row->ylen = 0;
240
0
  return 0;
241
0
}
242
243
static void add_cmy8(cmyrow *rb, char c, char m, char y)
244
0
{
245
0
  int cur=rb->current;
246
0
  rb->cbuf[cur]=c;
247
0
  if(c)
248
0
    rb->clen=cur+1;
249
0
  rb->mbuf[cur]=m;
250
0
  if(m)
251
0
    rb->mlen=cur+1;
252
0
  rb->ybuf[cur]=y;
253
0
  if(y)
254
0
    rb->ylen=cur+1;
255
0
  rb->current++;
256
0
  return;
257
0
}
258
259
static void write_cpass(cmyrow *buf, int rows, int pass, gp_file * pstream)
260
0
{
261
0
  int row, len;
262
0
    for(row=0; row<rows; row++)
263
0
      {
264
0
      len=buf[row].cmylen[pass];
265
0
      if(len == 0)
266
0
        CCEMPTYLINE(pstream);
267
0
      else
268
0
        {
269
0
          CCLINESTART(len,pstream);
270
0
          gp_fwrite( buf[row].cmybuf[pass], len, 1, pstream);
271
0
        }
272
0
    }
273
0
  return;
274
0
}
275
276
static void free_rb_line( gs_memory_t *mem, cmyrow *rbuf, int rows, int cols)
277
0
{
278
0
  int i;
279
0
  for(i=0; i<rows; i++)
280
0
    {
281
0
      if(rbuf[i].is_used)
282
0
        {
283
0
          gs_free(mem, rbuf[i].cbuf, cols, 1, rbuf[i].cname);
284
0
          gs_free(mem, rbuf[i].mbuf, cols, 1, rbuf[i].mname);
285
0
          gs_free(mem, rbuf[i].ybuf, cols, 1, rbuf[i].yname);
286
0
          rbuf[i].is_used = 0;
287
0
        }
288
0
      else
289
0
        break;
290
0
    }
291
0
  gs_free( mem, rbuf, rows, sizeof(cmyrow),  "rb");
292
0
  return;
293
0
}