static void i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth ) { mm_log((1,"i_tt_init_raster_map( bit %p, width %" i_DF ", height %" i_DF ", smooth %d)\n", bit, i_DFc(width), i_DFc(height), smooth)); bit->rows = height; bit->width = ( width + 3 ) & -4; bit->flow = TT_Flow_Down; if ( smooth ) { bit->cols = bit->width; bit->size = bit->rows * bit->width; } else { bit->cols = ( bit->width + 7 ) / 8; /* convert to # of bytes */ bit->size = bit->rows * bit->cols; /* number of bytes in buffer */ } /* rows can be 0 for some glyphs, for example ' ' */ if (bit->rows && bit->size / bit->rows != bit->cols) { i_fatal(0, "Integer overflow calculating bitmap size (%d, %d)\n", bit->width, bit->rows); } mm_log((1,"i_tt_init_raster_map: bit->width %d, bit->cols %d, bit->rows %d, bit->size %ld)\n", bit->width, bit->cols, bit->rows, bit->size )); bit->bitmap = (void *) mymalloc( bit->size ); /* checked 6Nov05 tonyc */ if ( !bit->bitmap ) i_fatal(0,"Not enough memory to allocate bitmap (%d)!\n",bit->size ); }
void i_mmarray_info(i_mmarray *ar) { i_img_dim i; for(i=0;i<ar->lines;i++) if (ar->data[i].max!=-1) printf("line %"i_DF ": min=%" i_DF ", max=%" i_DF ".\n", i_DFc(i), i_DFc(ar->data[i].min), i_DFc(ar->data[i].max)); }
static void i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, const i_color *cl, int smooth ) { unsigned char *bmap; i_img_dim x, y; mm_log((1,"i_tt_dump_raster_map2(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", cl %p)\n", im, bit, i_DFc(xb), i_DFc(yb), cl)); bmap = bit->bitmap; if ( smooth ) { i_render r; i_render_init(&r, im, bit->cols); for(y=0;y<bit->rows;y++) { i_render_color(&r, xb, yb+y, bit->cols, bmap + y*bit->cols, cl); } i_render_done(&r); } else { unsigned char *bmp = mymalloc(bit->width); i_render r; i_render_init(&r, im, bit->width); for(y=0;y<bit->rows;y++) { unsigned mask = 0x80; unsigned char *p = bmap + y * bit->cols; unsigned char *pout = bmp; for(x = 0; x < bit->width; x++) { *pout++ = (*p & mask) ? 0xFF : 0; mask >>= 1; if (!mask) { mask = 0x80; ++p; } } i_render_color(&r, xb, yb+y, bit->width, bmp, cl); } i_render_done(&r); myfree(bmp); } }
static void i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics, TT_Raster_Map *bit, TT_Raster_Map *small_bit, i_img_dim x_off, i_img_dim y_off, int smooth ) { mm_log((1,"i_tt_render_glyph(glyph %p, gmetrics %p, bit %p, small_bit %p, x_off %" i_DF ", y_off %" i_DF ", smooth %d)\n", USTRCT(glyph), gmetrics, bit, small_bit, i_DFc(x_off), i_DFc(y_off), smooth)); if ( !smooth ) TT_Get_Glyph_Bitmap( glyph, bit, x_off * 64, y_off * 64); else { TT_F26Dot6 xmin, ymin; xmin = gmetrics->bbox.xMin & -64; ymin = gmetrics->bbox.yMin & -64; i_tt_clear_raster_map( small_bit ); TT_Get_Glyph_Pixmap( glyph, small_bit, -xmin, -ymin ); i_tt_blit_or( bit, small_bit, xmin/64 + x_off, -ymin/64 - y_off ); } }
static void i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, int channel, int smooth ) { unsigned char *bmap; i_color val; int c; i_img_dim x,y; int old_mask = im->ch_mask; im->ch_mask = 1 << channel; mm_log((1,"i_tt_dump_raster_channel(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", channel %d)\n", im, bit, i_DFc(xb), i_DFc(yb), channel)); bmap = bit->bitmap; if ( smooth ) { for(y=0;y<bit->rows;y++) for(x=0;x<bit->width;x++) { c = bmap[y*(bit->cols)+x]; val.channel[channel] = c; i_ppix(im,x+xb,y+yb,&val); } } else { for(y=0;y<bit->rows;y++) { unsigned mask = 0x80; unsigned char *p = bmap + y * bit->cols; for(x=0;x<bit->width;x++) { val.channel[channel] = (*p & mask) ? 255 : 0; i_ppix(im,x+xb,y+yb,&val); mask >>= 1; if (!mask) { ++p; mask = 0x80; } } } } im->ch_mask = old_mask; }
int i_circle_out(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, const i_color *col) { i_img_dim x, y; i_img_dim dx, dy; int error; dIMCTXim(im); im_log((aIMCTX, 1, "i_circle_out(im %p, centre(" i_DFp "), rad %" i_DF ", col %p)\n", im, i_DFcp(xc, yc), i_DFc(r), col)); im_clear_error(aIMCTX); if (r < 0) { im_push_error(aIMCTX, 0, "circle: radius must be non-negative"); return 0; } i_ppix(im, xc+r, yc, col); i_ppix(im, xc-r, yc, col); i_ppix(im, xc, yc+r, col); i_ppix(im, xc, yc-r, col); x = 0; y = r; dx = 1; dy = -2 * r; error = 1 - r; while (x < y) { if (error >= 0) { --y; dy += 2; error += dy; } ++x; dx += 2; error += dx; i_ppix(im, xc + x, yc + y, col); i_ppix(im, xc + x, yc - y, col); i_ppix(im, xc - x, yc + y, col); i_ppix(im, xc - x, yc - y, col); if (x != y) { i_ppix(im, xc + y, yc + x, col); i_ppix(im, xc + y, yc - x, col); i_ppix(im, xc - y, yc + x, col); i_ppix(im, xc - y, yc - x, col); } } return 1; }
static int i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, i_img_dim cords[6], double points, char const* txt, size_t len, int smooth, int utf8 ) { int inst; i_img_dim width, height; TT_Raster_Map small_bit; /* find or install an instance */ if ( (inst=i_tt_get_instance(handle,points,smooth)) < 0) { mm_log((1,"i_tt_rasterize: get instance failed\n")); return 0; } /* calculate bounding box */ if (!i_tt_bbox_inst( handle, inst, txt, len, cords, utf8 )) return 0; width = cords[2]-cords[0]; height = cords[5]-cords[4]; mm_log((1,"i_tt_rasterize: width=%" i_DF ", height=%" i_DF "\n", i_DFc(width), i_DFc(height) )); i_tt_init_raster_map ( bit, width, height, smooth ); i_tt_clear_raster_map( bit ); if ( smooth ) i_tt_init_raster_map( &small_bit, handle->instanceh[inst].imetrics.x_ppem + 32, height, smooth ); if (!i_tt_render_all_glyphs( handle, inst, bit, &small_bit, cords, txt, len, smooth, utf8 )) { if ( smooth ) i_tt_done_raster_map( &small_bit ); return 0; } if ( smooth ) i_tt_done_raster_map( &small_bit ); return 1; }
int i_arc_out_aa(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, double d1, double d2, const i_color *col) { i_img_dim i, j; double t; i_color workc = *col; i_img_dim segs[2][2]; int seg_count; i_img_dim sin_th; i_img_dim seg_d1, seg_d2; int seg_num; int orig_alpha = col->channel[3]; i_img_dim scale = r + 1; i_img_dim seg1 = scale * 2; i_img_dim seg2 = scale * 4; i_img_dim seg3 = scale * 6; i_img_dim seg4 = scale * 8; dIMCTXim(im); im_log((aIMCTX,1,"i_arc_out_aa(im %p,centre(" i_DFp "), rad %" i_DF ", d1 %f, d2 %f, col %p)", im, i_DFcp(xc, yc), i_DFc(r), d1, d2, col)); im_clear_error(aIMCTX); if (r <= 0) { im_push_error(aIMCTX, 0, "arc: radius must be non-negative"); return 0; } if (d1 + 360 <= d2) return i_circle_out_aa(im, xc, yc, r, col); if (d1 < 0) d1 += 360 * floor((-d1 + 359) / 360); if (d2 < 0) d2 += 360 * floor((-d2 + 359) / 360); d1 = fmod(d1, 360); d2 = fmod(d2, 360); seg_d1 = arc_seg(d1, scale); seg_d2 = arc_seg(d2, scale); if (seg_d2 < seg_d1) { /* split into two segments */ segs[0][0] = 0; segs[0][1] = seg_d2; segs[1][0] = seg_d1; segs[1][1] = seg4; seg_count = 2; } else { segs[0][0] = seg_d1; segs[0][1] = seg_d2; seg_count = 1; } for (seg_num = 0; seg_num < seg_count; ++seg_num) { i_img_dim seg_start = segs[seg_num][0]; i_img_dim seg_end = segs[seg_num][1]; i = r; j = 0; t = 0; if (seg_start == 0) i_ppix_norm(im, xc+i, yc+j, col); if (seg_start <= seg1 && seg_end >= seg1) i_ppix_norm(im, xc+j, yc+i, col); if (seg_start <= seg2 && seg_end >= seg2) i_ppix_norm(im, xc-i, yc+j, col); if (seg_start <= seg3 && seg_end >= seg3) i_ppix_norm(im, xc+j, yc-i, col); while (i > j+1) { int cv, inv_cv; double d; j++; d = cover(r, j); cv = (int)(d * 255 + 0.5); inv_cv = 255-cv; if (d < t) { --i; } sin_th = j; if (inv_cv) { workc.channel[3] = orig_alpha * inv_cv / 255; if (seg_start <= sin_th && seg_end >= sin_th) i_ppix_norm(im, xc+i, yc+j, &workc); if (seg_start <= seg2 - sin_th && seg_end >= seg2 - sin_th) i_ppix_norm(im, xc-i, yc+j, &workc); if (seg_start <= seg4 - sin_th && seg_end >= seg4 - sin_th) i_ppix_norm(im, xc+i, yc-j, &workc); if (seg_start <= seg2 + sin_th && seg_end >= seg2 + sin_th) i_ppix_norm(im, xc-i, yc-j, &workc); if (i != j) { if (seg_start <= seg1 - sin_th && seg_end >= seg1 - sin_th) i_ppix_norm(im, xc+j, yc+i, &workc); if (seg_start <= seg1 + sin_th && seg_end >= seg1 + sin_th) i_ppix_norm(im, xc-j, yc+i, &workc); if (seg_start <= seg3 + sin_th && seg_end >= seg3 + sin_th) i_ppix_norm(im, xc+j, yc-i, &workc); if (seg_start <= seg3 - sin_th && seg_end >= seg3 - sin_th) i_ppix_norm(im, xc-j, yc-i, &workc); } } if (cv && i > j) { workc.channel[3] = orig_alpha * cv / 255; if (seg_start <= sin_th && seg_end >= sin_th) i_ppix_norm(im, xc+i-1, yc+j, &workc); if (seg_start <= seg2 - sin_th && seg_end >= seg2 - sin_th) i_ppix_norm(im, xc-i+1, yc+j, &workc); if (seg_start <= seg4 - sin_th && seg_end >= seg4 - sin_th) i_ppix_norm(im, xc+i-1, yc-j, &workc); if (seg_start <= seg2 + sin_th && seg_end >= seg2 + sin_th) i_ppix_norm(im, xc-i+1, yc-j, &workc); if (seg_start <= seg1 - sin_th && seg_end >= seg1 - sin_th) i_ppix_norm(im, xc+j, yc+i-1, &workc); if (seg_start <= seg1 + sin_th && seg_end >= seg1 + sin_th) i_ppix_norm(im, xc-j, yc+i-1, &workc); if (seg_start <= seg3 + sin_th && seg_end >= seg3 + sin_th) i_ppix_norm(im, xc+j, yc-i+1, &workc); if (seg_start <= seg3 - sin_th && seg_end >= seg3 - sin_th) i_ppix_norm(im, xc-j, yc-i+1, &workc); } t = d; } } return 1; }
int i_circle_out_aa(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, const i_color *col) { i_img_dim i, j; double t; i_color workc = *col; int orig_alpha = col->channel[3]; dIMCTXim(im); im_log((aIMCTX,1,"i_circle_out_aa(im %p,centre(" i_DFp "), rad %" i_DF ", col %p)", im, i_DFcp(xc, yc), i_DFc(r), col)); im_clear_error(aIMCTX); if (r <= 0) { im_push_error(aIMCTX, 0, "arc: radius must be non-negative"); return 0; } i = r; j = 0; t = 0; i_ppix_norm(im, xc+i, yc+j, col); i_ppix_norm(im, xc-i, yc+j, col); i_ppix_norm(im, xc+j, yc+i, col); i_ppix_norm(im, xc+j, yc-i, col); while (i > j+1) { double d; int cv, inv_cv; j++; d = cover(r, j); cv = (int)(d * 255 + 0.5); inv_cv = 255-cv; if (d < t) { --i; } if (inv_cv) { workc.channel[3] = orig_alpha * inv_cv / 255; i_ppix_norm(im, xc+i, yc+j, &workc); i_ppix_norm(im, xc-i, yc+j, &workc); i_ppix_norm(im, xc+i, yc-j, &workc); i_ppix_norm(im, xc-i, yc-j, &workc); if (i != j) { i_ppix_norm(im, xc+j, yc+i, &workc); i_ppix_norm(im, xc-j, yc+i, &workc); i_ppix_norm(im, xc+j, yc-i, &workc); i_ppix_norm(im, xc-j, yc-i, &workc); } } if (cv && i > j) { workc.channel[3] = orig_alpha * cv / 255; i_ppix_norm(im, xc+i-1, yc+j, &workc); i_ppix_norm(im, xc-i+1, yc+j, &workc); i_ppix_norm(im, xc+i-1, yc-j, &workc); i_ppix_norm(im, xc-i+1, yc-j, &workc); if (j != i-1) { i_ppix_norm(im, xc+j, yc+i-1, &workc); i_ppix_norm(im, xc-j, yc+i-1, &workc); i_ppix_norm(im, xc+j, yc-i+1, &workc); i_ppix_norm(im, xc-j, yc-i+1, &workc); } } t = d; } return 1; }
int i_arc_out(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, double d1, double d2, const i_color *col) { i_img_dim x, y; i_img_dim dx, dy; int error; i_img_dim segs[2][2]; int seg_count; i_img_dim sin_th; i_img_dim seg_d1, seg_d2; int seg_num; i_img_dim scale = r + 1; i_img_dim seg1 = scale * 2; i_img_dim seg2 = scale * 4; i_img_dim seg3 = scale * 6; i_img_dim seg4 = scale * 8; dIMCTXim(im); im_log((aIMCTX,1,"i_arc_out(im %p,centre(" i_DFp "), rad %" i_DF ", d1 %f, d2 %f, col %p)", im, i_DFcp(xc, yc), i_DFc(r), d1, d2, col)); im_clear_error(aIMCTX); if (r <= 0) { im_push_error(aIMCTX, 0, "arc: radius must be non-negative"); return 0; } if (d1 + 360 <= d2) return i_circle_out(im, xc, yc, r, col); if (d1 < 0) d1 += 360 * floor((-d1 + 359) / 360); if (d2 < 0) d2 += 360 * floor((-d2 + 359) / 360); d1 = fmod(d1, 360); d2 = fmod(d2, 360); seg_d1 = arc_seg(d1, scale); seg_d2 = arc_seg(d2, scale); if (seg_d2 < seg_d1) { /* split into two segments */ segs[0][0] = 0; segs[0][1] = seg_d2; segs[1][0] = seg_d1; segs[1][1] = seg4; seg_count = 2; } else { segs[0][0] = seg_d1; segs[0][1] = seg_d2; seg_count = 1; } for (seg_num = 0; seg_num < seg_count; ++seg_num) { i_img_dim seg_start = segs[seg_num][0]; i_img_dim seg_end = segs[seg_num][1]; if (seg_start == 0) i_ppix(im, xc+r, yc, col); if (seg_start <= seg1 && seg_end >= seg1) i_ppix(im, xc, yc+r, col); if (seg_start <= seg2 && seg_end >= seg2) i_ppix(im, xc-r, yc, col); if (seg_start <= seg3 && seg_end >= seg3) i_ppix(im, xc, yc-r, col); y = 0; x = r; dy = 1; dx = -2 * r; error = 1 - r; while (y < x) { if (error >= 0) { --x; dx += 2; error += dx; } ++y; dy += 2; error += dy; sin_th = y; if (seg_start <= sin_th && seg_end >= sin_th) i_ppix(im, xc + x, yc + y, col); if (seg_start <= seg1 - sin_th && seg_end >= seg1 - sin_th) i_ppix(im, xc + y, yc + x, col); if (seg_start <= seg1 + sin_th && seg_end >= seg1 + sin_th) i_ppix(im, xc - y, yc + x, col); if (seg_start <= seg2 - sin_th && seg_end >= seg2 - sin_th) i_ppix(im, xc - x, yc + y, col); if (seg_start <= seg2 + sin_th && seg_end >= seg2 + sin_th) i_ppix(im, xc - x, yc - y, col); if (seg_start <= seg3 - sin_th && seg_end >= seg3 - sin_th) i_ppix(im, xc - y, yc - x, col); if (seg_start <= seg3 + sin_th && seg_end >= seg3 + sin_th) i_ppix(im, xc + y, yc - x, col); if (seg_start <= seg4 - sin_th && seg_end >= seg4 - sin_th) i_ppix(im, xc + x, yc - y, col); } } return 1; }
static int i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth ) { int i,idx; TT_Error error; mm_log((1,"i_tt_get_instance(handle %p, points %" i_DF ", smooth %d)\n", handle, i_DFc(points), smooth)); if (smooth == -1) { /* Smooth doesn't matter for this search */ for(i=0;i<TT_CHC;i++) { if (handle->instanceh[i].ptsize==points) { mm_log((1,"i_tt_get_instance: in cache - (non selective smoothing search) returning %d\n",i)); return i; } } smooth=1; /* We will be adding a font - add it as smooth then */ } else { /* Smooth doesn't matter for this search */ for(i=0;i<TT_CHC;i++) { if (handle->instanceh[i].ptsize == points && handle->instanceh[i].smooth == smooth) { mm_log((1,"i_tt_get_instance: in cache returning %d\n",i)); return i; } } } /* Found the instance in the cache - return the cache index */ for(idx=0;idx<TT_CHC;idx++) { if (!(handle->instanceh[idx].order)) break; /* find the lru item */ } mm_log((1,"i_tt_get_instance: lru item is %d\n",idx)); mm_log((1,"i_tt_get_instance: lru pointer %p\n", USTRCT(handle->instanceh[idx].instance) )); if ( USTRCT(handle->instanceh[idx].instance) ) { mm_log((1,"i_tt_get_instance: freeing lru item from cache %d\n",idx)); /* Free cached glyphs */ for(i=0;i<256;i++) if ( USTRCT(handle->instanceh[idx].glyphs[i].glyph) ) TT_Done_Glyph( handle->instanceh[idx].glyphs[i].glyph ); for(i=0;i<256;i++) { handle->instanceh[idx].glyphs[i].ch = TT_NOCHAR; USTRCT(handle->instanceh[idx].glyphs[i].glyph)=NULL; } /* Free instance if needed */ TT_Done_Instance( handle->instanceh[idx].instance ); } /* create and initialize instance */ /* FIXME: probably a memory leak on fail */ (void) (( error = TT_New_Instance( handle->face, &handle->instanceh[idx].instance ) ) || ( error = TT_Set_Instance_Resolutions( handle->instanceh[idx].instance, LTT_dpi, LTT_dpi ) ) || ( error = TT_Set_Instance_CharSize( handle->instanceh[idx].instance, points*64 ) ) ); if ( error ) { mm_log((1, "Could not create and initialize instance: error %x.\n", (unsigned)error )); return -1; } /* Now that the instance should the inplace we need to lower all of the ru counts and put `this' one with the highest entry */ for(i=0;i<TT_CHC;i++) handle->instanceh[i].order--; handle->instanceh[idx].order=TT_CHC-1; handle->instanceh[idx].ptsize=points; handle->instanceh[idx].smooth=smooth; TT_Get_Instance_Metrics( handle->instanceh[idx].instance, &(handle->instanceh[idx].imetrics) ); /* Zero the memory for the glyph storage so they are not thought as cached if they haven't been cached since this new font was loaded */ for(i=0;i<256;i++) { handle->instanceh[idx].glyphs[i].ch = TT_NOCHAR; USTRCT(handle->instanceh[idx].glyphs[i].glyph)=NULL; } return idx; }