changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/cmd/gs/src/gdevm40.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: gdevm40.c,v 1.3 2005/06/20 08:59:23 igor Exp $ */
18 /* 40-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_mem40_s {
28  long
29  fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
30  fprevc[257];
31  double ftotal;
32 } stats_mem40;
33 static int prev_count = 0;
34 static gx_color_index prev_colors[256];
35 # define INCR(v) (++(stats_mem40.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 5
46 
47 /* Procedures */
48 declare_mem_procs(mem_true40_copy_mono, mem_true40_copy_color, mem_true40_fill_rectangle);
49 
50 /* The device descriptor. */
51 const gx_device_memory mem_true40_device =
52 mem_full_alpha_device("image40", 40, 0, mem_open,
53  gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
54  mem_true40_copy_mono, mem_true40_copy_color, mem_true40_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, color)\
65  byte a = (byte)((uint64_t)color >> 32);\
66  byte b = (byte)((uint)color >> 24);\
67  byte c = (byte)((uint)color >> 16);\
68  byte d = (byte)((uint)color >> 8);\
69  byte e = (byte)color
70 /* Put a 40-bit color into the bitmap. */
71 #define put5(ptr, a, b, c, d, e)\
72  (ptr)[0] = a, (ptr)[1] = b, (ptr)[2] = c, (ptr)[3] = d, (ptr)[4] = e
73 /* Put 4 bytes of color into the bitmap. */
74 #define putw(ptr, wxyz)\
75  *(bits32 *)(ptr) = (wxyz)
76 /* Load the 5-word 40-bit-color cache. */
77 /* Free variables: [m]dev, abcd, bcde, cdea, deab, earc. */
78 #if arch_is_big_endian
79 # define set_color40_cache(color, a, b, c, d, e)\
80  mdev->color40.abcd = abcd = (color) >> 8, \
81  mdev->color40.bcde = bcde = (abcd << 8) | (e),\
82  mdev->color40.cdea = cdea = (bcde << 8) | (a),\
83  mdev->color40.deab = deab = (cdea << 8) | (b),\
84  mdev->color40.eabc = eabc = (deab << 8) | (c),\
85  mdev->color40.abcde = (color)
86 #else
87 # define set_color40_cache(color, a, b, c, d, e)\
88  mdev->color40.abcd = abcd =\
89  ((bits32)(d) << 24) | ((bits32)(c) << 16) |\
90  ((bits16)(b) << 8) | (a),\
91  mdev->color40.eabc = eabc = (abcd << 8) | (e),\
92  mdev->color40.deab = deab = (eabc << 8) | (d),\
93  mdev->color40.cdea = cdea = (deab << 8) | (c),\
94  mdev->color40.bcde = bcde = (cdea << 8) | (b),\
95  mdev->color40.abcde = (color)
96 #endif
97 
98 /* Fill a rectangle with a color. */
99 private int
100 mem_true40_fill_rectangle(gx_device * dev,
101  int x, int y, int w, int h, gx_color_index color)
102 {
103  gx_device_memory * const mdev = (gx_device_memory *)dev;
104  declare_unpack_color(a, b, c, d, e, color);
105  declare_scan_ptr(dest);
106 
107  /*
108  * In order to avoid testing w > 0 and h > 0 twice, we defer
109  * executing setup_rect, and use fit_fill_xywh instead of
110  * fit_fill.
111  */
112  fit_fill_xywh(dev, x, y, w, h);
113  INCR(fill);
114 #ifdef DEBUG
115  stats_mem40.ftotal += w;
116 #endif
117  if (w >= 5) {
118  if (h <= 0)
119  return 0;
120  INCR(fwide);
121  setup_rect(dest);
122  if (a == b && b == c && c == d && d == e) {
123  int bcnt = w * PIXEL_SIZE;
124 
125  INCR(fgray[min(w, 100)]);
126  while (h-- > 0) {
127  memset(dest, a, bcnt);
128  inc_ptr(dest, draster);
129  }
130  } else {
131  int x3 = -x & 3, ww = w - x3; /* we know ww >= 2 */
132  bits32 abcd, bcde, cdea, deab, eabc;
133 
134  if (mdev->color40.abcde == color) {
135  abcd = mdev->color40.abcd;
136  bcde = mdev->color40.bcde;
137  cdea = mdev->color40.cdea;
138  deab = mdev->color40.deab;
139  eabc = mdev->color40.eabc;
140  } else {
141  INCR(fsetc);
142  set_color40_cache(color, a, b, c, d, e);
143  }
144 #ifdef DEBUG
145  {
146  int ci;
147  for (ci = 0; ci < prev_count; ++ci)
148  if (prev_colors[ci] == color)
149  break;
150  INCR(fprevc[ci]);
151  if (ci == prev_count) {
152  if (ci < countof(prev_colors))
153  ++prev_count;
154  else
155  --ci;
156  }
157  if (ci) {
158  memmove(&prev_colors[1], &prev_colors[0],
159  ci * sizeof(prev_colors[0]));
160  prev_colors[0] = color;
161  }
162  }
163 #endif
164  INCR(fcolor[min(w, 100)]);
165  while (h-- > 0) {
166  register byte *pptr = dest;
167  int w1 = ww;
168 
169  switch (x3) {
170  case 1:
171  pptr[0] = a;
172  putw(pptr + 1, bcde);
173  pptr += PIXEL_SIZE;
174  break;
175  case 2:
176  pptr[0] = a;
177  pptr[1] = b;
178  putw(pptr + 2, cdea);
179  putw(pptr + 6, bcde);
180  pptr += 2 * PIXEL_SIZE;
181  break;
182  case 3:
183  pptr[0] = a;
184  pptr[1] = b;
185  pptr[2] = c;
186  putw(pptr + 3, deab);
187  putw(pptr + 7, cdea);
188  putw(pptr + 11, bcde);
189  pptr += 3 * PIXEL_SIZE;
190  break;
191  case 0:
192  ;
193  }
194  while (w1 >= 4) {
195  putw(pptr, abcd);
196  putw(pptr + 4, eabc);
197  putw(pptr + 8, deab);
198  putw(pptr + 12, cdea);
199  putw(pptr + 16, bcde);
200  pptr += 4 * PIXEL_SIZE;
201  w1 -= 4;
202  }
203  switch (w1) {
204  case 1:
205  putw(pptr, abcd);
206  pptr[4] = e;
207  break;
208  case 2:
209  putw(pptr, abcd);
210  putw(pptr + 4, eabc);
211  pptr[8] = d;
212  pptr[9] = e;
213  break;
214  case 3:
215  putw(pptr, abcd);
216  putw(pptr + 4, eabc);
217  putw(pptr + 8, deab);
218  pptr[12] = c;
219  pptr[13] = d;
220  pptr[14] = e;
221  break;
222  case 0:
223  ;
224  }
225  inc_ptr(dest, draster);
226  }
227  }
228  } else if (h > 0) { /* w < 5 */
229  INCR(fnarrow[max(w, 0)]);
230  setup_rect(dest);
231  switch (w) {
232  case 4:
233  do {
234  dest[15] = dest[10] = dest[5] = dest[0] = a;
235  dest[16] = dest[11] = dest[6] = dest[1] = b;
236  dest[17] = dest[12] = dest[7] = dest[2] = c;
237  dest[18] = dest[13] = dest[8] = dest[3] = d;
238  dest[19] = dest[14] = dest[9] = dest[4] = e;
239  inc_ptr(dest, draster);
240  }
241  while (--h);
242  break;
243  case 3:
244  do {
245  dest[10] = dest[5] = dest[0] = a;
246  dest[11] = dest[6] = dest[1] = b;
247  dest[12] = dest[7] = dest[2] = c;
248  dest[13] = dest[8] = dest[3] = d;
249  dest[14] = dest[9] = dest[4] = e;
250  inc_ptr(dest, draster);
251  }
252  while (--h);
253  break;
254  case 2:
255  do {
256  dest[5] = dest[0] = a;
257  dest[6] = dest[1] = b;
258  dest[7] = dest[2] = c;
259  dest[8] = dest[3] = d;
260  dest[9] = dest[4] = e;
261  inc_ptr(dest, draster);
262  }
263  while (--h);
264  break;
265  case 1:
266  do {
267  dest[0] = a; dest[1] = b; dest[2] = c; dest[3] = d; dest[4] = e;
268  inc_ptr(dest, draster);
269  }
270  while (--h);
271  break;
272  case 0:
273  default:
274  ;
275  }
276  }
277  return 0;
278 }
279 
280 /* Copy a monochrome bitmap. */
281 private int
282 mem_true40_copy_mono(gx_device * dev,
283  const byte * base, int sourcex, int sraster, gx_bitmap_id id,
284  int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
285 {
286  gx_device_memory * const mdev = (gx_device_memory *)dev;
287  const byte *line;
288  int sbit;
289  int first_bit;
290 
291  declare_scan_ptr(dest);
292 
293  fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
294  setup_rect(dest);
295  line = base + (sourcex >> 3);
296  sbit = sourcex & 7;
297  first_bit = 0x80 >> sbit;
298  if (zero != gx_no_color_index) { /* Loop for halftones or inverted masks */
299  /* (never used). */
300  declare_unpack_color(a0, b0, c0, d0, e0, zero);
301  declare_unpack_color(a1, b1, c1, d1, e1, one);
302  while (h-- > 0) {
303  register byte *pptr = dest;
304  const byte *sptr = line;
305  register int sbyte = *sptr++;
306  register int bit = first_bit;
307  int count = w;
308 
309  do {
310  if (sbyte & bit) {
311  if (one != gx_no_color_index)
312  put5(pptr, a1, b1, c1, d1, e1);
313  } else
314  put5(pptr, a0, b0, c0, d0, e0);
315  pptr += PIXEL_SIZE;
316  if ((bit >>= 1) == 0)
317  bit = 0x80, sbyte = *sptr++;
318  }
319  while (--count > 0);
320  line += sraster;
321  inc_ptr(dest, draster);
322  }
323  } else if (one != gx_no_color_index) { /* Loop for character and pattern masks. */
324  /* This is used heavily. */
325  declare_unpack_color(a1, b1, c1, d1, e1, one);
326  int first_mask = first_bit << 1;
327  int first_count, first_skip;
328 
329  if (sbit + w > 8)
330  first_mask -= 1,
331  first_count = 8 - sbit;
332  else
333  first_mask -= first_mask >> w,
334  first_count = w;
335  first_skip = first_count * PIXEL_SIZE;
336  while (h-- > 0) {
337  register byte *pptr = dest;
338  const byte *sptr = line;
339  register int sbyte = *sptr++ & first_mask;
340  int count = w - first_count;
341 
342  if (sbyte) {
343  register int bit = first_bit;
344 
345  do {
346  if (sbyte & bit)
347  put5(pptr, a1, b1, c1, d1, e1);
348  pptr += PIXEL_SIZE;
349  }
350  while ((bit >>= 1) & first_mask);
351  } else
352  pptr += first_skip;
353  while (count >= 8) {
354  sbyte = *sptr++;
355  if (sbyte & 0xf0) {
356  if (sbyte & 0x80)
357  put5(pptr, a1, b1, c1, d1, e1);
358  if (sbyte & 0x40)
359  put5(pptr + 5, a1, b1, c1, d1, e1);
360  if (sbyte & 0x20)
361  put5(pptr + 10, a1, b1, c1, d1, e1);
362  if (sbyte & 0x10)
363  put5(pptr + 15, a1, b1, c1, d1, e1);
364  }
365  if (sbyte & 0xf) {
366  if (sbyte & 8)
367  put5(pptr + 20, a1, b1, c1, d1, e1);
368  if (sbyte & 4)
369  put5(pptr + 25, a1, b1, c1, d1, e1);
370  if (sbyte & 2)
371  put5(pptr + 30, a1, b1, c1, d1, e1);
372  if (sbyte & 1)
373  put5(pptr + 35, a1, b1, c1, d1, e1);
374  }
375  pptr += 8 * PIXEL_SIZE;
376  count -= 8;
377  }
378  if (count > 0) {
379  register int bit = 0x80;
380 
381  sbyte = *sptr++;
382  do {
383  if (sbyte & bit)
384  put5(pptr, a1, b1, c1, d1, e1);
385  pptr += PIXEL_SIZE;
386  bit >>= 1;
387  }
388  while (--count > 0);
389  }
390  line += sraster;
391  inc_ptr(dest, draster);
392  }
393  }
394  return 0;
395 }
396 
397 /* Copy a color bitmap. */
398 private int
399 mem_true40_copy_color(gx_device * dev,
400  const byte * base, int sourcex, int sraster, gx_bitmap_id id,
401  int x, int y, int w, int h)
402 {
403  gx_device_memory * const mdev = (gx_device_memory *)dev;
404 
405  fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
406  mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
407  return 0;
408 }
409 
410 /* ================ "Word"-oriented device ================ */
411 
412 /* Note that on a big-endian machine, this is the same as the */
413 /* standard byte-oriented-device. */
414 
415 #if !arch_is_big_endian
416 
417 /* Procedures */
418 declare_mem_procs(mem40_word_copy_mono, mem40_word_copy_color, mem40_word_fill_rectangle);
419 
420 /* Here is the device descriptor. */
421 const gx_device_memory mem_true40_word_device =
422 mem_full_device("image40w", 40, 0, mem_open,
423  gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
424  mem40_word_copy_mono, mem40_word_copy_color, mem40_word_fill_rectangle,
425  gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,
426  gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
427 
428 /* Fill a rectangle with a color. */
429 private int
430 mem40_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
431  gx_color_index color)
432 {
433  gx_device_memory * const mdev = (gx_device_memory *)dev;
434  byte *base;
435  uint raster;
436 
437  fit_fill(dev, x, y, w, h);
438  base = scan_line_base(mdev, y);
439  raster = mdev->raster;
440  mem_swap_byte_rect(base, raster, x * 40, w * 40, h, true);
441  mem_true40_fill_rectangle(dev, x, y, w, h, color);
442  mem_swap_byte_rect(base, raster, x * 40, w * 40, h, false);
443  return 0;
444 }
445 
446 /* Copy a bitmap. */
447 private int
448 mem40_word_copy_mono(gx_device * dev,
449  const byte * base, int sourcex, int sraster, gx_bitmap_id id,
450  int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
451 {
452  gx_device_memory * const mdev = (gx_device_memory *)dev;
453  byte *row;
454  uint raster;
455  bool store;
456 
457  fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
458  row = scan_line_base(mdev, y);
459  raster = mdev->raster;
460  store = (zero != gx_no_color_index && one != gx_no_color_index);
461  mem_swap_byte_rect(row, raster, x * 40, w * 40, h, store);
462  mem_true40_copy_mono(dev, base, sourcex, sraster, id,
463  x, y, w, h, zero, one);
464  mem_swap_byte_rect(row, raster, x * 40, w * 40, h, false);
465  return 0;
466 }
467 
468 /* Copy a color bitmap. */
469 private int
470 mem40_word_copy_color(gx_device * dev,
471  const byte * base, int sourcex, int sraster, gx_bitmap_id id,
472  int x, int y, int w, int h)
473 {
474  gx_device_memory * const mdev = (gx_device_memory *)dev;
475  byte *row;
476  uint raster;
477 
478  fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
479  row = scan_line_base(mdev, y);
480  raster = mdev->raster;
481  mem_swap_byte_rect(row, raster, x * 40, w * 40, h, true);
482  bytes_copy_rectangle(row + x * PIXEL_SIZE, raster, base + sourcex * PIXEL_SIZE,
483  sraster, w * PIXEL_SIZE, h);
484  mem_swap_byte_rect(row, raster, x * 40, w * 40, h, false);
485  return 0;
486 }
487 
488 #endif /* !arch_is_big_endian */