예제 #1
0
void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face,
                                                      const SkGlyph& glyph,
                                                      SkPath* path)
{
    if (fRec.fFlags & SkScalerContext::kEmbolden_Flag) {
        emboldenOutline(face, &face->glyph->outline);
    }

    FT_Outline_Funcs    funcs;

    funcs.move_to   = move_proc;
    funcs.line_to   = line_proc;
    funcs.conic_to  = quad_proc;
    funcs.cubic_to  = cubic_proc;
    funcs.shift     = 0;
    funcs.delta     = 0;

    FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path);

    if (err != 0) {
        path->reset();
        return;
    }

    path->close();
}
예제 #2
0
bool loadGlyph(Shape &output, FontHandle *font, int unicode, double *advance) {
    if (!font)
        return false;
    FT_Error error = FT_Load_Char(font->face, unicode, FT_LOAD_NO_SCALE);
    if (error)
        return false;
    output.contours.clear();
    output.inverseYAxis = false;
    if (advance)
        *advance = font->face->glyph->advance.x/64.;

    FtContext context = { };
    context.shape = &output;
    FT_Outline_Funcs ftFunctions;
    ftFunctions.move_to = &ftMoveTo;
    ftFunctions.line_to = &ftLineTo;
    ftFunctions.conic_to = &ftConicTo;
    ftFunctions.cubic_to = &ftCubicTo;
    ftFunctions.shift = 0;
    ftFunctions.delta = 0;
    error = FT_Outline_Decompose(&font->face->glyph->outline, &ftFunctions, &context);
    if (error)
        return false;
    return true;
}
예제 #3
0
파일: ftrandom.c 프로젝트: Ahbee/Cinder
  static void
  TestFace( FT_Face  face )
  {
    unsigned int  gid;
    int           load_flags = FT_LOAD_DEFAULT;


    if ( check_outlines         &&
         FT_IS_SCALABLE( face ) )
      load_flags = FT_LOAD_NO_BITMAP;

    if ( nohints )
      load_flags |= FT_LOAD_NO_HINTING;

    FT_Set_Char_Size( face, 0, font_size, 72, 72 );

    for ( gid = 0; gid < face->num_glyphs; gid++ )
    {
      if ( check_outlines         &&
           FT_IS_SCALABLE( face ) )
      {
        if ( !FT_Load_Glyph( face, gid, load_flags ) )
          FT_Outline_Decompose( &face->glyph->outline, &outlinefuncs, NULL );
      }
      else
        FT_Load_Glyph( face, gid, load_flags );

      if ( rasterize )
        FT_Render_Glyph( face->glyph, ft_render_mode_normal );
    }

    FT_Done_Face( face );
  }
예제 #4
0
status_t
ServerFont::GetGlyphShapes(const char charArray[], int32 numChars,
	BShape* shapeArray[]) const
{
	if (!charArray || numChars <= 0 || !shapeArray)
		return B_BAD_DATA;

	FT_Face face = GetTransformedFace(true, true);
	if (!face)
		return B_ERROR;

	FT_Outline_Funcs funcs;
	funcs.move_to = MoveToFunc;
	funcs.line_to = LineToFunc;
	funcs.conic_to = ConicToFunc;
	funcs.cubic_to = CubicToFunc;
	funcs.shift = 0;
	funcs.delta = 0;

	const char* string = charArray;
	for (int i = 0; i < numChars; i++) {
		shapeArray[i] = new (std::nothrow) BShape();
		if (shapeArray[i] == NULL) {
			PutTransformedFace(face);
			return B_NO_MEMORY;
		}
		FT_Load_Char(face, UTF8ToCharCode(&string), FT_LOAD_NO_BITMAP);
		FT_Outline outline = face->glyph->outline;
		FT_Outline_Decompose(&outline, &funcs, shapeArray[i]);
		shapeArray[i]->Close();
	}

	PutTransformedFace(face);
	return B_OK;
}
예제 #5
0
static void
glpath(
	int glyphno,
	GLYPH *glyf_list
)
{
	FT_Outline *ol;

	curg = &glyf_list[glyphno];

	if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING) 
	|| face->glyph->format != ft_glyph_format_outline ) {
		fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name);
		return;
	}

	ol = &face->glyph->outline;
	lastx = 0.0; lasty = 0.0;

	if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) {
		fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name);
		return;
	}

	/* FreeType does not do explicit closepath() */
	if(curg->lastentry) {
		g_closepath(curg);
	}

	if(ol->flags & ft_outline_reverse_fill) {
		assertpath(curg->entries, __FILE__, __LINE__, curg->name);
		reversepaths(curg);
	}
}
예제 #6
0
파일: rvgFont.cpp 프로젝트: ileben/RAVG
Object* Font::getGlyph (char code, const Vec2 &offset)
{
  FT_Error ftErr;
  FT_Glyph ftGlyph;
  FT_OutlineGlyph ftOutlineGlyph;

  //Set glyph size
  FT_F26Dot6 sz = ftFloatTo266( size );
  ftErr = FT_Set_Char_Size( ftFace, sz, sz, 72, 72 );
  if (ftErr)
  {
    std::cout << "Error while setting char size!" << std::endl;
    return NULL;
  }

  //Load glyph data into font face
  FT_UInt ftGlyphIndex = FT_Get_Char_Index( ftFace, (FT_ULong)code );
  ftErr = FT_Load_Glyph( ftFace, ftGlyphIndex, FT_LOAD_DEFAULT );
  if (ftErr)
  {
    std::cout << "Error while loading glyph!" << std::endl;
    return NULL;
  }

  //Get glyph from glyph slot of font face
  ftErr = FT_Get_Glyph( ftFace->glyph, &ftGlyph );
  if (ftErr)
  {
    std::cout << "Error while getting glyph from slot!" << std::endl;
    return NULL;
  }

  //Cast glyph to outline glyph
  ftOutlineGlyph = (FT_OutlineGlyph) ftGlyph;
  if (ftGlyph->format != FT_GLYPH_FORMAT_OUTLINE)
  {
    std::cout << "Error while casting glyph to outline glyph!" << std::endl;
    return NULL;
  }

  //Construct outline
  FT_Outline_Funcs ftFuncs;
  ftFuncs.move_to = ftMoveTo;
  ftFuncs.line_to = ftLineTo;
  ftFuncs.conic_to = ftQuadTo;
  ftFuncs.cubic_to = ftCubicTo;
  ftFuncs.shift = 0;
  ftFuncs.delta = 0;
  
  Object *object = new Object;
  this->object = object;
  this->offset = offset;
  ftErr = FT_Outline_Decompose( &ftOutlineGlyph->outline, &ftFuncs, this );

  //Cleanup
  FT_Done_Glyph( ftGlyph );
  return object;
}
예제 #7
0
void FreeTypeFont::init()
{
    FT_Error _error;
#if 0
    _error = FT_Set_Pixel_Sizes(_face, 32, 32);
    if (_error)
    {
        OSG_NOTICE << "FreeTypeFont3D: set pixel sizes failed ..." << std::endl;
        return;
    }
#endif
    FT_Set_Char_Size( _face, 64*64, 64*64, 600, 600);

    int glyphIndex = FT_Get_Char_Index( _face, 'M' );
    _error = FT_Load_Glyph( _face, glyphIndex, FT_LOAD_DEFAULT );
    if (_error)
    {
        OSG_NOTICE << "FreeTypeFont3D: initial glyph load failed ..." << std::endl;
        return;
    }

    if (_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
    {
        OSG_NOTICE << "FreeTypeFont3D: not a vector font" << std::endl;
        return;
    }

    {
        FreeType::Char3DInfo char3d(10);

        FT_Outline outline = _face->glyph->outline;
        FT_Outline_Funcs funcs;
        funcs.conic_to = (FT_Outline_ConicToFunc)&FreeType::conicTo;
        funcs.line_to = (FT_Outline_LineToFunc)&FreeType::lineTo;
        funcs.cubic_to = (FT_Outline_CubicToFunc)&FreeType::cubicTo;
        funcs.move_to = (FT_Outline_MoveToFunc)&FreeType::moveTo;
        funcs.shift = 0;
        funcs.delta = 0;
        _error = FT_Outline_Decompose(&outline,&funcs,&char3d);
        if (_error)
        {
            OSG_NOTICE << "FreeTypeFont3D: - outline decompose failed ..." << std::endl;
            return;
        }

        FT_BBox bb;
        FT_Outline_Get_BBox(&outline,&bb);

        long ymin = ft_floor( bb.yMin );
        long ymax = ft_ceiling( bb.yMax );
        double height = double(ymax - ymin)/64.0;

        // long xmin = ft_floor( bb.xMin );
        // long xmax = ft_ceiling( bb.xMax );
        // double width = (xmax - xmin)/64.0;
        _freetype_scale = 1.0f/height;
    }
}
예제 #8
0
void draw_bezier_outline(DiaPsRenderer *renderer,
			 int dpi_x,
			 FT_Face face,
			 FT_UInt glyph_index,
			 double pos_x,
			 double pos_y
			 )
{
  FT_Int load_flags = FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP;
  FT_Glyph glyph;
  FT_Error error;
  gchar px_buf[G_ASCII_DTOSTR_BUF_SIZE];
  gchar py_buf[G_ASCII_DTOSTR_BUF_SIZE];
  gchar d1_buf[G_ASCII_DTOSTR_BUF_SIZE];
  gchar d2_buf[G_ASCII_DTOSTR_BUF_SIZE];

  /* Need to transform */

  /* Output outline */
  FT_Outline_Funcs outlinefunc = 
    {
      paps_move_to,
      paps_line_to,
      paps_conic_to,
      paps_cubic_to
    };
  OutlineInfo outline_info;

  outline_info.glyph_origin.x = pos_x;
  outline_info.glyph_origin.y = pos_y;
  outline_info.dpi = dpi_x;
  outline_info.OUT = renderer->file;

  fprintf(renderer->file, 
	  "gsave %s %s translate %s %s scale\n",
	  g_ascii_formatd(px_buf, sizeof(px_buf), "%f", pos_x),
	  g_ascii_formatd(py_buf, sizeof(py_buf), "%f", pos_y),
	  g_ascii_formatd(d1_buf, sizeof(d1_buf), "%f", 2.54/72.0),
	  g_ascii_formatd(d2_buf, sizeof(d2_buf), "%f", -2.54/72.0) );
  fprintf(renderer->file, "start_ol\n");

  if ((error=FT_Load_Glyph(face, glyph_index, load_flags))) {
    fprintf(stderr, "Can't load glyph: %d\n", error);
    return;
  }
  if ((error=FT_Get_Glyph (face->glyph, &glyph))) {
    fprintf(stderr, "Can't get glyph: %d\n", error);
    FT_Done_Glyph (glyph);
    return;
  }
  if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
    FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline),
                          &outlinefunc, &outline_info);
  fprintf(renderer->file, "end_ol grestore \n");
  
  FT_Done_Glyph (glyph);
}
예제 #9
0
/**
 * Converts one single glyph (character, sign) into CXF.
 */
