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 /* RasterOp implementation for 2- and 4-bit memory devices */
17 #include "memory_.h"
18 #include "gx.h"
19 #include "gsbittab.h"
20 #include "gserrors.h"
21 #include "gsropt.h"
22 #include "gxcindex.h"
23 #include "gxdcolor.h"
24 #include "gxdevice.h"
25 #include "gxdevmem.h"
26 #include "gxdevrop.h"
27 #include "gdevmem.h"
28 #include "gdevmrop.h"
29 
30 /* Calculate the X offset for a given Y value, */
31 /* taking shift into account if necessary. */
32 #define x_offset(px, ty, textures)\
33   ((textures)->shift == 0 ? (px) :\
34    (px) + (ty) / (textures)->rep_height * (textures)->rep_shift)
35 
36 /* ---------------- Fake RasterOp for 2- and 4-bit devices ---------------- */
37 
38 /*
39  * Define patched versions of the driver procedures that may be called
40  * by mem_mono_strip_copy_rop (see below).  Currently we just punt to
41  * the slow, general case; we could do a lot better.
42  */
43 static int
mem_gray_rop_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)44 mem_gray_rop_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
45                             gx_color_index color)
46 {
47     return -1;
48 }
49 static int
mem_gray_rop_copy_mono(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)50 mem_gray_rop_copy_mono(gx_device * dev, const byte * data,
51                        int dx, int raster, gx_bitmap_id id,
52                        int x, int y, int w, int h,
53                        gx_color_index zero, gx_color_index one)
54 {
55     return -1;
56 }
57 static int
mem_gray_rop_strip_tile_rectangle(gx_device * dev,const gx_strip_bitmap * tiles,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1,int px,int py)58 mem_gray_rop_strip_tile_rectangle(gx_device * dev,
59                                   const gx_strip_bitmap * tiles,
60                                   int x, int y, int w, int h,
61                                   gx_color_index color0, gx_color_index color1,
62                                   int px, int py)
63 {
64     return -1;
65 }
66 
67 int
mem_gray_strip_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)68 mem_gray_strip_copy_rop(gx_device * dev,
69              const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
70                         const gx_color_index * scolors,
71            const gx_strip_bitmap * textures, const gx_color_index * tcolors,
72                         int x, int y, int width, int height,
73                         int phase_x, int phase_y, gs_logical_operation_t lop)
74 {
75     gx_color_index scolors2[2];
76     const gx_color_index *real_scolors = scolors;
77     gx_color_index tcolors2[2];
78     const gx_color_index *real_tcolors = tcolors;
79     gx_strip_bitmap texture2;
80     const gx_strip_bitmap *real_texture = textures;
81     long tdata;
82     int depth = dev->color_info.depth;
83     int log2_depth = depth >> 1;	/* works for 2, 4 */
84     gx_color_index max_pixel = ((gx_color_index)1 << depth) - 1;
85     int code;
86 
87 #ifdef DEBUG
88     if (gs_debug_c('b'))
89         trace_copy_rop("mem_gray_strip_copy_rop",
90                        dev, sdata, sourcex, sraster,
91                        id, scolors, textures, tcolors,
92                        x, y, width, height, phase_x, phase_y, lop);
93 #endif
94     lop = lop_sanitize(lop);
95     if (gx_device_has_color(dev) ||
96         (scolors &&		/* must be (0,0) or (max,max) */
97          ((scolors[0] | scolors[1]) != 0) &&
98          ((scolors[0] & scolors[1]) != max_pixel)) ||
99         (tcolors && (tcolors[0] != tcolors[1]))
100         ) {
101         /* We can't fake it: do it the slow, painful way. */
102         return mem_default_strip_copy_rop(dev, sdata, sourcex, sraster, id,
103                                           scolors, textures, tcolors,
104                                           x, y, width, height,
105                                           phase_x, phase_y, lop);
106     }
107     if (scolors) {		/* Must be a solid color: see above. */
108         scolors2[0] = scolors2[1] = scolors[0] & 1;
109         real_scolors = scolors2;
110     }
111     if (textures) {
112         texture2 = *textures;
113         texture2.size.x <<= log2_depth;
114         texture2.rep_width <<= log2_depth;
115         texture2.shift <<= log2_depth;
116         texture2.rep_shift <<= log2_depth;
117         texture2.num_planes = 1;
118         real_texture = &texture2;
119     }
120     if (tcolors) {
121         /* For polybit textures with colors other than */
122         /* all 0s or all 1s, fabricate the data. */
123         if (tcolors[0] != 0 && tcolors[0] != max_pixel) {
124             real_tcolors = 0;
125             *(byte *) & tdata = (byte) tcolors[0] << (8 - depth);
126             texture2.data = (byte *) & tdata;
127             texture2.raster = align_bitmap_mod;
128             texture2.size.x = texture2.rep_width = depth;
129             texture2.size.y = texture2.rep_height = 1;
130             texture2.id = gx_no_bitmap_id;
131             texture2.shift = texture2.rep_shift = 0;
132             real_texture = &texture2;
133         } else {
134             tcolors2[0] = tcolors2[1] = tcolors[0] & 1;
135             real_tcolors = tcolors2;
136         }
137     }
138     /*
139      * mem_mono_strip_copy_rop may call fill_rectangle, copy_mono, or
140      * strip_tile_rectangle for special cases.  Patch those procedures
141      * temporarily so they will either do the right thing or return
142      * an error.
143      */
144     {
145         dev_proc_fill_rectangle((*fill_rectangle)) =
146             dev_proc(dev, fill_rectangle);
147         dev_proc_copy_mono((*copy_mono)) =
148             dev_proc(dev, copy_mono);
149         dev_proc_strip_tile_rectangle((*strip_tile_rectangle)) =
150             dev_proc(dev, strip_tile_rectangle);
151 
152         set_dev_proc(dev, fill_rectangle, mem_gray_rop_fill_rectangle);
153         set_dev_proc(dev, copy_mono, mem_gray_rop_copy_mono);
154         set_dev_proc(dev, strip_tile_rectangle,
155                      mem_gray_rop_strip_tile_rectangle);
156         dev->width <<= log2_depth;
157         code = mem_mono_strip_copy_rop(dev, sdata,
158                                        (real_scolors == NULL ?
159                                         sourcex << log2_depth : sourcex),
160                                        sraster, id, real_scolors,
161                                        real_texture, real_tcolors,
162                                        x << log2_depth, y,
163                                        width << log2_depth, height,
164                                        phase_x << log2_depth, phase_y, lop);
165         set_dev_proc(dev, fill_rectangle, fill_rectangle);
166         set_dev_proc(dev, copy_mono, copy_mono);
167         set_dev_proc(dev, strip_tile_rectangle, strip_tile_rectangle);
168         dev->width >>= log2_depth;
169     }
170     /* If we punted, use the general procedure. */
171     if (code < 0)
172         return mem_default_strip_copy_rop(dev, sdata, sourcex, sraster, id,
173                                           scolors, textures, tcolors,
174                                           x, y, width, height,
175                                           phase_x, phase_y, lop);
176     return code;
177 }
178