2 * Copyright (C) 2000, Matias Atria
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /* Bitmap manipulation routines */
25 /* bit_masks[n] contains a BmUnit with `n' contiguous bits */
27 static BmUnit bit_masks[] = {
29 0xf, 0x1f, 0x3f, 0x7f,
33 0xfff, 0x1fff, 0x3fff, 0x7fff,
36 0x1ffff, 0x3ffff, 0x7ffff,
37 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
38 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff,
39 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
41 #endif /* BITMAP_BYTES > 2 */
42 #endif /* BITMAP_BYTES > 1 */
46 #define SHOW_OP_DATA (DEBUGGING(BITMAP_OPS) && DEBUGGING(BITMAP_DATA))
49 /* cache for color tables, to avoid creating them for every glyph */
61 * Some useful macros to manipulate bitmap data
62 * SEGMENT(m,n) = bit mask for a segment of `m' contiguous bits
63 * starting at column `n'. These macros assume that
64 * m + n <= BITMAP_BITS, 0 <= m, n.
66 #ifdef WORD_BIG_ENDIAN
67 #define SEGMENT(m,n) (bit_masks[m] << (BITMAP_BITS - (m) - (n)))
69 #define SEGMENT(m,n) (bit_masks[m] << (n))
72 /* sampling and shrinking routines shamelessly stolen from xdvi */
74 static int sample_count[] = {
75 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
76 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
77 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
78 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
79 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
80 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
81 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
82 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
83 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
84 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
85 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
86 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
87 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
88 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
89 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
90 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
93 /* bit_swap[j] = j with all bits inverted (i.e. msb -> lsb) */
94 static Uchar bit_swap[] = {
95 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
96 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
97 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
98 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
99 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
100 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
101 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
102 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
103 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
104 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
105 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
106 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
107 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
108 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
109 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
110 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
111 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
112 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
113 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
114 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
115 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
116 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
117 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
118 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
119 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
120 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
121 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
122 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
123 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
124 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
125 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
126 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
130 static ColorCache color_cache[CCSIZE];
131 static int cc_entries;
133 #define GAMMA_DIFF 0.005
135 static Ulong *get_color_table(DviDevice *dev,
136 int nlevels, Ulong fg, Ulong bg, double gamma, int density);
139 /* create a color table */
140 static Ulong *get_color_table(DviDevice *dev,
141 int nlevels, Ulong fg, Ulong bg, double gamma, int density)
143 ColorCache *cc, *tofree;
148 lohits = color_cache[0].hits;
149 tofree = &color_cache[0];
150 /* look in the cache and see if we have one that matches this request */
151 for(cc = &color_cache[0]; cc < &color_cache[cc_entries]; cc++) {
152 if(cc->hits < lohits) {
156 if(cc->fg == fg && cc->bg == bg && cc->density == density &&
157 cc->nlevels == nlevels && fabs(cc->gamma - gamma) <= GAMMA_DIFF)
161 if(cc < &color_cache[cc_entries]) {
166 DEBUG((DBG_DEVICE, "Adding color table to cache (fg=%lu, bg=%lu, n=%d)\n",
169 /* no entry was found in the cache, create a new one */
170 if(cc_entries < CCSIZE) {
171 cc = &color_cache[cc_entries++];
177 pixels = xnalloc(Ulong, nlevels);
178 status = dev->alloc_colors(dev->device_data,
179 pixels, nlevels, fg, bg, gamma, density);
187 cc->density = density;
188 cc->nlevels = nlevels;
195 * next we have three bitmap functions to convert bitmaps in LSB bit order
196 * with 8, 16 and 32 bits per unit, to our internal format. The differences
197 * are minimal, but writing a generic function to handle all unit sizes is
201 BITMAP *bitmap_convert_lsb8(Uchar *bits, int w, int h)
206 register Uchar *curr;
210 DEBUG((DBG_BITMAP_OPS, "convert LSB %dx%d@8 -> bitmap\n", w, h));
212 bm = bitmap_alloc_raw(w, h);
214 /* this is the number of bytes in the original bitmap */
216 unit = (Uchar *)bm->data;
217 end = unit + bm->stride;
219 /* we try to do this as fast as we can */
220 for(i = 0; i < h; i++) {
221 #ifdef WORD_LITTLE_ENDIAN
222 memcpy(unit, curr, bytes);
227 for(j = 0; j < bytes; curr++, j++)
228 unit[j] = bit_swap[*curr];
230 memzero(unit + bytes, bm->stride - bytes);
234 bitmap_print(stderr, bm);
238 BITMAP *bitmap_convert_msb8(Uchar *data, int w, int h)
246 bm = bitmap_alloc(w, h);
248 unit = (Uchar *)bm->data;
250 for(i = 0; i < h; i++) {
251 #ifdef WORD_LITTLE_ENDIAN
254 for(j = 0; j < bytes; curr++, j++)
255 unit[j] = bit_swap[*curr];
257 memcpy(unit, curr, bytes);
260 memzero(unit + bytes, bm->stride - bytes);
264 bitmap_print(stderr, bm);
269 BITMAP *bitmap_copy(BITMAP *bm)
271 BITMAP *nb = bitmap_alloc(bm->width, bm->height);
273 DEBUG((DBG_BITMAP_OPS, "copy %dx%d\n", bm->width, bm->height));
274 memcpy(nb->data, bm->data, bm->height * bm->stride);
278 BITMAP *bitmap_alloc(int w, int h)
285 bm->stride = BM_BYTES_PER_LINE(bm);
287 bm->data = (BmUnit *)xcalloc(h, bm->stride);
294 BITMAP *bitmap_alloc_raw(int w, int h)
301 bm->stride = BM_BYTES_PER_LINE(bm);
303 bm->data = (BmUnit *)xmalloc(h * bm->stride);
310 void bitmap_destroy(BITMAP *bm)
317 void bitmap_print(FILE *out, BITMAP *bm)
321 static const char labels[] = {
322 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
331 for(j = 2; j <= bm->width; j++)
337 fprintf(out, "%d", (j - sub)/10);
342 for(j = 0; j < bm->width; j++)
343 putc(labels[j % 10], out);
345 for(i = 0; i < bm->height; i++) {
347 a = (BmUnit *)((char *)bm->data + i * bm->stride);
348 fprintf(out, "%3d ", i+1);
349 for(j = 0; j < bm->width; j++) {
354 if(mask == LASTMASK) {
364 void bitmap_set_col(BITMAP *bm, int row, int col, int count, int state)
369 ptr = __bm_unit_ptr(bm, col, row);
370 mask = FIRSTMASKAT(col);
377 /* move to next row */
378 ptr = bm_offset(ptr, bm->stride);
383 * to use this function you should first make sure that
384 * there is room for `count' bits in the scanline
386 * A general-purpose (but not very efficient) function to paint `n' pixels
387 * on a bitmap, starting at position (x, y) would be:
389 * bitmap_paint_bits(__bm_unit_ptr(bitmap, x, y), x % BITMAP_BITS, n)
392 void bitmap_paint_bits(BmUnit *ptr, int n, int count)
395 if(n + count > BITMAP_BITS) {
396 *ptr |= SEGMENT(BITMAP_BITS - n, n);
397 count -= BITMAP_BITS - n;
400 *ptr |= SEGMENT(count, n);
404 /* paint the middle */
405 for(; count >= BITMAP_BITS; count -= BITMAP_BITS)
406 *ptr++ = bit_masks[BITMAP_BITS];
410 *ptr |= SEGMENT(count, 0);
414 * same as paint_bits but clears pixels instead of painting them. Written
415 * as a separate function for efficiency reasons.
417 void bitmap_clear_bits(BmUnit *ptr, int n, int count)
419 if(n + count > BITMAP_BITS) {
420 *ptr &= ~SEGMENT(BITMAP_BITS - n, n);
421 count -= BITMAP_BITS;
424 *ptr &= ~SEGMENT(count, n);
428 for(; count >= BITMAP_BITS; count -= BITMAP_BITS)
432 *ptr &= ~SEGMENT(count, 0);
435 /* the general function to paint rows. Still used by the PK reader, but that
436 * will change soon (The GF reader already uses bitmap_paint_bits()).
438 void bitmap_set_row(BITMAP *bm, int row, int col, int count, int state)
442 ptr = __bm_unit_ptr(bm, col, row);
444 bitmap_paint_bits(ptr, col & (BITMAP_BITS-1), count);
446 bitmap_clear_bits(ptr, col & (BITMAP_BITS-1), count);
450 * Now several `flipping' operations
453 void bitmap_flip_horizontally(BITMAP *bm)
460 nb.width = bm->width;
461 nb.height = bm->height;
462 nb.stride = bm->stride;
463 nb.data = xcalloc(bm->height, bm->stride);
466 tptr = __bm_unit_ptr(&nb, nb.width-1, 0);
467 for(h = 0; h < bm->height; h++) {
468 BmUnit *fline, *tline;
473 tmask = FIRSTMASKAT(nb.width-1);
474 for(w = 0; w < bm->width; w++) {
477 if(fmask == LASTMASK) {
482 if(tmask == FIRSTMASK) {
488 fptr = bm_offset(fptr, bm->stride);
489 tptr = bm_offset(tptr, bm->stride);
491 DEBUG((DBG_BITMAP_OPS, "flip_horizontally (%d,%d) -> (%d,%d)\n",
492 bm->width, bm->height, nb.width, nb.height));
496 bitmap_print(stderr, bm);
499 void bitmap_flip_vertically(BITMAP *bm)
506 nb.width = bm->width;
507 nb.height = bm->height;
508 nb.stride = bm->stride;
509 nb.data = xcalloc(bm->height, bm->stride);
512 tptr = __bm_unit_ptr(&nb, 0, nb.height-1);
513 for(h = 0; h < bm->height; h++) {
514 BmUnit *fline, *tline;
519 for(w = 0; w < bm->width; w++) {
522 if(fmask == LASTMASK) {
529 fptr = bm_offset(fptr, bm->stride);
530 tptr = (BmUnit *)((char *)tptr - bm->stride);
532 DEBUG((DBG_BITMAP_OPS, "flip_vertically (%d,%d) -> (%d,%d)\n",
533 bm->width, bm->height, nb.width, nb.height));
537 bitmap_print(stderr, bm);
540 void bitmap_flip_diagonally(BITMAP *bm)
547 nb.width = bm->width;
548 nb.height = bm->height;
549 nb.stride = bm->stride;
550 nb.data = xcalloc(bm->height, bm->stride);
553 tptr = __bm_unit_ptr(&nb, nb.width-1, nb.height-1);
554 for(h = 0; h < bm->height; h++) {
555 BmUnit *fline, *tline;
560 tmask = FIRSTMASKAT(nb.width-1);
561 for(w = 0; w < bm->width; w++) {
564 if(fmask == LASTMASK) {
569 if(tmask == FIRSTMASK) {
575 fptr = bm_offset(fptr, bm->stride);
576 tptr = bm_offset(tptr, -nb.stride);
578 DEBUG((DBG_BITMAP_OPS, "flip_diagonally (%d,%d) -> (%d,%d)\n",
579 bm->width, bm->height, nb.width, nb.height));
583 bitmap_print(stderr, bm);
586 void bitmap_rotate_clockwise(BITMAP *bm)
593 nb.width = bm->height;
594 nb.height = bm->width;
595 nb.stride = BM_BYTES_PER_LINE(&nb);
596 nb.data = xcalloc(nb.height, nb.stride);
599 tptr = __bm_unit_ptr(&nb, nb.width - 1, 0);
601 tmask = FIRSTMASKAT(nb.width-1);
602 for(h = 0; h < bm->height; h++) {
603 BmUnit *fline, *tline;
608 for(w = 0; w < bm->width; w++) {
611 if(fmask == LASTMASK) {
617 tline = bm_offset(tline, nb.stride);
619 fptr = bm_offset(fptr, bm->stride);
620 if(tmask == FIRSTMASK) {
627 DEBUG((DBG_BITMAP_OPS, "rotate_clockwise (%d,%d) -> (%d,%d)\n",
628 bm->width, bm->height, nb.width, nb.height));
631 bm->width = nb.width;
632 bm->height = nb.height;
633 bm->stride = nb.stride;
635 bitmap_print(stderr, bm);
638 void bitmap_rotate_counter_clockwise(BITMAP *bm)
645 nb.width = bm->height;
646 nb.height = bm->width;
647 nb.stride = BM_BYTES_PER_LINE(&nb);
648 nb.data = xcalloc(nb.height, nb.stride);
651 tptr = __bm_unit_ptr(&nb, 0, nb.height - 1);
654 for(h = 0; h < bm->height; h++) {
655 BmUnit *fline, *tline;
660 for(w = 0; w < bm->width; w++) {
663 if(fmask == LASTMASK) {
668 /* go to previous row */
669 tline = bm_offset(tline, -nb.stride);
671 fptr = bm_offset(fptr, bm->stride);
672 if(tmask == LASTMASK) {
679 DEBUG((DBG_BITMAP_OPS, "rotate_counter_clockwise (%d,%d) -> (%d,%d)\n",
680 bm->width, bm->height, nb.width, nb.height));
683 bm->width = nb.width;
684 bm->height = nb.height;
685 bm->stride = nb.stride;
687 bitmap_print(stderr, bm);
690 void bitmap_flip_rotate_clockwise(BITMAP *bm)
697 nb.width = bm->height;
698 nb.height = bm->width;
699 nb.stride = BM_BYTES_PER_LINE(&nb);
700 nb.data = xcalloc(nb.height, nb.stride);
703 tptr = __bm_unit_ptr(&nb, nb.width-1, nb.height-1);
705 tmask = FIRSTMASKAT(nb.width-1);
706 for(h = 0; h < bm->height; h++) {
707 BmUnit *fline, *tline;
712 for(w = 0; w < bm->width; w++) {
715 if(fmask == LASTMASK) {
720 /* go to previous line */
721 tline = bm_offset(tline, -nb.stride);
723 fptr = bm_offset(fptr, bm->stride);
724 if(tmask == FIRSTMASK) {
730 DEBUG((DBG_BITMAP_OPS, "flip_rotate_clockwise (%d,%d) -> (%d,%d)\n",
731 bm->width, bm->height, nb.width, nb.height));
734 bm->width = nb.width;
735 bm->height = nb.height;
736 bm->stride = nb.stride;
738 bitmap_print(stderr, bm);
741 void bitmap_flip_rotate_counter_clockwise(BITMAP *bm)
748 nb.width = bm->height;
749 nb.height = bm->width;
750 nb.stride = BM_BYTES_PER_LINE(&nb);
751 nb.data = xcalloc(nb.height, nb.stride);
757 for(h = 0; h < bm->height; h++) {
758 BmUnit *fline, *tline;
763 for(w = 0; w < bm->width; w++) {
766 if(fmask == LASTMASK) {
771 /* go to next line */
772 tline = bm_offset(tline, nb.stride);
774 fptr = bm_offset(fptr, bm->stride);
775 if(tmask == LASTMASK) {
782 DEBUG((DBG_BITMAP_OPS, "flip_rotate_counter_clockwise (%d,%d) -> (%d,%d)\n",
783 bm->width, bm->height, nb.width, nb.height));
786 bm->width = nb.width;
787 bm->height = nb.height;
788 bm->stride = nb.stride;
790 bitmap_print(stderr, bm);
794 void bitmap_transform(BITMAP *map, DviOrientation orient)
797 case MDVI_ORIENT_TBLR:
799 case MDVI_ORIENT_TBRL:
800 bitmap_flip_horizontally(map);
802 case MDVI_ORIENT_BTLR:
803 bitmap_flip_vertically(map);
805 case MDVI_ORIENT_BTRL:
806 bitmap_flip_diagonally(map);
808 case MDVI_ORIENT_RP90:
809 bitmap_rotate_counter_clockwise(map);
811 case MDVI_ORIENT_RM90:
812 bitmap_rotate_clockwise(map);
814 case MDVI_ORIENT_IRP90:
815 bitmap_flip_rotate_counter_clockwise(map);
817 case MDVI_ORIENT_IRM90:
818 bitmap_flip_rotate_clockwise(map);
825 * Count the number of non-zero bits in a box of dimensions w x h, starting
826 * at column `step' in row `data'.
828 * Shamelessly stolen from xdvi.
830 static int do_sample(BmUnit *data, int stride, int step, int w, int h)
832 BmUnit *ptr, *end, *cp;
837 ptr = data + step / BITMAP_BITS;
838 end = bm_offset(data, h * stride);
839 shift = FIRSTSHIFTAT(step);
843 #ifndef WORD_BIG_ENDIAN
844 wid = BITMAP_BITS - shift;
852 #ifdef WORD_BIG_ENDIAN
855 for(cp = ptr; cp < end; cp = bm_offset(cp, stride))
856 n += sample_count[(*cp >> shift) & bit_masks[wid]];
857 #ifndef WORD_BIG_ENDIAN
860 #ifdef WORD_BIG_ENDIAN
866 if(shift == BITMAP_BITS) {
876 void mdvi_shrink_box(DviContext *dvi, DviFont *font,
877 DviFontChar *pk, DviGlyph *dest)
883 hs = dvi->params.hshrink;
884 vs = dvi->params.vshrink;
887 x = (int)glyph->x / hs;
888 if((int)glyph->x - x * hs > 0)
890 dest->w = x + ROUND((int)glyph->w - glyph->x, hs);
892 z = (int)glyph->y + 1;
896 dest->h = y + ROUND((int)glyph->h - z, vs) + 1;
898 dest->y = glyph->y / vs;
899 dest->data = MDVI_GLYPH_EMPTY;
900 DEBUG((DBG_BITMAPS, "shrink_box: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",
901 glyph->w, glyph->h, glyph->x, glyph->y,
902 dest->w, dest->h, dest->x, dest->y));
905 void mdvi_shrink_glyph(DviContext *dvi, DviFont *font,
906 DviFontChar *pk, DviGlyph *dest)
908 int rows_left, rows, init_cols;
910 BmUnit *old_ptr, *new_ptr;
911 BITMAP *oldmap, *newmap;
914 int sample, min_sample;
921 hs = dvi->params.hshrink;
922 vs = dvi->params.vshrink;
924 min_sample = vs * hs * dvi->params.density / 100;
927 oldmap = (BITMAP *)glyph->data;
929 x = (int)glyph->x / hs;
930 init_cols = (int)glyph->x - x * hs;
935 w = x + ROUND((int)glyph->w - glyph->x, hs);
937 cols = (int)glyph->y + 1;
939 rows = cols - y * vs;
944 h = y + ROUND((int)glyph->h - cols, vs) + 1;
946 /* create the new glyph */
947 newmap = bitmap_alloc(w, h);
950 dest->y = glyph->y / vs;
954 old_ptr = oldmap->data;
955 old_stride = oldmap->stride;
956 new_ptr = newmap->data;
957 new_stride = newmap->stride;
958 rows_left = glyph->h;
963 cols_left = glyph->w;
967 while(cols_left > 0) {
970 sample = do_sample(old_ptr, old_stride,
971 glyph->w - cols_left, cols, rows);
972 if(sample >= min_sample)
982 new_ptr = bm_offset(new_ptr, new_stride);
983 old_ptr = bm_offset(old_ptr, rows * old_stride);
987 DEBUG((DBG_BITMAPS, "shrink_glyph: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",
988 glyph->w, glyph->h, glyph->x, glyph->y,
989 dest->w, dest->h, dest->x, dest->y));
990 if(DEBUGGING(BITMAP_DATA))
991 bitmap_print(stderr, newmap);
994 void mdvi_shrink_glyph_grey(DviContext *dvi, DviFont *font,
995 DviFontChar *pk, DviGlyph *dest)
998 int cols_left, cols, init_cols;
999 long sampleval, samplemax;
1012 hs = dvi->params.hshrink;
1013 vs = dvi->params.vshrink;
1017 map = (BITMAP *)glyph->data;
1019 x = (int)glyph->x / hs;
1020 init_cols = (int)glyph->x - x * hs;
1025 w = x + ROUND((int)glyph->w - glyph->x, hs);
1027 cols = (int)glyph->y + 1;
1029 rows = cols - y * vs;
1034 h = y + ROUND((int)glyph->h - cols, vs) + 1;
1037 /* before touching anything, do this */
1038 image = dev->create_image(dev->device_data, w, h, BITMAP_BITS);
1040 mdvi_shrink_glyph(dvi, font, pk, dest);
1044 /* save these colors */
1045 pk->fg = MDVI_CURRFG(dvi);
1046 pk->bg = MDVI_CURRBG(dvi);
1048 samplemax = vs * hs;
1049 npixels = samplemax + 1;
1050 pixels = get_color_table(&dvi->device, npixels, pk->fg, pk->bg,
1051 dvi->params.gamma, dvi->params.density);
1052 if(pixels == NULL) {
1054 colortab[0] = pk->fg;
1055 colortab[1] = pk->bg;
1056 pixels = &colortab[0];
1059 /* setup the new glyph */
1062 dest->y = glyph->y / vs;
1067 old_ptr = map->data;
1068 rows_left = glyph->h;
1070 while(rows_left && y < h) {
1072 if(rows > rows_left)
1074 cols_left = glyph->w;
1076 while(cols_left && x < w) {
1077 if(cols > cols_left)
1079 sampleval = do_sample(old_ptr, map->stride,
1080 glyph->w - cols_left, cols, rows);
1081 /* scale the sample value by the number of grey levels */
1082 if(npixels - 1 != samplemax)
1083 sampleval = ((npixels-1) * sampleval) / samplemax;
1084 ASSERT(sampleval < npixels);
1085 dev->put_pixel(image, x, y, pixels[sampleval]);
1091 dev->put_pixel(image, x, y, pixels[0]);
1092 old_ptr = bm_offset(old_ptr, rows * map->stride);
1099 for(x = 0; x < w; x++)
1100 dev->put_pixel(image, x, y, pixels[0]);
1102 DEBUG((DBG_BITMAPS, "shrink_glyph_grey: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",
1103 glyph->w, glyph->h, glyph->x, glyph->y,
1104 dest->w, dest->h, dest->x, dest->y));