FT_Error convertGlyph(FT_ULong charcode) {
    FT_Error error;
    FT_Glyph glyph;

    // load glyph
    error = FT_Load_Glyph(face,
                          FT_Get_Char_Index(face, charcode),
                          FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE);
    if (error) {
        std::cout << "FT_Load_Glyph: error\n";
    }

    FT_Get_Glyph(face->glyph, &glyph);
    FT_OutlineGlyph og = (FT_OutlineGlyph)glyph;
    if (face->glyph->format != ft_glyph_format_outline) {
        std::cout << "not an outline font\n";
    }

    // write glyph header
    if (fpLff!=NULL) {
        fprintf(fpLff, "\n[#%04X]\n", (uint)charcode);
    }

    // trace outline of the glyph
    xMin = 1000.0;
    firstpass = true;
    error = FT_Outline_Decompose(&(og->outline), &funcs, fpLff);
    firstpass = false;
    startcontour = true;
    error = FT_Outline_Decompose(&(og->outline), &funcs, fpLff);
    if (fpLff!=NULL) {
        fprintf(fpLff, "\n");
    }

    if (error==FT_Err_Invalid_Outline) {
        std::cout << "FT_Outline_Decompose: FT_Err_Invalid_Outline\n";
    } else if (error==FT_Err_Invalid_Argument) {
        std::cout << "FT_Outline_Decompose: FT_Err_Invalid_Argument\n";
    } else if (error) {
        std::cout << "FT_Outline_Decompose: error: " << error << "\n";
    }

    return error;
}
예제 #10
0
파일: main.cpp 프로젝트: Ngassa/LibreCAD
/**
 * Converts one single glyph (character, sign) into LFF.
 */
