Esempio n. 1
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 );
  }
}
Esempio n. 2
0
static void image_ttf_faceinstance_write(INT32 args)
{
   int **sstr;
   int *slen;
   int i,res=0,base=0,a;
   struct image_ttf_face_struct *face_s;
   struct image_ttf_faceinstance_struct *face_i=THISi;
   TT_CharMap charMap;
   TT_Kerning kerning;
   int has_kerning = 0;
   char *errs=NULL;
   int scalefactor=0;
   int xmin=1000,xmax=-1000,pos=0,ypos;
   int width,height,mod;

   unsigned char* pixmap;
   int maxcharwidth = 0;

   if (!(face_s=(struct image_ttf_face_struct*)
	 get_storage(THISi->faceobj,image_ttf_face_program)))
      Pike_error("Image.TTF.FaceInstance->write(): lost Face\n");

   if(!TT_Get_Kerning_Directory( face_s->face, &kerning ))
   {
     TT_Instance_Metrics metrics;
/*      fprintf(stderr, "has kerning!\n"); */
     has_kerning = 1;
     if(TT_Get_Instance_Metrics( face_i->instance, &metrics ))
       Pike_error("Nope. No way.\n");
     scalefactor = metrics.x_scale;
/*      fprintf(stderr, "offset=%d\n", (int)metrics.x_scale); */
   }

   if (args && sp[-1].type==T_INT)
   {
      base=sp[-1].u.integer;
      args--;
      pop_stack();
   }

   if (!args)
   {
      push_empty_string();
      args=1;
   }

   ttf_get_nice_charmap(face_s->face,&charMap,
			"Image.TTF.FaceInstance->write()");

   sstr=alloca(args*sizeof(int*));
   slen=alloca(args*sizeof(int));

   /* first pass: figure out total bounding box */

   for (a=0; a<args; a++)
   {
     char *errs=NULL;
     TT_Glyph_Metrics metrics;

      if (sp[a-args].type!=T_STRING)
	 Pike_error("Image.TTF.FaceInstance->write(): illegal argument %d\n",a+1);

      switch(sp[a-args].u.string->size_shift)
      {
       case 0:
	 ttf_translate_8bit(charMap,(unsigned char*)sp[a-args].u.string->str,
			    sstr+a,
			    DO_NOT_WARN(slen[a]=sp[a-args].u.string->len),
			    base);
	 break;
       case 1:
	 ttf_translate_16bit(charMap,(unsigned short*)sp[a-args].u.string->str,
			     sstr+a,
			     DO_NOT_WARN(slen[a]=sp[a-args].u.string->len),
			     base);
	 break;
       case 2:
	 Pike_error("Too wide string for truetype\n");
	 break;
      }

      pos=0;
      for (i=0; i<slen[a]; i++)
      {
	 TT_Glyph glyph;
	 int ind;

	 ind=sstr[a][i];
/* 	 fprintf(stderr,"glyph: %d\n",ind); */

	 if ((res=TT_New_Glyph(face_s->face,&glyph)))
	    { errs="TT_New_Glyph: "; break; }

	 if ((res=TT_Load_Glyph(face_i->instance, glyph, (TT_UShort)ind,
				(TT_UShort)face_i->load_flags)))
	    { errs="TT_Load_Glyph: "; break; }

	 if ((res=TT_Get_Glyph_Metrics(glyph,&metrics)))
	    { errs="TT_Get_Glyph_Metrics: "; break; }

	 if (pos+metrics.bbox.xMin<xmin)
	   xmin=pos+metrics.bbox.xMin;
	 if (pos+metrics.bbox.xMax>xmax)
	   xmax=pos+metrics.bbox.xMax;

	 if((metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0))
	    >maxcharwidth)
	   maxcharwidth =
	     (metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0));

	 pos+=metrics.advance;
	 if(has_kerning && i<slen[a]-1)
	 {
	   int kern = find_kerning( kerning, ind, sstr[a][i+1] );
	   pos += DOUBLE_TO_INT(kern * (scalefactor/65535.0));
	 }
	 if ((res=TT_Done_Glyph(glyph)))
	    { errs="TT_Done_Glyph: "; break; }
      }
      pos -= metrics.advance;
      pos += metrics.bbox.xMax-metrics.bbox.xMin;
      if (pos>xmax)
	xmax=pos;
      if (errs)
      {
	 for (i=0; i<a; i++) free(sstr[i]);
	 my_tt_error("Image.TTF.FaceInstance->write()",errs,res);
      }
   }

   pop_n_elems(args);

