Bug Summary

File:backend/dvi/mdvi-lib/bitmap.c
Warning:line 181, column 12
Array access (from variable 'unit') results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name bitmap.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/backend/dvi/mdvi-lib -fcoverage-compilation-dir=/rootdir/backend/dvi/mdvi-lib -resource-dir /usr/lib/llvm-21/lib/clang/21 -D HAVE_CONFIG_H -I . -I ../../.. -D PIC -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker security.ArrayBound -analyzer-checker unix.cstring.NotNullTerminated -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2026-04-13-164642-53075-1 -x c bitmap.c
1/*
2 * Copyright (C) 2000, Matias Atria
3 *
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.
8 *
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.
13 *
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.
17 */
18
19/* Bitmap manipulation routines */
20
21#include <config.h>
22#include <stdlib.h>
23
24#include "mdvi.h"
25#include "color.h"
26
27/* bit_masks[n] contains a BmUnit with `n' contiguous bits */
28
29static BmUnit bit_masks[] = {
30 0x0, 0x1, 0x3, 0x7,
31 0xf, 0x1f, 0x3f, 0x7f,
32 0xff,
33#if BITMAP_BYTES4 > 1
34 0x1ff, 0x3ff, 0x7ff,
35 0xfff, 0x1fff, 0x3fff, 0x7fff,
36 0xffff,
37#if BITMAP_BYTES4 > 2
38 0x1ffff, 0x3ffff, 0x7ffff,
39 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
40 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff,
41 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
42 0xffffffff
43#endif /* BITMAP_BYTES > 2 */
44#endif /* BITMAP_BYTES > 1 */
45};
46
47#ifndef NODEBUG
48#define SHOW_OP_DATA((_mdvi_debug_mask & (1 << 12)) && (_mdvi_debug_mask
& (1 << 13)))
(DEBUGGING(BITMAP_OPS)(_mdvi_debug_mask & (1 << 12)) && DEBUGGING(BITMAP_DATA)(_mdvi_debug_mask & (1 << 13)))
49#endif
50
51/*
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.
56 */
57#ifdef WORD_BIG_ENDIAN
58#define SEGMENT(m,n)(bit_masks[m] << (n)) (bit_masks[m] << (BITMAP_BITS(4 << 3) - (m) - (n)))
59#else
60#define SEGMENT(m,n)(bit_masks[m] << (n)) (bit_masks[m] << (n))
61#endif
62
63/* sampling and shrinking routines shamelessly stolen from xdvi */
64
65static 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
82};
83
84/* bit_swap[j] = j with all bits inverted (i.e. msb -> lsb) */
85static 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
118};
119
120
121/*
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
125 * hopelessly slow.
126 */
127
128BITMAP *bitmap_convert_lsb8(Uchar *bits, int w, int h, int stride)
129{
130 BITMAP *bm;
131 int i;
132 Uchar *unit;
133 register Uchar *curr;
134 int bytes;
135
136 DEBUG((DBG_BITMAP_OPS, "convert LSB %dx%d@8 -> bitmap\n", w, h))__debug ((1 << 12), "convert LSB %dx%d@8 -> bitmap\n"
, w, h)
;
137
138 bm = bitmap_alloc_raw(w, h);
139
140 /* this is the number of bytes in the original bitmap */
141 bytes = ROUND(w, 8)(((w) + (8) - 1) / (8));
142 unit = (Uchar *)bm->data;
143 curr = bits;
144 /* we try to do this as fast as we can */
145 for(i = 0; i < h; i++) {
146#ifdef WORD_LITTLE_ENDIAN1
147 memcpy(unit, curr, bytes);
148 curr += stride;
149#else
150 int j;
151
152 for(j = 0; j < bytes; curr++, j++)
153 unit[j] = bit_swap[*curr];
154 cur += stride - bytes;
155#endif
156 memzero(unit + bytes, bm->stride - bytes)memset((unit + bytes), 0, (bm->stride - bytes));
157 unit += bm->stride;
158 }
159 if(SHOW_OP_DATA((_mdvi_debug_mask & (1 << 12)) && (_mdvi_debug_mask
& (1 << 13)))
)
160 bitmap_print(stderrstderr, bm);
161 return bm;
162}
163
164BITMAP *bitmap_convert_msb8(Uchar *data, int w, int h, int stride)
165{
166 BITMAP *bm;
167 Uchar *unit;
168 Uchar *curr;
169 int i;
170 int bytes;
171
172 bm = bitmap_alloc(w, h);
1
Calling 'bitmap_alloc'
6
Returning from 'bitmap_alloc'
173 bytes = ROUND(w, 8)(((w) + (8) - 1) / (8));
174 unit = (Uchar *)bm->data;
7
Null pointer value stored to 'unit'
175 curr = data;
176 for(i = 0; i < h; i++) {
8
Assuming 'i' is < 'h'
9
Loop condition is true. Entering loop body
177#ifdef WORD_LITTLE_ENDIAN1
178 int j;
179
180 for(j = 0; j < bytes; curr++, j++)
10
Assuming 'j' is < 'bytes'
11
Loop condition is true. Entering loop body
181 unit[j] = bit_swap[*curr];
12
Array access (from variable 'unit') results in a null pointer dereference
182 curr += stride - bytes;
183#else
184 memcpy(unit, curr, bytes);
185 curr += stride;
186#endif
187 memzero(unit + bytes, bm->stride - bytes)memset((unit + bytes), 0, (bm->stride - bytes));
188 unit += bm->stride;
189 }
190 if(SHOW_OP_DATA((_mdvi_debug_mask & (1 << 12)) && (_mdvi_debug_mask
& (1 << 13)))
)
191 bitmap_print(stderrstderr, bm);
192 return bm;
193}
194
195
196BITMAP *bitmap_copy(BITMAP *bm)
197{
198 BITMAP *nb = bitmap_alloc(bm->width, bm->height);
199
200 DEBUG((DBG_BITMAP_OPS, "copy %dx%d\n", bm->width, bm->height))__debug ((1 << 12), "copy %dx%d\n", bm->width, bm->
height)
;
201 memcpy(nb->data, bm->data, bm->height * bm->stride);
202 return nb;
203}
204
205BITMAP *bitmap_alloc(int w, int h)
206{
207 BITMAP *bm;
208
209 bm = xalloc(BITMAP)(BITMAP *)mdvi_malloc(sizeof(BITMAP));
210 bm->width = w;
211 bm->height = h;
212 bm->stride = BM_BYTES_PER_LINE(bm)(((((bm)->width) + ((4 << 3)) - 1) / ((4 << 3)
)) * 4)
;
213 if(h && bm->stride)
2
Assuming 'h' is not equal to 0
3
Assuming field 'stride' is 0
4
Taking false branch
214 bm->data = (BmUnit *)mdvi_calloc(h, bm->stride);
215 else
216 bm->data = NULL((void*)0);
5
Null pointer value stored to field 'data'
217
218 return bm;
219}
220
221BITMAP *bitmap_alloc_raw(int w, int h)
222{
223 BITMAP *bm;
224
225 bm = xalloc(BITMAP)(BITMAP *)mdvi_malloc(sizeof(BITMAP));
226 bm->width = w;
227 bm->height = h;
228 bm->stride = BM_BYTES_PER_LINE(bm)(((((bm)->width) + ((4 << 3)) - 1) / ((4 << 3)
)) * 4)
;
229 if(h && bm->stride)
230 bm->data = (BmUnit *)mdvi_malloc(h * bm->stride);
231 else
232 bm->data = NULL((void*)0);
233
234 return bm;
235}
236
237void bitmap_destroy(BITMAP *bm)
238{
239 if(bm->data)
240 free(bm->data);
241 free(bm);
242}
243
244void bitmap_print(FILE *out, BITMAP *bm)
245{
246 int i, j;
247 BmUnit *a, mask;
248 static const char labels[] = {
249 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
250 };
251 int sub;
252
253 a = bm->data;
254 fprintf(out, " ");
255 if(bm->width > 10) {
256 putchar('0');
257 sub = 0;
258 for(j = 2; j <= bm->width; j++)
259 if((j %10) == 0) {
260 if((j % 100) == 0) {
261 fprintf(out, "*");
262 sub += 100;
263 } else
264 fprintf(out, "%d", (j - sub)/10);
265 } else
266 putc(' ', out);
267 fprintf(out, "\n ");
268 }
269 for(j = 0; j < bm->width; j++)
270 putc(labels[j % 10], out);
271 putchar('\n');
272 for(i = 0; i < bm->height; i++) {
273 mask = FIRSTMASK((BmUnit)1 << (0));
274 a = (BmUnit *)((char *)bm->data + i * bm->stride);
275 fprintf(out, "%3d ", i+1);
276 for(j = 0; j < bm->width; j++) {
277 if(*a & mask)
278 putc('#', out);
279 else
280 putc('.', out);
281 if(mask == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
282 a++;
283 mask = FIRSTMASK((BmUnit)1 << (0));
284 } else
285 NEXTMASK(mask)((mask) <<= 1);
286 }
287 putchar('\n');
288 }
289}
290
291void bitmap_set_col(BITMAP *bm, int row, int col, int count, int state)
292{
293 BmUnit *ptr;
294 BmUnit mask;
295
296 ptr = __bm_unit_ptr(bm, col, row)(BmUnit *)((Uchar *)((bm)->data) + ((row) * (bm)->stride
+ ((col) / (4 << 3)) * 4))
;
297 mask = FIRSTMASKAT(col)((BmUnit)1 << (((col) % (4 << 3))));
298
299 while(count-- > 0) {
300 if(state)
301 *ptr |= mask;
302 else
303 *ptr &= ~mask;
304 /* move to next row */
305 ptr = bm_offset(ptr, bm->stride)(BmUnit *)((Uchar *)(ptr) + (bm->stride));
306 }
307}
308
309/*
310 * to use this function you should first make sure that
311 * there is room for `count' bits in the scanline
312 *
313 * A general-purpose (but not very efficient) function to paint `n' pixels
314 * on a bitmap, starting at position (x, y) would be:
315 *
316 * bitmap_paint_bits(__bm_unit_ptr(bitmap, x, y), x % BITMAP_BITS, n)
317 *
318 */
319void bitmap_paint_bits(BmUnit *ptr, int n, int count)
320{
321 /* paint the head */
322 if(n + count > BITMAP_BITS(4 << 3)) {
323 *ptr |= SEGMENT(BITMAP_BITS - n, n)(bit_masks[(4 << 3) - n] << (n));
324 count -= BITMAP_BITS(4 << 3) - n;
325 ptr++;
326 } else {
327 *ptr |= SEGMENT(count, n)(bit_masks[count] << (n));
328 return;
329 }
330
331 /* paint the middle */
332 for(; count >= BITMAP_BITS(4 << 3); count -= BITMAP_BITS(4 << 3))
333 *ptr++ = bit_masks[BITMAP_BITS(4 << 3)];
334
335 /* paint the tail */
336 if(count > 0)
337 *ptr |= SEGMENT(count, 0)(bit_masks[count] << (0));
338}
339
340/*
341 * same as paint_bits but clears pixels instead of painting them. Written
342 * as a separate function for efficiency reasons.
343 */
344void bitmap_clear_bits(BmUnit *ptr, int n, int count)
345{
346 if(n + count > BITMAP_BITS(4 << 3)) {
347 *ptr &= ~SEGMENT(BITMAP_BITS - n, n)(bit_masks[(4 << 3) - n] << (n));
348 count -= BITMAP_BITS(4 << 3);
349 ptr++;
350 } else {
351 *ptr &= ~SEGMENT(count, n)(bit_masks[count] << (n));
352 return;
353 }
354
355 for(; count >= BITMAP_BITS(4 << 3); count -= BITMAP_BITS(4 << 3))
356 *ptr++ = 0;
357
358 if(count > 0)
359 *ptr &= ~SEGMENT(count, 0)(bit_masks[count] << (0));
360}
361
362/* the general function to paint rows. Still used by the PK reader, but that
363 * will change soon (The GF reader already uses bitmap_paint_bits()).
364 */
365void bitmap_set_row(BITMAP *bm, int row, int col, int count, int state)
366{
367 BmUnit *ptr;
368
369 ptr = __bm_unit_ptr(bm, col, row)(BmUnit *)((Uchar *)((bm)->data) + ((row) * (bm)->stride
+ ((col) / (4 << 3)) * 4))
;
370 if(state)
371 bitmap_paint_bits(ptr, col & (BITMAP_BITS(4 << 3)-1), count);
372 else
373 bitmap_clear_bits(ptr, col & (BITMAP_BITS(4 << 3)-1), count);
374}
375
376/*
377 * Now several `flipping' operations
378 */
379
380void bitmap_flip_horizontally(BITMAP *bm)
381{
382 BITMAP nb;
383 BmUnit *fptr, *tptr;
384 BmUnit fmask, tmask;
385 int w, h;
386
387 nb.width = bm->width;
388 nb.height = bm->height;
389 nb.stride = bm->stride;
390 nb.data = mdvi_calloc(bm->height, bm->stride);
391
392 fptr = bm->data;
393 tptr = __bm_unit_ptr(&nb, nb.width-1, 0)(BmUnit *)((Uchar *)((&nb)->data) + ((0) * (&nb)->
stride + ((nb.width-1) / (4 << 3)) * 4))
;
394 for(h = 0; h < bm->height; h++) {
395 BmUnit *fline, *tline;
396
397 fline = fptr;
398 tline = tptr;
399 fmask = FIRSTMASK((BmUnit)1 << (0));
400 tmask = FIRSTMASKAT(nb.width-1)((BmUnit)1 << (((nb.width-1) % (4 << 3))));
401 for(w = 0; w < bm->width; w++) {
402 if(*fline & fmask)
403 *tline |= tmask;
404 if(fmask == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
405 fmask = FIRSTMASK((BmUnit)1 << (0));
406 fline++;
407 } else
408 NEXTMASK(fmask)((fmask) <<= 1);
409 if(tmask == FIRSTMASK((BmUnit)1 << (0))) {
410 tmask = LASTMASK((BmUnit)1 << (((4 << 3) - 1)));
411 tline--;
412 } else
413 PREVMASK(tmask)((tmask) >>= 1);
414 }
415 fptr = bm_offset(fptr, bm->stride)(BmUnit *)((Uchar *)(fptr) + (bm->stride));
416 tptr = bm_offset(tptr, bm->stride)(BmUnit *)((Uchar *)(tptr) + (bm->stride));
417 }
418 DEBUG((DBG_BITMAP_OPS, "flip_horizontally (%d,%d) -> (%d,%d)\n",__debug ((1 << 12), "flip_horizontally (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
419 bm->width, bm->height, nb.width, nb.height))__debug ((1 << 12), "flip_horizontally (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
;
420 mdvi_free(bm->data);
421 bm->data = nb.data;
422 if(SHOW_OP_DATA((_mdvi_debug_mask & (1 << 12)) && (_mdvi_debug_mask
& (1 << 13)))
)
423 bitmap_print(stderrstderr, bm);
424}
425
426void bitmap_flip_vertically(BITMAP *bm)
427{
428 BITMAP nb;
429 BmUnit *fptr, *tptr;
430 BmUnit fmask;
431 int w, h;
432
433 nb.width = bm->width;
434 nb.height = bm->height;
435 nb.stride = bm->stride;
436 nb.data = mdvi_calloc(bm->height, bm->stride);
437
438 fptr = bm->data;
439 tptr = __bm_unit_ptr(&nb, 0, nb.height-1)(BmUnit *)((Uchar *)((&nb)->data) + ((nb.height-1) * (
&nb)->stride + ((0) / (4 << 3)) * 4))
;
440 for(h = 0; h < bm->height; h++) {
441 BmUnit *fline, *tline;
442
443 fline = fptr;
444 tline = tptr;
445 fmask = FIRSTMASK((BmUnit)1 << (0));
446 for(w = 0; w < bm->width; w++) {
447 if(*fline & fmask)
448 *tline |= fmask;
449 if(fmask == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
450 fmask = FIRSTMASK((BmUnit)1 << (0));
451 fline++;
452 tline++;
453 } else
454 NEXTMASK(fmask)((fmask) <<= 1);
455 }
456 fptr = bm_offset(fptr, bm->stride)(BmUnit *)((Uchar *)(fptr) + (bm->stride));
457 tptr = (BmUnit *)((char *)tptr - bm->stride);
458 }
459 DEBUG((DBG_BITMAP_OPS, "flip_vertically (%d,%d) -> (%d,%d)\n",__debug ((1 << 12), "flip_vertically (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
460 bm->width, bm->height, nb.width, nb.height))__debug ((1 << 12), "flip_vertically (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
;
461 mdvi_free(bm->data);
462 bm->data = nb.data;
463 if(SHOW_OP_DATA((_mdvi_debug_mask & (1 << 12)) && (_mdvi_debug_mask
& (1 << 13)))
)
464 bitmap_print(stderrstderr, bm);
465}
466
467void bitmap_flip_diagonally(BITMAP *bm)
468{
469 BITMAP nb;
470 BmUnit *fptr, *tptr;
471 BmUnit fmask, tmask;
472 int w, h;
473
474 nb.width = bm->width;
475 nb.height = bm->height;
476 nb.stride = bm->stride;
477 nb.data = mdvi_calloc(bm->height, bm->stride);
478
479 fptr = bm->data;
480 tptr = __bm_unit_ptr(&nb, nb.width-1, nb.height-1)(BmUnit *)((Uchar *)((&nb)->data) + ((nb.height-1) * (
&nb)->stride + ((nb.width-1) / (4 << 3)) * 4))
;
481 for(h = 0; h < bm->height; h++) {
482 BmUnit *fline, *tline;
483
484 fline = fptr;
485 tline = tptr;
486 fmask = FIRSTMASK((BmUnit)1 << (0));
487 tmask = FIRSTMASKAT(nb.width-1)((BmUnit)1 << (((nb.width-1) % (4 << 3))));
488 for(w = 0; w < bm->width; w++) {
489 if(*fline & fmask)
490 *tline |= tmask;
491 if(fmask == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
492 fmask = FIRSTMASK((BmUnit)1 << (0));
493 fline++;
494 } else
495 NEXTMASK(fmask)((fmask) <<= 1);
496 if(tmask == FIRSTMASK((BmUnit)1 << (0))) {
497 tmask = LASTMASK((BmUnit)1 << (((4 << 3) - 1)));
498 tline--;
499 } else
500 PREVMASK(tmask)((tmask) >>= 1);
501 }
502 fptr = bm_offset(fptr, bm->stride)(BmUnit *)((Uchar *)(fptr) + (bm->stride));
503 tptr = bm_offset(tptr, -nb.stride)(BmUnit *)((Uchar *)(tptr) + (-nb.stride));
504 }
505 DEBUG((DBG_BITMAP_OPS, "flip_diagonally (%d,%d) -> (%d,%d)\n",__debug ((1 << 12), "flip_diagonally (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
506 bm->width, bm->height, nb.width, nb.height))__debug ((1 << 12), "flip_diagonally (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
;
507 mdvi_free(bm->data);
508 bm->data = nb.data;
509 if(SHOW_OP_DATA((_mdvi_debug_mask & (1 << 12)) && (_mdvi_debug_mask
& (1 << 13)))
)
510 bitmap_print(stderrstderr, bm);
511}
512
513void bitmap_rotate_clockwise(BITMAP *bm)
514{
515 BITMAP nb;
516 BmUnit *fptr, *tptr;
517 BmUnit fmask, tmask;
518 int w, h;
519
520 nb.width = bm->height;
521 nb.height = bm->width;
522 nb.stride = BM_BYTES_PER_LINE(&nb)(((((&nb)->width) + ((4 << 3)) - 1) / ((4 <<
3))) * 4)
;
523 nb.data = mdvi_calloc(nb.height, nb.stride);
524
525 fptr = bm->data;
526 tptr = __bm_unit_ptr(&nb, nb.width - 1, 0)(BmUnit *)((Uchar *)((&nb)->data) + ((0) * (&nb)->
stride + ((nb.width - 1) / (4 << 3)) * 4))
;
527
528 tmask = FIRSTMASKAT(nb.width-1)((BmUnit)1 << (((nb.width-1) % (4 << 3))));
529 for(h = 0; h < bm->height; h++) {
530 BmUnit *fline, *tline;
531
532 fmask = FIRSTMASK((BmUnit)1 << (0));
533 fline = fptr;
534 tline = tptr;
535 for(w = 0; w < bm->width; w++) {
536 if(*fline & fmask)
537 *tline |= tmask;
538 if(fmask == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
539 fmask = FIRSTMASK((BmUnit)1 << (0));
540 fline++;
541 } else
542 NEXTMASK(fmask)((fmask) <<= 1);
543 /* go to next row */
544 tline = bm_offset(tline, nb.stride)(BmUnit *)((Uchar *)(tline) + (nb.stride));
545 }
546 fptr = bm_offset(fptr, bm->stride)(BmUnit *)((Uchar *)(fptr) + (bm->stride));
547 if(tmask == FIRSTMASK((BmUnit)1 << (0))) {
548 tmask = LASTMASK((BmUnit)1 << (((4 << 3) - 1)));
549 tptr--;
550 } else
551 PREVMASK(tmask)((tmask) >>= 1);
552 }
553
554 DEBUG((DBG_BITMAP_OPS, "rotate_clockwise (%d,%d) -> (%d,%d)\n",__debug ((1 << 12), "rotate_clockwise (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
555 bm->width, bm->height, nb.width, nb.height))__debug ((1 << 12), "rotate_clockwise (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
;
556 mdvi_free(bm->data);
557 bm->data = nb.data;
558 bm->width = nb.width;
559 bm->height = nb.height;
560 bm->stride = nb.stride;
561 if(SHOW_OP_DATA((_mdvi_debug_mask & (1 << 12)) && (_mdvi_debug_mask
& (1 << 13)))
)
562 bitmap_print(stderrstderr, bm);
563}
564
565void bitmap_rotate_counter_clockwise(BITMAP *bm)
566{
567 BITMAP nb;
568 BmUnit *fptr, *tptr;
569 BmUnit fmask, tmask;
570 int w, h;
571
572 nb.width = bm->height;
573 nb.height = bm->width;
574 nb.stride = BM_BYTES_PER_LINE(&nb)(((((&nb)->width) + ((4 << 3)) - 1) / ((4 <<
3))) * 4)
;
575 nb.data = mdvi_calloc(nb.height, nb.stride);
576
577 fptr = bm->data;
578 tptr = __bm_unit_ptr(&nb, 0, nb.height - 1)(BmUnit *)((Uchar *)((&nb)->data) + ((nb.height - 1) *
(&nb)->stride + ((0) / (4 << 3)) * 4))
;
579
580 tmask = FIRSTMASK((BmUnit)1 << (0));
581 for(h = 0; h < bm->height; h++) {
582 BmUnit *fline, *tline;
583
584 fmask = FIRSTMASK((BmUnit)1 << (0));
585 fline = fptr;
586 tline = tptr;
587 for(w = 0; w < bm->width; w++) {
588 if(*fline & fmask)
589 *tline |= tmask;
590 if(fmask == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
591 fmask = FIRSTMASK((BmUnit)1 << (0));
592 fline++;
593 } else
594 NEXTMASK(fmask)((fmask) <<= 1);
595 /* go to previous row */
596 tline = bm_offset(tline, -nb.stride)(BmUnit *)((Uchar *)(tline) + (-nb.stride));
597 }
598 fptr = bm_offset(fptr, bm->stride)(BmUnit *)((Uchar *)(fptr) + (bm->stride));
599 if(tmask == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
600 tmask = FIRSTMASK((BmUnit)1 << (0));
601 tptr++;
602 } else
603 NEXTMASK(tmask)((tmask) <<= 1);
604 }
605
606 DEBUG((DBG_BITMAP_OPS, "rotate_counter_clockwise (%d,%d) -> (%d,%d)\n",__debug ((1 << 12), "rotate_counter_clockwise (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
607 bm->width, bm->height, nb.width, nb.height))__debug ((1 << 12), "rotate_counter_clockwise (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
;
608 mdvi_free(bm->data);
609 bm->data = nb.data;
610 bm->width = nb.width;
611 bm->height = nb.height;
612 bm->stride = nb.stride;
613 if(SHOW_OP_DATA((_mdvi_debug_mask & (1 << 12)) && (_mdvi_debug_mask
& (1 << 13)))
)
614 bitmap_print(stderrstderr, bm);
615}
616
617void bitmap_flip_rotate_clockwise(BITMAP *bm)
618{
619 BITMAP nb;
620 BmUnit *fptr, *tptr;
621 BmUnit fmask, tmask;
622 int w, h;
623
624 nb.width = bm->height;
625 nb.height = bm->width;
626 nb.stride = BM_BYTES_PER_LINE(&nb)(((((&nb)->width) + ((4 << 3)) - 1) / ((4 <<
3))) * 4)
;
627 nb.data = mdvi_calloc(nb.height, nb.stride);
628
629 fptr = bm->data;
630 tptr = __bm_unit_ptr(&nb, nb.width-1, nb.height-1)(BmUnit *)((Uchar *)((&nb)->data) + ((nb.height-1) * (
&nb)->stride + ((nb.width-1) / (4 << 3)) * 4))
;
631
632 tmask = FIRSTMASKAT(nb.width-1)((BmUnit)1 << (((nb.width-1) % (4 << 3))));
633 for(h = 0; h < bm->height; h++) {
634 BmUnit *fline, *tline;
635
636 fmask = FIRSTMASK((BmUnit)1 << (0));
637 fline = fptr;
638 tline = tptr;
639 for(w = 0; w < bm->width; w++) {
640 if(*fline & fmask)
641 *tline |= tmask;
642 if(fmask == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
643 fmask = FIRSTMASK((BmUnit)1 << (0));
644 fline++;
645 } else
646 NEXTMASK(fmask)((fmask) <<= 1);
647 /* go to previous line */
648 tline = bm_offset(tline, -nb.stride)(BmUnit *)((Uchar *)(tline) + (-nb.stride));
649 }
650 fptr = bm_offset(fptr, bm->stride)(BmUnit *)((Uchar *)(fptr) + (bm->stride));
651 if(tmask == FIRSTMASK((BmUnit)1 << (0))) {
652 tmask = LASTMASK((BmUnit)1 << (((4 << 3) - 1)));
653 tptr--;
654 } else
655 PREVMASK(tmask)((tmask) >>= 1);
656 }
657 DEBUG((DBG_BITMAP_OPS, "flip_rotate_clockwise (%d,%d) -> (%d,%d)\n",__debug ((1 << 12), "flip_rotate_clockwise (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
658 bm->width, bm->height, nb.width, nb.height))__debug ((1 << 12), "flip_rotate_clockwise (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
;
659 mdvi_free(bm->data);
660 bm->data = nb.data;
661 bm->width = nb.width;
662 bm->height = nb.height;
663 bm->stride = nb.stride;
664 if(SHOW_OP_DATA((_mdvi_debug_mask & (1 << 12)) && (_mdvi_debug_mask
& (1 << 13)))
)
665 bitmap_print(stderrstderr, bm);
666}
667
668void bitmap_flip_rotate_counter_clockwise(BITMAP *bm)
669{
670 BITMAP nb;
671 BmUnit *fptr, *tptr;
672 BmUnit fmask, tmask;
673 int w, h;
674
675 nb.width = bm->height;
676 nb.height = bm->width;
677 nb.stride = BM_BYTES_PER_LINE(&nb)(((((&nb)->width) + ((4 << 3)) - 1) / ((4 <<
3))) * 4)
;
678 nb.data = mdvi_calloc(nb.height, nb.stride);
679
680 fptr = bm->data;
681 tptr = nb.data;
682 tmask = FIRSTMASK((BmUnit)1 << (0));
683
684 for(h = 0; h < bm->height; h++) {
685 BmUnit *fline, *tline;
686
687 fmask = FIRSTMASK((BmUnit)1 << (0));
688 fline = fptr;
689 tline = tptr;
690 for(w = 0; w < bm->width; w++) {
691 if(*fline & fmask)
692 *tline |= tmask;
693 if(fmask == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
694 fmask = FIRSTMASK((BmUnit)1 << (0));
695 fline++;
696 } else
697 NEXTMASK(fmask)((fmask) <<= 1);
698 /* go to next line */
699 tline = bm_offset(tline, nb.stride)(BmUnit *)((Uchar *)(tline) + (nb.stride));
700 }
701 fptr = bm_offset(fptr, bm->stride)(BmUnit *)((Uchar *)(fptr) + (bm->stride));
702 if(tmask == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
703 tmask = FIRSTMASK((BmUnit)1 << (0));
704 tptr++;
705 } else
706 NEXTMASK(tmask)((tmask) <<= 1);
707 }
708
709 DEBUG((DBG_BITMAP_OPS, "flip_rotate_counter_clockwise (%d,%d) -> (%d,%d)\n",__debug ((1 << 12), "flip_rotate_counter_clockwise (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
710 bm->width, bm->height, nb.width, nb.height))__debug ((1 << 12), "flip_rotate_counter_clockwise (%d,%d) -> (%d,%d)\n"
, bm->width, bm->height, nb.width, nb.height)
;
711 mdvi_free(bm->data);
712 bm->data = nb.data;
713 bm->width = nb.width;
714 bm->height = nb.height;
715 bm->stride = nb.stride;
716 if(SHOW_OP_DATA((_mdvi_debug_mask & (1 << 12)) && (_mdvi_debug_mask
& (1 << 13)))
)
717 bitmap_print(stderrstderr, bm);
718}
719
720#if 0
721void bitmap_transform(BITMAP *map, DviOrientation orient)
722{
723 switch(orient) {
724 case MDVI_ORIENT_TBLR:
725 break;
726 case MDVI_ORIENT_TBRL:
727 bitmap_flip_horizontally(map);
728 break;
729 case MDVI_ORIENT_BTLR:
730 bitmap_flip_vertically(map);
731 break;
732 case MDVI_ORIENT_BTRL:
733 bitmap_flip_diagonally(map);
734 break;
735 case MDVI_ORIENT_RP90:
736 bitmap_rotate_counter_clockwise(map);
737 break;
738 case MDVI_ORIENT_RM90:
739 bitmap_rotate_clockwise(map);
740 break;
741 case MDVI_ORIENT_IRP90:
742 bitmap_flip_rotate_counter_clockwise(map);
743 break;
744 case MDVI_ORIENT_IRM90:
745 bitmap_flip_rotate_clockwise(map);
746 break;
747 }
748}
749#endif
750
751/*
752 * Count the number of non-zero bits in a box of dimensions w x h, starting
753 * at column `step' in row `data'.
754 *
755 * Shamelessly stolen from xdvi.
756 */
757static int do_sample(BmUnit *data, int stride, int step, int w, int h)
758{
759 BmUnit *ptr, *end, *cp;
760 int shift, n;
761 int bits_left;
762 int wid;
763
764 ptr = data + step / BITMAP_BITS(4 << 3);
765 end = bm_offset(data, h * stride)(BmUnit *)((Uchar *)(data) + (h * stride));
766 shift = FIRSTSHIFTAT(step)((step) % (4 << 3));
767 bits_left = w;
768 n = 0;
769 while(bits_left) {
770#ifndef WORD_BIG_ENDIAN
771 wid = BITMAP_BITS(4 << 3) - shift;
772#else
773 wid = shift;
774#endif
775 if(wid > bits_left)
776 wid = bits_left;
777 if(wid > 8)
778 wid = 8;
779#ifdef WORD_BIG_ENDIAN
780 shift -= wid;
781#endif
782 for(cp = ptr; cp < end; cp = bm_offset(cp, stride)(BmUnit *)((Uchar *)(cp) + (stride)))
783 n += sample_count[(*cp >> shift) & bit_masks[wid]];
784#ifndef WORD_BIG_ENDIAN
785 shift += wid;
786#endif
787#ifdef WORD_BIG_ENDIAN
788 if(shift == 0) {
789 shift = BITMAP_BITS(4 << 3);
790 ptr++;
791 }
792#else
793 if(shift == BITMAP_BITS(4 << 3)) {
794 shift = 0;
795 ptr++;
796 }
797#endif
798 bits_left -= wid;
799 }
800 return n;
801}
802
803void
804mdvi_shrink_box (DviContext *dvi,
805 DviFont *font GNUC_UNUSED__attribute__ ((__unused__)),
806 DviFontChar *pk,
807 DviGlyph *dest)
808{
809 int x, y, z;
810 DviGlyph *glyph;
811 int hs, vs;
812
813 hs = dvi->params.hshrink;
814 vs = dvi->params.vshrink;
815 glyph = &pk->glyph;
816
817 x = (int)glyph->x / hs;
818 if((int)glyph->x - x * hs > 0)
819 x++;
820 dest->w = x + ROUND((int)glyph->w - glyph->x, hs)((((int)glyph->w - glyph->x) + (hs) - 1) / (hs));
821
822 z = (int)glyph->y + 1;
823 y = z / vs;
824 if(z - y * vs <= 0)
825 y--;
826 dest->h = y + ROUND((int)glyph->h - z, vs)((((int)glyph->h - z) + (vs) - 1) / (vs)) + 1;
827 dest->x = x;
828 dest->y = glyph->y / vs;
829 dest->data = MDVI_GLYPH_EMPTY((void *)1);
830 DEBUG((DBG_BITMAPS, "shrink_box: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",__debug ((1 << 8), "shrink_box: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n"
, glyph->w, glyph->h, glyph->x, glyph->y, dest->
w, dest->h, dest->x, dest->y)
831 glyph->w, glyph->h, glyph->x, glyph->y,__debug ((1 << 8), "shrink_box: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n"
, glyph->w, glyph->h, glyph->x, glyph->y, dest->
w, dest->h, dest->x, dest->y)
832 dest->w, dest->h, dest->x, dest->y))__debug ((1 << 8), "shrink_box: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n"
, glyph->w, glyph->h, glyph->x, glyph->y, dest->
w, dest->h, dest->x, dest->y)
;
833}
834
835void
836mdvi_shrink_glyph (DviContext *dvi,
837 DviFont *font GNUC_UNUSED__attribute__ ((__unused__)),
838 DviFontChar *pk,
839 DviGlyph *dest)
840{
841 int rows_left, rows, init_cols;
842 int cols_left, cols;
843 BmUnit *old_ptr, *new_ptr;
844 BITMAP *oldmap, *newmap;
845 BmUnit m, *cp;
846 DviGlyph *glyph;
847 int sample, min_sample;
848 int old_stride;
849 int new_stride;
850 int x, y;
851 int w, h;
852 int hs, vs;
853
854 hs = dvi->params.hshrink;
855 vs = dvi->params.vshrink;
856
857 min_sample = vs * hs * dvi->params.density / 100;
858
859 glyph = &pk->glyph;
860 oldmap = (BITMAP *)glyph->data;
861
862 x = (int)glyph->x / hs;
863 init_cols = (int)glyph->x - x * hs;
864 if(init_cols <= 0)
865 init_cols += hs;
866 else
867 x++;
868 w = x + ROUND((int)glyph->w - glyph->x, hs)((((int)glyph->w - glyph->x) + (hs) - 1) / (hs));
869
870 cols = (int)glyph->y + 1;
871 y = cols / vs;
872 rows = cols - y * vs;
873 if(rows <= 0) {
874 rows += vs;
875 y--;
876 }
877 h = y + ROUND((int)glyph->h - cols, vs)((((int)glyph->h - cols) + (vs) - 1) / (vs)) + 1;
878
879 /* create the new glyph */
880 newmap = bitmap_alloc(w, h);
881 dest->data = newmap;
882 dest->x = x;
883 dest->y = glyph->y / vs;
884 dest->w = w;
885 dest->h = h;
886
887 old_ptr = oldmap->data;
888 old_stride = oldmap->stride;
889 new_ptr = newmap->data;
890 new_stride = newmap->stride;
891 rows_left = glyph->h;
892
893 while(rows_left) {
894 if(rows > rows_left)
895 rows = rows_left;
896 cols_left = glyph->w;
897 m = FIRSTMASK((BmUnit)1 << (0));
898 cp = new_ptr;
899 cols = init_cols;
900 while(cols_left > 0) {
901 if(cols > cols_left)
902 cols = cols_left;
903 sample = do_sample(old_ptr, old_stride,
904 glyph->w - cols_left, cols, rows);
905 if(sample >= min_sample)
906 *cp |= m;
907 if(m == LASTMASK((BmUnit)1 << (((4 << 3) - 1)))) {
908 m = FIRSTMASK((BmUnit)1 << (0));
909 cp++;
910 } else
911 NEXTMASK(m)((m) <<= 1);
912 cols_left -= cols;
913 cols = hs;
914 }
915 new_ptr = bm_offset(new_ptr, new_stride)(BmUnit *)((Uchar *)(new_ptr) + (new_stride));
916 old_ptr = bm_offset(old_ptr, rows * old_stride)(BmUnit *)((Uchar *)(old_ptr) + (rows * old_stride));
917 rows_left -= rows;
918 rows = vs;
919 }
920 DEBUG((DBG_BITMAPS, "shrink_glyph: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",__debug ((1 << 8), "shrink_glyph: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n"
, glyph->w, glyph->h, glyph->x, glyph->y, dest->
w, dest->h, dest->x, dest->y)
921 glyph->w, glyph->h, glyph->x, glyph->y,__debug ((1 << 8), "shrink_glyph: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n"
, glyph->w, glyph->h, glyph->x, glyph->y, dest->
w, dest->h, dest->x, dest->y)
922 dest->w, dest->h, dest->x, dest->y))__debug ((1 << 8), "shrink_glyph: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n"
, glyph->w, glyph->h, glyph->x, glyph->y, dest->
w, dest->h, dest->x, dest->y)
;
923 if(DEBUGGING(BITMAP_DATA)(_mdvi_debug_mask & (1 << 13)))
924 bitmap_print(stderrstderr, newmap);
925}
926
927void mdvi_shrink_glyph_grey(DviContext *dvi, DviFont *font,
928 DviFontChar *pk, DviGlyph *dest)
929{
930 int rows_left, rows;
931 int cols_left, cols, init_cols;
932 long sampleval, samplemax;
933 BmUnit *old_ptr;
934 void *image;
935 int w, h;
936 int x, y;
937 DviGlyph *glyph;
938 BITMAP *map;
939 Ulong *pixels;
940 int npixels;
941 Ulong colortab[2];
942 int hs, vs;
943 DviDevice *dev;
944
945 hs = dvi->params.hshrink;
946 vs = dvi->params.vshrink;
947 dev = &dvi->device;
948
949 glyph = &pk->glyph;
950 map = (BITMAP *)glyph->data;
951
952 x = (int)glyph->x / hs;
953 init_cols = (int)glyph->x - x * hs;
954 if(init_cols <= 0)
955 init_cols += hs;
956 else
957 x++;
958 w = x + ROUND((int)glyph->w - glyph->x, hs)((((int)glyph->w - glyph->x) + (hs) - 1) / (hs));
959
960 cols = (int)glyph->y + 1;
961 y = cols / vs;
962 rows = cols - y * vs;
963 if(rows <= 0) {
964 rows += vs;
965 y--;
966 }
967 h = y + ROUND((int)glyph->h - cols, vs)((((int)glyph->h - cols) + (vs) - 1) / (vs)) + 1;
968 ASSERT(w && h)do { if(!(w && h)) mdvi_crash("%s:%d: Assertion %s failed\n"
, "bitmap.c", 968, "w && h"); } while(0)
;
969
970 /* before touching anything, do this */
971 image = dev->create_image(dev->device_data, w, h, BITMAP_BITS(4 << 3));
972 if(image == NULL((void*)0)) {
973 mdvi_shrink_glyph(dvi, font, pk, dest);
974 return;
975 }
976
977 /* save these colors */
978 pk->fg = MDVI_CURRFG(dvi)(dvi)->curr_fg;
979 pk->bg = MDVI_CURRBG(dvi)(dvi)->curr_bg;
980
981 samplemax = vs * hs;
982 npixels = samplemax + 1;
983 pixels = get_color_table(&dvi->device, npixels, pk->fg, pk->bg,
984 dvi->params.gamma, dvi->params.density);
985 if(pixels == NULL((void*)0)) {
986 npixels = 2;
987 colortab[0] = pk->fg;
988 colortab[1] = pk->bg;
989 pixels = &colortab[0];
990 }
991
992 /* setup the new glyph */
993 dest->data = image;
994 dest->x = x;
995 dest->y = glyph->y / vs;
996 dest->w = w;
997 dest->h = h;
998
999 y = 0;
1000 old_ptr = map->data;
1001 rows_left = glyph->h;
1002
1003 while(rows_left && y < h) {
1004 x = 0;
1005 if(rows > rows_left)
1006 rows = rows_left;
1007 cols_left = glyph->w;
1008 cols = init_cols;
1009 while(cols_left && x < w) {
1010 if(cols > cols_left)
1011 cols = cols_left;
1012 sampleval = do_sample(old_ptr, map->stride,
1013 glyph->w - cols_left, cols, rows);
1014 /* scale the sample value by the number of grey levels */
1015 if(npixels - 1 != samplemax)
1016 sampleval = ((npixels-1) * sampleval) / samplemax;
1017 ASSERT(sampleval < npixels)do { if(!(sampleval < npixels)) mdvi_crash("%s:%d: Assertion %s failed\n"
, "bitmap.c", 1017, "sampleval < npixels"); } while(0)
;
1018 dev->put_pixel(image, x, y, pixels[sampleval]);
1019 cols_left -= cols;
1020 cols = hs;
1021 x++;
1022 }
1023 for(; x < w; x++)
1024 dev->put_pixel(image, x, y, pixels[0]);
1025 old_ptr = bm_offset(old_ptr, rows * map->stride)(BmUnit *)((Uchar *)(old_ptr) + (rows * map->stride));
1026 rows_left -= rows;
1027 rows = vs;
1028 y++;
1029 }
1030
1031 for(; y < h; y++) {
1032 for(x = 0; x < w; x++)
1033 dev->put_pixel(image, x, y, pixels[0]);
1034 }
1035
1036 dev->image_done(image);
1037 DEBUG((DBG_BITMAPS, "shrink_glyph_grey: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",__debug ((1 << 8), "shrink_glyph_grey: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n"
, glyph->w, glyph->h, glyph->x, glyph->y, dest->
w, dest->h, dest->x, dest->y)
1038 glyph->w, glyph->h, glyph->x, glyph->y,__debug ((1 << 8), "shrink_glyph_grey: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n"
, glyph->w, glyph->h, glyph->x, glyph->y, dest->
w, dest->h, dest->x, dest->y)
1039 dest->w, dest->h, dest->x, dest->y))__debug ((1 << 8), "shrink_glyph_grey: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n"
, glyph->w, glyph->h, glyph->x, glyph->y, dest->
w, dest->h, dest->x, dest->y)
;
1040}
1041