FT_Error convertGlyph(FT_ULong charcode) {
    FT_Error error;
    FT_Glyph glyph;

    // load glyph
    error = FT_Load_Glyph(face,
                          FT_Get_Char_Index(face, charcode),
                          FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE);
    if (error) {
        std::cerr << "FT_Load_Glyph: " << FT_StrError(error) << std::endl;
        return error;
    }

    FT_Get_Glyph(face->glyph, &glyph);
    FT_OutlineGlyph og = (FT_OutlineGlyph)glyph;
    if (face->glyph->format != ft_glyph_format_outline) {
        std::cerr << "Not an outline font\n";
    }

    // write glyph header
    if (fpLff) {
        fprintf(fpLff, "\n[#%04X]\n", (unsigned)charcode);
    }

    // trace outline of the glyph
    xMin = 1000.0;
    firstpass = true;
    error = FT_Outline_Decompose(&(og->outline), &funcs, fpLff);
    firstpass = false;
    startcontour = true;
    error = FT_Outline_Decompose(&(og->outline), &funcs, fpLff);
    if (fpLff) {
        fprintf(fpLff, "\n");
    }

    if (error) {
        std::cerr << "FT_Outline_Decompose: " << FT_StrError(error) << std::endl;
    }

    return error;
}
void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path) {
    FT_Outline_Funcs    funcs;

    funcs.move_to   = move_proc;
    funcs.line_to   = line_proc;
    funcs.conic_to  = quad_proc;
    funcs.cubic_to  = cubic_proc;
    funcs.shift     = 0;
    funcs.delta     = 0;

    FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path);

    if (err != 0) {
        path->reset();
        return;
    }

    path->close();
}
예제 #12
0
static void addToGP(GPData* gpdata, FT_Outline*outline) {
    static const FT_Outline_Funcs outline_funcs = {
        (FT_Outline_MoveToFunc) moveTo,
        (FT_Outline_LineToFunc) lineTo,
        (FT_Outline_ConicToFunc) conicTo,
        (FT_Outline_CubicToFunc) cubicTo,
        0, /* shift */
        0, /* delta */
    };

    FT_Outline_Decompose(outline, &outline_funcs, gpdata);
    if (gpdata->numCoords)
        addSeg(gpdata, SEG_CLOSE);

    /* If set to 1, the outline will be filled using the even-odd fill rule */
    if (outline->flags & FT_OUTLINE_EVEN_ODD_FILL) {
        gpdata->wr = WIND_EVEN_ODD;
    }
}
예제 #13
0
static void
gimp_text_render_vectors (PangoFont     *font,
                          PangoGlyph     pango_glyph,
                          FT_Int32       flags,
                          FT_Matrix     *trafo,
                          gint           x,
                          gint           y,
                          RenderContext *context)
{
  const FT_Outline_Funcs  outline_funcs =
  {
    moveto,
    lineto,
    conicto,
    cubicto,
    0,
    0
  };

  FT_Face   face;
  FT_Glyph  glyph;

  face = pango_fc_font_lock_face (PANGO_FC_FONT (font));

  FT_Load_Glyph (face, (FT_UInt) pango_glyph, flags);

  FT_Get_Glyph (face->glyph, &glyph);

  if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
    {
      FT_OutlineGlyph outline_glyph = (FT_OutlineGlyph) glyph;

      context->offset_x = (gdouble) x / PANGO_SCALE;
      context->offset_y = (gdouble) y / PANGO_SCALE;

      FT_Outline_Decompose (&outline_glyph->outline, &outline_funcs, context);
    }

  FT_Done_Glyph (glyph);

  pango_fc_font_unlock_face (PANGO_FC_FONT (font));
}
예제 #14
0
void SWFShape_addString(SWFShape shape, const wchar_t* str, size_t nchar,
                        double fontSize,
                        FT_Face face, FT_Outline_Funcs *funs)
{
    OutlineData data;
    FT_Outline outline;
    FT_Error err;
    int i;
    
    data.shape = shape;
    data.ratio_EM = fontSize / face->units_per_EM;
    data.deltax = 0.0;

    for(i = 0; i < nchar; i++)
    {
        /* str should be Unicode */
        err = FT_Load_Char(face, str[i], FT_LOAD_NO_SCALE);
        if(err)
        {
            errorcode(err);
            continue;
        }
        outline = face->glyph->outline;
        err = FT_Outline_Decompose(&outline, funs, &data);
        if(err)
        {
            errorcode(err);
            continue;
        }
        /* After we draw a character, we move the pen right to a distance
        of the advance */
        /* See the picture in
        http://www.freetype.org/freetype2/docs/tutorial/step2.html */
        data.deltax += face->glyph->metrics.horiAdvance * data.ratio_EM;
    }
}
예제 #15
0
파일: ft_font.c 프로젝트: jnorthrup/gpac
static GF_Glyph *ft_load_glyph(GF_FontReader *dr, u32 glyph_name)
{
	GF_Glyph *glyph;
	u32 glyph_idx;
	FT_BBox bbox;
	FT_OutlineGlyph outline;
	ft_outliner outl;
	FT_Outline_Funcs ft_outl_funcs;

	FTBuilder *ftpriv = (FTBuilder *)dr->udta;
	if (!ftpriv->active_face || !glyph_name) return NULL;

	FT_Select_Charmap(ftpriv->active_face, FT_ENCODING_UNICODE);

	glyph_idx = FT_Get_Char_Index(ftpriv->active_face, glyph_name);
	/*missing glyph*/
	if (!glyph_idx) {
		GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[FreeType] Glyph not found for char %d in font %s (style %s)\n", glyph_name, ftpriv->active_face->family_name, ftpriv->active_face->style_name));
		return NULL;
	}

	/*work in design units*/
	FT_Load_Glyph(ftpriv->active_face, glyph_idx, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);

	FT_Get_Glyph(ftpriv->active_face->glyph, (FT_Glyph*)&outline);

#ifdef FT_GLYPH_FORMAT_OUTLINE
	/*oops not vectorial...*/
	if (outline->root.format != FT_GLYPH_FORMAT_OUTLINE) return NULL;
#endif


	GF_SAFEALLOC(glyph, GF_Glyph);
	GF_SAFEALLOC(glyph->path, GF_Path);

	/*setup outliner*/
	ft_outl_funcs.shift = 0;
	ft_outl_funcs.delta = 0;
	ft_outl_funcs.move_to = ft_move_to;
	ft_outl_funcs.line_to = ft_line_to;
	ft_outl_funcs.conic_to = ft_conic_to;
	ft_outl_funcs.cubic_to = ft_cubic_to;
	outl.path = glyph->path;
	outl.ftpriv = ftpriv;

	/*FreeType is marvelous and gives back the right advance on space char !!!*/
	FT_Outline_Decompose(&outline->outline, &ft_outl_funcs, &outl);

	FT_Glyph_Get_CBox((FT_Glyph) outline, ft_glyph_bbox_unscaled, &bbox);

	glyph->ID = glyph_name;
	glyph->utf_name = glyph_name;
	glyph->horiz_advance = ftpriv->active_face->glyph->metrics.horiAdvance;
	glyph->vert_advance = ftpriv->active_face->glyph->metrics.vertAdvance;
/*
	glyph->x = bbox.xMin;
	glyph->y = bbox.yMax;
*/
	glyph->width = ftpriv->active_face->glyph->metrics.width;
	glyph->height = ftpriv->active_face->glyph->metrics.height;
	FT_Done_Glyph((FT_Glyph) outline);
	return glyph;
}
예제 #16
0
파일: libpaps.c 프로젝트: Distrotech/paps
void draw_bezier_outline(paps_private_t *paps,
			 GString *layout_str,
                         FT_Face face,
                         PangoGlyphInfo *glyph_info,
                         double pos_x,
                         double pos_y)
{
  static gchar glyph_hash_string[100];
  double scale = 72.0 / PANGO_SCALE  / PAPS_DPI;
  double epsilon = 1e-2;
  double glyph_width = glyph_info->geometry.width * scale * paps->scale_x;
  gchar *id = NULL;

  /* Output outline */
  static FT_Outline_Funcs ps_outlinefunc = 
    {
      (FT_Outline_MoveToFunc)paps_ps_move_to,
      (FT_Outline_LineToFunc )paps_ps_line_to,
      (FT_Outline_ConicToFunc)paps_ps_conic_to,
      (FT_Outline_CubicToFunc)paps_ps_cubic_to
    };
  FT_Outline_Funcs *outlinefunc;
  OutlineInfo outline_info;

  get_glyph_hash_string(face,
                        glyph_info,
                        // output
                        glyph_hash_string);

  // Look up the key in the hash table
  if (!(id = g_hash_table_lookup(paps->glyph_cache,
                                 glyph_hash_string)))
    {
      FT_Int load_flags = FT_LOAD_DEFAULT;
      FT_Glyph glyph;
      GString *glyph_def_string;
      FT_Error ft_ret;

      ft_ret = FT_Load_Glyph(face, glyph_info->glyph, load_flags);

      if (ft_ret != 0
          // Sorry - No support for bitmap glyphs at the moment. :-(
          || face->glyph->format == FT_GLYPH_FORMAT_BITMAP)
        ;
      else
        {
          glyph_def_string = g_string_new("");
          
          // The key doesn't exist. Define the outline
          id = get_next_char_id_strdup(paps);
          
          // Create the outline
          outlinefunc = &ps_outlinefunc;
          outline_info.paps = paps;
          outline_info.glyph_origin.x = pos_x;
          outline_info.is_empty = 1;
          outline_info.glyph_origin.y = pos_y;
          outline_info.out_string = glyph_def_string;
          
          
          g_string_append(glyph_def_string,
                          "start_ol\n");
          
          FT_Get_Glyph (face->glyph, &glyph);
          FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline),
                                outlinefunc, &outline_info);
          
          g_string_append_printf(glyph_def_string,
                                 "%.0f fwd_x\n"
                                 "end_ol\n",
                                 glyph_info->geometry.width * scale * paps->scale_x * PAPS_DPI
                                 );
          
          // TBD - Check if the glyph_def_string is empty. If so, set the
          // id to the character to "" and don't draw it.
          if (outline_info.is_empty
              || glyph_info->glyph == 0) 
            id[0] = '*';
          else
            // Put the font in the font def dictionary
            g_string_append_printf(paps->header,
                                   "/%s { %s } def\n",
                                   id,
                                   glyph_def_string->str);
          
          g_hash_table_insert(paps->glyph_cache,
                              g_strdup(glyph_hash_string),
                              id);
          
          g_string_free(glyph_def_string, TRUE);
          FT_Done_Glyph (glyph);
        }
    }

  if (id && id[0] != '*')
    {
      glyph_width *= PAPS_DPI;
      pos_x *=PAPS_DPI;
      pos_y *= PAPS_DPI;

      // Output codes according to the ps_exec string encoding!
      if (fabs (pos_y - paps->last_pos_y ) > epsilon)
	{
	  g_string_append_printf(layout_str,
				 "+%8.0f%8.0f",
				 pos_x, pos_y
				 );
	}
      else if (fabs(pos_x - paps->last_pos_x) > epsilon)
	{
	  int dx = (int)(pos_x - paps->last_pos_x+0.5);

	  // The extra 2 factor makes the small dx encoding trigger
	  // more often...
	  if (dx > 0 && dx < 20000) 
	    g_string_append_printf(layout_str,
				   ">%4d", dx/2
				   );
	  else if (dx < 0 && dx > -20000) 
	    g_string_append_printf(layout_str,
				   "-%4d", abs(dx)/2
				   );
	  else if (dx != 0)
	    g_string_append_printf(layout_str,
				   "*%8.0f", pos_x
				   );
	}
      
      // Put character on page
      g_string_append_printf(layout_str,
			     "%s",
			     id
			     );

    }

  paps->last_pos_y = pos_y;
  paps->last_pos_x = pos_x+glyph_width; // glyph_with is added by the outline def
}
예제 #17
0
osgText::Glyph3D * FreeTypeFont::getGlyph3D(unsigned int charcode)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex());

    //
    // GT: fix for symbol fonts (i.e. the Webdings font) as the wrong character are being
    // returned, for symbol fonts in windows (FT_ENCONDING_MS_SYMBOL in freetype) the correct
    // values are from 0xF000 to 0xF0FF not from 0x000 to 0x00FF (0 to 255) as you would expect.
    // Microsoft uses a private field for its symbol fonts
    //
    unsigned int charindex = charcode;
    if (_face->charmap != NULL)
    {
        if (_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
        {
            charindex |= 0xF000;
        }
    }

    FT_Error error = FT_Load_Char( _face, charindex, FT_LOAD_DEFAULT|_flags );
    if (error)
    {
        OSG_WARN << "FT_Load_Char(...) error 0x"<<std::hex<<error<<std::dec<<std::endl;
        return 0;
    }
    if (_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
    {
        OSG_WARN << "FreeTypeFont3D::getGlyph : not a vector font" << std::endl;
        return 0;
    }

    float coord_scale = _freetype_scale/64.0f;

    // ** init FreeType to describe the glyph
    FreeType::Char3DInfo char3d(_facade->getNumberCurveSamples());
    char3d._coord_scale = coord_scale;

    FT_Outline outline = _face->glyph->outline;
    FT_Outline_Funcs funcs;
    funcs.conic_to = (FT_Outline_ConicToFunc)&FreeType::conicTo;
    funcs.line_to = (FT_Outline_LineToFunc)&FreeType::lineTo;
    funcs.cubic_to = (FT_Outline_CubicToFunc)&FreeType::cubicTo;
    funcs.move_to = (FT_Outline_MoveToFunc)&FreeType::moveTo;
    funcs.shift = 0;
    funcs.delta = 0;

    // ** record description
    FT_Error _error = FT_Outline_Decompose(&outline, &funcs, &char3d);
    if (_error)
    {
        OSG_WARN << "FreeTypeFont3D::getGlyph : - outline decompose failed ..." << std::endl;
        return 0;
    }

    // ** create geometry for each part of the glyph
    osg::ref_ptr<osg::Geometry> frontGeo(new osg::Geometry);

    osg::ref_ptr<osg::Vec3Array> rawVertices = new osg::Vec3Array(*(char3d._verts));
    osg::Geometry::PrimitiveSetList rawPrimitives;
    for(osg::Geometry::PrimitiveSetList::iterator itr = char3d.get()->getPrimitiveSetList().begin();
        itr != char3d.get()->getPrimitiveSetList().end();
        ++itr)
    {
        rawPrimitives.push_back(dynamic_cast<osg::PrimitiveSet*>((*itr)->clone(osg::CopyOp::DEEP_COPY_ALL)));
    }

    // ** save vertices and PrimitiveSetList of each face in the Glyph3D PrimitiveSet face list
    osg::ref_ptr<osgText::Glyph3D> glyph3D = new osgText::Glyph3D(_facade, charcode);

    // copy the raw primitive set list before we tessellate it.
    glyph3D->getRawFacePrimitiveSetList() = rawPrimitives;
    glyph3D->setRawVertexArray(rawVertices.get());


    FT_Glyph_Metrics* metrics = &(_face->glyph->metrics);

    glyph3D->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX * coord_scale,(float)(metrics->horiBearingY-metrics->height) * coord_scale)); // bottom left.
    glyph3D->setHorizontalAdvance((float)metrics->horiAdvance * coord_scale);
    glyph3D->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX * coord_scale,(float)(metrics->vertBearingY-metrics->height) * coord_scale)); // top middle.
    glyph3D->setVerticalAdvance((float)metrics->vertAdvance * coord_scale);

    glyph3D->setWidth((float)metrics->width * coord_scale);
    glyph3D->setHeight((float)metrics->height * coord_scale);

    FT_BBox ftbb;
    FT_Outline_Get_BBox(&outline, &ftbb);

    long xmin = ft_floor( ftbb.xMin );
    long xmax = ft_ceiling( ftbb.xMax );
    long ymin = ft_floor( ftbb.yMin );
    long ymax = ft_ceiling( ftbb.yMax );

    osg::BoundingBox bb(xmin * coord_scale, ymin * coord_scale, 0.0f, xmax * coord_scale, ymax * coord_scale, 0.0f);

    glyph3D->setBoundingBox(bb);

    return glyph3D.release();
}
예제 #18
0
void font_instance::LoadGlyph(int glyph_id)
{
    if ( pFont == NULL ) {
        return;
    }
    InitTheFace();
#ifndef USE_PANGO_WIN32
    if ( !FT_IS_SCALABLE(theFace) ) {
        return; // bitmap font
    }
#endif

    if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
        Geom::PathBuilder path_builder;

        if ( nbGlyph >= maxGlyph ) {
            maxGlyph=2*nbGlyph+1;
            glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph));
        }
        font_glyph  n_g;
        n_g.pathvector=NULL;
        n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0;
        n_g.h_advance = 0;
        n_g.v_advance = 0;
        n_g.h_width = 0;
        n_g.v_width = 0;
        bool   doAdd=false;