/*    fprintf(stderr,"xmin=%f xmax=%f\n",xmin/64.0,xmax/64.0); */

   xmin&=~63;
   width=((xmax-xmin+63)>>6)+4;
   height=face_i->height*args;
   mod=(4-(maxcharwidth&3))&3;
   if (width<1) width=1;

   if ((pixmap=malloc((maxcharwidth+mod)*face_i->height)))
   {
      /* second pass: write the stuff */

      TT_Raster_Map rastermap;
      struct object *o;
      struct image *img;
      rgb_group *d;


      rastermap.rows=face_i->height;
      rastermap.cols=rastermap.width=maxcharwidth+mod;
      rastermap.flow=TT_Flow_Down;
      rastermap.bitmap=pixmap;
      rastermap.size=rastermap.cols*rastermap.rows;

      ypos=0;

/*       fprintf(stderr,"rastermap.rows=%d cols=%d width=%d\n", */
/* 	      rastermap.rows,rastermap.cols,rastermap.width); */


      push_int(width);
      push_int(height);
      o=clone_object(image_program,2);
      img=(struct image*)get_storage(o,image_program);
      d=img->img;

      for (a=0; a<args; a++)
      {
         pos=-xmin;
	 for (i=0; i<slen[a]; i++)
	 {
    	    int sw, xp;
	    TT_Glyph glyph;
	    TT_Glyph_Metrics metrics;
	    int ind, x, y;

	    ind=sstr[a][i];
/* 	    fprintf(stderr,"glyph: %d\n",ind); */


	    if ((res=TT_New_Glyph(face_s->face,&glyph)))
	       { errs="TT_New_Glyph: "; break; }

	    if ((res=TT_Load_Glyph(face_i->instance, glyph, (TT_UShort)ind,
				   (TT_UShort)face_i->load_flags)))
	       { errs="TT_Load_Glyph: "; break; }

	    if ((res=TT_Get_Glyph_Metrics(glyph,&metrics)))
	       { errs="TT_Get_Glyph_Metrics: "; break; }

	    MEMSET(pixmap,0,rastermap.size);

	    if ((res=TT_Get_Glyph_Pixmap(glyph,
					 &rastermap,
					 -metrics.bbox.xMin
                                         /*+pos%64*/,
					 face_i->height*64-
					 face_i->trans)))
	       { errs="TT_Get_Glyph_Pixmap: "; break; }


	    sw = metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0);
	    /* Copy source pixmap to destination image object. */
	    for(y=0; y<face_i->height; y++)
	    {
	      unsigned int s;
	      unsigned char * source = pixmap+rastermap.width*y;
	      rgb_group *dt=d+(ypos+y)*width+(xp=(metrics.bbox.xMin+pos)/64);

	      for(x=0; x<sw && xp<width; x++,xp++,source++,dt++)
		if(xp<0 || !(s = *source))
		  continue;
		else if((s=dt->r+s) < 256)
		  dt->r=dt->g=dt->b=s;
		else
		  dt->r=dt->g=dt->b=255;
	    }

	    pos+=metrics.advance;
/* 	    if(metrics.bbox.xMin < 0) */
/* 	      pos += metrics.bbox.xMin; */
	    if(has_kerning && i<slen[a]-1)
	    {
	      int kern = find_kerning( kerning, sstr[a][i], sstr[a][i+1] );
	      pos += DOUBLE_TO_INT(kern * (scalefactor/65535.0));
/* 	      fprintf(stderr, "Adjusted is %d\n", */
/* 		      (int)(kern * (scalefactor/65535.0))); */
	    }

	    if ((res=TT_Done_Glyph(glyph)))
	       { errs="TT_Done_Glyph: "; break; }
	 }
	 if (errs)
	 {
	    for (a=0; a<args; a++) free(sstr[a]);
	    free(pixmap);
	    free_object(o);
	    my_tt_error("Image.TTF.FaceInstance->write()",errs,res);
	 }
	 ypos+=face_i->height;
      }
      free(pixmap);
      push_object(o);
   }
   else
   {
      Pike_error("Image.TTF.FaceInstance->write(): out of memory\n");
   }

   for (a=0; a<args; a++)
      free(sstr[a]);
}