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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 /* Bitmap manipulation routines */
27 /* bit_masks[n] contains a BmUnit with `n' contiguous bits */
29 static BmUnit bit_masks[] = {
31 0xf, 0x1f, 0x3f, 0x7f,
35 0xfff, 0x1fff, 0x3fff, 0x7fff,
38 0x1ffff, 0x3ffff, 0x7ffff,
39 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
40 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff,
41 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
43 #endif /* BITMAP_BYTES > 2 */
44 #endif /* BITMAP_BYTES > 1 */
48 #define SHOW_OP_DATA (DEBUGGING(BITMAP_OPS) && DEBUGGING(BITMAP_DATA))
52 * Some useful macros to manipulate bitmap data
53 * SEGMENT(m,n) = bit mask for a segment of `m' contiguous bits
54 * starting at column `n'. These macros assume that
55 * m + n <= BITMAP_BITS, 0 <= m, n.
57 #ifdef WORD_BIG_ENDIAN
58 #define SEGMENT(m,n) (bit_masks[m] << (BITMAP_BITS - (m) - (n)))
60 #define SEGMENT(m,n) (bit_masks[m] << (n))
63 /* sampling and shrinking routines shamelessly stolen from xdvi */
65 static int sample_count[] = {
66 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
67 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
68 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
69 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
70 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
71 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
72 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
73 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
74 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
75 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
76 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
77 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
78 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
79 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
80 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
81 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
84 /* bit_swap[j] = j with all bits inverted (i.e. msb -> lsb) */
85 static Uchar bit_swap[] = {
86 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
87 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
88 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
89 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
90 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
91 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
92 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
93 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
94 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
95 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
96 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
97 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
98 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
99 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
100 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
101 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
102 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
103 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
104 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
105 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
106 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
107 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
108 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
109 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
110 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
111 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
112 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
113 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
114 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
115 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
116 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
117 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
122 * next we have three bitmap functions to convert bitmaps in LSB bit order
123 * with 8, 16 and 32 bits per unit, to our internal format. The differences
124 * are minimal, but writing a generic function to handle all unit sizes is
128 BITMAP *bitmap_convert_lsb8(Uchar *bits, int w, int h, int stride)
133 register Uchar *curr;
137 DEBUG((DBG_BITMAP_OPS, "convert LSB %dx%d@8 -> bitmap\n", w, h));
139 bm = bitmap_alloc_raw(w, h);
141 /* this is the number of bytes in the original bitmap */
143 unit = (Uchar *)bm->data;
144 end = unit + bm->stride;
146 /* we try to do this as fast as we can */
147 for(i = 0; i < h; i++) {
148 #ifdef WORD_LITTLE_ENDIAN
149 memcpy(unit, curr, bytes);
154 for(j = 0; j < bytes; curr++, j++)
155 unit[j] = bit_swap[*curr];
156 cur += stride - bytes;
158 memzero(unit + bytes, bm->stride - bytes);
162 bitmap_print(stderr, bm);
166 BITMAP *bitmap_convert_msb8(Uchar *data, int w, int h, int stride)
174 bm = bitmap_alloc(w, h);
176 unit = (Uchar *)bm->data;
178 for(i = 0; i < h; i++) {
179 #ifdef WORD_LITTLE_ENDIAN
182 for(j = 0; j < bytes; curr++, j++)
183 unit[j] = bit_swap[*curr];
184 curr += stride - bytes;
186 memcpy(unit, curr, bytes);
189 memzero(unit + bytes, bm->stride - bytes);
193 bitmap_print(stderr, bm);
198 BITMAP *bitmap_copy(BITMAP *bm)
200 BITMAP *nb = bitmap_alloc(bm->width, bm->height);
202 DEBUG((DBG_BITMAP_OPS, "copy %dx%d\n", bm->width, bm->height));
203 memcpy(nb->data, bm->data, bm->height * bm->stride);
207 BITMAP *bitmap_alloc(int w, int h)
214 bm->stride = BM_BYTES_PER_LINE(bm);
216 bm->data = (BmUnit *)mdvi_calloc(h, bm->stride);
223 BITMAP *bitmap_alloc_raw(int w, int h)
230 bm->stride = BM_BYTES_PER_LINE(bm);
232 bm->data = (BmUnit *)mdvi_malloc(h * bm->stride);
239 void bitmap_destroy(BITMAP *bm)
246 void bitmap_print(FILE *out, BITMAP *bm)
250 static const char labels[] = {
251 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
260 for(j = 2; j <= bm->width; j++)
266 fprintf(out, "%d", (j - sub)/10);
271 for(j = 0; j < bm->width; j++)
272 putc(labels[j % 10], out);
274 for(i = 0; i < bm->height; i++) {
276 a = (BmUnit *)((char *)bm->data + i * bm->stride);
277 fprintf(out, "%3d ", i+1);
278 for(j = 0; j < bm->width; j++) {
283 if(mask == LASTMASK) {
293 void bitmap_set_col(BITMAP *bm, int row, int col, int count, int state)
298 ptr = __bm_unit_ptr(bm, col, row);
299 mask = FIRSTMASKAT(col);
306 /* move to next row */
307 ptr = bm_offset(ptr, bm->stride);
312 * to use this function you should first make sure that
313 * there is room for `count' bits in the scanline
315 * A general-purpose (but not very efficient) function to paint `n' pixels
316 * on a bitmap, starting at position (x, y) would be:
318 * bitmap_paint_bits(__bm_unit_ptr(bitmap, x, y), x % BITMAP_BITS, n)
321 void bitmap_paint_bits(BmUnit *ptr, int n, int count)
324 if(n + count > BITMAP_BITS) {
325 *ptr |= SEGMENT(BITMAP_BITS - n, n);
326 count -= BITMAP_BITS - n;
329 *ptr |= SEGMENT(count, n);
333 /* paint the middle */
334 for(; count >= BITMAP_BITS; count -= BITMAP_BITS)
335 *ptr++ = bit_masks[BITMAP_BITS];
339 *ptr |= SEGMENT(count, 0);
343 * same as paint_bits but clears pixels instead of painting them. Written
344 * as a separate function for efficiency reasons.
346 void bitmap_clear_bits(BmUnit *ptr, int n, int count)
348 if(n + count > BITMAP_BITS) {
349 *ptr &= ~SEGMENT(BITMAP_BITS - n, n);
350 count -= BITMAP_BITS;
353 *ptr &= ~SEGMENT(count, n);
357 for(; count >= BITMAP_BITS; count -= BITMAP_BITS)
361 *ptr &= ~SEGMENT(count, 0);
364 /* the general function to paint rows. Still used by the PK reader, but that
365 * will change soon (The GF reader already uses bitmap_paint_bits()).
367 void bitmap_set_row(BITMAP *bm, int row, int col, int count, int state)
371 ptr = __bm_unit_ptr(bm, col, row);
373 bitmap_paint_bits(ptr, col & (BITMAP_BITS-1), count);
375 bitmap_clear_bits(ptr, col & (BITMAP_BITS-1), count);
379 * Now several `flipping' operations
382 void bitmap_flip_horizontally(BITMAP *bm)
389 nb.width = bm->width;
390 nb.height = bm->height;
391 nb.stride = bm->stride;
392 nb.data = mdvi_calloc(bm->height, bm->stride);
395 tptr = __bm_unit_ptr(&nb, nb.width-1, 0);
396 for(h = 0; h < bm->height; h++) {
397 BmUnit *fline, *tline;
402 tmask = FIRSTMASKAT(nb.width-1);
403 for(w = 0; w < bm->width; w++) {
406 if(fmask == LASTMASK) {
411 if(tmask == FIRSTMASK) {
417 fptr = bm_offset(fptr, bm->stride);
418 tptr = bm_offset(tptr, bm->stride);
420 DEBUG((DBG_BITMAP_OPS, "flip_horizontally (%d,%d) -> (%d,%d)\n",
421 bm->width, bm->height, nb.width, nb.height));
425 bitmap_print(stderr, bm);
428 void bitmap_flip_vertically(BITMAP *bm)
435 nb.width = bm->width;
436 nb.height = bm->height;
437 nb.stride = bm->stride;
438 nb.data = mdvi_calloc(bm->height, bm->stride);
441 tptr = __bm_unit_ptr(&nb, 0, nb.height-1);
442 for(h = 0; h < bm->height; h++) {
443 BmUnit *fline, *tline;
448 for(w = 0; w < bm->width; w++) {
451 if(fmask == LASTMASK) {
458 fptr = bm_offset(fptr, bm->stride);
459 tptr = (BmUnit *)((char *)tptr - bm->stride);
461 DEBUG((DBG_BITMAP_OPS, "flip_vertically (%d,%d) -> (%d,%d)\n",
462 bm->width, bm->height, nb.width, nb.height));
466 bitmap_print(stderr, bm);
469 void bitmap_flip_diagonally(BITMAP *bm)
476 nb.width = bm->width;
477 nb.height = bm->height;
478 nb.stride = bm->stride;
479 nb.data = mdvi_calloc(bm->height, bm->stride);
482 tptr = __bm_unit_ptr(&nb, nb.width-1, nb.height-1);
483 for(h = 0; h < bm->height; h++) {
484 BmUnit *fline, *tline;
489 tmask = FIRSTMASKAT(nb.width-1);
490 for(w = 0; w < bm->width; w++) {
493 if(fmask == LASTMASK) {
498 if(tmask == FIRSTMASK) {
504 fptr = bm_offset(fptr, bm->stride);
505 tptr = bm_offset(tptr, -nb.stride);
507 DEBUG((DBG_BITMAP_OPS, "flip_diagonally (%d,%d) -> (%d,%d)\n",
508 bm->width, bm->height, nb.width, nb.height));
512 bitmap_print(stderr, bm);
515 void bitmap_rotate_clockwise(BITMAP *bm)
522 nb.width = bm->height;
523 nb.height = bm->width;
524 nb.stride = BM_BYTES_PER_LINE(&nb);
525 nb.data = mdvi_calloc(nb.height, nb.stride);
528 tptr = __bm_unit_ptr(&nb, nb.width - 1, 0);
530 tmask = FIRSTMASKAT(nb.width-1);
531 for(h = 0; h < bm->height; h++) {
532 BmUnit *fline, *tline;
537 for(w = 0; w < bm->width; w++) {
540 if(fmask == LASTMASK) {
546 tline = bm_offset(tline, nb.stride);
548 fptr = bm_offset(fptr, bm->stride);
549 if(tmask == FIRSTMASK) {
556 DEBUG((DBG_BITMAP_OPS, "rotate_clockwise (%d,%d) -> (%d,%d)\n",
557 bm->width, bm->height, nb.width, nb.height));
560 bm->width = nb.width;
561 bm->height = nb.height;
562 bm->stride = nb.stride;
564 bitmap_print(stderr, bm);
567 void bitmap_rotate_counter_clockwise(BITMAP *bm)
574 nb.width = bm->height;
575 nb.height = bm->width;
576 nb.stride = BM_BYTES_PER_LINE(&nb);
577 nb.data = mdvi_calloc(nb.height, nb.stride);
580 tptr = __bm_unit_ptr(&nb, 0, nb.height - 1);
583 for(h = 0; h < bm->height; h++) {
584 BmUnit *fline, *tline;
589 for(w = 0; w < bm->width; w++) {
592 if(fmask == LASTMASK) {
597 /* go to previous row */
598 tline = bm_offset(tline, -nb.stride);
600 fptr = bm_offset(fptr, bm->stride);
601 if(tmask == LASTMASK) {
608 DEBUG((DBG_BITMAP_OPS, "rotate_counter_clockwise (%d,%d) -> (%d,%d)\n",
609 bm->width, bm->height, nb.width, nb.height));
612 bm->width = nb.width;
613 bm->height = nb.height;
614 bm->stride = nb.stride;
616 bitmap_print(stderr, bm);
619 void bitmap_flip_rotate_clockwise(BITMAP *bm)
626 nb.width = bm->height;
627 nb.height = bm->width;
628 nb.stride = BM_BYTES_PER_LINE(&nb);
629 nb.data = mdvi_calloc(nb.height, nb.stride);
632 tptr = __bm_unit_ptr(&nb, nb.width-1, nb.height-1);
634 tmask = FIRSTMASKAT(nb.width-1);
635 for(h = 0; h < bm->height; h++) {
636 BmUnit *fline, *tline;
641 for(w = 0; w < bm->width; w++) {
644 if(fmask == LASTMASK) {
649 /* go to previous line */
650 tline = bm_offset(tline, -nb.stride);
652 fptr = bm_offset(fptr, bm->stride);
653 if(tmask == FIRSTMASK) {
659 DEBUG((DBG_BITMAP_OPS, "flip_rotate_clockwise (%d,%d) -> (%d,%d)\n",
660 bm->width, bm->height, nb.width, nb.height));
663 bm->width = nb.width;
664 bm->height = nb.height;
665 bm->stride = nb.stride;
667 bitmap_print(stderr, bm);
670 void bitmap_flip_rotate_counter_clockwise(BITMAP *bm)
677 nb.width = bm->height;
678 nb.height = bm->width;
679 nb.stride = BM_BYTES_PER_LINE(&nb);
680 nb.data = mdvi_calloc(nb.height, nb.stride);
686 for(h = 0; h < bm->height; h++) {
687 BmUnit *fline, *tline;
692 for(w = 0; w < bm->width; w++) {
695 if(fmask == LASTMASK) {
700 /* go to next line */
701 tline = bm_offset(tline, nb.stride);
703 fptr = bm_offset(fptr, bm->stride);
704 if(tmask == LASTMASK) {
711 DEBUG((DBG_BITMAP_OPS, "flip_rotate_counter_clockwise (%d,%d) -> (%d,%d)\n",
712 bm->width, bm->height, nb.width, nb.height));
715 bm->width = nb.width;
716 bm->height = nb.height;
717 bm->stride = nb.stride;
719 bitmap_print(stderr, bm);
723 void bitmap_transform(BITMAP *map, DviOrientation orient)
726 case MDVI_ORIENT_TBLR:
728 case MDVI_ORIENT_TBRL:
729 bitmap_flip_horizontally(map);
731 case MDVI_ORIENT_BTLR:
732 bitmap_flip_vertically(map);
734 case MDVI_ORIENT_BTRL:
735 bitmap_flip_diagonally(map);
737 case MDVI_ORIENT_RP90:
738 bitmap_rotate_counter_clockwise(map);
740 case MDVI_ORIENT_RM90:
741 bitmap_rotate_clockwise(map);
743 case MDVI_ORIENT_IRP90:
744 bitmap_flip_rotate_counter_clockwise(map);
746 case MDVI_ORIENT_IRM90:
747 bitmap_flip_rotate_clockwise(map);
754 * Count the number of non-zero bits in a box of dimensions w x h, starting
755 * at column `step' in row `data'.
757 * Shamelessly stolen from xdvi.
759 static int do_sample(BmUnit *data, int stride, int step, int w, int h)
761 BmUnit *ptr, *end, *cp;
766 ptr = data + step / BITMAP_BITS;
767 end = bm_offset(data, h * stride);
768 shift = FIRSTSHIFTAT(step);
772 #ifndef WORD_BIG_ENDIAN
773 wid = BITMAP_BITS - shift;
781 #ifdef WORD_BIG_ENDIAN
784 for(cp = ptr; cp < end; cp = bm_offset(cp, stride))
785 n += sample_count[(*cp >> shift) & bit_masks[wid]];
786 #ifndef WORD_BIG_ENDIAN
789 #ifdef WORD_BIG_ENDIAN
795 if(shift == BITMAP_BITS) {
805 void mdvi_shrink_box(DviContext *dvi, DviFont *font,
806 DviFontChar *pk, DviGlyph *dest)
812 hs = dvi->params.hshrink;
813 vs = dvi->params.vshrink;
816 x = (int)glyph->x / hs;
817 if((int)glyph->x - x * hs > 0)
819 dest->w = x + ROUND((int)glyph->w - glyph->x, hs);
821 z = (int)glyph->y + 1;
825 dest->h = y + ROUND((int)glyph->h - z, vs) + 1;
827 dest->y = glyph->y / vs;
828 dest->data = MDVI_GLYPH_EMPTY;
829 DEBUG((DBG_BITMAPS, "shrink_box: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",
830 glyph->w, glyph->h, glyph->x, glyph->y,
831 dest->w, dest->h, dest->x, dest->y));
834 void mdvi_shrink_glyph(DviContext *dvi, DviFont *font,
835 DviFontChar *pk, DviGlyph *dest)
837 int rows_left, rows, init_cols;
839 BmUnit *old_ptr, *new_ptr;
840 BITMAP *oldmap, *newmap;
843 int sample, min_sample;
850 hs = dvi->params.hshrink;
851 vs = dvi->params.vshrink;
853 min_sample = vs * hs * dvi->params.density / 100;
856 oldmap = (BITMAP *)glyph->data;
858 x = (int)glyph->x / hs;
859 init_cols = (int)glyph->x - x * hs;
864 w = x + ROUND((int)glyph->w - glyph->x, hs);
866 cols = (int)glyph->y + 1;
868 rows = cols - y * vs;
873 h = y + ROUND((int)glyph->h - cols, vs) + 1;
875 /* create the new glyph */
876 newmap = bitmap_alloc(w, h);
879 dest->y = glyph->y / vs;
883 old_ptr = oldmap->data;
884 old_stride = oldmap->stride;
885 new_ptr = newmap->data;
886 new_stride = newmap->stride;
887 rows_left = glyph->h;
892 cols_left = glyph->w;
896 while(cols_left > 0) {
899 sample = do_sample(old_ptr, old_stride,
900 glyph->w - cols_left, cols, rows);
901 if(sample >= min_sample)
911 new_ptr = bm_offset(new_ptr, new_stride);
912 old_ptr = bm_offset(old_ptr, rows * old_stride);
916 DEBUG((DBG_BITMAPS, "shrink_glyph: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",
917 glyph->w, glyph->h, glyph->x, glyph->y,
918 dest->w, dest->h, dest->x, dest->y));
919 if(DEBUGGING(BITMAP_DATA))
920 bitmap_print(stderr, newmap);
923 void mdvi_shrink_glyph_grey(DviContext *dvi, DviFont *font,
924 DviFontChar *pk, DviGlyph *dest)
927 int cols_left, cols, init_cols;
928 long sampleval, samplemax;
941 hs = dvi->params.hshrink;
942 vs = dvi->params.vshrink;
946 map = (BITMAP *)glyph->data;
948 x = (int)glyph->x / hs;
949 init_cols = (int)glyph->x - x * hs;
954 w = x + ROUND((int)glyph->w - glyph->x, hs);
956 cols = (int)glyph->y + 1;
958 rows = cols - y * vs;
963 h = y + ROUND((int)glyph->h - cols, vs) + 1;
966 /* before touching anything, do this */
967 image = dev->create_image(dev->device_data, w, h, BITMAP_BITS);
969 mdvi_shrink_glyph(dvi, font, pk, dest);
973 /* save these colors */
974 pk->fg = MDVI_CURRFG(dvi);
975 pk->bg = MDVI_CURRBG(dvi);
978 npixels = samplemax + 1;
979 pixels = get_color_table(&dvi->device, npixels, pk->fg, pk->bg,
980 dvi->params.gamma, dvi->params.density);
983 colortab[0] = pk->fg;
984 colortab[1] = pk->bg;
985 pixels = &colortab[0];
988 /* setup the new glyph */
991 dest->y = glyph->y / vs;
997 rows_left = glyph->h;
999 while(rows_left && y < h) {
1001 if(rows > rows_left)
1003 cols_left = glyph->w;
1005 while(cols_left && x < w) {
1006 if(cols > cols_left)
1008 sampleval = do_sample(old_ptr, map->stride,
1009 glyph->w - cols_left, cols, rows);
1010 /* scale the sample value by the number of grey levels */
1011 if(npixels - 1 != samplemax)
1012 sampleval = ((npixels-1) * sampleval) / samplemax;
1013 ASSERT(sampleval < npixels);
1014 dev->put_pixel(image, x, y, pixels[sampleval]);
1020 dev->put_pixel(image, x, y, pixels[0]);
1021 old_ptr = bm_offset(old_ptr, rows * map->stride);
1028 for(x = 0; x < w; x++)
1029 dev->put_pixel(image, x, y, pixels[0]);
1031 DEBUG((DBG_BITMAPS, "shrink_glyph_grey: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",
1032 glyph->w, glyph->h, glyph->x, glyph->y,
1033 dest->w, dest->h, dest->x, dest->y));