#ifdef USE_PANGO_WIN32

#ifndef GGO_UNHINTED         // For compatibility with old SDKs.
#define GGO_UNHINTED 0x0100
#endif

        MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
        OUTLINETEXTMETRIC otm;
        GetOutlineTextMetrics(daddy->hScreenDC, sizeof(otm), &otm);
        GLYPHMETRICS metrics;
        DWORD bufferSize=GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity);
        double scale=1.0/daddy->fontSize;
        n_g.h_advance=metrics.gmCellIncX*scale;
        n_g.v_advance=otm.otmTextMetrics.tmHeight*scale;
        n_g.h_width=metrics.gmBlackBoxX*scale;
        n_g.v_width=metrics.gmBlackBoxY*scale;
        if ( bufferSize == GDI_ERROR) {
            // shit happened
        } else if ( bufferSize == 0) {
            // character has no visual representation, but is valid (eg whitespace)
            doAdd=true;
        } else {
            char *buffer = new char[bufferSize];
            if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer, &identity) <= 0 ) {
                // shit happened
            } else {
                // Platform SDK is rubbish, read KB87115 instead
                DWORD polyOffset=0;
                while ( polyOffset < bufferSize ) {
                    TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer+polyOffset);
                    if (polyOffset+polyHeader->cb > bufferSize) break;

                    if (polyHeader->dwType == TT_POLYGON_TYPE) {
                        path_builder.moveTo(pointfx_to_nrpoint(polyHeader->pfxStart, scale));
                        DWORD curveOffset=polyOffset+sizeof(TTPOLYGONHEADER);

                        while ( curveOffset < polyOffset+polyHeader->cb ) {
                            TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer+curveOffset);
                            POINTFX const *p=polyCurve->apfx;
                            POINTFX const *endp=p+polyCurve->cpfx;

                            switch (polyCurve->wType) {
                            case TT_PRIM_LINE:
                                while ( p != endp )
                                    path_builder.lineTo(pointfx_to_nrpoint(*p++, scale));
                                break;

                            case TT_PRIM_QSPLINE:
                                {
                                    g_assert(polyCurve->cpfx >= 2);

                                    // The list of points specifies one or more control points and ends with the end point.
                                    // The intermediate points (on the curve) are the points between the control points.
                                    Geom::Point this_control = pointfx_to_nrpoint(*p++, scale);
                                    while ( p+1 != endp ) { // Process all "midpoints" (all points except the last)
                                        Geom::Point new_control = pointfx_to_nrpoint(*p++, scale);
                                        path_builder.quadTo(this_control, (new_control+this_control)/2);
                                        this_control = new_control;
                                    }
                                    Geom::Point end = pointfx_to_nrpoint(*p++, scale);
                                    path_builder.quadTo(this_control, end);
                                }
                                break;

                            case 3:  // TT_PRIM_CSPLINE
                                g_assert(polyCurve->cpfx % 3 == 0);
                                while ( p != endp ) {
                                    path_builder.curveTo(pointfx_to_nrpoint(p[0], scale),
                                                         pointfx_to_nrpoint(p[1], scale),
                                                         pointfx_to_nrpoint(p[2], scale));
                                    p += 3;
                                }
                                break;
                            }
                            curveOffset += sizeof(TTPOLYCURVE)+sizeof(POINTFX)*(polyCurve->cpfx-1);
                        }
                    }
                    polyOffset += polyHeader->cb;
                }
                doAdd=true;
            }
            delete [] buffer;
        }
#else
        if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) {
            // shit happened
        } else {
            if ( FT_HAS_HORIZONTAL(theFace) ) {
                n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM);
                n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM);
            } else {
                n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM);
            }
            if ( FT_HAS_VERTICAL(theFace) ) {
                n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM);
                n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM);
            } else {
                n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM);
            }
            if ( theFace->glyph->format == ft_glyph_format_outline ) {
                FT_Outline_Funcs ft2_outline_funcs = {
                    ft2_move_to,
                    ft2_line_to,
                    ft2_conic_to,
                    ft2_cubic_to,
                    0, 0
                };
                FT2GeomData user(path_builder, 1.0/((double)theFace->units_per_EM));
                FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &user);
            }
            doAdd=true;
        }
