Beispiel #1
0
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 );
}
Beispiel #2
0
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));
}
Beispiel #3
0
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);
  }
}
Beispiel #4
0
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 );
  }
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}