void bitmap_flip_rotate_counter_clockwise(BITMAP *bm) { BITMAP nb; BmUnit *fptr, *tptr; BmUnit fmask, tmask; int w, h; nb.width = bm->height; nb.height = bm->width; nb.stride = BM_BYTES_PER_LINE(&nb); nb.data = mdvi_calloc(nb.height, nb.stride); fptr = bm->data; tptr = nb.data; tmask = FIRSTMASK; for(h = 0; h < bm->height; h++) { BmUnit *fline, *tline; fmask = FIRSTMASK; fline = fptr; tline = tptr; for(w = 0; w < bm->width; w++) { if(*fline & fmask) *tline |= tmask; if(fmask == LASTMASK) { fmask = FIRSTMASK; fline++; } else NEXTMASK(fmask); /* go to next line */ tline = bm_offset(tline, nb.stride); } fptr = bm_offset(fptr, bm->stride); if(tmask == LASTMASK) { tmask = FIRSTMASK; tptr++; } else NEXTMASK(tmask); } DEBUG((DBG_BITMAP_OPS, "flip_rotate_counter_clockwise (%d,%d) -> (%d,%d)\n", bm->width, bm->height, nb.width, nb.height)); mdvi_free(bm->data); bm->data = nb.data; bm->width = nb.width; bm->height = nb.height; bm->stride = nb.stride; if(SHOW_OP_DATA) bitmap_print(stderr, bm); }
/* * Count the number of non-zero bits in a box of dimensions w x h, starting * at column `step' in row `data'. * * Shamelessly stolen from xdvi. */ static int do_sample(BmUnit *data, int stride, int step, int w, int h) { BmUnit *ptr, *end, *cp; int shift, n; int bits_left; int wid; ptr = data + step / BITMAP_BITS; end = bm_offset(data, h * stride); shift = FIRSTSHIFTAT(step); bits_left = w; n = 0; while(bits_left) { #ifndef WORD_BIG_ENDIAN wid = BITMAP_BITS - shift; #else wid = shift; #endif if(wid > bits_left) wid = bits_left; if(wid > 8) wid = 8; #ifdef WORD_BIG_ENDIAN shift -= wid; #endif for(cp = ptr; cp < end; cp = bm_offset(cp, stride)) n += sample_count[(*cp >> shift) & bit_masks[wid]]; #ifndef WORD_BIG_ENDIAN shift += wid; #endif #ifdef WORD_BIG_ENDIAN if(shift == 0) { shift = BITMAP_BITS; ptr++; } #else if(shift == BITMAP_BITS) { shift = 0; ptr++; } #endif bits_left -= wid; } return n; }
void bitmap_flip_diagonally(BITMAP *bm) { BITMAP nb; BmUnit *fptr, *tptr; BmUnit fmask, tmask; int w, h; nb.width = bm->width; nb.height = bm->height; nb.stride = bm->stride; nb.data = mdvi_calloc(bm->height, bm->stride); fptr = bm->data; tptr = __bm_unit_ptr(&nb, nb.width-1, nb.height-1); for(h = 0; h < bm->height; h++) { BmUnit *fline, *tline; fline = fptr; tline = tptr; fmask = FIRSTMASK; tmask = FIRSTMASKAT(nb.width-1); for(w = 0; w < bm->width; w++) { if(*fline & fmask) *tline |= tmask; if(fmask == LASTMASK) { fmask = FIRSTMASK; fline++; } else NEXTMASK(fmask); if(tmask == FIRSTMASK) { tmask = LASTMASK; tline--; } else PREVMASK(tmask); } fptr = bm_offset(fptr, bm->stride); tptr = bm_offset(tptr, -nb.stride); } DEBUG((DBG_BITMAP_OPS, "flip_diagonally (%d,%d) -> (%d,%d)\n", bm->width, bm->height, nb.width, nb.height)); mdvi_free(bm->data); bm->data = nb.data; if(SHOW_OP_DATA) bitmap_print(stderr, bm); }
void bitmap_set_col(BITMAP *bm, int row, int col, int count, int state) { BmUnit *ptr; BmUnit mask; ptr = __bm_unit_ptr(bm, col, row); mask = FIRSTMASKAT(col); while(count-- > 0) { if(state) *ptr |= mask; else *ptr &= ~mask; /* move to next row */ ptr = bm_offset(ptr, bm->stride); } }
static int gf_read_bitmap(FILE *p, DviFontChar *ch) { int op; int min_n, max_n; int min_m, max_m; int paint_switch; int x, y; int bpl; Int32 par; BmUnit *line; BITMAP *map; fseek(p, (long)ch->offset, SEEK_SET); op = fuget1(p); if(op == GF_BOC) { /* skip character code */ fuget4(p); /* skip pointer */ fuget4(p); min_m = fsget4(p); max_m = fsget4(p); min_n = fsget4(p); max_n = fsget4(p); } else if(op == GF_BOC1) { /* skip character code */ fuget1(p); min_m = fuget1(p); /* this is max_m - min_m */ max_m = fuget1(p); min_n = fuget1(p); /* this is max_n - min_n */ max_n = fuget1(p); min_m = max_m - min_m; min_n = max_n - min_n; } else { mdvi_error(_("GF: invalid opcode %d in character %d\n"), op, ch->code); return -1; } ch->x = -min_m; ch->y = max_n; ch->width = max_m - min_m + 1; ch->height = max_n - min_n + 1; map = bitmap_alloc(ch->width, ch->height); ch->glyph.data = map; ch->glyph.x = ch->x; ch->glyph.y = ch->y; ch->glyph.w = ch->width; ch->glyph.h = ch->height; #define COLOR(x) ((x) ? "BLACK" : "WHITE") paint_switch = WHITE; x = y = 0; line = map->data; bpl = map->stride; DEBUG((DBG_BITMAPS, "(gf) reading character %d\n", ch->code)); while((op = fuget1(p)) != GF_EOC) { Int32 n; if(feof(p)) break; if(op == GF_PAINT0) { DEBUG((DBG_BITMAPS, "(gf) Paint0 %s -> %s\n", COLOR(paint_switch), COLOR(!paint_switch))); paint_switch = !paint_switch; } else if(op <= GF_PAINT3) { if(op < GF_PAINT1) par = op; else par = fugetn(p, op - GF_PAINT1 + 1); if(y >= ch->height || x + par >= ch->width) goto toobig; /* paint everything between columns x and x + par - 1 */ DEBUG((DBG_BITMAPS, "(gf) Paint %d %s from (%d,%d)\n", par, COLOR(paint_switch), x, y)); if(paint_switch == BLACK) bitmap_paint_bits(line + (x / BITMAP_BITS), x % BITMAP_BITS, par); paint_switch = !paint_switch; x += par; } else if(op >= GF_NEW_ROW_0 && op <= GF_NEW_ROW_MAX) { y++; line = bm_offset(line, bpl); x = op - GF_NEW_ROW_0; paint_switch = BLACK; DEBUG((DBG_BITMAPS, "(gf) new_row_%d\n", x)); } else switch(op) { case GF_SKIP0: y++; line = bm_offset(line, bpl); x = 0; paint_switch = WHITE; DEBUG((DBG_BITMAPS, "(gf) skip_0\n")); break; case GF_SKIP1: case GF_SKIP2: case GF_SKIP3: par = fugetn(p, op - GF_SKIP1 + 1); y += par + 1; line = bm_offset(line, (par + 1) * bpl); x = 0; paint_switch = WHITE; DEBUG((DBG_BITMAPS, "(gf) skip_%d\n", op - GF_SKIP1)); break; case GF_XXX1: case GF_XXX2: case GF_XXX3: case GF_XXX4: { #ifndef NODEBUG char *s; s = read_string(p, op - GF_XXX1 + 1, NULL, 0); DEBUG((DBG_SPECIAL, "(gf) Character %d: Special \"%s\"\n", ch->code, s)); mdvi_free(s); #else n = fugetn(p, op - GF_XXX1 + 1); fseek(p, (long)n, SEEK_CUR); #endif break; } case GF_YYY: n = fuget4(p); DEBUG((DBG_SPECIAL, "(gf) Character %d: MF special %u\n", ch->code, n)); break; case GF_NOOP: DEBUG((DBG_BITMAPS, "(gf) no_op\n")); break; default: mdvi_error(_("(gf) Character %d: invalid opcode %d\n"), ch->code, op); goto error; } /* chech that we're still inside the bitmap */ if(x > ch->width || y > ch->height) goto toobig; DEBUG((DBG_BITMAPS, "(gf) curr_loc @ (%d,%d)\n", x, y)); } if(op != GF_EOC) goto error; DEBUG((DBG_BITMAPS, "(gf) end of character %d\n", ch->code)); return 0; toobig: mdvi_error(_("(gf) character %d has an incorrect bounding box\n"), ch->code); error: bitmap_destroy(map); ch->glyph.data = NULL; return -1; }
void mdvi_shrink_glyph_grey(DviContext *dvi, DviFont *font, DviFontChar *pk, DviGlyph *dest) { int rows_left, rows; int cols_left, cols, init_cols; long sampleval, samplemax; BmUnit *old_ptr; void *image; int w, h; int x, y; DviGlyph *glyph; BITMAP *map; Ulong *pixels; int npixels; Ulong colortab[2]; int hs, vs; DviDevice *dev; hs = dvi->params.hshrink; vs = dvi->params.vshrink; dev = &dvi->device; glyph = &pk->glyph; map = (BITMAP *)glyph->data; x = (int)glyph->x / hs; init_cols = (int)glyph->x - x * hs; if(init_cols <= 0) init_cols += hs; else x++; w = x + ROUND((int)glyph->w - glyph->x, hs); cols = (int)glyph->y + 1; y = cols / vs; rows = cols - y * vs; if(rows <= 0) { rows += vs; y--; } h = y + ROUND((int)glyph->h - cols, vs) + 1; ASSERT(w && h); /* before touching anything, do this */ image = dev->create_image(dev->device_data, w, h, BITMAP_BITS); if(image == NULL) { mdvi_shrink_glyph(dvi, font, pk, dest); return; } /* save these colors */ pk->fg = MDVI_CURRFG(dvi); pk->bg = MDVI_CURRBG(dvi); samplemax = vs * hs; npixels = samplemax + 1; pixels = get_color_table(&dvi->device, npixels, pk->fg, pk->bg, dvi->params.gamma, dvi->params.density); if(pixels == NULL) { npixels = 2; colortab[0] = pk->fg; colortab[1] = pk->bg; pixels = &colortab[0]; } /* setup the new glyph */ dest->data = image; dest->x = x; dest->y = glyph->y / vs; dest->w = w; dest->h = h; y = 0; old_ptr = map->data; rows_left = glyph->h; while(rows_left && y < h) { x = 0; if(rows > rows_left) rows = rows_left; cols_left = glyph->w; cols = init_cols; while(cols_left && x < w) { if(cols > cols_left) cols = cols_left; sampleval = do_sample(old_ptr, map->stride, glyph->w - cols_left, cols, rows); /* scale the sample value by the number of grey levels */ if(npixels - 1 != samplemax) sampleval = ((npixels-1) * sampleval) / samplemax; ASSERT(sampleval < npixels); dev->put_pixel(image, x, y, pixels[sampleval]); cols_left -= cols; cols = hs; x++; } for(; x < w; x++) dev->put_pixel(image, x, y, pixels[0]); old_ptr = bm_offset(old_ptr, rows * map->stride); rows_left -= rows; rows = vs; y++; } for(; y < h; y++) { for(x = 0; x < w; x++) dev->put_pixel(image, x, y, pixels[0]); } dev->image_done(image); DEBUG((DBG_BITMAPS, "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)); }
void mdvi_shrink_glyph(DviContext *dvi, DviFont *font, DviFontChar *pk, DviGlyph *dest) { int rows_left, rows, init_cols; int cols_left, cols; BmUnit *old_ptr, *new_ptr; BITMAP *oldmap, *newmap; BmUnit m, *cp; DviGlyph *glyph; int sample, min_sample; int old_stride; int new_stride; int x, y; int w, h; int hs, vs; hs = dvi->params.hshrink; vs = dvi->params.vshrink; min_sample = vs * hs * dvi->params.density / 100; glyph = &pk->glyph; oldmap = (BITMAP *)glyph->data; x = (int)glyph->x / hs; init_cols = (int)glyph->x - x * hs; if(init_cols <= 0) init_cols += hs; else x++; w = x + ROUND((int)glyph->w - glyph->x, hs); cols = (int)glyph->y + 1; y = cols / vs; rows = cols - y * vs; if(rows <= 0) { rows += vs; y--; } h = y + ROUND((int)glyph->h - cols, vs) + 1; /* create the new glyph */ newmap = bitmap_alloc(w, h); dest->data = newmap; dest->x = x; dest->y = glyph->y / vs; dest->w = w; dest->h = h; old_ptr = oldmap->data; old_stride = oldmap->stride; new_ptr = newmap->data; new_stride = newmap->stride; rows_left = glyph->h; while(rows_left) { if(rows > rows_left) rows = rows_left; cols_left = glyph->w; m = FIRSTMASK; cp = new_ptr; cols = init_cols; while(cols_left > 0) { if(cols > cols_left) cols = cols_left; sample = do_sample(old_ptr, old_stride, glyph->w - cols_left, cols, rows); if(sample >= min_sample) *cp |= m; if(m == LASTMASK) { m = FIRSTMASK; cp++; } else NEXTMASK(m); cols_left -= cols; cols = hs; } new_ptr = bm_offset(new_ptr, new_stride); old_ptr = bm_offset(old_ptr, rows * old_stride); rows_left -= rows; rows = vs; } DEBUG((DBG_BITMAPS, "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)); if(DEBUGGING(BITMAP_DATA)) bitmap_print(stderr, newmap); }