#endif
        path_builder.finish();

        if ( doAdd ) {
            Geom::PathVector pv = path_builder.peek();
            // close all paths
            for (Geom::PathVector::iterator i = pv.begin(); i != pv.end(); ++i) {
                i->close();
            }
            if ( !pv.empty() ) {
                n_g.pathvector = new Geom::PathVector(pv);
                Geom::OptRect bounds = bounds_exact(*n_g.pathvector);
                if (bounds) {
                    n_g.bbox[0] = bounds->left();
                    n_g.bbox[1] = bounds->top();
                    n_g.bbox[2] = bounds->right();
                    n_g.bbox[3] = bounds->bottom();
                }
            }
            glyphs[nbGlyph]=n_g;
            id_to_no[glyph_id]=nbGlyph;
            nbGlyph++;
        }
    } else {
    }
}
예제 #19
0
//******************** M A I N ************************
void get_font(string FontName_base, char letter, int ptsize, vect2d *times)
{
    _mkdir("font_rasters");
    std::string FontName = "fonts/" + FontName_base + ".ttf";
    char buf[256];
    string letter_name;
    letter_name += letter;
    if (letter >= 'A' && letter <= 'Z')
        letter_name += letter;

    //-----------------------------------------
    // Load contour of glyph
    //-----------------------------------------

    lines.clear();
    bez2s.clear();

    FT_Face face;
    FT_Library    library;
    FT_Error error;

    error = FT_Init_FreeType( &library );
    Check(error, "", "error initializing FT lib");

    error = FT_New_Face( library, FontName.c_str(), 0, &face );
    Check(error, "",  "error loading font");

    FT_F26Dot6 font_size = ptsize*64;
    error = FT_Set_Char_Size( face, font_size, font_size, 72, 72 );
    Check(error, "", "error setting char size");

    FT_UInt   glyph_index = FT_Get_Char_Index( face, letter );
    FT_Int32  load_flags = FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
    error = FT_Load_Glyph( face,  glyph_index, load_flags );
    Check(error, "", "error loading glyph");

    FT_Glyph glyph;
    error = FT_Get_Glyph( face->glyph, &glyph );
    Check(error, "", "error getting glyph");

    FT_OutlineGlyph Outg;
    error = GetOutLine(glyph, &Outg);
    Check(error,"", "error getting outline");

    // use my own callcacks to walk over the contour
    FT_Outline_Funcs func_interface;
    func_interface.shift = 0;
    func_interface.delta = 0;
    func_interface.move_to = move_to;
    func_interface.line_to = line_to;
    func_interface.conic_to = conic_to;
    func_interface.cubic_to = cubic_to;
    FT_Outline_Decompose(&Outg->outline, &func_interface, 0);

    //-----------------------------------------
    // Rasterize using FreeType
    //-----------------------------------------

    // rasterize using FreeType so that a comparison to my code can be made
    double t_ft_start = get_time();
    FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
    double t_ft_stop = get_time();

    // save timing
    FILE *fa = fopen("timings.txt", "a");
    fprintf(fa, "time FreeType = %f\n", t_ft_stop - t_ft_start);
    fclose(fa);

    // create grid / calculate resolution
    g.max_depth = 0;
    g.grid_res = 2;

    int maxsize = max(face->glyph->bitmap.width, face->glyph->bitmap.rows);
    while (g.grid_res < maxsize)
    {
        g.grid_res *= 2;
        g.max_depth++;
    }

    vect2i offset;
    offset.set((g.grid_res - face->glyph->bitmap.width) / 2, (g.grid_res - face->glyph->bitmap.rows) / 2);

    // copy bitmap into a buffer
    Array2D<vect3ub> ftgrid;
    ftgrid.resize(g.grid_res, g.grid_res);

    for (int k = 0; k < g.grid_res*g.grid_res; k++)
        ftgrid.data[k].set(0);

    for (int j = 0; j < face->glyph->bitmap.rows; j++)
    {
        unsigned char *row = face->glyph->bitmap.buffer + (face->glyph->bitmap.rows-j-1)*face->glyph->bitmap.pitch;

        for (int i = 0; i < face->glyph->bitmap.width; i++)
        {
            ftgrid(i + offset[0], j + offset[1]) = row[i];
        }
    }

    sprintf(buf, "font_rasters/%s_%04d_%s_1_ft.png", FontName_base.c_str(), ptsize, letter_name.c_str());
    save_png(buf, ftgrid);

    //-----------------------------------------
    // Rasterize using our method
    //-----------------------------------------

    // get bbox
    FT_BBox bbox;
    FT_Outline_Get_BBox(&Outg->outline, &bbox);
    //printf("bbox = (%f, %f), (%f, %f)\n", bbox.xMin/64., bbox.yMin/64., bbox.xMax/64., bbox.yMax/64.);

    // fit in box
    vect2f ext;
    ext.set(bbox.xMax/64. - bbox.xMin/64., bbox.yMax/64. - bbox.yMin/64.);
    float maxext = std::max(ext[0], ext[1]) * 1.1;

    for (int i = 0; i < lines.s; i++)
    {
        //printf("line\n");
        for (int j = 0; j < 2; j++)
        {
            lines[i][j][0] = (lines[i][j][0] - floor(bbox.xMin/64.) + offset[0]) / g.grid_res;
            lines[i][j][1] = (lines[i][j][1] - floor(bbox.yMin/64.) + offset[1]) / g.grid_res;
            //printf("%f %f\n", lines[i][j][0], lines[i][j][1]);
        }
    }
    for (int i = 0; i < bez2s.s; i++)
    {
        //printf("bez2\n");
        for (int j = 0; j < 3; j++)
        {
            bez2s[i][j][0] = (bez2s[i][j][0] - floor(bbox.xMin/64.) + offset[0]) / g.grid_res;
            bez2s[i][j][1] = (bez2s[i][j][1] - floor(bbox.yMin/64.) + offset[1]) / g.grid_res;
            //printf("%f %f\n", bez2s[i][j][0], bez2s[i][j][1]);
        }
    }

    //vect3ub *grid = new vect3ub [g.grid_res*g.grid_res];
    Array2D<float> grid;
    Array2D<vect3ub> ourgrid;
    grid.resize(g.grid_res, g.grid_res);
    ourgrid.resize(g.grid_res, g.grid_res);

    // rasterize
    for (int k = 0; k < g.grid_res*g.grid_res; k++)
        grid.data[k] = 0;
    double t_ours_start = get_time();
    raster_poly(lines, bez2s, grid.data);
    double t_ours_stop = get_time();

    // save timing
    FILE *f = fopen("timings.txt", "a");
    fprintf(f, "time wavelet = %f\n", (t_ours_stop - t_ours_start));
    fclose(f);

    // copy into color image and save
    for (int k = 0; k < g.grid_res*g.grid_res; k++)
    {
        if (grid.data[k] >= 1)
            ourgrid.data[k] = 255;
        else if (grid.data[k] <= 0)
            ourgrid.data[k] = 0;
        else
            ourgrid.data[k] = grid.data[k]*255;
    }
    sprintf(buf, "font_rasters/%s_%04d_%s_2_ours.png", FontName_base.c_str(), ptsize, letter_name.c_str());
    save_png(buf, ourgrid);

    //-----------------------------------------
    // Calculate difference between renders
    //-----------------------------------------
    Array2D<vect3ub> grid_dif;
    grid_dif.resize(g.grid_res, g.grid_res);

    for (int i = 0; i < grid_dif.data_size; i++)
    {
        int dif = (grid.data[i]*255 - ftgrid.data[i][0]) * 10;
        if (dif > 255)
            dif = 255;
        else if (dif < -255)
            dif = -255;

#if 1
        grid_dif.data[i] = 255;

        if (dif < 0)
        {
            grid_dif.data[i][0] += dif;
            grid_dif.data[i][1] += dif;
        }
        else
        {
            grid_dif.data[i][1] -= dif;
            grid_dif.data[i][2] -= dif;
        }
#else
        grid_dif.data[i] = 0;

        if (dif < 0)
            grid_dif.data[i][2] -= dif;
        else
            grid_dif.data[i][0] += dif;
#endif
    }

    sprintf(buf, "font_rasters/%s_%04d_%s_3_dif.png", FontName_base.c_str(), ptsize, letter_name.c_str());
    save_png(buf, grid_dif);

    //printf("--== timing comparison ==--\n");
    //printf("time freetype = %f\n", t_ft_stop - t_ft_start);
    //printf("time wavelets = %f\n", t_ours_stop - t_ours_start);
    //printf("times slower = %f\n", (t_ours_stop - t_ours_start) / (t_ft_stop - t_ft_start) );

    if (times)
    {
        times->v[0] += t_ft_stop - t_ft_start;
        times->v[1] += t_ours_stop - t_ours_start;
    }
}
JNIEXPORT jobject JNICALL 
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphOutlineNative
 (JNIEnv *env, jobject obj __attribute__((unused)), jint glyphIndex, jlong fnt)
{
  generalpath *path;
  jobject gp;
  FT_Outline_Funcs ftCallbacks =
    {
      (FT_Outline_MoveToFunc) _moveTo,
      (FT_Outline_LineToFunc) _lineTo,
      (FT_Outline_ConicToFunc) _quadTo,
      (FT_Outline_CubicToFunc) _curveTo,
      0,
      0
    };
  PangoFcFont *font;
  FT_Face ft_face;
  FT_Glyph glyph;

  font = JLONG_TO_PTR(PangoFcFont, fnt);
  ft_face = pango_fc_font_lock_face( font );

  g_assert (ft_face != NULL);

  path = g_malloc0 (sizeof (generalpath));
  g_assert(path != NULL);
  path->env = env;

  path->px = path->py = 0.0;
  path->sx = 1.0/64.0;
  path->sy = -1.0/64.0;

  {  /* create a GeneralPath instance */
    jclass cls;
    jmethodID method;
    
    cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
    method = (*env)->GetMethodID (env, cls, "<init>", "()V");
    gp = path->obj = (*env)->NewObject (env, cls, method);
  }
	      
  if(FT_Load_Glyph(ft_face,
		   (FT_UInt)(glyphIndex),
		   FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP) != 0)
    {
      pango_fc_font_unlock_face( font );
      g_free(path); 
      return NULL;
    }

  FT_Get_Glyph( ft_face->glyph, &glyph );
  if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
    {
      FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline),
			    &ftCallbacks, path);
    }
  else
    {
      char format[5];

      format[0] = (glyph->format & 0xFF000000) >> 24;
      format[1] = (glyph->format & 0x00FF0000) >> 16;
      format[2] = (glyph->format & 0x0000FF00) >> 8;
      format[3] = (glyph->format & 0x000000FF);
      format[4] = '\0';
      printf("WARNING: Unable to create outline for font %s %s of format %s\n",
	     ft_face->family_name, ft_face->style_name, format);
    }
  FT_Done_Glyph( glyph );
  
  pango_fc_font_unlock_face( font );

  g_free(path); 

  return gp; 
}
예제 #21
0
// lookup glyph and extract all the shapes required to draw the outline
long int Ttt::render_char(FT_Face face, wchar_t c, long int offset, int linescale) {
    int error;
    int glyph_index;
    FT_Outline outline;
    FT_Outline_Funcs func_interface;

    error = FT_Set_Pixel_Sizes(face, 4096, linescale ? linescale : 64); if(error) handle_ft_error("FT_Set_Pixel_Sizes", error, __LINE__);
    /* lookup glyph */
    glyph_index = FT_Get_Char_Index(face, (FT_ULong)c); if(!glyph_index) handle_ft_error("FT_Get_Char_Index", 0, __LINE__);
    
    /* load glyph */
    error = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); if(error) handle_ft_error("FT_Load_Glyph", error, __LINE__);
    error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO); if(error) handle_ft_error("FT_Render_Glyph", error, __LINE__);
    
    if(linescale > 0) // this is for the "zigzag" fill of letters?
        my_draw_bitmap(&face->glyph->bitmap, 
                       face->glyph->bitmap_left + offset,
                       face->glyph->bitmap_top,
                       linescale);

    error = FT_Set_Pixel_Sizes(face, 0, 64); if(error) handle_ft_error("FT_Set_Pixel_Sizes", error, __LINE__);
    error = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); if(error) handle_ft_error("FT_Load_Glyph", error, __LINE__);

    /* shortcut to the outline for our desired character */
    outline = face->glyph->outline;

    /* set up entries in the interface used by FT_Outline_Decompose() */
    func_interface.shift = 0;
    func_interface.delta = 0;
    func_interface.move_to = move_to_wrapper;
    func_interface.line_to = line_to_wrapper;
    func_interface.conic_to = conic_to_wrapper;
    func_interface.cubic_to = cubic_to_wrapper;

    /* offset the outline to the correct position in x */
    FT_Outline_Translate( &outline, offset, 0L );

    /* plot the current character */
    error = FT_Outline_Decompose( &outline, &func_interface, NULL);  if(error) handle_ft_error("FT_Outline_Decompose", error, __LINE__);

    /* save advance in a global */
    advance.x = face->glyph->advance.x;
    advance.y = face->glyph->advance.y;
    
    /*
    FT_Bool use_kerning = FT_HAS_KERNING( face );
    std::cout << " not using kerning \n";
    if ( use_kerning && previous ) {
        FT_Vector kerning;
        error = FT_Get_Kerning( face, // handle to face object  
                                previous_glyph_index, // left glyph index  
                                glyph_index, // right glyph index  
                                FT_KERNING_DEFAULT, // kerning mode   FT_KERNING_DEFAULT , FT_KERNING_UNFITTED , FT_KERNING_UNSCALED
                                &kerning ); // target vector
        std::cout << " kerning x-advance: " << kerning.x << "\n";
    }
    */
    /*
    FT_Vector kerning; 
    error = FT_Get_Kerning( face, // handle to face object  
                            left, // left glyph index  
                            right, // right glyph index  
                            kerning_mode, // kerning mode   FT_KERNING_DEFAULT , FT_KERNING_UNFITTED , FT_KERNING_UNSCALED
                            &kerning ); // target vector 
    */
    
    // delete glyph with FT_Done_Glyph?
    
    previous = true; // we have a prev glyph, for kerning
    previous_glyph_index = glyph_index; 
    
    /* offset will get bumped up by the x size of the char just plotted */
    return face->glyph->advance.x;
}
예제 #22
0
파일: ttf.cpp 프로젝트: Kenzu/solvespace
void TtfFont::PlotString(const std::string &str,
                         SBezierList *sbl, Vector origin, Vector u, Vector v)
{
    ssassert(fontFace != NULL, "Expected font face to be loaded");

    FT_Pos dx = 0;
    for(char32_t chr : ReadUTF8(str)) {
        uint32_t gid = FT_Get_Char_Index(fontFace, chr);
        if (gid == 0) {
            dbp("freetype: CID-to-GID mapping for CID 0x%04x failed: %s; using CID as GID",
                chr, ft_error_string(gid));
        }

        FT_F26Dot6 scale = fontFace->units_per_EM;
        if(int fterr = FT_Set_Char_Size(fontFace, scale, scale, 72, 72)) {
            dbp("freetype: cannot set character size: %s",
                ft_error_string(fterr));
            return;
        }

        /*
         * Stupid hacks:
         *  - if we want fake-bold, use FT_Outline_Embolden(). This actually looks
         *    quite good.
         *  - if we want fake-italic, apply a shear transform [1 s s 1 0 0] here using
         *    FT_Set_Transform. This looks decent at small font sizes and bad at larger
         *    ones, antialiasing mitigates this considerably though.
         */
        if(int fterr = FT_Load_Glyph(fontFace, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) {
            dbp("freetype: cannot load glyph (gid %d): %s",
                gid, ft_error_string(fterr));
            return;
        }

        /* A point that has x = xMin should be plotted at (dx0 + lsb); fix up
         * our x-position so that the curve-generating code will put stuff
         * at the right place.
         *
         * There's no point in getting the glyph BBox here - not only can it be
         * needlessly slow sometimes, but because we're about to render a single glyph,
         * what we want actually *is* the CBox.
         *
         * This is notwithstanding that this makes extremely little sense, this
         * looks like a workaround for either mishandling the start glyph on a line,
         * or as a really hacky pseudo-track-kerning (in which case it works better than
         * one would expect! especially since most fonts don't set track kerning).
         */
        FT_BBox cbox;
        FT_Outline_Get_CBox(&fontFace->glyph->outline, &cbox);
        FT_Pos bx = dx - cbox.xMin;
        // Yes, this is what FreeType calls left-side bearing.
        // Then interchangeably uses that with "left-side bearing". Sigh.
        bx += fontFace->glyph->metrics.horiBearingX;

        OutlineData data = {};
        data.origin  = origin;
        data.u       = u;
        data.v       = v;
        data.beziers = sbl;
        data.factor  = 1.0f/(float)scale;
        data.bx      = bx;
        if(int fterr = FT_Outline_Decompose(&fontFace->glyph->outline, &outline_funcs, &data)) {
            dbp("freetype: bezier decomposition failed (gid %d): %s",
                gid, ft_error_string(fterr));
        }

        // And we're done, so advance our position by the requested advance
        // width, plus the user-requested extra advance.
        dx += fontFace->glyph->advance.x;
    }
}
예제 #23
0
bool FontParser::parseFontFile(GXFont *font ,  const std::string &filename )
{
    if ( font == nullptr)
        return false;
    
    if (!FileSystem::fileExists( filename ))
        return false;

    
    FT_Face face;
    
    int faceIndex = 0;
    
    if( FT_New_Face( _library, filename.c_str(), faceIndex, &face ) != 0 )
    {
        Log::log("couldn't load new face\n");
        return false;
    }
    
    font->m_fileName = filename;
    
    if (face->family_name != NULL)
        font->m_fontName = face->family_name;
    else
        font->m_fontName = "No Name";

    font->m_fontName += " ";
    
    if  (face->style_name != NULL)
        font->m_fontName += face->style_name;
    else
        font->m_fontName += " No Style";
    
    
    FT_Set_Char_Size(
                     face,     
                     0 ,                              /* char_width in 1/64th of points  */
                     64*64,                           /* char_height in 1/64th of points */
                     HorizontalDeviceResolution ,     /* horizontal device resolution    */
                     VerticalDeviceResolution         /* vertical device resolution      */
                     );
    
   
    int num_glyphs = 0;
    
    int descent = face->descender;
    
    if (descent <0)
        descent *= -1;
    
    font->m_lineSpace = face->ascender + descent +  face->height;

    for(int cc = 0 ; cc<256 ; cc++ )
    {

        
        
        if( cc < 32 )
            continue;   //discard the first 32 characters
        
        int glyphIndex = FT_Get_Char_Index( face, cc );
        
        if( !FT_Load_Glyph( face, glyphIndex, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING | FT_LOAD_IGNORE_TRANSFORM ) )
        {
            GXGlyph *glyph = new GXGlyph(); // empty
            
            glyph->m_advanceX = (float) ( face->glyph->advance.x );
            glyph->m_advanceY = (float) ( face->glyph->advance.y );
            
            if( cc == ' ' )
            {

            }
            
            else
            {
                _functions.delta = 0;
                _functions.shift = 0;
                
                FT_Outline_Decompose( &face->glyph->outline, &_functions , glyph );

            }
            
            font->addChar(cc, glyph);
            
            num_glyphs++;
        }
    }
    if(! num_glyphs )
        Log::log("warning: no glyphs found\n");
    


    
    FT_Done_Face( face );
    return true;
}
예제 #24
0
SWFFONT* swf_LoadTrueTypeFont(const char*filename, char flashtype)
{
    FT_Face face;
    FT_Error error;
    const char* name = 0;
    FT_ULong charcode;
    FT_UInt gindex;
    SWFFONT* font;
    int t;
    int*glyph2glyph;
    int max_unicode = 0;
    int charmap = -1;

    if(ftlibrary == 0) {
	if(FT_Init_FreeType(&ftlibrary)) {
	    fprintf(stderr, "Couldn't init freetype library!\n");
	    exit(1);
	}
    }
    error = FT_New_Face(ftlibrary, filename, 0, &face);

    if(error || !face) {
	fprintf(stderr, "Couldn't load file %s- not a TTF file?\n", filename);
	return 0;
    }
   
    int scale = flashtype?20:1;
    FT_Set_Pixel_Sizes (face, 16*loadfont_scale*scale, 16*loadfont_scale*scale);

    if(face->num_glyphs <= 0) {
	fprintf(stderr, "File %s contains %d glyphs\n", filename, (int)face->num_glyphs);
	return 0;
    }

    font = (SWFFONT*)rfx_calloc(sizeof(SWFFONT));
    font->id = -1;
    font->version = flashtype?3:2;

    font->layout = (SWFLAYOUT*)rfx_calloc(sizeof(SWFLAYOUT));
    font->layout->bounds = (SRECT*)rfx_calloc(face->num_glyphs*sizeof(SRECT));
    font->style =  ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0)
	          |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
    font->encoding = FONT_ENCODING_UNICODE;
    font->glyph2ascii = (U16*)rfx_calloc(face->num_glyphs*sizeof(U16));
    font->maxascii = 0;
    font->glyph = (SWFGLYPH*)rfx_calloc(face->num_glyphs*sizeof(SWFGLYPH));
    if(FT_HAS_GLYPH_NAMES(face)) {
	font->glyphnames = (char**)rfx_calloc(face->num_glyphs*sizeof(char*));
    }
    
    font->layout->kerningcount = 0;
    
    name = face->family_name;
    if(!(name && *name))
        name = FT_Get_Postscript_Name(face);
    if(name && *name)
	font->name = (U8*)strdup(name);

    while(1) 
    {
    /*    // Map Glyphs to Unicode, version 1 (quick and dirty):
	int t;
	for(t=0;t<65536;t++) {
	    int index = FT_Get_Char_Index(face, t);
	    if(index>=0 && index<face->num_glyphs) {
		if(font->glyph2ascii[index]<0)
		    font->glyph2ascii[index] = t;
	    }
	}*/
	
	// Map Glyphs to Unicode, version 2 (much nicer):
	// (The third way would be the AGL algorithm, as proposed
	//  by Werner Lemberg on [email protected])

	charcode = FT_Get_First_Char(face, &gindex);
	while(gindex != 0)
	{
	    if(gindex >= 0 && gindex<face->num_glyphs) {
		if(!font->glyph2ascii[gindex]) {
		    font->glyph2ascii[gindex] = charcode;
		    if(charcode + 1 > font->maxascii) {
			font->maxascii = charcode + 1;
		    }
		}
	    }
	    charcode = FT_Get_Next_Char(face, charcode, &gindex);
	}

	/* if we didn't find a single encoding character, try
	   the font's charmaps instead. That usually means that
	   the encoding is no longer unicode. 
	   TODO: find a way to convert the encoding to unicode
	 */
	if(font->maxascii == 0 && charmap < face->num_charmaps - 1) {
	    charmap++;
	    FT_Set_Charmap(face, face->charmaps[charmap]);
	    font->encoding = 0;//anything but unicode FIXME
	} else 
	    break;
    }

    if(full_unicode)
	font->maxascii = 65535;
    
    font->ascii2glyph = (int*)rfx_calloc(font->maxascii*sizeof(int));
    
    for(t=0;t<font->maxascii;t++) {
	int g = FT_Get_Char_Index(face, t);
	if(!g || g>=face->num_glyphs)
	    g = -1;
	font->ascii2glyph[t] = g;
	if(g>=0) {
	    max_unicode = t+1;
	    if(!font->glyph2ascii[g]) {
		font->glyph2ascii[g] = t;
	    }
	}
    }
    font->maxascii = max_unicode;

    font->numchars = 0;

    glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int));

    SRECT fontbbox = {0,0,0,0};

    for(t=0; t < face->num_glyphs; t++) {
	FT_Glyph glyph;
	FT_BBox bbox;
	char name[128];
	drawer_t draw;
	char hasname = 0;
	name[0]=0;
	if(FT_HAS_GLYPH_NAMES(face)) {
	    error = FT_Get_Glyph_Name(face, t, name, 127);
	    if(!error && name[0] && !strstr(name, "notdef")) {
		font->glyphnames[font->numchars] = strdup(name);
		hasname = 1;
	    }
	}
	if(!font->glyph2ascii[t] && !hasname && skip_unused) {
	    continue;
	}
	error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
	if(error) {
	    //tends to happen with some pdfs
	    fprintf(stderr, "Warning: Glyph %d has return code %d\n", t, error);
	    glyph=0;
	    if(skip_unused) 
		continue;
	} else {
	    error = FT_Get_Glyph(face->glyph, &glyph);
	    if(error) {
		fprintf(stderr, "Couldn't get glyph %d, error:%d\n", t, error);
		glyph=0;
		if(skip_unused) 
		    continue;
	    }
	}

	if(glyph)
	    FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &bbox);
	else
	    memset(&bbox, 0, sizeof(bbox));

	bbox.yMin = -bbox.yMin;
	bbox.yMax = -bbox.yMax;
	if(bbox.xMax < bbox.xMin) {
	    // swap
	    bbox.xMax ^= bbox.xMin;
	    bbox.xMin ^= bbox.xMax;
	    bbox.xMax ^= bbox.xMin;
	}
	if(bbox.yMax < bbox.yMin) {
	    // swap
	    bbox.yMax ^= bbox.yMin;
	    bbox.yMin ^= bbox.yMax;
	    bbox.yMax ^= bbox.yMin;
	}

	swf_Shape01DrawerInit(&draw, 0);

	//error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw);
	if(glyph)
	    error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw);
	else
	    error = 0;
	draw.finish(&draw);
	
	if(error) {
	    fprintf(stderr, "Couldn't decompose glyph %d\n", t);
	    draw.dealloc(&draw);
	    continue;
	}

