1 /* Copyright (C) 2001-2019 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 
17 #include "gxdownscale.h"
18 #include "gserrors.h"
19 #include "string_.h"
20 #include "gdevprn.h"
21 #include "assert_.h"
22 
23 #ifdef WITH_CAL
24 #include "cal_ets.h"
25 #else
26 #include "ets.h"
27 #endif
28 
29 /* Nasty inline declaration, as gxht_thresh.h requires penum */
30 void gx_ht_threshold_row_bit_sub(byte *contone,  byte *threshold_strip,
31                              int contone_stride, byte *halftone,
32                              int dithered_stride, int width, int num_rows,
33                              int offset_bits);
34 
35 enum
36 {
37     MAX_ETS_PLANES = 8
38 };
39 
40 /* Error diffusion data is stored in errors block.
41  * We have 1 empty entry at each end to avoid overflow. When
42  * moving left to right we read from entries 2->width+1 (inclusive), and
43  * write to 1->width. When moving right to left we read from width->1 and
44  * write to width+1->2.
45  *
46  * Minimum feature size data is stored in the mfs_data block.
47  * We have 1 extra entry at the end to avoid overflow. When moving left to
48  * right we read from entries 1->width (inclusive), and write to 0->width-1.
49  * When moving right to left we read from width-1->0 and write to width->1.
50  */
51 
52 enum {
53     mfs_clear           = 0,
54     mfs_force_off       = 1,
55     mfs_above_is_0      = 2,
56     mfs_above_left_is_0 = 4,
57 };
58 
59 /* Mono downscale/error diffusion/min feature size code */
60 
61 /* Subsidiary function to pack the data from 8 bits to 1 */
pack_8to1(byte * outp,byte * inp,int w)62 static void pack_8to1(byte *outp, byte *inp, int w)
63 {
64     int mask  = 128;
65     int value = 0;
66     for (; w > 0; w--)
67     {
68         if (*inp++)
69             value |= mask;
70         mask >>= 1;
71         if (mask == 0) {
72             mask = 128;
73             *outp++= value;
74             value = 0;
75         }
76     }
77     if (mask != 128) {
78         *outp++ = value;
79     }
80 }
81 
down_core(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)82 static void down_core(gx_downscaler_t *ds,
83                       byte            *out_buffer,
84                       byte            *in_buffer,
85                       int              row,
86                       int              plane,
87                       int              span)
88 {
89     int        x, xx, y, value;
90     int        e_downleft, e_down, e_forward = 0;
91     int        pad_white;
92     byte      *inp, *outp;
93     int        width     = ds->width;
94     int        awidth    = ds->awidth;
95     int        factor    = ds->factor;
96     int       *errors    = ds->errors + (awidth+3)*plane;
97     const int  threshold = factor*factor*128;
98     const int  max_value = factor*factor*255;
99 
100     pad_white = (awidth - width) * factor;
101     if (pad_white < 0)
102         pad_white = 0;
103 
104     if (pad_white)
105     {
106         inp = in_buffer + width*factor;
107         for (y = factor; y > 0; y--)
108         {
109             memset(inp, 0xFF, pad_white);
110             inp += span;
111         }
112     }
113 
114     inp = in_buffer;
115     if ((row & 1) == 0)
116     {
117         /* Left to Right pass (no min feature size) */
118         const int back = span * factor - 1;
119         errors += 2;
120         outp = inp;
121         for (x = awidth; x > 0; x--)
122         {
123             value = e_forward + *errors;
124             for (xx = factor; xx > 0; xx--)
125             {
126                 for (y = factor; y > 0; y--)
127                 {
128                     value += *inp;
129                     inp += span;
130                 }
131                 inp -= back;
132             }
133             if (value >= threshold)
134             {
135                 *outp++ = 1;
136                 value -= max_value;
137             }
138             else
139             {
140                 *outp++ = 0;
141             }
142             e_forward  = value * 7/16;
143             e_downleft = value * 3/16;
144             e_down     = value * 5/16;
145             value     -= e_forward + e_downleft + e_down;
146             errors[-2] += e_downleft;
147             errors[-1] += e_down;
148             *errors++   = value;
149         }
150         outp -= awidth;
151     }
152     else
153     {
154         /* Right to Left pass (no min feature size) */
155         const int back = span * factor + 1;
156         errors += awidth;
157         inp += awidth*factor-1;
158         outp = inp;
159         for (x = awidth; x > 0; x--)
160         {
161             value = e_forward + *errors;
162             for (xx = factor; xx > 0; xx--)
163             {
164                 for (y = factor; y > 0; y--)
165                 {
166                     value += *inp;
167                     inp += span;
168                 }
169                 inp -= back;
170             }
171             if (value >= threshold)
172             {
173                 *outp-- = 1;
174                 value -= max_value;
175             }
176             else
177             {
178                 *outp-- = 0;
179             }
180             e_forward  = value * 7/16;
181             e_downleft = value * 3/16;
182             e_down     = value * 5/16;
183             value     -= e_forward + e_downleft + e_down;
184             errors[2] += e_downleft;
185             errors[1] += e_down;
186             *errors--   = value;
187         }
188         outp++;
189     }
190     pack_8to1(out_buffer, outp, awidth);
191 }
192 
down_core_ets_1(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)193 static void down_core_ets_1(gx_downscaler_t *ds,
194                             byte            *out_buffer,
195                             byte            *in_buffer,
196                             int              row,
197                             int              plane,
198                             int              span)
199 {
200     unsigned char *dest[MAX_ETS_PLANES];
201     ETS_SrcPixel *src[MAX_ETS_PLANES];
202     int pad_white, y;
203     int factor = ds->factor;
204 
205     pad_white = (ds->awidth - ds->width) * factor * 4;
206     if (pad_white < 0)
207         pad_white = 0;
208 
209     if (pad_white)
210     {
211         unsigned char *inp = in_buffer + ds->width * factor * 4;
212         for (y = factor; y > 0; y--)
213         {
214             memset(inp, 0xFF, pad_white);
215             inp += span;
216         }
217     }
218 
219     if (ds->ets_downscale)
220         ds->ets_downscale(ds, in_buffer, in_buffer, row, plane, span);
221 
222     src[0] = in_buffer;
223     dest[0] = in_buffer;
224     ets_line((ETS_Ctx *)ds->ets_config, dest, (const ETS_SrcPixel * const *)src);
225 
226     pack_8to1(out_buffer, in_buffer, ds->awidth);
227 }
228 
down_core_1(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)229 static void down_core_1(gx_downscaler_t *ds,
230                         byte            *out_buffer,
231                         byte            *in_buffer,
232                         int              row,
233                         int              plane,
234                         int              span)
235 {
236     int        x, value;
237     int        e_downleft, e_down, e_forward = 0;
238     int        pad_white;
239     byte      *inp, *outp;
240     int        width     = ds->width;
241     int        awidth    = ds->awidth;
242     int       *errors    = ds->errors + (awidth+3)*plane;
243     const int  threshold = 128;
244     const int  max_value = 255;
245 
246     pad_white = (awidth - width);
247     if (pad_white < 0)
248         pad_white = 0;
249 
250     if (pad_white)
251     {
252         memset(in_buffer + width, 0xFF, pad_white);
253     }
254 
255     inp = in_buffer;
256     if ((row & 1) == 0)
257     {
258         /* Left to Right pass (no min feature size) */
259         errors += 2;
260         outp = inp;
261         for (x = awidth; x > 0; x--)
262         {
263             value = e_forward + *errors + *inp++;
264             if (value >= threshold)
265             {
266                 *outp++ = 1;
267                 value -= max_value;
268             }
269             else
270             {
271                 *outp++ = 0;
272             }
273             e_forward  = value * 7/16;
274             e_downleft = value * 3/16;
275             e_down     = value * 5/16;
276             value     -= e_forward + e_downleft + e_down;
277             errors[-2] += e_downleft;
278             errors[-1] += e_down;
279             *errors++   = value;
280         }
281         outp -= awidth;
282     }
283     else
284     {
285         /* Right to Left pass (no min feature size) */
286         errors += awidth;
287         inp += awidth-1;
288         outp = inp;
289         for (x = awidth; x > 0; x--)
290         {
291             value = e_forward + *errors + *inp--;
292             if (value >= threshold)
293             {
294                 *outp-- = 1;
295                 value -= max_value;
296             }
297             else
298             {
299                 *outp-- = 0;
300             }
301             e_forward  = value * 7/16;
302             e_downleft = value * 3/16;
303             e_down     = value * 5/16;
304             value     -= e_forward + e_downleft + e_down;
305             errors[2] += e_downleft;
306             errors[1] += e_down;
307             *errors--   = value;
308         }
309         outp++;
310     }
311     pack_8to1(out_buffer, outp, awidth);
312 }
313 
down_core_2(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)314 static void down_core_2(gx_downscaler_t *ds,
315                         byte            *out_buffer,
316                         byte            *in_buffer,
317                         int              row,
318                         int              plane,
319                         int              span)
320 {
321     int        x, value;
322     int        e_downleft, e_down, e_forward = 0;
323     int        pad_white;
324     byte      *inp, *outp;
325     int        width     = ds->width;
326     int        awidth    = ds->awidth;
327     int       *errors    = ds->errors + (awidth+3)*plane;
328     const int  threshold = 2*2*128;
329     const int  max_value = 2*2*255;
330 
331     pad_white = (awidth - width) * 2;
332     if (pad_white < 0)
333         pad_white = 0;
334 
335     if (pad_white)
336     {
337         inp = in_buffer + width*2;
338         for (x = 2; x > 0; x--)
339         {
340             memset(inp, 0xFF, pad_white);
341             inp += span;
342         }
343     }
344 
345     inp = in_buffer;
346     if ((row & 1) == 0)
347     {
348         /* Left to Right pass (no min feature size) */
349         errors += 2;
350         outp = inp;
351         for (x = awidth; x > 0; x--)
352         {
353             value = e_forward + *errors + inp[0] + inp[1] + inp[span] + inp[span+1];
354             inp += 2;
355             if (value >= threshold)
356             {
357                 *outp++ = 1;
358                 value -= max_value;
359             }
360             else
361             {
362                 *outp++ = 0;
363             }
364             e_forward  = value * 7/16;
365             e_downleft = value * 3/16;
366             e_down     = value * 5/16;
367             value     -= e_forward + e_downleft + e_down;
368             errors[-2] += e_downleft;
369             errors[-1] += e_down;
370             *errors++   = value;
371         }
372         outp -= awidth;
373     }
374     else
375     {
376         /* Right to Left pass (no min feature size) */
377         errors += awidth;
378         inp += (awidth-1)*2;
379         outp = inp;
380         for (x = awidth; x > 0; x--)
381         {
382             value = e_forward + *errors + inp[0] + inp[1] + inp[span] + inp[span+1];
383             inp -= 2;
384             if (value >= threshold)
385             {
386                 *outp-- = 1;
387                 value -= max_value;
388             }
389             else
390             {
391                 *outp-- = 0;
392             }
393             e_forward  = value * 7/16;
394             e_downleft = value * 3/16;
395             e_down     = value * 5/16;
396             value     -= e_forward + e_downleft + e_down;
397             errors[2] += e_downleft;
398             errors[1] += e_down;
399             *errors--   = value;
400         }
401         outp++;
402     }
403     pack_8to1(out_buffer, outp, awidth);
404 }
405 
down_core_3(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)406 static void down_core_3(gx_downscaler_t *ds,
407                         byte            *out_buffer,
408                         byte            *in_buffer,
409                         int              row,
410                         int              plane,
411                         int              span)
412 {
413     int        x, value;
414     int        e_downleft, e_down, e_forward = 0;
415     int        pad_white;
416     byte      *inp, *outp;
417     int        width     = ds->width;
418     int        awidth    = ds->awidth;
419     int       *errors    = ds->errors + (awidth+3)*plane;
420     const int  threshold = 3*3*128;
421     const int  max_value = 3*3*255;
422 
423     pad_white = (awidth - width) * 3;
424     if (pad_white < 0)
425         pad_white = 0;
426 
427     if (pad_white)
428     {
429         inp = in_buffer + width*3;
430         for (x = 3; x > 0; x--)
431         {
432             memset(inp, 0xFF, pad_white);
433             inp += span;
434         }
435     }
436 
437     inp = in_buffer;
438     if ((row & 1) == 0)
439     {
440         /* Left to Right pass (no min feature size) */
441         errors += 2;
442         outp = inp;
443         for (x = awidth; x > 0; x--)
444         {
445             value = e_forward + *errors +
446                     inp[     0] + inp[       1] + inp[       2] +
447                     inp[span  ] + inp[span  +1] + inp[span  +2] +
448                     inp[span*2] + inp[span*2+1] + inp[span*2+2];
449             inp += 3;
450             if (value >= threshold)
451             {
452                 *outp++ = 1;
453                 value -= max_value;
454             }
455             else
456             {
457                 *outp++ = 0;
458             }
459             e_forward  = value * 7/16;
460             e_downleft = value * 3/16;
461             e_down     = value * 5/16;
462             value     -= e_forward + e_downleft + e_down;
463             errors[-2] += e_downleft;
464             errors[-1] += e_down;
465             *errors++   = value;
466         }
467         outp -= awidth;
468     }
469     else
470     {
471         /* Right to Left pass (no min feature size) */
472         errors += awidth;
473         inp += (awidth-1)*3;
474         outp = inp;
475         for (x = awidth; x > 0; x--)
476         {
477             value = e_forward + *errors +
478                     inp[     0] + inp[       1] + inp[       2] +
479                     inp[span  ] + inp[span  +1] + inp[span  +2] +
480                     inp[span*2] + inp[span*2+1] + inp[span*2+2];
481             inp -= 3;
482             if (value >= threshold)
483             {
484                 *outp-- = 1;
485                 value -= max_value;
486             }
487             else
488             {
489                 *outp-- = 0;
490             }
491             e_forward  = value * 7/16;
492             e_downleft = value * 3/16;
493             e_down     = value * 5/16;
494             value     -= e_forward + e_downleft + e_down;
495             errors[2] += e_downleft;
496             errors[1] += e_down;
497             *errors--   = value;
498         }
499         outp++;
500     }
501     pack_8to1(out_buffer, outp, awidth);
502 }
503 
down_core_4(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)504 static void down_core_4(gx_downscaler_t *ds,
505                         byte            *out_buffer,
506                         byte            *in_buffer,
507                         int              row,
508                         int              plane,
509                         int              span)
510 {
511     int        x, value;
512     int        e_downleft, e_down, e_forward = 0;
513     int        pad_white;
514     byte      *inp, *outp;
515     int        width     = ds->width;
516     int        awidth    = ds->awidth;
517     int       *errors    = ds->errors + (awidth+3)*plane;
518     const int  threshold = 4*4*128;
519     const int  max_value = 4*4*255;
520 
521     pad_white = (awidth - width) * 4;
522     if (pad_white < 0)
523         pad_white = 0;
524 
525     if (pad_white)
526     {
527         inp = in_buffer + width*4;
528         for (x = 4; x > 0; x--)
529         {
530             memset(inp, 0xFF, pad_white);
531             inp += span;
532         }
533     }
534 
535     inp = in_buffer;
536     if ((row & 1) == 0)
537     {
538         /* Left to Right pass (no min feature size) */
539         errors += 2;
540         outp = inp;
541         for (x = awidth; x > 0; x--)
542         {
543             value = e_forward + *errors +
544                     inp[     0] + inp[       1] + inp[       2] + inp[3       ] +
545                     inp[span  ] + inp[span  +1] + inp[span  +2] + inp[span  +3] +
546                     inp[span*2] + inp[span*2+1] + inp[span*2+2] + inp[span*2+3] +
547                     inp[span*3] + inp[span*3+1] + inp[span*3+2] + inp[span*3+3];
548             inp += 4;
549             if (value >= threshold)
550             {
551                 *outp++ = 1;
552                 value -= max_value;
553             }
554             else
555             {
556                 *outp++ = 0;
557             }
558             e_forward  = value * 7/16;
559             e_downleft = value * 3/16;
560             e_down     = value * 5/16;
561             value     -= e_forward + e_downleft + e_down;
562             errors[-2] += e_downleft;
563             errors[-1] += e_down;
564             *errors++   = value;
565         }
566         outp -= awidth;
567     }
568     else
569     {
570         /* Right to Left pass (no min feature size) */
571         errors += awidth;
572         inp += (awidth-1)*4;
573         outp = inp;
574         for (x = awidth; x > 0; x--)
575         {
576             value = e_forward + *errors +
577                     inp[     0] + inp[       1] + inp[       2] + inp[3       ] +
578                     inp[span  ] + inp[span  +1] + inp[span  +2] + inp[span  +3] +
579                     inp[span*2] + inp[span*2+1] + inp[span*2+2] + inp[span*2+3] +
580                     inp[span*3] + inp[span*3+1] + inp[span*3+2] + inp[span*3+3];
581             inp -= 4;
582             if (value >= threshold)
583             {
584                 *outp-- = 1;
585                 value -= max_value;
586             }
587             else
588             {
589                 *outp-- = 0;
590             }
591             e_forward  = value * 7/16;
592             e_downleft = value * 3/16;
593             e_down     = value * 5/16;
594             value     -= e_forward + e_downleft + e_down;
595             errors[2] += e_downleft;
596             errors[1] += e_down;
597             *errors--   = value;
598         }
599         outp++;
600     }
601     pack_8to1(out_buffer, outp, awidth);
602 }
603 
down_core_mfs(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)604 static void down_core_mfs(gx_downscaler_t *ds,
605                           byte            *out_buffer,
606                           byte            *in_buffer,
607                           int              row,
608                           int              plane,
609                           int              span)
610 {
611     int        x, xx, y, value;
612     int        e_downleft, e_down, e_forward = 0;
613     int        pad_white;
614     byte      *inp, *outp;
615     int        width     = ds->width;
616     int        awidth    = ds->awidth;
617     int        factor    = ds->factor;
618     int       *errors    = ds->errors + (awidth+3)*plane;
619     byte      *mfs_data  = ds->mfs_data + (awidth+1)*plane;
620     const int  threshold = factor*factor*128;
621     const int  max_value = factor*factor*255;
622 
623     pad_white = (awidth - width) * factor;
624     if (pad_white < 0)
625         pad_white = 0;
626 
627     if (pad_white)
628     {
629         inp = in_buffer + width*factor;
630         for (y = factor; y > 0; y--)
631         {
632             memset(inp, 0xFF, pad_white);
633             inp += span;
634         }
635     }
636 
637     inp = in_buffer;
638     if ((row & 1) == 0)
639     {
640         /* Left to Right pass (with min feature size = 2) */
641         const int back = span * factor -1;
642         byte mfs, force_forward = 0;
643         errors += 2;
644         outp = inp;
645         *mfs_data++ = mfs_clear;
646         for (x = awidth; x > 0; x--)
647         {
648             value = e_forward + *errors;
649             for (xx = factor; xx > 0; xx--)
650             {
651                 for (y = factor; y > 0; y--)
652                 {
653                     value += *inp;
654                     inp += span;
655                 }
656                 inp -= back;
657             }
658             mfs = *mfs_data;
659             *mfs_data++ = mfs_clear;
660             if ((mfs & mfs_force_off) || force_forward)
661             {
662                 /* We are being forced to be 0 */
663                 *outp++ = 0;
664                 force_forward = 0;
665             }
666             else if (value < threshold)
667             {
668                 /* We want to be 0 anyway */
669                 *outp++ = 0;
670                 if ((mfs & (mfs_above_is_0 | mfs_above_left_is_0))
671                         != (mfs_above_is_0 | mfs_above_left_is_0))
672                 {
673                     /* We aren't in a group anyway, so must force other
674                      * pixels. */
675                     mfs_data[-2] |= mfs_force_off;
676                     mfs_data[-1] |= mfs_force_off;
677                     force_forward = 1;
678                 }
679                 else
680                 {
681                     /* No forcing, but we need to tell other pixels that
682                      * we were 0. */
683                     mfs_data[-2] |= mfs_above_is_0;
684                     mfs_data[-1] |= mfs_above_left_is_0;
685                 }
686             }
687             else
688             {
689                 *outp++ = 1;
690                 value -= max_value;
691             }
692             e_forward  = value * 7/16;
693             e_downleft = value * 3/16;
694             e_down     = value * 5/16;
695             value     -= e_forward + e_downleft + e_down;
696             errors[-2] += e_downleft;
697             errors[-1] += e_down;
698             *errors++   = value;
699         }
700         outp -= awidth;
701     }
702     else
703     {
704         /* Right to Left pass (with min feature size = 2) */
705         const int back = span * factor + 1;
706         byte mfs, force_forward = 0;
707         errors += awidth;
708         mfs_data += awidth;
709         inp += awidth*factor-1;
710         outp = inp;
711         *mfs_data-- = mfs_clear;
712         for (x = awidth; x > 0; x--)
713         {
714             value = e_forward + *errors;
715             for (xx = factor; xx > 0; xx--)
716             {
717                 for (y = factor; y > 0; y--)
718                 {
719                     value += *inp;
720                     inp += span;
721                 }
722                 inp -= back;
723             }
724             mfs = *mfs_data;
725             *mfs_data-- = mfs_clear;
726             if ((mfs & mfs_force_off) || force_forward)
727             {
728                 /* We are being forced to be 0 */
729                 *outp-- = 0;
730                 force_forward = 0;
731             }
732             else if (value < threshold)
733             {
734                 *outp-- = 0;
735                 if ((mfs & (mfs_above_is_0 | mfs_above_left_is_0))
736                         != (mfs_above_is_0 | mfs_above_left_is_0))
737                 {
738                     /* We aren't in a group anyway, so must force other
739                      * pixels. */
740                     mfs_data[1] |= mfs_force_off;
741                     mfs_data[2] |= mfs_force_off;
742                     force_forward = 1;
743                 }
744                 else
745                 {
746                     /* No forcing, but we need to tell other pixels that
747                      * we were 0. */
748                     mfs_data[1] |= mfs_above_is_0;
749                     mfs_data[2] |= mfs_above_left_is_0;
750                 }
751             }
752             else
753             {
754                 *outp-- = 1;
755                 value -= max_value;
756             }
757             e_forward  = value * 7/16;
758             e_downleft = value * 3/16;
759             e_down     = value * 5/16;
760             value     -= e_forward + e_downleft + e_down;
761             errors[2] += e_downleft;
762             errors[1] += e_down;
763             *errors--   = value;
764         }
765         outp++;
766     }
767     pack_8to1(out_buffer, outp, awidth);
768 }
769 
770 /* CMYK 32 -> 4bit core */
down_core4(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)771 static void down_core4(gx_downscaler_t *ds,
772                        byte            *out_buffer,
773                        byte            *in_buffer,
774                        int              row,
775                        int              plane /* unused */,
776                        int              span)
777 {
778     int        x, xx, y, value, comp;
779     int        e_downleft, e_down, e_forward = 0;
780     int        pad_white;
781     byte      *inp, *outp;
782     int        width     = ds->width;
783     int        awidth    = ds->awidth;
784     int        factor    = ds->factor;
785     int       *errors    = ds->errors;
786     const int  threshold = factor*factor*128;
787     const int  max_value = factor*factor*255;
788 
789     pad_white = (awidth - width) * factor * 4;
790     if (pad_white < 0)
791         pad_white = 0;
792 
793     if (pad_white)
794     {
795         inp = in_buffer + width*factor * 4;
796         for (y = factor; y > 0; y--)
797         {
798             memset(inp, 0xFF, pad_white);
799             inp += span;
800         }
801     }
802 
803     if ((row & 1) == 0)
804     {
805         /* Left to Right pass (no min feature size) */
806         const int back = span * factor - 4;
807         for (comp = 0; comp < 4; comp++)
808         {
809             errors = ds->errors + (awidth+3)*comp + 2;
810             inp = in_buffer + comp;
811             outp = inp;
812             for (x = awidth; x > 0; x--)
813             {
814                 value = e_forward + *errors;
815                 for (xx = factor; xx > 0; xx--)
816                 {
817                     for (y = factor; y > 0; y--)
818                     {
819                         value += *inp;
820                         inp += span;
821                     }
822                     inp -= back;
823                 }
824                 if (value >= threshold)
825                 {
826                     *outp = 1; outp += 4;
827                     value -= max_value;
828                 }
829                 else
830                 {
831                     *outp = 0; outp += 4;
832                 }
833                 e_forward  = value * 7/16;
834                 e_downleft = value * 3/16;
835                 e_down     = value * 5/16;
836                 value     -= e_forward + e_downleft + e_down;
837                 errors[-2] += e_downleft;
838                 errors[-1] += e_down;
839                 *errors++   = value;
840             }
841         }
842         outp = in_buffer;
843     }
844     else
845     {
846         /* Right to Left pass (no min feature size) */
847         const int back = span * factor + 4;
848         for (comp = 0; comp < 4; comp++)
849         {
850             errors = ds->errors + (awidth+3)*comp + awidth;
851             inp = in_buffer + awidth*factor*4 - 4 + comp;
852             outp = inp;
853             for (x = awidth; x > 0; x--)
854             {
855                 value = e_forward + *errors;
856                 for (xx = factor; xx > 0; xx--)
857                 {
858                     for (y = factor; y > 0; y--)
859                     {
860                         value += *inp;
861                         inp += span;
862                     }
863                     inp -= back;
864                 }
865                 if (value >= threshold)
866                 {
867                     *outp = 1; outp -= 4;
868                     value -= max_value;
869                 }
870                 else
871                 {
872                     *outp = 0; outp -= 4;
873                 }
874                 e_forward  = value * 7/16;
875                 e_downleft = value * 3/16;
876                 e_down     = value * 5/16;
877                 value     -= e_forward + e_downleft + e_down;
878                 errors[2] += e_downleft;
879                 errors[1] += e_down;
880                 *errors--   = value;
881             }
882         }
883         outp = in_buffer + awidth*factor*4 - (awidth*4);
884     }
885     pack_8to1(out_buffer, outp, awidth*4);
886 }
887 
down_core4_ht(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)888 static void down_core4_ht(gx_downscaler_t *ds,
889                           byte            *out_buffer, /* Guaranteed aligned */
890                           byte            *in_buffer,  /* Not guaranteed aligned */
891                           int              row,
892                           int              plane /* unused */,
893                           int              span)
894 {
895     int pad_white, y;
896     int factor = ds->factor;
897     int i;
898     int nc = ds->early_cm ? ds->post_cm_num_comps : ds->num_comps;
899     byte *downscaled_data = ds->inbuf;
900 
901     pad_white = (ds->awidth - ds->width) * factor * 4;
902     if (pad_white < 0)
903         pad_white = 0;
904 
905     if (pad_white)
906     {
907         unsigned char *inp = in_buffer + ds->width * factor * 4;
908         for (y = factor; y > 0; y--)
909         {
910             memset(inp, 0xFF, pad_white);
911             inp += span;
912         }
913     }
914 
915     /* Color conversion has already happened. Do any downscale required. */
916     if (ds->ets_downscale)
917         ds->ets_downscale(ds, downscaled_data, in_buffer, row, plane, span);
918     else if ((31 & (intptr_t)in_buffer) == 0)
919         downscaled_data = in_buffer; /* Already aligned! Yay! */
920     else
921         memcpy(downscaled_data, in_buffer, nc*ds->width); /* Copy to align */
922 
923     /* Do the halftone */
924     for (i = 0; i < nc; i++)
925     {
926         /* Make the expanded threshold row */
927         byte *d = ds->htrow + i;
928         int len = ds->width;
929         const byte *srow = ds->ht[i].data + ds->ht[i].stride * ((row + ds->ht[i].y_phase) % ds->ht[i].h);
930         {
931             int o = ds->ht[i].x_phase;
932             int run = ds->ht[i].w - o;
933             const byte *s = &srow[o];
934             if (run > len)
935                 run = len;
936             len -= run;
937             do {
938                 *d = *s++;
939                 d += nc;
940             } while (--run);
941         }
942         while (len)
943         {
944             const byte *s = srow;
945             int run = ds->ht[i].w;
946             if (run > len)
947                 run = len;
948             len -= run;
949             do {
950                 *d = *s++;
951                 d += nc;
952             }
953             while (--run);
954         }
955     }
956 
957     /* Do the halftone */
958     gx_ht_threshold_row_bit_sub(downscaled_data, ds->htrow, 0,
959                                 out_buffer, 0,
960                                 ds->width * nc, 1, 0);
961 }
962 
down_core4_ets(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)963 static void down_core4_ets(gx_downscaler_t *ds,
964                            byte            *out_buffer,
965                            byte            *in_buffer,
966                            int              row,
967                            int              plane /* unused */,
968                            int              span)
969 {
970     unsigned char *dest[MAX_ETS_PLANES];
971     ETS_SrcPixel *src[MAX_ETS_PLANES];
972     int pad_white, y;
973     int factor = ds->factor;
974 
975     pad_white = (ds->awidth - ds->width) * factor * 4;
976     if (pad_white < 0)
977         pad_white = 0;
978 
979     if (pad_white)
980     {
981         unsigned char *inp = in_buffer + ds->width * factor * 4;
982         for (y = factor; y > 0; y--)
983         {
984             memset(inp, 0xFF, pad_white);
985             inp += span;
986         }
987     }
988 
989     if (ds->ets_downscale)
990         ds->ets_downscale(ds, in_buffer, in_buffer, row, plane, span);
991 
992     src[0] = in_buffer+3;
993     dest[0] = in_buffer+3;
994     src[1] = in_buffer+1;
995     dest[1] = in_buffer+1;
996     src[2] = in_buffer+0;
997     dest[2] = in_buffer+0;
998     src[3] = in_buffer+2;
999     dest[3] = in_buffer+2;
1000     ets_line((ETS_Ctx *)ds->ets_config, dest, (const ETS_SrcPixel * const *)src);
1001 
1002     pack_8to1(out_buffer, in_buffer, ds->awidth * 4);
1003 }
1004 
down_core4_mfs(gx_downscaler_t * ds,byte * out_buffer,byte * in_buffer,int row,int plane,int span)1005 static void down_core4_mfs(gx_downscaler_t *ds,
1006                            byte            *out_buffer,
1007                            byte            *in_buffer,
1008                            int              row,
1009                            int              plane /* unused */,
1010                            int              span)
1011 {
1012     int        x, xx, y, value, comp;
1013     int        e_downleft, e_down, e_forward = 0;
1014     int        pad_white;
1015     byte      *inp, *outp;
1016     int        width     = ds->width;
1017     int        awidth    = ds->awidth;
1018     int        factor    = ds->factor;
1019     int       *errors;
1020     const int  threshold = factor*factor*128;
1021     const int  max_value = factor*factor*255;
1022     byte      *mfs_data;
1023 
1024     pad_white = (awidth - width) * factor * 4;
1025     if (pad_white < 0)
1026         pad_white = 0;
1027 
1028     if (pad_white)
1029     {
1030         inp = in_buffer + width*factor*4;
1031         for (y = factor*4; y > 0; y--)
1032         {
1033             memset(inp, 0xFF, pad_white);
1034             inp += span;
1035         }
1036     }
1037 
1038     if ((row & 1) == 0)
1039     {
1040         /* Left to Right pass (with min feature size = 2) */
1041         const int back = span * factor - 4;
1042         for (comp = 0; comp < 4; comp++)
1043         {
1044             byte mfs, force_forward = 0;
1045             errors = ds->errors + (awidth+3)*comp + 2;
1046             inp = in_buffer + comp;
1047             outp = inp;
1048             mfs_data = ds->mfs_data + (awidth+1)*comp;
1049             *mfs_data++ = mfs_clear;
1050             for (x = awidth; x > 0; x--)
1051             {
1052                 value = e_forward + *errors;
1053                 for (xx = factor; xx > 0; xx--)
1054                 {
1055                     for (y = factor; y > 0; y--)
1056                     {
1057                         value += *inp;
1058                         inp += span;
1059                     }
1060                     inp -= back;
1061                 }
1062                 mfs = *mfs_data;
1063                 *mfs_data++ = mfs_clear;
1064                 if ((mfs & mfs_force_off) || force_forward)
1065                 {
1066                     /* We are being forced to be 0 */
1067                     *outp = 1; outp += 4;
1068                     value -= max_value;
1069                     force_forward = 0;
1070                 }
1071                 else if (value >= threshold)
1072                 {
1073                     /* We want to be 1 anyway */
1074                     *outp = 1; outp += 4;
1075                     value -= max_value;
1076                     if ((mfs & (mfs_above_is_0 | mfs_above_left_is_0))
1077                             != (mfs_above_is_0 | mfs_above_left_is_0))
1078                     {
1079                         /* We aren't in a group anyway, so must force other
1080                          * pixels. */
1081                         mfs_data[-2] |= mfs_force_off;
1082                         mfs_data[-1] |= mfs_force_off;
1083                         force_forward = 1;
1084                     }
1085                     else
1086                     {
1087                         /* No forcing, but we need to tell other pixels that
1088                          * we were 1. */
1089                         mfs_data[-2] |= mfs_above_is_0;
1090                         mfs_data[-1] |= mfs_above_left_is_0;
1091                     }
1092                 }
1093                 else
1094                 {
1095                     *outp = 0; outp += 4;
1096                 }
1097                 e_forward  = value * 7/16;
1098                 e_downleft = value * 3/16;
1099                 e_down     = value * 5/16;
1100                 value     -= e_forward + e_downleft + e_down;
1101                 errors[-2] += e_downleft;
1102                 errors[-1] += e_down;
1103                 *errors++   = value;
1104             }
1105         }
1106         outp = in_buffer;
1107     }
1108     else
1109     {
1110         /* Right to Left pass (with min feature size = 2) */
1111         const int back = span * factor + 4;
1112         for (comp = 0; comp < 4; comp++)
1113         {
1114             byte mfs, force_forward = 0;
1115             errors = ds->errors + (awidth+3)*comp + awidth;
1116             inp = in_buffer + awidth*factor*4 - 4 + comp;
1117             outp = inp;
1118             mfs_data = ds->mfs_data + (awidth+1)*comp + awidth;
1119             *mfs_data-- = mfs_clear;
1120             for (x = awidth; x > 0; x--)
1121             {
1122                 value = e_forward + *errors;
1123                 for (xx = factor; xx > 0; xx--)
1124                 {
1125                     for (y = factor; y > 0; y--)
1126                     {
1127                         value += *inp;
1128                         inp += span;
1129                     }
1130                     inp -= back;
1131                 }
1132                 mfs = *mfs_data;
1133                 *mfs_data-- = mfs_clear;
1134                 if ((mfs & mfs_force_off) || force_forward)
1135                 {
1136                     /* We are being forced to be 0 */
1137                     *outp = 1; outp -= 4;
1138                     value -= max_value;
1139                     force_forward = 0;
1140                 }
1141                 else if (value >= threshold)
1142                 {
1143                     *outp = 1; outp -= 4;
1144                     value -= max_value;
1145                     if ((mfs & (mfs_above_is_0 | mfs_above_left_is_0))
1146                             != (mfs_above_is_0 | mfs_above_left_is_0))
1147                     {
1148                         /* We aren't in a group anyway, so must force other
1149                          * pixels. */
1150                         mfs_data[1] |= mfs_force_off;
1151                         mfs_data[2] |= mfs_force_off;
1152                         force_forward = 1;
1153                     }
1154                     else
1155                     {
1156                         /* No forcing, but we need to tell other pixels that
1157                          * we were 1. */
1158                         mfs_data[1] |= mfs_above_is_0;
1159                         mfs_data[2] |= mfs_above_left_is_0;
1160                     }
1161                 }
1162                 else
1163                 {
1164                     *outp = 0; outp -= 4;
1165                 }
1166                 e_forward  = value * 7/16;
1167                 e_downleft = value * 3/16;
1168                 e_down     = value * 5/16;
1169                 value     -= e_forward + e_downleft + e_down;
1170                 errors[2] += e_downleft;
1171                 errors[1] += e_down;
1172                 *errors--   = value;
1173             }
1174         }
1175         outp = in_buffer + awidth*factor*4 - (awidth*4);
1176     }
1177     pack_8to1(out_buffer, outp, awidth*4);
1178 }
1179 
1180 /* Grey (or planar) downscale code */
down_core16(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1181 static void down_core16(gx_downscaler_t *ds,
1182                         byte            *outp,
1183                         byte            *in_buffer,
1184                         int              row,
1185                         int              plane,
1186                         int              span)
1187 {
1188     int   x, xx, y, value;
1189     int   pad_white;
1190     byte *inp;
1191     int   width  = ds->width;
1192     int   awidth = ds->awidth;
1193     int   factor = ds->factor;
1194     int   div    = factor*factor;
1195 
1196     pad_white = (awidth - width) * factor;
1197     if (pad_white < 0)
1198         pad_white = 0;
1199 
1200     if (pad_white)
1201     {
1202         inp = in_buffer + width*2*factor;
1203         for (y = factor; y > 0; y--)
1204         {
1205             memset(inp, 0xFF, pad_white*2);
1206             inp += span;
1207         }
1208     }
1209 
1210     inp = in_buffer;
1211     {
1212         /* Left to Right pass (no min feature size) */
1213         const int back = span * factor -2;
1214         for (x = awidth; x > 0; x--)
1215         {
1216             value = 0;
1217             for (xx = factor; xx > 0; xx--)
1218             {
1219                 for (y = factor; y > 0; y--)
1220                 {
1221                     value += inp[0]<<8;
1222                     value += inp[1];
1223                     inp += span;
1224                 }
1225                 inp -= back;
1226             }
1227             value = (value + (div>>1))/div;
1228             outp[0] = value>>8;
1229             outp[1] = value;
1230             outp += 2;
1231         }
1232     }
1233 }
1234 
down_core8(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1235 static void down_core8(gx_downscaler_t *ds,
1236                        byte            *outp,
1237                        byte            *in_buffer,
1238                        int              row,
1239                        int              plane,
1240                        int              span)
1241 {
1242     int   x, xx, y, value;
1243     int   pad_white;
1244     byte *inp;
1245     int   width  = ds->width;
1246     int   awidth = ds->awidth;
1247     int   factor = ds->factor;
1248     int   div    = factor*factor;
1249 
1250     pad_white = (awidth - width) * factor;
1251     if (pad_white < 0)
1252         pad_white = 0;
1253 
1254     if (pad_white)
1255     {
1256         inp = in_buffer + width*factor;
1257         for (y = factor; y > 0; y--)
1258         {
1259             memset(inp, 0xFF, pad_white);
1260             inp += span;
1261         }
1262     }
1263 
1264     inp = in_buffer;
1265     {
1266         /* Left to Right pass (no min feature size) */
1267         const int back = span * factor -1;
1268         for (x = awidth; x > 0; x--)
1269         {
1270             value = 0;
1271             for (xx = factor; xx > 0; xx--)
1272             {
1273                 for (y = factor; y > 0; y--)
1274                 {
1275                     value += *inp;
1276                     inp += span;
1277                 }
1278                 inp -= back;
1279             }
1280             *outp++ = (value+(div>>1))/div;
1281         }
1282     }
1283 }
1284 
down_core8_2(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1285 static void down_core8_2(gx_downscaler_t *ds,
1286                          byte            *outp,
1287                          byte            *in_buffer,
1288                          int              row,
1289                          int              plane,
1290                          int              span)
1291 {
1292     int   x;
1293     int   pad_white;
1294     byte *inp;
1295     int   width  = ds->width;
1296     int   awidth = ds->awidth;
1297 
1298     pad_white = (awidth - width) * 2;
1299     if (pad_white < 0)
1300         pad_white = 0;
1301 
1302     if (pad_white)
1303     {
1304         inp = in_buffer + width*2;
1305         for (x = 2; x > 0; x--)
1306         {
1307             memset(inp, 0xFF, pad_white);
1308             inp += span;
1309         }
1310     }
1311 
1312     inp = in_buffer;
1313 
1314     /* Left to Right pass (no min feature size) */
1315     for (x = awidth; x > 0; x--)
1316     {
1317         *outp++ = (inp[0] + inp[1] + inp[span] + inp[span+1] + 2)>>2;
1318         inp += 2;
1319     }
1320 }
1321 
down_core8_3(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1322 static void down_core8_3(gx_downscaler_t *ds,
1323                          byte            *outp,
1324                          byte            *in_buffer,
1325                          int              row,
1326                          int              plane,
1327                          int              span)
1328 {
1329     int   x;
1330     int   pad_white;
1331     byte *inp;
1332     int   width  = ds->width;
1333     int   awidth = ds->awidth;
1334 
1335     pad_white = (awidth - width) * 3;
1336     if (pad_white < 0)
1337         pad_white = 0;
1338 
1339     if (pad_white)
1340     {
1341         inp = in_buffer + width*3;
1342         for (x = 3; x > 0; x--)
1343         {
1344             memset(inp, 0xFF, pad_white);
1345             inp += span;
1346         }
1347     }
1348 
1349     inp = in_buffer;
1350 
1351     /* Left to Right pass (no min feature size) */
1352     for (x = awidth; x > 0; x--)
1353     {
1354         *outp++ = (inp[0     ] + inp[       1] + inp[       2] +
1355                    inp[span  ] + inp[span  +1] + inp[span  +2] +
1356                    inp[span*2] + inp[span*2+1] + inp[span*2+2] + 4)/9;
1357         inp += 3;
1358     }
1359 }
1360 
down_core8_4(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1361 static void down_core8_4(gx_downscaler_t *ds,
1362                          byte            *outp,
1363                          byte            *in_buffer,
1364                          int              row,
1365                          int              plane,
1366                          int              span)
1367 {
1368     int   x;
1369     int   pad_white;
1370     byte *inp;
1371     int   width  = ds->width;
1372     int   awidth = ds->awidth;
1373 
1374     pad_white = (awidth - width) * 4;
1375     if (pad_white < 0)
1376         pad_white = 0;
1377 
1378     if (pad_white)
1379     {
1380         inp = in_buffer + width*4;
1381         for (x = 4; x > 0; x--)
1382         {
1383             memset(inp, 0xFF, pad_white);
1384             inp += span;
1385         }
1386     }
1387 
1388     inp = in_buffer;
1389 
1390     /* Left to Right pass (no min feature size) */
1391     for (x = awidth; x > 0; x--)
1392     {
1393         *outp++ = (inp[0     ] + inp[       1] + inp[       2] + inp[       3] +
1394                    inp[span  ] + inp[span  +1] + inp[span  +2] + inp[span  +3] +
1395                    inp[span*2] + inp[span*2+1] + inp[span*2+2] + inp[span*2+3] +
1396                    inp[span*3] + inp[span*3+1] + inp[span*3+2] + inp[span*3+3] +
1397                    8)>>4;
1398         inp += 4;
1399     }
1400 }
1401 
down_core8_3_2(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1402 static void down_core8_3_2(gx_downscaler_t *ds,
1403                            byte            *outp,
1404                            byte            *in_buffer,
1405                            int              row,
1406                            int              plane,
1407                            int              span)
1408 {
1409     int   x;
1410     int   pad_white;
1411     byte *inp;
1412     int   width  = ds->width;
1413     int   awidth = ds->awidth;
1414     int   dspan  = ds->scaled_span;
1415 
1416     pad_white = (awidth - width) * 3 / 2;
1417     if (pad_white < 0)
1418         pad_white = 0;
1419 
1420     if (pad_white)
1421     {
1422         inp = in_buffer + width*3/2;
1423         for (x = 2; x > 0; x--)
1424         {
1425             memset(inp, 0xFF, pad_white);
1426             inp += span;
1427         }
1428     }
1429 
1430     inp = in_buffer;
1431 
1432     /* Left to Right pass (no min feature size) */
1433     for (x = awidth/2; x > 0; x--)
1434     {
1435         int a = inp[       0];
1436         int b = inp[       1];
1437         int c = inp[       2];
1438         int d = inp[  span+0];
1439         int e = inp[  span+1];
1440         int f = inp[  span+2];
1441         int g = inp[2*span+0];
1442         int h = inp[2*span+1];
1443         int i = inp[2*span+2];
1444         outp[0      ] = (4*a+2*b+2*d+e+4)/9;
1445         outp[1      ] = (4*c+2*b+2*f+e+4)/9;
1446         outp[dspan+0] = (4*g+2*h+2*d+e+4)/9;
1447         outp[dspan+1] = (4*i+2*h+2*f+e+4)/9;
1448         outp += 2;
1449         inp += 3;
1450     }
1451 }
1452 
down_core8_3_4(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1453 static void down_core8_3_4(gx_downscaler_t *ds,
1454                            byte            *outp,
1455                            byte            *in_buffer,
1456                            int              row,
1457                            int              plane,
1458                            int              span)
1459 {
1460     int   x;
1461     int   pad_white;
1462     byte *inp;
1463     int   width  = ds->width;
1464     int   awidth = ds->awidth;
1465     int   dspan  = ds->scaled_span;
1466 
1467     pad_white = (awidth - width) * 3 / 4;
1468     if (pad_white < 0)
1469         pad_white = 0;
1470 
1471     if (pad_white)
1472     {
1473         inp = in_buffer + width*3/4;
1474         for (x = 4; x > 0; x--)
1475         {
1476             memset(inp, 0xFF, pad_white);
1477             inp += span;
1478         }
1479     }
1480 
1481     inp = in_buffer;
1482 
1483     /* Left to Right pass (no min feature size) */
1484     for (x = awidth/4; x > 0; x--)
1485     {
1486         int a = inp[       0];
1487         int b = inp[       1];
1488         int c = inp[       2];
1489         int d = inp[  span+0];
1490         int e = inp[  span+1];
1491         int f = inp[  span+2];
1492         int g = inp[2*span+0];
1493         int h = inp[2*span+1];
1494         int i = inp[2*span+2];
1495         outp[        0] = a;
1496         outp[        1] = (a+2*b+1)/3;
1497         outp[        2] = (c+2*b+1)/3;
1498         outp[        3] = c;
1499         outp[  dspan+0] = (a+2*d+1)/3;
1500         outp[  dspan+1] = (a+2*b+2*d+4*e+3)/9;
1501         outp[  dspan+2] = (c+2*b+2*f+4*e+3)/9;
1502         outp[  dspan+3] = (c+2*f+1)/3;
1503         outp[2*dspan+0] = (g+2*d+1)/3;
1504         outp[2*dspan+1] = (g+2*h+2*d+4*e+3)/9;
1505         outp[2*dspan+2] = (i+2*h+2*f+4*e+3)/9;
1506         outp[2*dspan+3] = (i+2*f+1)/3;
1507         outp[3*dspan+0] = g;
1508         outp[3*dspan+1] = (g+2*h+1)/3;
1509         outp[3*dspan+2] = (i+2*h+1)/3;
1510         outp[3*dspan+3] = i;
1511         outp += 4;
1512         inp += 3;
1513     }
1514 }
1515 
1516 /* RGB downscale (no error diffusion) code */
1517 
down_core24(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1518 static void down_core24(gx_downscaler_t *ds,
1519                         byte            *outp,
1520                         byte            *in_buffer,
1521                         int              row,
1522                         int              plane,
1523                         int              span)
1524 {
1525     int   x, xx, y, value;
1526     int   pad_white;
1527     byte *inp;
1528     int   width  = ds->width;
1529     int   awidth = ds->awidth;
1530     int   factor = ds->factor;
1531     int   div    = factor*factor;
1532 
1533     pad_white = (awidth - width) * factor * 3;
1534     if (pad_white < 0)
1535         pad_white = 0;
1536 
1537     if (pad_white)
1538     {
1539         inp = in_buffer + width*factor*3;
1540         for (y = factor; y > 0; y--)
1541         {
1542             memset(inp, 0xFF, pad_white);
1543             inp += span;
1544         }
1545     }
1546 
1547     inp = in_buffer;
1548     {
1549         /* Left to Right pass (no min feature size) */
1550         const int back  = span * factor - 3;
1551         const int back2 = factor * 3 - 1;
1552         for (x = awidth; x > 0; x--)
1553         {
1554             /* R */
1555             value = 0;
1556             for (xx = factor; xx > 0; xx--)
1557             {
1558                 for (y = factor; y > 0; y--)
1559                 {
1560                     value += *inp;
1561                     inp += span;
1562                 }
1563                 inp -= back;
1564             }
1565             inp -= back2;
1566             *outp++ = (value+(div>>1))/div;
1567             /* G */
1568             value = 0;
1569             for (xx = factor; xx > 0; xx--)
1570             {
1571                 for (y = factor; y > 0; y--)
1572                 {
1573                     value += *inp;
1574                     inp += span;
1575                 }
1576                 inp -= back;
1577             }
1578             inp -= back2;
1579             *outp++ = (value+(div>>1))/div;
1580             /* B */
1581             value = 0;
1582             for (xx = factor; xx > 0; xx--)
1583             {
1584                 for (y = factor; y > 0; y--)
1585                 {
1586                     value += *inp;
1587                     inp += span;
1588                 }
1589                 inp -= back;
1590             }
1591             inp -= 2;
1592             *outp++ = (value+(div>>1))/div;
1593         }
1594     }
1595 }
1596 
1597 /* CMYK downscale (no error diffusion) code */
1598 
down_core32(gx_downscaler_t * ds,byte * outp,byte * in_buffer,int row,int plane,int span)1599 static void down_core32(gx_downscaler_t *ds,
1600                         byte            *outp,
1601                         byte            *in_buffer,
1602                         int              row,
1603                         int              plane,
1604                         int              span)
1605 {
1606     int   x, xx, y, value;
1607     int   pad_white;
1608     byte *inp;
1609     int   width  = ds->width;
1610     int   awidth = ds->awidth;
1611     int   factor = ds->factor;
1612     int   div    = factor*factor;
1613 
1614     pad_white = (awidth - width) * factor * 4;
1615     if (pad_white < 0)
1616         pad_white = 0;
1617 
1618     if (pad_white)
1619     {
1620         inp = in_buffer + width*factor*4;
1621         for (y = factor; y > 0; y--)
1622         {
1623             memset(inp, 0xFF, pad_white);
1624             inp += span;
1625         }
1626     }
1627 
1628     inp = in_buffer;
1629     {
1630         /* Left to Right pass (no min feature size) */
1631         const int back  = span * factor - 4;
1632         const int back2 = factor * 4 - 1;
1633         for (x = awidth; x > 0; x--)
1634         {
1635             /* C */
1636             value = 0;
1637             for (xx = factor; xx > 0; xx--)
1638             {
1639                 for (y = factor; y > 0; y--)
1640                 {
1641                     value += *inp;
1642                     inp += span;
1643                 }
1644                 inp -= back;
1645             }
1646             inp -= back2;
1647             *outp++ = (value+(div>>1))/div;
1648             /* M */
1649             value = 0;
1650             for (xx = factor; xx > 0; xx--)
1651             {
1652                 for (y = factor; y > 0; y--)
1653                 {
1654                     value += *inp;
1655                     inp += span;
1656                 }
1657                 inp -= back;
1658             }
1659             inp -= back2;
1660             *outp++ = (value+(div>>1))/div;
1661             /* Y */
1662             value = 0;
1663             for (xx = factor; xx > 0; xx--)
1664             {
1665                 for (y = factor; y > 0; y--)
1666                 {
1667                     value += *inp;
1668                     inp += span;
1669                 }
1670                 inp -= back;
1671             }
1672             inp -= back2;
1673             *outp++ = (value+(div>>1))/div;
1674             /* K */
1675             value = 0;
1676             for (xx = factor; xx > 0; xx--)
1677             {
1678                 for (y = factor; y > 0; y--)
1679                 {
1680                     value += *inp;
1681                     inp += span;
1682                 }
1683                 inp -= back;
1684             }
1685             inp -= 3;
1686             *outp++ = (value+(div>>1))/div;
1687         }
1688     }
1689 }
1690 
decode_factor(int factor,int * up,int * down)1691 static void decode_factor(int factor, int *up, int *down)
1692 {
1693     if (factor == 32)
1694         *down = 3, *up = 2;
1695     else if (factor == 34)
1696         *down = 3, *up = 4;
1697     else
1698         *down = factor, *up = 1;
1699 }
1700 
1701 int
gx_downscaler_scale(int width,int factor)1702 gx_downscaler_scale(int width, int factor)
1703 {
1704     int up, down;
1705 
1706     decode_factor(factor, &up, &down);
1707     return (width*up)/down;
1708 }
1709 
gx_downscaler_adjust_bandheight(int factor,int band_height)1710 int gx_downscaler_adjust_bandheight(int factor, int band_height)
1711 {
1712     int up, down;
1713 
1714     decode_factor(factor, &up, &down);
1715     return (band_height/down)*down;
1716 }
1717 
1718 int
gx_downscaler_scale_rounded(int width,int factor)1719 gx_downscaler_scale_rounded(int width, int factor)
1720 {
1721     int up, down;
1722 
1723     decode_factor(factor, &up, &down);
1724     return (width*up + down-1)/down;
1725 }
1726 
get_planar_line_for_trap(void * arg,unsigned char * buf)1727 static int get_planar_line_for_trap(void *arg, unsigned char *buf)
1728 {
1729     gx_downscaler_t *ds = (gx_downscaler_t *)arg;
1730     gs_int_rect rect;
1731     gs_get_bits_params_t params; /* params (if trapping) */
1732     int nc = ds->num_planes;
1733     int i, code;
1734     unsigned char *buf2;
1735 
1736     rect.p.x = 0;
1737     rect.p.y = ds->claptrap_y++;
1738     rect.q.x = ds->dev->width;
1739     rect.q.y = rect.p.y+1;
1740     /* Allow for devices (like psdcmyk) that make several passes through
1741      * the image. */
1742     if (ds->claptrap_y == ds->dev->height)
1743         ds->claptrap_y = 0;
1744 
1745     params = *ds->claptrap_params;
1746     buf2 = buf;
1747     for (i = 0; i < nc; i++)
1748     {
1749         params.data[i] = buf2;
1750         buf2 += ds->width;
1751     }
1752 
1753     code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, &params, NULL);
1754     if (code < 0)
1755         return code;
1756 
1757     /* Now cope with the fact we might have been returned pointers */
1758     for (i = 0; i < nc; i++)
1759     {
1760         if (params.data[i] != buf)
1761             memcpy(buf, params.data[i], ds->width);
1762         buf += ds->width;
1763     }
1764 
1765     return code;
1766 }
1767 
check_trapping(gs_memory_t * memory,int trap_w,int trap_h,int num_comps,const int * comp_order)1768 static int check_trapping(gs_memory_t *memory, int trap_w, int trap_h,
1769                           int num_comps, const int *comp_order)
1770 {
1771     if (trap_w < 0 || trap_h < 0)
1772     {
1773         dmprintf(memory, "Trapping range must be >= 0");
1774         return_error(gs_error_rangecheck);
1775     }
1776 
1777     if (trap_w > 0 || trap_h > 0)
1778     {
1779         if (comp_order == NULL)
1780         {
1781             emprintf(memory, "Trapping cannot be used without comp_order being defined");
1782             return_error(gs_error_rangecheck);
1783         }
1784 
1785         /* Check that the comp_order we have been passed is sane */
1786         {
1787             char comps[GS_CLIENT_COLOR_MAX_COMPONENTS] = { 0 };
1788             int i;
1789 
1790             for (i = 0; i < num_comps; i++)
1791             {
1792                 int n = comp_order[i];
1793                 if (n < 0 || n >= num_comps || comps[n] != 0)
1794                     break;
1795                 comps[n] = 1;
1796             }
1797             if (i != num_comps)
1798             {
1799                 emprintf(memory, "Illegal component order passed to trapping");
1800                 return_error(gs_error_rangecheck);
1801             }
1802         }
1803     }
1804     return 0;
1805 }
1806 
1807 static void
find_aspect_ratio(float * res,int * a,int * b)1808 find_aspect_ratio(float *res, int *a, int *b)
1809 {
1810     float xres = res[0];
1811     float yres = res[1];
1812     float f;
1813 
1814     if (xres == yres) {
1815         *a = *b = 1;
1816         return;
1817     }
1818     else if (xres > yres)
1819     {
1820         xres /= yres;
1821         f = xres - (int)xres;
1822         if (f >= 0.2 && f < 0.3)
1823             xres *= 4, yres = 4;
1824         else if (f >= 0.3 && f < 0.4)
1825             xres *= 3, yres = 3;
1826         else if (f >= 0.4 && f < 0.6)
1827             xres *= 2, yres = 2;
1828         else if (f >= 0.6 && f < 0.7)
1829             xres *= 3, yres = 3;
1830         else if (f >= 0.7 && f < 0.8)
1831             xres *= 4, yres = 4;
1832         else
1833             yres = 1;
1834         *a = (int)(xres + 0.5);
1835         *b = (int)yres;
1836     }
1837     else
1838     {
1839         yres /= xres;
1840         f = yres - (int)yres;
1841         if (f >= 0.2 && f < 0.3)
1842             yres *= 4, xres = 4;
1843         else if (f >= 0.3 && f < 0.4)
1844             yres *= 3, xres = 3;
1845         else if (f >= 0.4 && f < 0.6)
1846             yres *= 2, xres = 2;
1847         else if (f >= 0.6 && f < 0.7)
1848             yres *= 3, xres = 3;
1849         else if (f >= 0.7 && f < 0.8)
1850             yres *= 4, xres = 4;
1851         else
1852             xres = 1;
1853         *a = (int)xres;
1854         *b = (int)(yres + 0.5);
1855     }
1856 }
1857 
init_ets(gx_downscaler_t * ds,int num_planes,gx_downscale_core * downscale_core)1858 static int init_ets(gx_downscaler_t *ds, int num_planes, gx_downscale_core *downscale_core)
1859 {
1860     ETS_Params params = { 0 };
1861     int strengths[MAX_ETS_PLANES] = { 128, 51, 51, 13, 13, 13, 13, 13 };
1862     int lut[ETS_SRC_MAX+1];
1863     int *luts[MAX_ETS_PLANES];
1864     int rs_lut[ETS_SRC_MAX+1];
1865     int *rs_luts[MAX_ETS_PLANES];
1866     int i;
1867     int c1_scale[MAX_ETS_PLANES] = { 1, 1, 1, 1, 1, 1, 1, 1 };
1868     ETS_POLARITY polarity = ETS_BLACK_IS_ONE;
1869 
1870     polarity = ETS_BLACK_IS_ONE;
1871 
1872     if (num_planes > MAX_ETS_PLANES)
1873         return gs_error_rangecheck;
1874 
1875     ds->ets_downscale = downscale_core;
1876 
1877     /* Setup a simple gamma scale */
1878     {
1879         double scale = ETS_SRC_MAX;
1880         for (i = 0; i < (ETS_SRC_MAX+1); i++)
1881             lut[i] = (int)((1 << 24) * (pow (i / scale, 1.0)));
1882     }
1883     for (i = 0; i < (ETS_SRC_MAX+1); i++)
1884         rs_lut[i] = 2 << 16;
1885     for (i = 0; i < num_planes; i++)
1886         luts[i] = lut;
1887     for (i = 0; i < num_planes; i++)
1888         rs_luts[i] = rs_lut;
1889 
1890 #ifdef WITH_CAL
1891     params.context = ds->dev->memory->gs_lib_ctx->core->cal_ctx;
1892 #endif
1893     params.width = ds->width;
1894     params.n_planes = num_planes;
1895     params.levels = 2;
1896     params.luts = luts;
1897     params.distscale = 0;
1898     find_aspect_ratio(ds->dev->HWResolution, &params.aspect_x, &params.aspect_y);
1899     params.strengths = strengths;
1900     params.rand_scale = 0;
1901     params.c1_scale = c1_scale;
1902     params.ets_bias = ETS_BIAS_REDUCE_POSITIVE;
1903     params.r_style = ETS_RSTYLE_THRESHOLD;
1904     params.dump_file = NULL;
1905     params.dump_level = 0;
1906     params.rand_scale_luts = rs_luts;
1907     params.polarity = polarity;
1908 
1909     ds->ets_config = ets_create(ds->dev->memory, &params);
1910     if (ds->ets_config == NULL)
1911         return gs_note_error(gs_error_VMerror);
1912 
1913     return 0;
1914 }
1915 
init_ht(gx_downscaler_t * ds,int num_planes,gx_downscale_core * downscale_core)1916 static int init_ht(gx_downscaler_t *ds, int num_planes, gx_downscale_core *downscale_core)
1917 {
1918     int nc = ds->early_cm ? ds->post_cm_num_comps : ds->num_comps;
1919 
1920     ds->ets_downscale = downscale_core;
1921 
1922     /* Allocate us a row (with padding for alignment) so we can hold the
1923      * expanded threshold array. */
1924     ds->htrow_alloc = gs_alloc_bytes(ds->dev->memory, ds->width * nc + 64,
1925                                      "gx_downscaler(htrow)");
1926     if (ds->htrow_alloc == NULL)
1927         return gs_error_VMerror;
1928     /* Make an aligned version */
1929     ds->htrow = ds->htrow_alloc + ((32-(intptr_t)ds->htrow_alloc) & 31);
1930 
1931     /* Allocate us a row (with padding for alignment) for the downscaled data. */
1932     ds->inbuf_alloc = gs_alloc_bytes(ds->dev->memory, ds->width * nc + 64,
1933                                      "gx_downscaler(inbuf)");
1934     if (ds->inbuf_alloc == NULL)
1935     {
1936         gs_free_object(ds->dev->memory, ds->htrow_alloc, "gx_downscaler(htrow)");
1937         ds->htrow_alloc = ds->htrow = NULL;
1938         return gs_error_VMerror;
1939     }
1940     /* Make an aligned version */
1941     ds->inbuf = ds->inbuf_alloc + ((32-(intptr_t)ds->inbuf_alloc) & 31);
1942 
1943     return 0;
1944 }
1945 
gx_downscaler_init_planar(gx_downscaler_t * ds,gx_device * dev,gs_get_bits_params_t * params,int num_comps,int factor,int mfs,int src_bpc,int dst_bpc)1946 int gx_downscaler_init_planar(gx_downscaler_t      *ds,
1947                               gx_device            *dev,
1948                               gs_get_bits_params_t *params,
1949                               int                   num_comps,
1950                               int                   factor,
1951                               int                   mfs,
1952                               int                   src_bpc,
1953                               int                   dst_bpc)
1954 {
1955     return gx_downscaler_init_planar_trapped_cm(ds, dev, params, num_comps,
1956         factor, mfs, src_bpc, dst_bpc, 0, 0, NULL, NULL, NULL, num_comps);
1957 }
1958 
gx_downscaler_init_planar_trapped(gx_downscaler_t * ds,gx_device * dev,gs_get_bits_params_t * params,int num_comps,int factor,int mfs,int src_bpc,int dst_bpc,int trap_w,int trap_h,const int * comp_order)1959 int gx_downscaler_init_planar_trapped(gx_downscaler_t      *ds,
1960                                       gx_device            *dev,
1961                                       gs_get_bits_params_t *params,
1962                                       int                   num_comps,
1963                                       int                   factor,
1964                                       int                   mfs,
1965                                       int                   src_bpc,
1966                                       int                   dst_bpc,
1967                                       int                   trap_w,
1968                                       int                   trap_h,
1969                                       const int            *comp_order)
1970 {
1971     return gx_downscaler_init_planar_trapped_cm(ds, dev, params, num_comps,
1972                                                 factor, mfs, src_bpc, dst_bpc,
1973                                                 trap_w, trap_h, comp_order,
1974                                                 NULL, NULL, num_comps);
1975 }
1976 
gx_downscaler_init_planar_trapped_cm(gx_downscaler_t * ds,gx_device * dev,gs_get_bits_params_t * params,int num_comps,int factor,int mfs,int src_bpc,int dst_bpc,int trap_w,int trap_h,const int * comp_order,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps)1977 int gx_downscaler_init_planar_trapped_cm(gx_downscaler_t      *ds,
1978                                          gx_device            *dev,
1979                                          gs_get_bits_params_t *params,
1980                                          int                   num_comps,
1981                                          int                   factor,
1982                                          int                   mfs,
1983                                          int                   src_bpc,
1984                                          int                   dst_bpc,
1985                                          int                   trap_w,
1986                                          int                   trap_h,
1987                                          const int            *comp_order,
1988                                          gx_downscale_cm_fn   *apply_cm,
1989                                          void                 *apply_cm_arg,
1990                                          int                   post_cm_num_comps)
1991 {
1992     int                span = bitmap_raster(dev->width * src_bpc);
1993     int                post_span = bitmap_raster(dev->width * src_bpc);
1994     int                width;
1995     int                code;
1996     gx_downscale_core *core;
1997     int                i;
1998     int                upfactor, downfactor;
1999 
2000     decode_factor(factor, &upfactor, &downfactor);
2001 
2002     /* width = scaled width */
2003     width = (dev->width*upfactor)/downfactor;
2004     memset(ds, 0, sizeof(*ds));
2005     ds->dev               = dev;
2006     ds->width             = width;
2007     ds->awidth            = width;
2008     ds->span              = span;
2009     ds->factor            = factor;
2010     ds->num_planes        = num_comps;
2011     ds->src_bpc           = src_bpc;
2012     ds->scaled_data       = NULL;
2013     ds->scaled_span       = bitmap_raster((dst_bpc*dev->width*upfactor + downfactor-1)/downfactor);
2014     ds->apply_cm          = apply_cm;
2015     ds->apply_cm_arg      = apply_cm_arg;
2016     ds->early_cm          = dst_bpc < src_bpc;
2017     ds->post_cm_num_comps = post_cm_num_comps;
2018 
2019     if (apply_cm) {
2020         for (i = 0; i < post_cm_num_comps; i++) {
2021             ds->post_cm[i] = gs_alloc_bytes(dev->memory, post_span * downfactor,
2022                                                 "gx_downscaler(planar_data)");
2023             if (ds->post_cm[i] == NULL) {
2024                 code = gs_note_error(gs_error_VMerror);
2025                 goto cleanup;
2026             }
2027         }
2028     }
2029 
2030     code = check_trapping(dev->memory, trap_w, trap_h, num_comps, comp_order);
2031     if (code < 0)
2032         return code;
2033 
2034     if (trap_w > 0 || trap_h > 0) {
2035         ds->claptrap = ClapTrap_Init(dev->memory, width, dev->height, num_comps, comp_order, trap_w, trap_h, get_planar_line_for_trap, ds);
2036         if (ds->claptrap == NULL) {
2037             emprintf(dev->memory, "Trapping initialisation failed");
2038             code = gs_note_error(gs_error_VMerror);
2039             goto cleanup;
2040         }
2041     }
2042     else
2043         ds->claptrap = NULL;
2044 
2045     memcpy(&ds->params, params, sizeof(*params));
2046     ds->params.raster = span;
2047     for (i = 0; i < num_comps; i++) {
2048         ds->pre_cm[i] = gs_alloc_bytes(dev->memory, span * downfactor,
2049                                             "gx_downscaler(planar_data)");
2050         if (ds->pre_cm[i] == NULL) {
2051             code = gs_note_error(gs_error_VMerror);
2052             goto cleanup;
2053         }
2054     }
2055     if (upfactor > 1) {
2056         ds->scaled_data = gs_alloc_bytes(dev->memory, ds->scaled_span * upfactor * num_comps,
2057                                          "gx_downscaler(scaled_data)");
2058         if (ds->scaled_data == NULL) {
2059             code = gs_note_error(gs_error_VMerror);
2060             goto cleanup;
2061         }
2062     }
2063 
2064     if ((src_bpc == 8) && (dst_bpc == 8) && (factor == 32)) {
2065         core = &down_core8_3_2;
2066     } else if ((src_bpc == 8) && (dst_bpc == 8) && (factor == 34)) {
2067         core = &down_core8_3_4;
2068     } else if (factor > 8) {
2069         code = gs_note_error(gs_error_rangecheck);
2070         goto cleanup;
2071     } else if (dst_bpc == 1) {
2072         if (mfs > 1)
2073             core = &down_core_mfs;
2074         else if (factor == 4)
2075             core = &down_core_4;
2076         else if (factor == 3)
2077             core = &down_core_3;
2078         else if (factor == 2)
2079             core = &down_core_2;
2080         else if (factor == 1)
2081             core = &down_core_1;
2082         else
2083             core = &down_core;
2084     } else if (factor == 1)
2085         core = NULL;
2086     else if (src_bpc == 16)
2087         core = &down_core16;
2088     else if (factor == 4)
2089         core = &down_core8_4;
2090     else if (factor == 3)
2091         core = &down_core8_3;
2092     else if (factor == 2)
2093         core = &down_core8_2;
2094     else
2095         core = &down_core8;
2096     ds->down_core = core;
2097 
2098     if (mfs > 1) {
2099         ds->mfs_data = (byte *)gs_alloc_bytes(dev->memory,
2100                                               (width+1) * num_comps,
2101                                               "gx_downscaler(mfs)");
2102         if (ds->mfs_data == NULL) {
2103             code = gs_note_error(gs_error_VMerror);
2104             goto cleanup;
2105         }
2106         memset(ds->mfs_data, 0, (width+1) * num_comps);
2107     }
2108     if (dst_bpc == 1) {
2109         ds->errors = (int *)gs_alloc_bytes(dev->memory,
2110                                            num_comps*(width+3)*sizeof(int),
2111                                            "gx_downscaler(errors)");
2112         if (ds->errors == NULL) {
2113             code = gs_note_error(gs_error_VMerror);
2114             goto cleanup;
2115         }
2116         memset(ds->errors, 0, num_comps * (width+3) * sizeof(int));
2117     }
2118 
2119     return 0;
2120 
2121   cleanup:
2122     gx_downscaler_fin(ds);
2123     return code;
2124 }
2125 
get_line_for_trap(void * arg,unsigned char * buf)2126 static int get_line_for_trap(void *arg, unsigned char *buf)
2127 {
2128     gx_downscaler_t *ds = (gx_downscaler_t *)arg;
2129 
2130     /* Allow for devices (like psdcmyk) that make several passes through
2131      * the image. */
2132     if (ds->claptrap_y == ds->dev->height)
2133         ds->claptrap_y = 0;
2134 
2135     return (*dev_proc(ds->dev, get_bits))(ds->dev, ds->claptrap_y++, buf, NULL);
2136 }
2137 
gx_downscaler_init(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width)2138 int gx_downscaler_init(gx_downscaler_t   *ds,
2139                        gx_device         *dev,
2140                        int                src_bpc,
2141                        int                dst_bpc,
2142                        int                num_comps,
2143                        int                factor,
2144                        int                mfs,
2145                        int              (*adjust_width_proc)(int, int),
2146                        int                adjust_width)
2147 {
2148     return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc, num_comps,
2149         factor, mfs, adjust_width_proc, adjust_width, 0, 0, NULL, NULL, NULL, 0, 0);
2150 }
2151 
2152 
gx_downscaler_init_ets(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int ets)2153 int gx_downscaler_init_ets(gx_downscaler_t   *ds,
2154                            gx_device         *dev,
2155                            int                src_bpc,
2156                            int                dst_bpc,
2157                            int                num_comps,
2158                            int                factor,
2159                            int                mfs,
2160                            int              (*adjust_width_proc)(int, int),
2161                            int                adjust_width,
2162                            int                ets)
2163 {
2164     return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc, num_comps,
2165         factor, mfs, adjust_width_proc, adjust_width, 0, 0, NULL, NULL, NULL, 0, ets);
2166 }
2167 
gx_downscaler_init_trapped(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int trap_w,int trap_h,const int * comp_order)2168 int gx_downscaler_init_trapped(gx_downscaler_t   *ds,
2169                                gx_device         *dev,
2170                                int                src_bpc,
2171                                int                dst_bpc,
2172                                int                num_comps,
2173                                int                factor,
2174                                int                mfs,
2175                                int              (*adjust_width_proc)(int, int),
2176                                int                adjust_width,
2177                                int                trap_w,
2178                                int                trap_h,
2179                                const int         *comp_order)
2180 {
2181     return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
2182                                              num_comps, factor, mfs,
2183                                              adjust_width_proc, adjust_width,
2184                                              trap_w, trap_h, comp_order,
2185                                              NULL, NULL, 0, 0);
2186 }
2187 
gx_downscaler_init_trapped_ets(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int trap_w,int trap_h,const int * comp_order,int ets)2188 int gx_downscaler_init_trapped_ets(gx_downscaler_t   *ds,
2189                                    gx_device         *dev,
2190                                    int                src_bpc,
2191                                    int                dst_bpc,
2192                                    int                num_comps,
2193                                    int                factor,
2194                                    int                mfs,
2195                                    int              (*adjust_width_proc)(int, int),
2196                                    int                adjust_width,
2197                                    int                trap_w,
2198                                    int                trap_h,
2199                                    const int         *comp_order,
2200                                    int                ets)
2201 {
2202     return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
2203                                              num_comps, factor, mfs,
2204                                              adjust_width_proc, adjust_width,
2205                                              trap_w, trap_h, comp_order,
2206                                              NULL, NULL, 0, ets);
2207 }
gx_downscaler_init_cm(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps)2208 int gx_downscaler_init_cm(gx_downscaler_t    *ds,
2209                            gx_device          *dev,
2210                            int                 src_bpc,
2211                            int                 dst_bpc,
2212                            int                 num_comps,
2213                            int                 factor,
2214                            int                 mfs,
2215                            int               (*adjust_width_proc)(int, int),
2216                            int                 adjust_width,
2217                            gx_downscale_cm_fn *apply_cm,
2218                            void               *apply_cm_arg,
2219                            int                 post_cm_num_comps)
2220 {
2221     return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
2222                                              num_comps, factor, mfs,
2223                                              adjust_width_proc, adjust_width,
2224                                              0, 0, NULL,
2225                                              apply_cm, apply_cm_arg, post_cm_num_comps, 0);
2226 }
2227 
gx_downscaler_init_cm_ets(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps,int ets)2228 int gx_downscaler_init_cm_ets(gx_downscaler_t    *ds,
2229                               gx_device          *dev,
2230                               int                 src_bpc,
2231                               int                 dst_bpc,
2232                               int                 num_comps,
2233                               int                 factor,
2234                               int                 mfs,
2235                               int               (*adjust_width_proc)(int, int),
2236                               int                 adjust_width,
2237                               gx_downscale_cm_fn *apply_cm,
2238                               void               *apply_cm_arg,
2239                               int                 post_cm_num_comps,
2240                               int                 ets)
2241 {
2242     return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
2243                                              num_comps, factor, mfs,
2244                                              adjust_width_proc, adjust_width,
2245                                              0, 0, NULL,
2246                                              apply_cm, apply_cm_arg, post_cm_num_comps, ets);
2247 }
2248 
gx_downscaler_init_trapped_cm(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int trap_w,int trap_h,const int * comp_order,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps)2249 int gx_downscaler_init_trapped_cm(gx_downscaler_t    *ds,
2250                                   gx_device          *dev,
2251                                   int                 src_bpc,
2252                                   int                 dst_bpc,
2253                                   int                 num_comps,
2254                                   int                 factor,
2255                                   int                 mfs,
2256                                   int               (*adjust_width_proc)(int, int),
2257                                   int                 adjust_width,
2258                                   int                 trap_w,
2259                                   int                 trap_h,
2260                                   const int          *comp_order,
2261                                   gx_downscale_cm_fn *apply_cm,
2262                                   void               *apply_cm_arg,
2263                                   int                 post_cm_num_comps)
2264 {
2265     return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
2266                                              num_comps, factor, mfs,
2267                                              adjust_width_proc, adjust_width,
2268                                              trap_w, trap_h, comp_order,
2269                                              apply_cm, apply_cm_arg, post_cm_num_comps,
2270                                              0);
2271 }
2272 
2273 static gx_downscaler_ht_t bogus_ets_halftone;
2274 
gx_downscaler_init_trapped_cm_ets(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int trap_w,int trap_h,const int * comp_order,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps,int ets)2275 int gx_downscaler_init_trapped_cm_ets(gx_downscaler_t    *ds,
2276                                   gx_device          *dev,
2277                                   int                 src_bpc,
2278                                   int                 dst_bpc,
2279                                   int                 num_comps,
2280                                   int                 factor,
2281                                   int                 mfs,
2282                                   int               (*adjust_width_proc)(int, int),
2283                                   int                 adjust_width,
2284                                   int                 trap_w,
2285                                   int                 trap_h,
2286                                   const int          *comp_order,
2287                                   gx_downscale_cm_fn *apply_cm,
2288                                   void               *apply_cm_arg,
2289                                   int                 post_cm_num_comps,
2290                                   int                 ets)
2291 {
2292     return gx_downscaler_init_trapped_cm_halftone(ds,
2293                                                   dev,
2294                                                   src_bpc,
2295                                                   dst_bpc,
2296                                                   num_comps,
2297                                                   factor,
2298                                                   mfs,
2299                                                   adjust_width_proc,
2300                                                   adjust_width,
2301                                                   trap_w,
2302                                                   trap_h,
2303                                                   comp_order,
2304                                                   apply_cm,
2305                                                   apply_cm_arg,
2306                                                   post_cm_num_comps,
2307                                                   ets ? &bogus_ets_halftone : NULL);
2308 }
2309 
2310 
2311 static gx_downscale_core *
select_8_to_8_core(int nc,int factor)2312 select_8_to_8_core(int nc, int factor)
2313 {
2314     if (factor == 1)
2315         return NULL; /* No sense doing anything */
2316     if (nc == 1)
2317     {
2318         if (factor == 4)
2319             return &down_core8_4;
2320         else if (factor == 3)
2321             return &down_core8_3;
2322         else if (factor == 2)
2323             return &down_core8_2;
2324         else
2325             return &down_core8;
2326     }
2327     else if (nc == 3)
2328         return &down_core24;
2329     else if (nc == 4)
2330         return &down_core32;
2331 
2332     return NULL;
2333 }
2334 
2335 int
gx_downscaler_init_trapped_cm_halftone(gx_downscaler_t * ds,gx_device * dev,int src_bpc,int dst_bpc,int num_comps,int factor,int mfs,int (* adjust_width_proc)(int,int),int adjust_width,int trap_w,int trap_h,const int * comp_order,gx_downscale_cm_fn * apply_cm,void * apply_cm_arg,int post_cm_num_comps,gx_downscaler_ht_t * ht)2336 gx_downscaler_init_trapped_cm_halftone(gx_downscaler_t    *ds,
2337                                   gx_device          *dev,
2338                                   int                 src_bpc,
2339                                   int                 dst_bpc,
2340                                   int                 num_comps,
2341                                   int                 factor,
2342                                   int                 mfs,
2343                                   int               (*adjust_width_proc)(int, int),
2344                                   int                 adjust_width,
2345                                   int                 trap_w,
2346                                   int                 trap_h,
2347                                   const int          *comp_order,
2348                                   gx_downscale_cm_fn *apply_cm,
2349                                   void               *apply_cm_arg,
2350                                   int                 post_cm_num_comps,
2351                                   gx_downscaler_ht_t *ht)
2352 {
2353     int                size;
2354     int                post_size;
2355     int                span;
2356     int                width;
2357     int                awidth;
2358     int                pad_white;
2359     int                code;
2360     gx_downscale_core *core;
2361     int                upfactor;
2362     int                downfactor;
2363     int                nc;
2364 
2365     size = gdev_mem_bytes_per_scan_line((gx_device *)dev);
2366     post_size = bitmap_raster(dev->width * src_bpc * post_cm_num_comps);
2367 
2368     decode_factor(factor, &upfactor, &downfactor);
2369 
2370     /* width = scaled width */
2371     width = (dev->width * upfactor)/downfactor;
2372     awidth = width;
2373     if (adjust_width_proc != NULL)
2374         awidth = (*adjust_width_proc)(width, adjust_width);
2375     pad_white = awidth - width;
2376     if (pad_white < 0)
2377         pad_white = 0;
2378 
2379     /* size = unscaled size. span = unscaled size + padding */
2380     span = size + pad_white*downfactor*num_comps/upfactor + downfactor-1;
2381     memset(ds, 0, sizeof(*ds));
2382     ds->dev               = dev;
2383     ds->width             = width;
2384     ds->awidth            = awidth;
2385     ds->span              = span;
2386     ds->factor            = factor;
2387     ds->num_planes        = 0;
2388     ds->src_bpc           = src_bpc;
2389     ds->apply_cm          = apply_cm;
2390     ds->apply_cm_arg      = apply_cm_arg;
2391     ds->early_cm          = dst_bpc < src_bpc;
2392     ds->post_cm_num_comps = post_cm_num_comps;
2393     ds->ht                = ht;
2394     ds->dst_bpc           = dst_bpc;
2395     ds->num_comps         = num_comps;
2396 
2397     code = check_trapping(dev->memory, trap_w, trap_h, num_comps, comp_order);
2398     if (code < 0)
2399         return code;
2400 
2401     if (trap_w > 0 || trap_h > 0) {
2402         ds->claptrap = ClapTrap_Init(dev->memory, width, dev->height, num_comps, comp_order, trap_w, trap_h, get_line_for_trap, ds);
2403         if (ds->claptrap == NULL) {
2404             emprintf(dev->memory, "Trapping initialisation failed");
2405             code = gs_note_error(gs_error_VMerror);
2406             goto cleanup;
2407         }
2408     } else
2409         ds->claptrap = NULL;
2410 
2411     /* Choose an appropriate core. Try to honour our early_cm
2412      * choice, and fallback to late cm if we can't. */
2413     core = NULL;
2414     while (1)
2415     {
2416         nc = ds->early_cm ? post_cm_num_comps : num_comps;
2417 
2418         if (factor > 8) {
2419             code = gs_note_error(gs_error_rangecheck);
2420             goto cleanup;
2421         }
2422         else if ((src_bpc == 16) && (dst_bpc == 16) && (nc == 1))
2423         {
2424             core = &down_core16;
2425         }
2426         else if ((src_bpc == 8) && (dst_bpc == 1) && (nc == 4))
2427         {
2428             if (mfs > 1)
2429                 core = &down_core4_mfs;
2430             else if (ht == &bogus_ets_halftone)
2431             {
2432                 code = init_ets(ds, 4, select_8_to_8_core(nc, factor));
2433                 if (code)
2434                     goto cleanup;
2435                 core = &down_core4_ets;
2436             }
2437             else if (ht != NULL)
2438             {
2439                 code = init_ht(ds, 4, select_8_to_8_core(nc, factor));
2440                 if (code)
2441                     goto cleanup;
2442                 core = &down_core4_ht;
2443             }
2444             else
2445                 core = &down_core4;
2446         }
2447         else if ((src_bpc == 8) && (dst_bpc == 1) && (nc == 1))
2448         {
2449             if (mfs > 1)
2450                 core = &down_core_mfs;
2451             else if (ht == &bogus_ets_halftone)
2452             {
2453                 code = init_ets(ds, 1, select_8_to_8_core(nc, factor));
2454                 if (code)
2455                     goto cleanup;
2456                 core = &down_core_ets_1;
2457             }
2458             else if (factor == 4)
2459                 core = &down_core_4;
2460             else if (factor == 3)
2461                 core = &down_core_3;
2462             else if (factor == 2)
2463                 core = &down_core_2;
2464             else if (factor == 1)
2465                 core = &down_core_1;
2466             else
2467                 core = &down_core;
2468         }
2469         else if ((factor == 1) && (src_bpc == dst_bpc))
2470             break;
2471         else if (src_bpc == 8 && dst_bpc == 8)
2472             core = select_8_to_8_core(nc, factor);
2473 
2474         /* If we found one, or we have nothing to fallback to, exit */
2475         if (core || !ds->early_cm)
2476             break;
2477 
2478         /* Fallback */
2479         ds->early_cm = false;
2480     }
2481     if (factor == 1 && src_bpc == dst_bpc) {
2482         /* core can permissibly be NULL */
2483     } else if (core == NULL) {
2484         code = gs_note_error(gs_error_rangecheck);
2485         goto cleanup;
2486     }
2487     ds->down_core = core;
2488 
2489     if (apply_cm) {
2490         ds->post_cm[0] = gs_alloc_bytes(dev->memory,
2491                                         post_size * downfactor,
2492                                         "gx_downscaler(data)");
2493         if (ds->post_cm[0] == NULL) {
2494             code = gs_note_error(gs_error_VMerror);
2495             goto cleanup;
2496         }
2497     }
2498 
2499     if (core != NULL || apply_cm) {
2500         ds->pre_cm[0] = gs_alloc_bytes(dev->memory,
2501             span * downfactor,
2502             "gx_downscaler(data)");
2503         if (ds->pre_cm[0] == NULL) {
2504             code = gs_note_error(gs_error_VMerror);
2505             goto cleanup;
2506         }
2507     }
2508     if (core != NULL) {
2509         if (mfs > 1) {
2510             ds->mfs_data = (byte *)gs_alloc_bytes(dev->memory,
2511                                                   (awidth+1)*nc,
2512                                                   "gx_downscaler(mfs)");
2513             if (ds->mfs_data == NULL) {
2514                 code = gs_note_error(gs_error_VMerror);
2515                 goto cleanup;
2516             }
2517             memset(ds->mfs_data, 0, (awidth+1)*nc);
2518         }
2519         if (dst_bpc == 1) {
2520             ds->errors = (int *)gs_alloc_bytes(dev->memory,
2521                                                nc*(awidth+3)*sizeof(int),
2522                                                "gx_downscaler(errors)");
2523             if (ds->errors == NULL) {
2524                 code = gs_note_error(gs_error_VMerror);
2525                 goto cleanup;
2526             }
2527             memset(ds->errors, 0, nc * (awidth+3) * sizeof(int));
2528         }
2529     }
2530 
2531     return 0;
2532 
2533   cleanup:
2534     gx_downscaler_fin(ds);
2535     return code;
2536 }
2537 
gx_downscaler_fin(gx_downscaler_t * ds)2538 void gx_downscaler_fin(gx_downscaler_t *ds)
2539 {
2540     int plane;
2541     for (plane=0; plane < GS_CLIENT_COLOR_MAX_COMPONENTS; plane++) {
2542         gs_free_object(ds->dev->memory, ds->pre_cm[plane],
2543                        "gx_downscaler(planar_data)");
2544         gs_free_object(ds->dev->memory, ds->post_cm[plane],
2545                        "gx_downscaler(planar_data)");
2546     }
2547     ds->num_planes = 0;
2548 
2549     gs_free_object(ds->dev->memory, ds->mfs_data, "gx_downscaler(mfs)");
2550     ds->mfs_data = NULL;
2551     gs_free_object(ds->dev->memory, ds->errors, "gx_downscaler(errors)");
2552     ds->errors = NULL;
2553     gs_free_object(ds->dev->memory, ds->scaled_data, "gx_downscaler(scaled_data)");
2554     ds->scaled_data = NULL;
2555     gs_free_object(ds->dev->memory, ds->htrow_alloc, "gx_downscaler(htrow)");
2556     ds->htrow = NULL;
2557     ds->htrow_alloc = NULL;
2558 
2559     if (ds->claptrap)
2560         ClapTrap_Fin(ds->dev->memory, ds->claptrap);
2561 
2562     if (ds->ets_config)
2563         ets_destroy(ds->dev->memory, ds->ets_config);
2564 }
2565 
2566 /* Chunky case */
gx_downscaler_getbits(gx_downscaler_t * ds,byte * out_data,int row)2567 int gx_downscaler_getbits(gx_downscaler_t *ds,
2568                           byte            *out_data,
2569                           int              row)
2570 {
2571     int   code = 0;
2572     int   y, y_end;
2573     byte *data_ptr;
2574     int   upfactor, downfactor;
2575 
2576     decode_factor(ds->factor, &upfactor, &downfactor);
2577 
2578     /* Check for the simple case */
2579     if (ds->down_core == NULL) {
2580         if (ds->claptrap)
2581             code = ClapTrap_GetLine(ds->claptrap, ds->apply_cm ? ds->pre_cm[0] : out_data);
2582         else
2583             code = (*dev_proc(ds->dev, get_bits))(ds->dev, row, ds->apply_cm ? ds->pre_cm[0] : out_data, NULL);
2584         if (code < 0)
2585             return code;
2586         if (ds->apply_cm) {
2587             data_ptr = out_data;
2588             return ds->apply_cm(ds->apply_cm_arg, &data_ptr, ds->pre_cm, ds->width, 1, 0);
2589         }
2590         return 0;
2591     }
2592 
2593     /* Get factor rows worth of data */
2594     y        = row * downfactor;
2595     y_end    = y + downfactor;
2596     data_ptr = ds->pre_cm[0];
2597     if (ds->claptrap) {
2598         do {
2599             code = ClapTrap_GetLine(ds->claptrap, data_ptr);
2600             if (code < 0)
2601                 return code;
2602             data_ptr += ds->span;
2603             y++;
2604         } while (y < y_end);
2605     } else {
2606         do {
2607             code = (*dev_proc(ds->dev, get_bits))(ds->dev, y, data_ptr, NULL);
2608             if (code < 0)
2609                 return code;
2610             data_ptr += ds->span;
2611             y++;
2612         } while (y < y_end);
2613     }
2614 
2615     if (ds->apply_cm) {
2616         if (ds->early_cm) {
2617             code = ds->apply_cm(ds->apply_cm_arg, ds->post_cm, ds->pre_cm, ds->dev->width, 1, 0);
2618             if (code < 0)
2619                 return code;
2620             (ds->down_core)(ds, out_data, ds->post_cm[0], row, 0, ds->span);
2621         } else {
2622             data_ptr = out_data;
2623             (ds->down_core)(ds, ds->post_cm[0], ds->pre_cm[0], row, 0, ds->span);
2624             code = ds->apply_cm(ds->apply_cm_arg, &out_data, ds->post_cm, ds->width, 1, 0);
2625             if (code < 0)
2626                 return code;
2627         }
2628     } else
2629         (ds->down_core)(ds, out_data, ds->pre_cm[0], row, 0, ds->span);
2630 
2631     return code;
2632 }
2633 
2634 /* Planar case */
gx_downscaler_get_bits_rectangle(gx_downscaler_t * ds,gs_get_bits_params_t * params,int row)2635 int gx_downscaler_get_bits_rectangle(gx_downscaler_t      *ds,
2636                                      gs_get_bits_params_t *params,
2637                                      int                   row)
2638 {
2639     int                   code;
2640     gs_int_rect           rect;
2641     int                   plane;
2642     int                   factor = ds->factor;
2643     gs_get_bits_params_t  params2;
2644     int                   upfactor, downfactor;
2645     int                   subrow;
2646     int                   copy = (ds->dev->width * ds->src_bpc + 7)>>3;
2647     int                   i, j;
2648 
2649     decode_factor(factor, &upfactor, &downfactor);
2650 
2651     subrow = row % upfactor;
2652     if (subrow) {
2653         /* Just copy a previous row from our stored buffer */
2654         for (plane=0; plane < ds->num_planes; plane++)
2655             params->data[plane] = ds->scaled_data + (upfactor * plane + subrow) * ds->scaled_span;
2656         return 0;
2657     }
2658 
2659     rect.p.x = 0;
2660     rect.p.y = (row/upfactor) * downfactor;
2661     rect.q.x = ds->dev->width;
2662     rect.q.y = ((row/upfactor) + 1) * downfactor;
2663 
2664     /* Check for the simple case */
2665     if (ds->down_core == NULL && ds->claptrap == NULL) {
2666         gs_get_bits_params_t saved;
2667         if (ds->apply_cm) {
2668             /* Always do the request giving our own workspace,
2669              * and be prepared to accept a pointer */
2670             saved = *params;
2671             for (i = 0; i < ds->num_planes; i++)
2672                 params->data[i] = ds->pre_cm[i];
2673             params->options |= GB_RETURN_POINTER;
2674         }
2675         code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, params, NULL);
2676         if (code < 0)
2677             return code;
2678         if (ds->apply_cm) {
2679             byte **buffer;
2680             if (saved.options & GB_RETURN_COPY) {
2681                 /* They will accept a copy. Let's use the buffer they supplied */
2682                 params->options &= ~GB_RETURN_POINTER;
2683                 buffer = saved.data;
2684             } else
2685                 buffer = ds->pre_cm;
2686             code = ds->apply_cm(ds->apply_cm_arg, params->data, buffer, ds->dev->width, rect.q.y - rect.p.y, params->raster);
2687             if ((saved.options & GB_RETURN_COPY) == 0)
2688                 for (i = 0; i < ds->num_planes; i++)
2689                     params->data[i] = buffer[i];
2690         }
2691         return code;
2692     }
2693 
2694     /* Copy the params, because get_bits_rectangle can helpfully overwrite
2695      * them. */
2696     memcpy(&params2, &ds->params, sizeof(params2));
2697     for (i = 0; i < ds->num_planes; i++)
2698          params2.data[i] = ds->pre_cm[i];
2699 
2700     /* Get downfactor rows worth of data */
2701     if (ds->claptrap)
2702         code = gs_error_rangecheck; /* Always work a line at a time with claptrap */
2703     else
2704         code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, &params2, NULL);
2705     if (code == gs_error_rangecheck) {
2706         /* At the bottom of a band, the get_bits_rectangle call can fail to be
2707          * able to return us enough lines of data at the same time. We therefore
2708          * drop back to reading them one at a time, and copying them into our
2709          * own buffer. */
2710         for (i = 0; i < downfactor; i++) {
2711             rect.q.y = rect.p.y+1;
2712             if (rect.q.y > ds->dev->height)
2713                 break;
2714             memcpy(&params2, &ds->params, sizeof(params2));
2715             for (j = 0; j < ds->num_planes; j++)
2716                 params2.data[j] = ds->pre_cm[j] + i * ds->span;
2717             if (ds->claptrap) {
2718                 ds->claptrap_params = &params2;
2719                 code = ClapTrap_GetLinePlanar(ds->claptrap, &params2.data[0]);
2720             } else {
2721                 /* We always want a copy */
2722                 params2.options &= ~GB_RETURN_POINTER;
2723                 params2.options |=  GB_RETURN_COPY;
2724                 code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, &params2, NULL);
2725             }
2726             if (code < 0)
2727                 break;
2728             rect.p.y++;
2729         }
2730         if (i == 0)
2731             return code;
2732         /* If we still haven't got enough, we've hit the end of the page; just
2733          * duplicate the last line we did get. */
2734         for (;i < downfactor; i++)
2735             for (j = 0; j < ds->num_planes; j++)
2736                 memcpy(ds->pre_cm[j] + i*ds->span, ds->pre_cm[j] + (i-1)*ds->span, copy);
2737     }
2738     if (code < 0)
2739         return code;
2740 
2741     if (ds->early_cm && ds->apply_cm) {
2742         code = ds->apply_cm(ds->apply_cm_arg, ds->params.data, ds->post_cm, ds->dev->width, downfactor, params->raster);
2743         if (code < 0)
2744             return code;
2745         for (j = 0; j < ds->num_planes; j++)
2746             params2.data[j] = ds->post_cm[j];
2747     }
2748 
2749     if (upfactor > 1) {
2750         /* Downscale the block of lines into our output buffer */
2751         for (plane=0; plane < ds->num_planes; plane++) {
2752             byte *scaled = ds->scaled_data + upfactor * plane * ds->scaled_span;
2753             (ds->down_core)(ds, scaled, params2.data[plane], row, plane, params2.raster);
2754             params->data[plane] = scaled;
2755         }
2756     } else if (ds->down_core != NULL) {
2757         /* Downscale direct into output buffer */
2758         for (plane=0; plane < ds->num_planes; plane++)
2759             (ds->down_core)(ds, params->data[plane], params2.data[plane], row, plane, params2.raster);
2760     } else {
2761         /* Copy into output buffer */
2762         /* No color management can be required here */
2763         assert(!ds->early_cm || ds->apply_cm == NULL);
2764         for (plane=0; plane < ds->num_planes; plane++)
2765             memcpy(params->data[plane], params2.data[plane], params2.raster);
2766     }
2767 
2768     if (!ds->early_cm && ds->apply_cm) {
2769         code = ds->apply_cm(ds->apply_cm_arg, ds->params.data, params2.data, ds->width, 1, params->raster);
2770         if (code < 0)
2771             return code;
2772     }
2773 
2774     return code;
2775 }
2776 
2777 typedef struct downscaler_process_page_arg_s
2778 {
2779     gx_process_page_options_t *orig_options;
2780     int upfactor;
2781     int downfactor;
2782     gx_downscaler_t ds;
2783 }
2784 downscaler_process_page_arg_t;
2785 
2786 typedef struct downscaler_process_page_buffer_s
2787 {
2788     gx_device *bdev;
2789     void *orig_buffer;
2790 }
2791 downscaler_process_page_buffer_t;
2792 
downscaler_init_fn(void * arg_,gx_device * dev,gs_memory_t * memory,int w,int h,void ** pbuffer)2793 static int downscaler_init_fn(void *arg_, gx_device *dev, gs_memory_t *memory, int w, int h, void **pbuffer)
2794 {
2795     downscaler_process_page_arg_t *arg = (downscaler_process_page_arg_t *)arg_;
2796     downscaler_process_page_buffer_t *buffer;
2797     int code = 0;
2798 
2799     buffer = (downscaler_process_page_buffer_t *)gs_alloc_bytes(memory, sizeof(*buffer), "downscaler process_page buffer");
2800     if (buffer == NULL)
2801         return_error(gs_error_VMerror);
2802     memset(buffer, 0, sizeof(*buffer));
2803 
2804     if (arg->upfactor > arg->downfactor) {
2805         code = gx_default_create_buf_device(&buffer->bdev, dev,
2806                           (h*arg->upfactor + arg->downfactor-1)/arg->downfactor,
2807                           NULL, memory, NULL);
2808         if (code < 0) {
2809             gs_free_object(memory, buffer, "downscaler process_page buffer");
2810             return code;
2811         }
2812     }
2813 
2814     if (arg->orig_options && arg->orig_options->init_buffer_fn) {
2815         code = arg->orig_options->init_buffer_fn(arg->orig_options->arg, dev, memory,
2816                                                  (w * arg->upfactor + arg->downfactor-1)/arg->downfactor,
2817                                                  (h * arg->upfactor + arg->downfactor-1)/arg->downfactor,
2818                                                  &buffer->orig_buffer);
2819         if (code < 0) {
2820             if (buffer->bdev)
2821                 dev_proc(dev, close_device)(dev);
2822             gs_free_object(memory, buffer, "downscaler process_page buffer");
2823             return code;
2824         }
2825     }
2826 
2827     *pbuffer = (void *)buffer;
2828     return code;
2829 }
2830 
downscaler_process_fn(void * arg_,gx_device * dev,gx_device * bdev,const gs_int_rect * rect,void * buffer_)2831 static int downscaler_process_fn(void *arg_, gx_device *dev, gx_device *bdev, const gs_int_rect *rect, void *buffer_)
2832 {
2833     downscaler_process_page_arg_t *arg = (downscaler_process_page_arg_t *)arg_;
2834     downscaler_process_page_buffer_t *buffer = (downscaler_process_page_buffer_t *)buffer_;
2835     int code, raster_in, raster_out;
2836     gs_get_bits_params_t params;
2837     gs_int_rect in_rect, out_rect;
2838     byte *in_ptr, *out_ptr;
2839 
2840     in_rect.p.x = 0;
2841     in_rect.p.y = 0;
2842     in_rect.q.x = rect->q.x - rect->p.x;
2843     in_rect.q.y = rect->q.y - rect->p.y;
2844     out_rect.p.x = 0;
2845     out_rect.p.y = 0;
2846     out_rect.q.x = (in_rect.q.x * arg->upfactor + arg->downfactor-1) / arg->downfactor;
2847     out_rect.q.y = (in_rect.q.y * arg->upfactor + arg->downfactor-1) / arg->downfactor;
2848 
2849     /* Where do we get the data from? */
2850     params.options = GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_PACKING_CHUNKY | GB_RETURN_POINTER | GB_ALIGN_ANY | GB_OFFSET_0 | GB_RASTER_ANY;
2851     code = dev_proc(bdev, get_bits_rectangle)(bdev, &in_rect, &params, NULL);
2852     if (code < 0)
2853         return code;
2854     raster_in = params.raster;
2855     in_ptr = params.data[0];
2856 
2857     /* Where do we write it to? */
2858     if (buffer->bdev) {
2859         code = dev_proc(bdev, get_bits_rectangle)(buffer->bdev, &out_rect, &params, NULL);
2860         if (code < 0)
2861             return code;
2862         raster_out = params.raster;
2863         out_ptr = params.data[0];
2864     } else {
2865         raster_out = raster_in;
2866         out_ptr = params.data[0];
2867     }
2868 
2869     /* Do the downscale */
2870     if (arg->ds.down_core) {
2871         int y;
2872         for (y = rect->p.y; y < rect->q.y; y += arg->downfactor)
2873         {
2874             arg->ds.down_core(&arg->ds, out_ptr, in_ptr, y, 0, arg->ds.span);
2875             in_ptr += arg->ds.span * arg->downfactor;
2876             out_ptr += raster_out * arg->upfactor;
2877         }
2878     }
2879 
2880     /* Pass on to further processing */
2881     if (code >= 0 && arg->orig_options && arg->orig_options->process_fn) {
2882         out_rect.p.y = rect->p.y*arg->upfactor/arg->downfactor;
2883         out_rect.q.y += out_rect.p.y;
2884         code = arg->orig_options->process_fn(arg->orig_options->arg, dev,
2885                                              (buffer->bdev ? buffer->bdev : bdev),
2886                                              &out_rect, buffer->orig_buffer);
2887     }
2888     return code;
2889 }
2890 
2891 static void
downscaler_free_fn(void * arg_,gx_device * dev,gs_memory_t * memory,void * buffer_)2892 downscaler_free_fn(void *arg_, gx_device *dev, gs_memory_t *memory, void *buffer_)
2893 {
2894     downscaler_process_page_arg_t *arg = (downscaler_process_page_arg_t *)arg_;
2895     downscaler_process_page_buffer_t *buffer = (downscaler_process_page_buffer_t *)buffer_;
2896 
2897     arg->orig_options->free_buffer_fn(arg->orig_options->arg, dev, memory,
2898                                       buffer->orig_buffer);
2899     if (buffer->bdev)
2900         dev_proc(dev, close_device)(dev);
2901     gs_free_object(memory, buffer, "downscaler process_page buffer");
2902 }
2903 
2904 static int
downscaler_output_fn(void * arg_,gx_device * dev,void * buffer_)2905 downscaler_output_fn(void *arg_, gx_device *dev, void *buffer_)
2906 {
2907     downscaler_process_page_arg_t *arg = (downscaler_process_page_arg_t *)arg_;
2908     downscaler_process_page_buffer_t *buffer = (downscaler_process_page_buffer_t *)buffer_;
2909 
2910     return arg->orig_options->output_fn(arg->orig_options->arg, dev,
2911                                         buffer->orig_buffer);
2912 }
2913 
2914 /* No error diffusion with process_page as bands need to be handled
2915  * separately. */
gx_downscaler_process_page(gx_device * dev,gx_process_page_options_t * options,int factor)2916 int gx_downscaler_process_page(gx_device                 *dev,
2917                                gx_process_page_options_t *options,
2918                                int                        factor)
2919 {
2920     downscaler_process_page_arg_t arg = { 0 };
2921     gx_process_page_options_t my_options = { 0 };
2922     int num_comps = dev->color_info.num_components;
2923     int src_bpc = dev->color_info.comp_bits[0];
2924     int scaled_w;
2925     gx_downscale_core *core;
2926 
2927     arg.orig_options = options;
2928     decode_factor(factor, &arg.upfactor, &arg.downfactor);
2929     arg.ds.dev = dev;
2930     arg.ds.width = (dev->width * arg.upfactor + arg.downfactor-1)/arg.downfactor;
2931     arg.ds.awidth = arg.ds.width;
2932     arg.ds.span = bitmap_raster(dev->width * num_comps * src_bpc);
2933     scaled_w = (dev->width * arg.upfactor + arg.downfactor-1)/arg.downfactor;
2934     arg.ds.factor = factor;
2935     arg.ds.src_bpc = src_bpc;
2936     arg.ds.scaled_span = bitmap_raster(scaled_w * num_comps * src_bpc);
2937     arg.ds.num_planes = 0;
2938 
2939     /* Choose an appropriate core */
2940     if (factor > 8)
2941     {
2942         return gs_note_error(gs_error_rangecheck);
2943     }
2944     else if ((src_bpc == 16) && (num_comps == 1))
2945     {
2946         core = &down_core16;
2947     }
2948     else if (factor == 1)
2949         core = NULL;
2950     else if ((src_bpc == 8) && (num_comps == 1))
2951     {
2952         if (factor == 4)
2953             core = &down_core8_4;
2954         else if (factor == 3)
2955             core = &down_core8_3;
2956         else if (factor == 2)
2957             core = &down_core8_2;
2958         else
2959             core = &down_core8;
2960     }
2961     else if ((src_bpc == 8) && (num_comps == 3))
2962         core = &down_core24;
2963     else if ((src_bpc == 8) && (num_comps == 4))
2964          core = &down_core32;
2965     else {
2966         return gs_note_error(gs_error_rangecheck);
2967     }
2968     arg.ds.down_core = core;
2969 
2970     my_options.init_buffer_fn = downscaler_init_fn;
2971     my_options.process_fn = downscaler_process_fn;
2972     my_options.output_fn = downscaler_output_fn;
2973     my_options.free_buffer_fn = downscaler_free_fn;
2974     my_options.arg = &arg;
2975 
2976     return dev_proc(dev, process_page)(dev, &my_options);
2977 }
2978 
gx_downscaler_read_params(gs_param_list * plist,gx_downscaler_params * params,int features)2979 int gx_downscaler_read_params(gs_param_list        *plist,
2980                               gx_downscaler_params *params,
2981                               int                   features)
2982 {
2983     int code;
2984     int downscale, mfs, ets;
2985     int trap_w, trap_h;
2986     const char *param_name;
2987     gs_param_int_array trap_order;
2988 
2989     trap_order.data = NULL;
2990 
2991     switch (code = param_read_int(plist,
2992                                    (param_name = "DownScaleFactor"),
2993                                    &downscale)) {
2994         case 1:
2995             break;
2996         case 0:
2997             if (downscale >= 1) {
2998                 params->downscale_factor = downscale;
2999                 break;
3000             }
3001             code = gs_error_rangecheck;
3002         default:
3003             param_signal_error(plist, param_name, code);
3004             return code;
3005     }
3006 
3007     if (features & GX_DOWNSCALER_PARAMS_MFS)
3008     {
3009         switch (code = param_read_int(plist, (param_name = "MinFeatureSize"), &mfs)) {
3010             case 1:
3011                 break;
3012             case 0:
3013                 if ((mfs >= 0) && (mfs <= 4)) {
3014                     params->min_feature_size = mfs;
3015                     break;
3016                 }
3017                 code = gs_error_rangecheck;
3018             default:
3019                 param_signal_error(plist, param_name, code);
3020                 return code;
3021         }
3022     }
3023 
3024     if (features & GX_DOWNSCALER_PARAMS_TRAP)
3025     {
3026         switch (code = param_read_int(plist,
3027                                       (param_name = "TrapX"),
3028                                       &trap_w)) {
3029             case 1:
3030                 break;
3031             case 0:
3032                 if (trap_w >= 0)
3033                 {
3034                     params->trap_w = trap_w;
3035                     break;
3036                 }
3037                 code = gs_error_rangecheck;
3038             default:
3039                 param_signal_error(plist, param_name, code);
3040                 return code;
3041         }
3042         switch (code = param_read_int(plist,
3043                                       (param_name = "TrapY"),
3044                                       &trap_h)) {
3045             case 1:
3046                 break;
3047             case 0:
3048                 if (trap_h >= 0)
3049                 {
3050                     params->trap_h = trap_h;
3051                     break;
3052                 }
3053                 code = gs_error_rangecheck;
3054             default:
3055                 param_signal_error(plist, param_name, code);
3056                 return code;
3057         }
3058         switch (code = param_read_int_array(plist, (param_name = "TrapOrder"), &trap_order)) {
3059             case 0:
3060                 break;
3061             case 1:
3062                 trap_order.data = 0;          /* mark as not filled */
3063                 break;
3064             default:
3065                 param_signal_error(plist, param_name, code);
3066                 return code;
3067         }
3068 
3069         if (trap_order.data != NULL)
3070         {
3071             int i;
3072             int n = trap_order.size;
3073 
3074             if (n > GS_CLIENT_COLOR_MAX_COMPONENTS)
3075                 n = GS_CLIENT_COLOR_MAX_COMPONENTS;
3076 
3077             for (i = 0; i < n; i++)
3078             {
3079                 params->trap_order[i] = trap_order.data[i];
3080             }
3081             for (; i < GS_CLIENT_COLOR_MAX_COMPONENTS; i++)
3082             {
3083                 params->trap_order[i] = i;
3084             }
3085         }
3086         else
3087         {
3088             /* Set some sane defaults */
3089             int i;
3090 
3091             params->trap_order[0] = 3; /* K */
3092             params->trap_order[1] = 1; /* M */
3093             params->trap_order[2] = 0; /* C */
3094             params->trap_order[3] = 2; /* Y */
3095 
3096             for (i = 4; i < GS_CLIENT_COLOR_MAX_COMPONENTS; i++)
3097             {
3098                 params->trap_order[i] = i;
3099             }
3100         }
3101     }
3102     if (features & GX_DOWNSCALER_PARAMS_ETS)
3103     {
3104         switch (code = param_read_int(plist,
3105                                       (param_name = "DownScaleETS"),
3106                                       &ets)) {
3107             case 1:
3108                 break;
3109             case 0:
3110                 if (ets >= 0)
3111                 {
3112                     params->ets = ets;
3113                     break;
3114                 }
3115                 code = gs_error_rangecheck;
3116             default:
3117                 param_signal_error(plist, param_name, code);
3118                 return code;
3119         }
3120     }
3121 
3122     return 0;
3123 }
3124 
gx_downscaler_write_params(gs_param_list * plist,gx_downscaler_params * params,int features)3125 int gx_downscaler_write_params(gs_param_list        *plist,
3126                                gx_downscaler_params *params,
3127                                int                   features)
3128 {
3129     int code;
3130     int ecode = 0;
3131     gs_param_int_array trap_order;
3132 
3133     trap_order.data = params->trap_order;
3134     trap_order.size = GS_CLIENT_COLOR_MAX_COMPONENTS;
3135     trap_order.persistent = false;
3136 
3137     if ((code = param_write_int(plist, "DownScaleFactor", &params->downscale_factor)) < 0)
3138         ecode = code;
3139     if (features & GX_DOWNSCALER_PARAMS_MFS)
3140     {
3141         if ((code = param_write_int(plist, "MinFeatureSize", &params->min_feature_size)) < 0)
3142             ecode = code;
3143     }
3144     if (features & GX_DOWNSCALER_PARAMS_TRAP)
3145     {
3146         if ((code = param_write_int(plist, "TrapX", &params->trap_w)) < 0)
3147             ecode = code;
3148         if ((code = param_write_int(plist, "TrapY", &params->trap_h)) < 0)
3149             ecode = code;
3150         if ((code = param_write_int_array(plist, "TrapOrder", &trap_order)) < 0)
3151             ecode = code;
3152     }
3153     if (features & GX_DOWNSCALER_PARAMS_ETS)
3154     {
3155         if ((code = param_write_int(plist, "DownScaleETS", &params->ets)) < 0)
3156             ecode = code;
3157     }
3158 
3159     return ecode;
3160 }
3161 
3162 /* ETS relies on some malloc wrappers */
ets_malloc(void * malloc_arg,int size)3163 void *ets_malloc(void *malloc_arg, int size)
3164 {
3165     return gs_alloc_bytes((gs_memory_t *)malloc_arg, size, "ets_malloc");
3166 }
3167 
ets_calloc(void * malloc_arg,int count,int size)3168 void *ets_calloc(void *malloc_arg, int count, int size)
3169 {
3170     void *p = ets_malloc(malloc_arg, count * size);
3171     if (p)
3172         memset(p, 0, count * size);
3173     return p;
3174 }
3175 
ets_free(void * malloc_arg,void * p)3176 void ets_free(void *malloc_arg, void *p)
3177 {
3178     if (!p)
3179         return;
3180 
3181     gs_free_object((gs_memory_t *)malloc_arg, p, "ets_malloc");
3182 }
3183