changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/cmd/gs/src/gdevm48.c

changeset 7191: 753613b3b8c4
parent: eaccc3e8d226
author: cinap_lenrek@felloff.net
date: Fri, 03 May 2019 21:10:01 +0200
permissions: -rw-r--r--
description: gs: avoid stupid shifts by casting to uint64_t
1 /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises, 2001 Artifex Software. All rights reserved.
2 
3  This software is provided AS-IS with no warranty, either express or
4  implied.
5 
6  This software is distributed under license and may not be copied,
7  modified or distributed except as expressly authorized under the terms
8  of the license contained in the file LICENSE in this distribution.
9 
10  For more information about licensing, please refer to
11  http://www.ghostscript.com/licensing/. For information on
12  commercial licensing, go to http://www.artifex.com/licensing/ or
13  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14  San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /*$Id: gdevm48.c,v 1.3 2005/06/20 08:59:23 igor Exp $ */
18 /* 48-bit-per-pixel "memory" (stored bitmap) device */
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gxdevice.h"
22 #include "gxdevmem.h" /* semi-public definitions */
23 #include "gdevmem.h" /* private definitions */
24 
25 /* Define debugging statistics. */
26 #ifdef DEBUG
27 struct stats_mem48_s {
28  long
29  fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
30  fprevc[257];
31  double ftotal;
32 } stats_mem48;
33 static int prev_count = 0;
34 static gx_color_index prev_colors[256];
35 # define INCR(v) (++(stats_mem48.v))
36 #else
37 # define INCR(v) DO_NOTHING
38 #endif
39 
40 
41 /* ================ Standard (byte-oriented) device ================ */
42 
43 #undef chunk
44 #define chunk byte
45 #define PIXEL_SIZE 6
46 
47 /* Procedures */
48 declare_mem_procs(mem_true48_copy_mono, mem_true48_copy_color, mem_true48_fill_rectangle);
49 
50 /* The device descriptor. */
51 const gx_device_memory mem_true48_device =
52 mem_full_alpha_device("image48", 48, 0, mem_open,
53  gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
54  mem_true48_copy_mono, mem_true48_copy_color, mem_true48_fill_rectangle,
55  gx_default_map_cmyk_color, gx_default_copy_alpha,
56  gx_default_strip_tile_rectangle, mem_default_strip_copy_rop,
57  mem_get_bits_rectangle);
58 
59 /* Convert x coordinate to byte offset in scan line. */
60 #undef x_to_byte
61 #define x_to_byte(x) ((x) * PIXEL_SIZE)
62 
63 /* Unpack a color into its bytes. */
64 #define declare_unpack_color(a, b, c, d, e, f, color)\
65  byte a = (byte)((uint64_t)color >> 40);\
66  byte b = (byte)((uint64_t)color >> 32);\
67  byte c = (byte)((uint)color >> 24);\
68  byte d = (byte)((uint)color >> 16);\
69  byte e = (byte)((uint)color >> 8);\
70  byte f = (byte)color
71 /* Put a 48-bit color into the bitmap. */
72 #define put6(ptr, a, b, c, d, e, f)\
73  (ptr)[0] = a, (ptr)[1] = b, (ptr)[2] = c, (ptr)[3] = d, (ptr)[4] = e, (ptr)[5] = f
74 /* Put 4 bytes of color into the bitmap. */
75 #define putw(ptr, wxyz)\
76  *(bits32 *)(ptr) = (wxyz)
77 /* Load the 3-word 48-bit-color cache. */
78 /* Free variables: [m]dev, abcd, bcde, cdea, deab, earc. */
79 #if arch_is_big_endian
80 # define set_color48_cache(color, a, b, c, d, e, f)\
81  mdev->color48.abcd = abcd = (color) >> 16, \
82  mdev->color48.cdef = cdef = (abcd << 16) | ((e) <<8) | (f),\
83  mdev->color48.efab = efab = (cdef << 16) | ((a) <<8) | (b),\
84  mdev->color48.abcdef = (color)
85 #else
86 # define set_color48_cache(color, a, b, c, d, e, f)\
87  mdev->color48.abcd = abcd =\
88  ((bits32)(d) << 24) | ((bits32)(c) << 16) |\
89  ((bits16)(b) << 8) | (a),\
90  mdev->color48.efab = efab = (abcd << 16) | ((f) <<8) | (e),\
91  mdev->color48.cdef = cdef = (efab << 16) | ((d) <<8) | (c),\
92  mdev->color48.abcdef = (color)
93 #endif
94 
95 /* Fill a rectangle with a color. */
96 private int
97 mem_true48_fill_rectangle(gx_device * dev,
98  int x, int y, int w, int h, gx_color_index color)
99 {
100  gx_device_memory * const mdev = (gx_device_memory *)dev;
101  declare_unpack_color(a, b, c, d, e, f, color);
102  declare_scan_ptr(dest);
103 
104  /*
105  * In order to avoid testing w > 0 and h > 0 twice, we defer
106  * executing setup_rect, and use fit_fill_xywh instead of
107  * fit_fill.
108  */
109  fit_fill_xywh(dev, x, y, w, h);
110  INCR(fill);
111 #ifdef DEBUG
112  stats_mem48.ftotal += w;
113 #endif
114  if (w >= 5) {
115  if (h <= 0)
116  return 0;
117  INCR(fwide);
118  setup_rect(dest);
119  if (a == b && b == c && c == d && d == e && e == f) {
120  int bcnt = w * PIXEL_SIZE;
121 
122  INCR(fgray[min(w, 100)]);
123  while (h-- > 0) {
124  memset(dest, a, bcnt);
125  inc_ptr(dest, draster);
126  }
127  } else {
128  int x1 = -x & 1, ww = w - x1; /* we know ww >= 4 */
129  bits32 abcd, cdef, efab;
130 
131  if (mdev->color48.abcdef == color) {
132  abcd = mdev->color48.abcd;
133  cdef = mdev->color48.cdef;
134  efab = mdev->color48.efab;
135  } else {
136  INCR(fsetc);
137  set_color48_cache(color, a, b, c, d, e, f);
138  }
139 #ifdef DEBUG
140  {
141  int ci;
142  for (ci = 0; ci < prev_count; ++ci)
143  if (prev_colors[ci] == color)
144  break;
145  INCR(fprevc[ci]);
146  if (ci == prev_count) {
147  if (ci < countof(prev_colors))
148  ++prev_count;
149  else
150  --ci;
151  }
152  if (ci) {
153  memmove(&prev_colors[1], &prev_colors[0],
154  ci * sizeof(prev_colors[0]));
155  prev_colors[0] = color;
156  }
157  }
158 #endif
159  INCR(fcolor[min(w, 100)]);
160  while (h-- > 0) {
161  register byte *pptr = dest;
162  int w1 = ww;
163 
164  switch (x1) {
165  case 1:
166  pptr[0] = a;
167  pptr[1] = b;
168  putw(pptr + 2, cdef);
169  pptr += PIXEL_SIZE;
170  break;
171  case 0:
172  ;
173  }
174  while (w1 >= 2) {
175  putw(pptr, abcd);
176  putw(pptr + 4, efab);
177  putw(pptr + 8, cdef);
178  pptr += 2 * PIXEL_SIZE;
179  w1 -= 2;
180  }
181  switch (w1) {
182  case 1:
183  putw(pptr, abcd);
184  pptr[4] = e;
185  pptr[5] = f;
186  break;
187  case 0:
188  ;
189  }
190  inc_ptr(dest, draster);
191  }
192  }
193  } else if (h > 0) { /* w < 5 */
194  INCR(fnarrow[max(w, 0)]);
195  setup_rect(dest);
196  switch (w) {
197  case 4:
198  do {
199  dest[18] = dest[12] = dest[6] = dest[0] = a;
200  dest[19] = dest[13] = dest[7] = dest[1] = b;
201  dest[20] = dest[14] = dest[8] = dest[2] = c;
202  dest[21] = dest[15] = dest[9] = dest[3] = d;
203  dest[22] = dest[16] = dest[10] = dest[4] = e;
204  dest[23] = dest[17] = dest[11] = dest[5] = f;
205  inc_ptr(dest, draster);
206  }
207  while (--h);
208  break;
209  case 3:
210  do {
211  dest[12] = dest[6] = dest[0] = a;
212  dest[13] = dest[7] = dest[1] = b;
213  dest[14] = dest[8] = dest[2] = c;
214  dest[15] = dest[9] = dest[3] = d;
215  dest[16] = dest[10] = dest[4] = e;
216  dest[17] = dest[11] = dest[5] = f;
217  inc_ptr(dest, draster);
218  }
219  while (--h);
220  break;
221  case 2:
222  do {
223  dest[6] = dest[0] = a;
224  dest[7] = dest[1] = b;
225  dest[8] = dest[2] = c;
226  dest[9] = dest[3] = d;
227  dest[10] = dest[4] = e;
228  dest[11] = dest[5] = f;
229  inc_ptr(dest, draster);
230  }
231  while (--h);
232  break;
233  case 1:
234  do {
235  dest[0] = a; dest[1] = b; dest[2] = c;
236  dest[3] = d; dest[4] = e; dest[5] = f;
237  inc_ptr(dest, draster);
238  }
239  while (--h);
240  break;
241  case 0:
242  default:
243  ;
244  }
245  }
246  return 0;
247 }
248 
249 /* Copy a monochrome bitmap. */
250 private int
251 mem_true48_copy_mono(gx_device * dev,
252  const byte * base, int sourcex, int sraster, gx_bitmap_id id,
253  int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
254 {
255  gx_device_memory * const mdev = (gx_device_memory *)dev;
256  const byte *line;
257  int sbit;
258  int first_bit;
259 
260  declare_scan_ptr(dest);
261 
262  fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
263  setup_rect(dest);
264  line = base + (sourcex >> 3);
265  sbit = sourcex & 7;
266  first_bit = 0x80 >> sbit;
267  if (zero != gx_no_color_index) { /* Loop for halftones or inverted masks */
268  /* (never used). */
269  declare_unpack_color(a0, b0, c0, d0, e0, f0, zero);
270  declare_unpack_color(a1, b1, c1, d1, e1, f1, one);
271  while (h-- > 0) {
272  register byte *pptr = dest;
273  const byte *sptr = line;
274  register int sbyte = *sptr++;
275  register int bit = first_bit;
276  int count = w;
277 
278  do {
279  if (sbyte & bit) {
280  if (one != gx_no_color_index)
281  put6(pptr, a1, b1, c1, d1, e1, f1);
282  } else
283  put6(pptr, a0, b0, c0, d0, e0, f0);
284  pptr += PIXEL_SIZE;
285  if ((bit >>= 1) == 0)
286  bit = 0x80, sbyte = *sptr++;
287  }
288  while (--count > 0);
289  line += sraster;
290  inc_ptr(dest, draster);
291  }
292  } else if (one != gx_no_color_index) { /* Loop for character and pattern masks. */
293  /* This is used heavily. */
294  declare_unpack_color(a1, b1, c1, d1, e1, f1, one);
295  int first_mask = first_bit << 1;
296  int first_count, first_skip;
297 
298  if (sbit + w > 8)
299  first_mask -= 1,
300  first_count = 8 - sbit;
301  else
302  first_mask -= first_mask >> w,
303  first_count = w;
304  first_skip = first_count * PIXEL_SIZE;
305  while (h-- > 0) {
306  register byte *pptr = dest;
307  const byte *sptr = line;
308  register int sbyte = *sptr++ & first_mask;
309  int count = w - first_count;
310 
311  if (sbyte) {
312  register int bit = first_bit;
313 
314  do {
315  if (sbyte & bit)
316  put6(pptr, a1, b1, c1, d1, e1, f1);
317  pptr += PIXEL_SIZE;
318  }
319  while ((bit >>= 1) & first_mask);
320  } else
321  pptr += first_skip;
322  while (count >= 8) {
323  sbyte = *sptr++;
324  if (sbyte & 0xf0) {
325  if (sbyte & 0x80)
326  put6(pptr, a1, b1, c1, d1, e1, f1);
327  if (sbyte & 0x40)
328  put6(pptr + 6, a1, b1, c1, d1, e1, f1);
329  if (sbyte & 0x20)
330  put6(pptr + 12, a1, b1, c1, d1, e1, f1);
331  if (sbyte & 0x10)
332  put6(pptr + 18, a1, b1, c1, d1, e1, f1);
333  }
334  if (sbyte & 0xf) {
335  if (sbyte & 8)
336  put6(pptr + 24, a1, b1, c1, d1, e1, f1);
337  if (sbyte & 4)
338  put6(pptr + 30, a1, b1, c1, d1, e1, f1);
339  if (sbyte & 2)
340  put6(pptr + 36, a1, b1, c1, d1, e1, f1);
341  if (sbyte & 1)
342  put6(pptr + 42, a1, b1, c1, d1, e1, f1);
343  }
344  pptr += 8 * PIXEL_SIZE;
345  count -= 8;
346  }
347  if (count > 0) {
348  register int bit = 0x80;
349 
350  sbyte = *sptr++;
351  do {
352  if (sbyte & bit)
353  put6(pptr, a1, b1, c1, d1, e1, f1);
354  pptr += PIXEL_SIZE;
355  bit >>= 1;
356  }
357  while (--count > 0);
358  }
359  line += sraster;
360  inc_ptr(dest, draster);
361  }
362  }
363  return 0;
364 }
365 
366 /* Copy a color bitmap. */
367 private int
368 mem_true48_copy_color(gx_device * dev,
369  const byte * base, int sourcex, int sraster, gx_bitmap_id id,
370  int x, int y, int w, int h)
371 {
372  gx_device_memory * const mdev = (gx_device_memory *)dev;
373 
374  fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
375  mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
376  return 0;
377 }
378 
379 /* ================ "Word"-oriented device ================ */
380 
381 /* Note that on a big-endian machine, this is the same as the */
382 /* standard byte-oriented-device. */
383 
384 #if !arch_is_big_endian
385 
386 /* Procedures */
387 declare_mem_procs(mem48_word_copy_mono, mem48_word_copy_color, mem48_word_fill_rectangle);
388 
389 /* Here is the device descriptor. */
390 const gx_device_memory mem_true48_word_device =
391 mem_full_device("image48w", 48, 0, mem_open,
392  gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
393  mem48_word_copy_mono, mem48_word_copy_color, mem48_word_fill_rectangle,
394  gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,
395  gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
396 
397 /* Fill a rectangle with a color. */
398 private int
399 mem48_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
400  gx_color_index color)
401 {
402  gx_device_memory * const mdev = (gx_device_memory *)dev;
403  byte *base;
404  uint raster;
405 
406  fit_fill(dev, x, y, w, h);
407  base = scan_line_base(mdev, y);
408  raster = mdev->raster;
409  mem_swap_byte_rect(base, raster, x * 48, w * 48, h, true);
410  mem_true48_fill_rectangle(dev, x, y, w, h, color);
411  mem_swap_byte_rect(base, raster, x * 48, w * 48, h, false);
412  return 0;
413 }
414 
415 /* Copy a bitmap. */
416 private int
417 mem48_word_copy_mono(gx_device * dev,
418  const byte * base, int sourcex, int sraster, gx_bitmap_id id,
419  int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
420 {
421  gx_device_memory * const mdev = (gx_device_memory *)dev;
422  byte *row;
423  uint raster;
424  bool store;
425 
426  fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
427  row = scan_line_base(mdev, y);
428  raster = mdev->raster;
429  store = (zero != gx_no_color_index && one != gx_no_color_index);
430  mem_swap_byte_rect(row, raster, x * 48, w * 48, h, store);
431  mem_true48_copy_mono(dev, base, sourcex, sraster, id,
432  x, y, w, h, zero, one);
433  mem_swap_byte_rect(row, raster, x * 48, w * 48, h, false);
434  return 0;
435 }
436 
437 /* Copy a color bitmap. */
438 private int
439 mem48_word_copy_color(gx_device * dev,
440  const byte * base, int sourcex, int sraster, gx_bitmap_id id,
441  int x, int y, int w, int h)
442 {
443  gx_device_memory * const mdev = (gx_device_memory *)dev;
444  byte *row;
445  uint raster;
446 
447  fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
448  row = scan_line_base(mdev, y);
449  raster = mdev->raster;
450  mem_swap_byte_rect(row, raster, x * 48, w * 48, h, true);
451  bytes_copy_rectangle(row + x * PIXEL_SIZE, raster, base + sourcex * PIXEL_SIZE,
452  sraster, w * PIXEL_SIZE, h);
453  mem_swap_byte_rect(row, raster, x * 48, w * 48, h, false);
454  return 0;
455 }
456 
457 #endif /* !arch_is_big_endian */