#if 0
	if(bbox.xMin > 0) {
	    font->glyph[font->numchars].advance = (bbox.xMax*20*FT_SCALE)/FT_SUBPIXELS;
	} else {
	    font->glyph[font->numchars].advance = ((bbox.xMax - bbox.xMin)*20*FT_SCALE)/FT_SUBPIXELS;
	}
#else
	if(glyph)
	    font->glyph[font->numchars].advance = glyph->advance.x*20/65536;
	else
	    font->glyph[font->numchars].advance = 0;
#endif
	
	SRECT b = swf_ShapeDrawerGetBBox(&draw);

	//font->layout->bounds[font->numchars].xmin = (bbox.xMin*FT_SCALE*20)/FT_SUBPIXELS;
	//font->layout->bounds[font->numchars].ymin = (bbox.yMin*FT_SCALE*20)/FT_SUBPIXELS;
	//font->layout->bounds[font->numchars].xmax = (bbox.xMax*FT_SCALE*20)/FT_SUBPIXELS;
	//font->layout->bounds[font->numchars].ymax = (bbox.yMax*FT_SCALE*20)/FT_SUBPIXELS;

	font->layout->bounds[font->numchars] = b;
	font->glyph[font->numchars].shape = swf_ShapeDrawerToShape(&draw);

	swf_ExpandRect2(&fontbbox, &font->layout->bounds[font->numchars]);

	draw.dealloc(&draw);

	if(glyph)
	    FT_Done_Glyph(glyph);
	font->glyph2ascii[font->numchars] = font->glyph2ascii[t];
	glyph2glyph[t] = font->numchars;
	font->numchars++;
    }
    
    //font->layout->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin;
    //font->layout->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax;
    //font->layout->leading = font->layout->ascent + font->layout->descent;

    if(-fontbbox.ymin < 0)
        font->layout->ascent = 0;
    else
	font->layout->ascent = -fontbbox.ymin;

    if(fontbbox.ymax < 0)
        font->layout->descent = 0;
    else
	font->layout->descent = fontbbox.ymax;

    int leading = fontbbox.ymax - fontbbox.ymin;
    font->layout->leading = leading>0x7fff?0x7fff:leading;

    /* notice: if skip_unused is true, font->glyph2ascii, font->glyphnames and font->layout->bounds will 
	       have more memory allocated than just font->numchars, but only the first font->numchars 
	       are used/valid */

    for(t=0;t<font->maxascii;t++) {
	if(font->ascii2glyph[t]>=0) {
	    font->ascii2glyph[t] = glyph2glyph[font->ascii2glyph[t]];
	}
    }
    rfx_free(glyph2glyph);

    FT_Done_Face(face);
    FT_Done_FreeType(ftlibrary);ftlibrary=0;

    return font;
}
예제 #25
0
static PyObject*
Py_Outline_to_points_and_codes(Py_Outline* self, PyObject* args, PyObject* kwds)
{
    PyObject *result = NULL;
    PyObject *points = NULL;
    PyObject *codes = NULL;
    DecomposeToPointsAndCodesData data;
    const FT_Outline_Funcs funcs = {
        .move_to = Py_Outline_to_points_and_codes_moveto_func,
        .line_to = Py_Outline_to_points_and_codes_lineto_func,
        .conic_to = Py_Outline_to_points_and_codes_conicto_func,
        .cubic_to = Py_Outline_to_points_and_codes_cubicto_func,

        .shift = 0,
        .delta = 0
    };
    int error;

    if (!self->points || !self->codes) {
        memset(&data, 0, sizeof(DecomposeToPointsAndCodesData));

        error = FT_Outline_Decompose(&self->x, &funcs, &data);
        if (PyErr_Occurred()) {
            PyMem_Free(data.points);
            PyMem_Free(data.codes);
            goto exit;
        } else if (ftpy_exc(error)) {
            PyMem_Free(data.points);
            PyMem_Free(data.codes);
            goto exit;
        }

        self->points = data.points;
        self->codes = data.codes;
        self->n_points = data.cursor;
    }

    points = Py_Outline_Decomposed_Points_Buffer_cnew((PyObject *)self);
    if (points == NULL) {
        goto exit;
    }

    codes = Py_Outline_Codes_Buffer_cnew((PyObject *)self);
    if (codes == NULL) {
        Py_DECREF(points);
        goto exit;
    }

    result = Py_BuildValue("(OO)", points, codes);
    if (result == NULL) {
        Py_DECREF(points);
        Py_DECREF(codes);
        goto exit;
    }

 exit:

    return result;
}


static PyObject*
Py_Outline_to_string(Py_Outline* self, PyObject* args, PyObject* kwds)
{
    PyObject *result = NULL;
    DecomposeToStringData data;
    const FT_Outline_Funcs funcs = {
        .move_to = Py_Outline_to_string_moveto_func,
        .line_to = Py_Outline_to_string_lineto_func,
        .conic_to = Py_Outline_to_string_conicto_func,
        .cubic_to = Py_Outline_to_string_cubicto_func,

        .shift = 0,
        .delta = 0
    };
    int error;

    const char* keywords[] = {
        "move_command", "line_command", "cubic_command", "conic_command",
        "prefix", NULL};

    data.prefix = 0;
    data.conic_command = NULL;

    if (!PyArg_ParseTupleAndKeywords(
            args, kwds, "sss|si:to_string", (char **)keywords,
            &data.move_command, &data.line_command,
            &data.cubic_command, &data.conic_command,
            &data.prefix)) {
        return NULL;
    }

    data.buffer = PyMem_Malloc(BUFFER_CHUNK_SIZE);
    if (data.buffer == NULL) {
        return NULL;
    }
    data.buffer[0] = 0;
    data.buffer_size = BUFFER_CHUNK_SIZE;
    data.cursor = 0;
    data.last_x = 0;
    data.last_y = 0;

    error = FT_Outline_Decompose(&self->x, &funcs, &data);
    if (PyErr_Occurred()) {
        goto exit;
    } else if (ftpy_exc(error)) {
        goto exit;
    }

    result = PyBytes_FromStringAndSize(data.buffer, data.cursor);
    if (result == NULL) {
        goto exit;
    }

 exit:
    PyMem_Free(data.buffer);

    return result;
}


static PyObject*
Py_Outline_translate(Py_Outline* self, PyObject* args, PyObject* kwds)
{
    long xOffset;
    long yOffset;

    /* TODO: What is the scale of these arguments? */

    const char* keywords[] = {"x_offset", "y_offset", NULL};

    if (!PyArg_ParseTupleAndKeywords(
            args, kwds, "ll:translate", (char **)keywords,
            &xOffset, &yOffset)) {
        return NULL;
    }

    FT_Outline_Translate(&self->x, xOffset, yOffset);

    Py_RETURN_NONE;
};
예제 #26
0
static PyObject*
Py_Outline_decompose(Py_Outline* self, PyObject* args, PyObject* kwds)
{
    /* TODO: Also implement this as an iterator */

    DecomposeData data;
    PyObject *obj;
    const FT_Outline_Funcs funcs = {
        .move_to = Py_Outline_moveto_func,
        .line_to = Py_Outline_lineto_func,
        .conic_to = Py_Outline_conicto_func,
        .cubic_to = Py_Outline_cubicto_func,

        .shift = 0,
        .delta = 0
    };
    int error;

    const char* keywords[] = {"obj", "shift", "delta", NULL};

    if (!PyArg_ParseTupleAndKeywords(
            args, kwds, "O|ii:decompose", (char **)keywords,
            &obj, &funcs.shift, &funcs.delta)) {
        return NULL;
    }

    if (!PyObject_HasAttrString(obj, "move_to")) {
        PyErr_SetString(PyExc_AttributeError, "obj has no move_to method");
        return NULL;
    }
    if (!PyObject_HasAttrString(obj, "line_to")) {
        PyErr_SetString(PyExc_AttributeError, "obj has no line_to method");
        return NULL;
    }
    if (!PyObject_HasAttrString(obj, "cubic_to")) {
        PyErr_SetString(PyExc_AttributeError, "obj has no cubic_to method");
        return NULL;
    }
    data.has_conic_to = PyObject_HasAttrString(obj, "conic_to");
    data.callback = obj;
    data.last_x = 0;
    data.last_y = 0;

    error = FT_Outline_Decompose(&self->x, &funcs, &data);
    if (PyErr_Occurred()) {
        return NULL;
    } else if (ftpy_exc(error)) {
        return NULL;
    }

    Py_RETURN_NONE;
};


static PyObject*
Py_Outline_embolden(Py_Outline* self, PyObject* args, PyObject* kwds)
{
    double strength;

    const char* keywords[] = {"strength", NULL};

    if (!PyArg_ParseTupleAndKeywords(
            args, kwds, "d:embolden", (char **)keywords,
            &strength)) {
        return NULL;
    }

    if (ftpy_exc(
            FT_Outline_Embolden(&self->x, TO_F26DOT6(strength)))) {
        return NULL;
    }

    Py_RETURN_NONE;
};