Exemple #1
1
void
WriteGlyphAsTGA(FT_Library &library,
                const std::string &fileName,
                wchar_t ch,
                FT_Face &face,
                int size,
                const Pixel32 &fontCol,
                const Pixel32 outlineCol,
                float outlineWidth)
{
	// Set the size to use.
	if (FT_Set_Char_Size(face, size << 6, size << 6, 90, 90) == 0)
	{
		// Load the glyph we are looking for.
		FT_UInt gindex = FT_Get_Char_Index(face, ch);
		if (FT_Load_Glyph(face, gindex, FT_LOAD_NO_BITMAP) == 0)
		{
			// Need an outline for this to work.
			if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
			{
				// Render the basic glyph to a span list.
				Spans spans;
				RenderSpans(library, &face->glyph->outline, &spans);

				// Next we need the spans for the outline.
				Spans outlineSpans;

				// Set up a stroker.
				FT_Stroker stroker;
				FT_Stroker_New(library, &stroker);
				FT_Stroker_Set(stroker,
					       (int)(outlineWidth * 64),
					       FT_STROKER_LINECAP_ROUND,
					       FT_STROKER_LINEJOIN_ROUND,
					       0);

				FT_Glyph glyph;
				if (FT_Get_Glyph(face->glyph, &glyph) == 0)
				{
					FT_Glyph_StrokeBorder(&glyph, stroker, 0, 1);
					// Again, this needs to be an outline to work.
					if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
					{
						// Render the outline spans to the span list
						FT_Outline *o =
						  &reinterpret_cast<FT_OutlineGlyph>(glyph)->outline;
						RenderSpans(library, o, &outlineSpans);
					}

					// Clean up afterwards.
					FT_Stroker_Done(stroker);
					FT_Done_Glyph(glyph);

					// Now we need to put it all together.
					if (!spans.empty())
					{
						// Figure out what the bounding rect is for both the span lists.
						Rect rect(spans.front().x,
							  spans.front().y,
							  spans.front().x,
							  spans.front().y);
						for (Spans::iterator s = spans.begin();
						     s != spans.end(); ++s)
						{
							rect.Include(Vec2(s->x, s->y));
							rect.Include(Vec2(s->x + s->width - 1, s->y));
						}
						for (Spans::iterator s = outlineSpans.begin();
						     s != outlineSpans.end(); ++s)
						{
							rect.Include(Vec2(s->x, s->y));
							rect.Include(Vec2(s->x + s->width - 1, s->y));
						}

#if 0
						// This is unused in this test but you would need this to draw
						// more than one glyph.
						float bearingX = face->glyph->metrics.horiBearingX >> 6;
						float bearingY = face->glyph->metrics.horiBearingY >> 6;
						float advance = face->glyph->advance.x >> 6;
#endif

						// Get some metrics of our image.
						int imgWidth = rect.Width(),
						  imgHeight = rect.Height(),
						  imgSize = imgWidth * imgHeight;

						// Allocate data for our image and clear it out to transparent.
						Pixel32 *pxl = new Pixel32[imgSize];
						memset(pxl, 0, sizeof(Pixel32) * imgSize);

						// Loop over the outline spans and just draw them into the
						// image.
						for (Spans::iterator s = outlineSpans.begin();
						     s != outlineSpans.end(); ++s)
						  for (int w = 0; w < s->width; ++w)
						    pxl[(int)((imgHeight - 1 - (s->y - rect.ymin)) * imgWidth
							      + s->x - rect.xmin + w)] =
						      Pixel32(outlineCol.r, outlineCol.g, outlineCol.b,
							      s->coverage);

						// Then loop over the regular glyph spans and blend them into
						// the image.
						for (Spans::iterator s = spans.begin();
						     s != spans.end(); ++s)
						  for (int w = 0; w < s->width; ++w)
						  {
							  Pixel32 &dst =
							    pxl[(int)((imgHeight - 1 - (s->y - rect.ymin)) * imgWidth
								      + s->x - rect.xmin + w)];
							  Pixel32 src = Pixel32(fontCol.r, fontCol.g, fontCol.b,
										s->coverage);
							  dst.r = (int)(dst.r + ((src.r - dst.r) * src.a) / 255.0f);
							  dst.g = (int)(dst.g + ((src.g - dst.g) * src.a) / 255.0f);
							  dst.b = (int)(dst.b + ((src.b - dst.b) * src.a) / 255.0f);
							  dst.a = MIN(255, dst.a + src.a);
						  }

						// Dump the image to disk.
						WriteTGA(fileName, pxl, imgWidth, imgHeight);

						delete [] pxl;
					}
				}
	void Glyph::SetOutline(FT_Library& library, int outlineThickness)
	{
		_error = FT_Stroker_New(library, &_stroker);
		if (_error)
			return;

		FT_Stroker_Set(_stroker, outlineThickness * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);

		_error = FT_Glyph_StrokeBorder(&_glyph, _stroker, false, true);
		if (_error)
			return;


		FT_Raster_Params params;
		memset(&params, 0, sizeof(params));

		params.target = 0;
		params.flags = FT_RASTER_FLAG_DIRECT | FT_RASTER_FLAG_AA;
		params.user = this;
		params.gray_spans = Glyph::SpanCallback;

		FT_OutlineGlyph outlineGlyph = reinterpret_cast<FT_OutlineGlyph>(_glyph);

		_error = FT_Outline_Render(library, &outlineGlyph->outline, &params);
		if (_error)
			return;
	}
Exemple #3
0
/**
 * \brief Change border width
 *
 * \param render_priv renderer state object
 * \param info glyph state object
 */
void change_border(ASS_Renderer *render_priv, double border_x, double border_y)
{
    int bord = 64 * border_x * render_priv->border_scale;

    if (bord > 0 && border_x == border_y) {
        if (!render_priv->state.stroker) {
            int error;
            error =
                FT_Stroker_New(render_priv->ftlibrary,
                               &render_priv->state.stroker);
            if (error) {
                ass_msg(render_priv->library, MSGL_V,
                        "failed to get stroker");
                render_priv->state.stroker = 0;
            }
            render_priv->state.stroker_radius = -1.0;
        }
        if (render_priv->state.stroker && render_priv->state.stroker_radius != bord) {
            FT_Stroker_Set(render_priv->state.stroker, bord,
                           FT_STROKER_LINECAP_ROUND,
                           FT_STROKER_LINEJOIN_ROUND, 0);
            render_priv->state.stroker_radius = bord;
        }
    } else {
        FT_Stroker_Done(render_priv->state.stroker);
        render_priv->state.stroker = 0;
    }
}
Exemple #4
0
unsigned create_freetype_font()
{
    if(!s_freetype) {
		unsigned error = FT_Init_FreeType( &s_freetype);
  		if(!error) error = FT_Stroker_New(s_freetype, &m_stroker ); 		
		if(error)return error;
    }
	return 0;
}
stroker_ptr freetype_engine::create_stroker()
{
    FT_Stroker s;
    FT_Error error = FT_Stroker_New(library_, &s);
    if (!error)
    {
        return std::make_shared<stroker>(s);
    }
    return stroker_ptr();
}
Exemple #6
0
stroker_ptr freetype_engine::create_stroker()
{
    FT_Stroker s;
    FT_Error error = FT_Stroker_New(library_, &s); 
    if (!error)
    {
        return stroker_ptr(new stroker(s));
    }
    return stroker_ptr();
}
  FTDemo_Handle*
  FTDemo_New( void )
  {
    FTDemo_Handle*  handle;


    handle = (FTDemo_Handle *)malloc( sizeof ( FTDemo_Handle ) );
    if ( !handle )
      return NULL;

    memset( handle, 0, sizeof ( FTDemo_Handle ) );

    error = FT_Init_FreeType( &handle->library );
    if ( error )
      PanicZ( "could not initialize FreeType" );

    error = FTC_Manager_New( handle->library, 0, 0, 0,
                             my_face_requester, 0, &handle->cache_manager );
    if ( error )
      PanicZ( "could not initialize cache manager" );

    error = FTC_SBitCache_New( handle->cache_manager, &handle->sbits_cache );
    if ( error )
      PanicZ( "could not initialize small bitmaps cache" );

    error = FTC_ImageCache_New( handle->cache_manager, &handle->image_cache );
    if ( error )
      PanicZ( "could not initialize glyph image cache" );

    error = FTC_CMapCache_New( handle->cache_manager, &handle->cmap_cache );
    if ( error )
      PanicZ( "could not initialize charmap cache" );

    FT_Bitmap_New( &handle->bitmap );

    FT_Stroker_New( handle->library, &handle->stroker );

    handle->encoding = FT_ENCODING_NONE;

    handle->hinted    = 1;
    handle->antialias = 1;
    handle->use_sbits = 1;
    handle->autohint  = 0;
    handle->lcd_mode  = 0;
    handle->color     = 1;

    handle->use_sbits_cache = 1;

    /* string_init */
    memset( handle->string, 0, sizeof ( TGlyph ) * MAX_GLYPHS );
    handle->string_length = 0;
    handle->string_reload = 1;

    return handle;
  }
Exemple #8
0
  FT_Stroker GetStroker()
  {
    if (!m_library)
      return NULL;

    FT_Stroker stroker;
    if (FT_Stroker_New(m_library, &stroker))
      return NULL;

    return stroker;
  };
JNIEXPORT jlong JNICALL Java_com_badlogic_gdx_graphics_g2d_freetype_FreeType_00024Library_strokerNew(JNIEnv* env, jclass clazz, jlong library) {


//@line:104

			FT_Stroker stroker;
			FT_Error error = FT_Stroker_New((FT_Library)library, &stroker);
			if(error) return 0;
			else return (jlong)stroker;
		

}
Exemple #10
0
Font::Font(u32 Size, const char *Font_Path, Minimum *min){
	FontColor = COLOR_BLACK;
	FontSize = Size;
	Lenght = 0;
	m = min;
	FT_Init_FreeType(&library);
	FT_New_Face(library,Font_Path,0,&face);
	FT_Stroker_New(library,&stroker);
	Kerning = FT_HAS_KERNING(face);
	FT_Set_Pixel_Sizes(face,0,FontSize);
	font=0;
}
Exemple #11
0
bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
{
    // Cleanup the previous resources
    cleanup();
    m_refCount = new int(1);

    // Initialize FreeType
    // Note: we initialize FreeType for every font instance in order to avoid having a single
    // global manager that would create a lot of issues regarding creation and destruction order.
    FT_Library library;
    if (FT_Init_FreeType(&library) != 0)
    {
        err() << "Failed to load font from memory (failed to initialize FreeType)" << std::endl;
        return false;
    }
    m_library = library;

    // Load the new font face from the specified file
    FT_Face face;
    if (FT_New_Memory_Face(static_cast<FT_Library>(m_library), reinterpret_cast<const FT_Byte*>(data), static_cast<FT_Long>(sizeInBytes), 0, &face) != 0)
    {
        err() << "Failed to load font from memory (failed to create the font face)" << std::endl;
        return false;
    }

    // Load the stroker that will be used to outline the font
    FT_Stroker stroker;
    if (FT_Stroker_New(static_cast<FT_Library>(m_library), &stroker) != 0)
    {
        err() << "Failed to load font from memory (failed to create the stroker)" << std::endl;
        FT_Done_Face(face);
        return false;
    }

    // Select the Unicode character map
    if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
    {
        err() << "Failed to load font from memory (failed to set the Unicode character set)" << std::endl;
        FT_Stroker_Done(stroker);
        FT_Done_Face(face);
        return false;
    }

    // Store the loaded font in our ugly void* :)
    m_stroker = stroker;
    m_face = face;

    // Store the font information
    m_info.family = face->family_name ? face->family_name : std::string();

    return true;
}
void SubtitleRenderer::
initialize_fonts(const std::string& font_path, float font_size) {
  ENFORCE(!FT_Init_FreeType(&ft_library_));
  ENFORCE2(!FT_New_Face(ft_library_, font_path.c_str(), 0, &ft_face_),
           "Unable to open font");
  ENFORCE(!FT_Set_Pixel_Sizes(ft_face_, 0, font_size*screen_height_));

  auto get_bbox = [this](char32_t cp) {
    auto glyph_index = FT_Get_Char_Index(ft_face_, cp);
    ENFORCE(!FT_Load_Glyph(ft_face_, glyph_index, FT_LOAD_NO_HINTING));
    FT_Glyph glyph;
    ENFORCE(!FT_Get_Glyph(ft_face_->glyph, &glyph));
    SCOPE_EXIT {FT_Done_Glyph(glyph);};
    FT_BBox bbox;
    FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox);
    return bbox;
  };

  constexpr float padding_factor = 0.05f;
  int y_min = get_bbox('g').yMin;
  int y_max = get_bbox('M').yMax;
  y_max += -y_min*0.7f;
  line_height_ = y_max - y_min;
  const int v_padding = line_height_*padding_factor + 0.5f;
  line_height_ += v_padding*2;
  box_offset_ = y_min-v_padding;
  box_h_padding_ = line_height_/5.0f + 0.5f;


  constexpr float border_thickness = 0.045f;
  ENFORCE(!FT_Stroker_New(ft_library_, &ft_stroker_));
  FT_Stroker_Set(ft_stroker_,
                 line_height_*border_thickness*64.0f,
                 FT_STROKER_LINECAP_ROUND,
                 FT_STROKER_LINEJOIN_ROUND,
                 0);

  vgSeti(VG_FILTER_FORMAT_LINEAR, VG_TRUE);
  assert(!vgGetError());

  vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED);
  assert(!vgGetError());

  auto create_vg_font = [](VGFont& font) {
    font = vgCreateFont(128);
    ENFORCE(font);
  };

  create_vg_font(vg_font_);
  create_vg_font(vg_font_border_);
}
face_manager::face_manager(font_library & library,
                           freetype_engine::font_file_mapping_type const& font_file_mapping,
                           freetype_engine::font_memory_cache_type const& font_cache)
    : face_cache_(new face_cache()),
      library_(library),
      font_file_mapping_(font_file_mapping),
      font_memory_cache_(font_cache)
      {
            FT_Stroker s;
            FT_Error error = FT_Stroker_New(library_.get(), &s);
            if (!error)
            {
                stroker_ = std::make_shared<stroker>(s);
            }
      }
Exemple #14
0
Font::Font(const void *MemFont, u32 MemFont_size, Minimum *min){
	FontColor = COLOR_BLACK;
	FontSize = DEFAULT_FONT_SIZE;
	Pointer = (FT_Byte*)MemFont;
	Lenght = MemFont_size;
	m = min;

	FT_Init_FreeType(&library);
	FT_New_Memory_Face(library,Pointer,Lenght,0,&face);
	FT_Stroker_New(library,&stroker);
	Kerning = FT_HAS_KERNING(face);
	FT_Set_Pixel_Sizes(face,0,FontSize);
	
	font=0;
}
Exemple #15
0
fontRenderClass::fontRenderClass(): fb(fbClass::getInstance())
{
	instance=this;
	eDebug("[FONT] initializing lib...");
	{
		if (FT_Init_FreeType(&library))
		{
			eDebug("[FONT] initializing failed.");
			return;
		}
	}
	eDebug("[FONT] loading fonts...");
	fflush(stdout);
	font=0;
	
	int maxbytes=4*1024*1024;
	eDebug("[FONT] Intializing font cache, using max. %dMB...", maxbytes/1024/1024);
	fflush(stdout);
	{
		if (FTC_Manager_New(library, 8, 8, maxbytes, myFTC_Face_Requester, this, &cacheManager))
		{
			eDebug("[FONT] initializing font cache failed!");
			return;
		}
		if (!cacheManager)
		{
			eDebug("[FONT] initializing font cache manager error.");
			return;
		}
		if (FTC_SBit_Cache_New(cacheManager, &sbitsCache))
		{
			eDebug("[FONT] initializing font cache sbit failed!");
			return;
		}
		if (FTC_Image_Cache_New(cacheManager, &imageCache))
		{
			eDebug("[FONT] initializing font cache imagecache failed!");
		}
		if (FT_Stroker_New(library, &stroker))
		{
			eDebug("[FONT] initializing font stroker failed!");
		}
	}
	strokerRadius = -1;
	return;
}
void SubtitleRenderer::
initialize_fonts(const std::string& font_path,
                 const std::string& italic_font_path,
                 unsigned int font_size) {
  ENFORCE(!FT_Init_FreeType(&ft_library_));
  ENFORCE2(!FT_New_Face(ft_library_, font_path.c_str(), 0, &ft_face_),
           "Unable to open font");
  ENFORCE2(!FT_New_Face(ft_library_, italic_font_path.c_str(), 0, &ft_face_italic_),
           "Unable to open italic font");
  ENFORCE(!FT_Set_Pixel_Sizes(ft_face_, 0, font_size));
  ENFORCE(!FT_Set_Pixel_Sizes(ft_face_italic_, 0, font_size));

  auto get_bbox = [this](char32_t cp) {
    auto glyph_index = FT_Get_Char_Index(ft_face_, cp);
    ENFORCE(!FT_Load_Glyph(ft_face_, glyph_index, FT_LOAD_NO_HINTING));
    FT_Glyph glyph;
    ENFORCE(!FT_Get_Glyph(ft_face_->glyph, &glyph));
    SCOPE_EXIT {FT_Done_Glyph(glyph);};
    FT_BBox bbox;
    FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox);
    return bbox;
  };

  constexpr float padding_factor = 0.05f;
  int y_min = get_bbox('g').yMin;
  int y_max = get_bbox('M').yMax;
  y_max += -y_min*0.7f;
  line_height_ = y_max - y_min;
  const int v_padding = line_height_*padding_factor + 0.5f;
  line_height_ += v_padding*2;
  box_offset_ = y_min-v_padding;
  box_h_padding_ = line_height_/5.0f + 0.5f;


  constexpr float border_thickness = 0.044f;
  ENFORCE(!FT_Stroker_New(ft_library_, &ft_stroker_));
  FT_Stroker_Set(ft_stroker_,
                 line_height_*border_thickness*64.0f,
                 FT_STROKER_LINECAP_ROUND,
                 FT_STROKER_LINEJOIN_ROUND,
                 0);
}
Exemple #17
0
/**
 * \brief Change border width
 * negative value resets border to style value
 */
void change_border(ASS_Renderer *render_priv, double border_x,
                   double border_y)
{
    int bord;
    if (!render_priv->state.font)
        return;

    if (border_x < 0 && border_y < 0) {
        if (render_priv->state.style->BorderStyle == 1 ||
            render_priv->state.style->BorderStyle == 3)
            border_x = border_y = render_priv->state.style->Outline;
        else
            border_x = border_y = 1.;
    }

    render_priv->state.border_x = border_x;
    render_priv->state.border_y = border_y;

    bord = 64 * border_x * render_priv->border_scale;
    if (bord > 0 && border_x == border_y) {
        if (!render_priv->state.stroker) {
            int error;
            error =
                FT_Stroker_New(render_priv->ftlibrary,
                               &render_priv->state.stroker);
            if (error) {
                ass_msg(render_priv->library, MSGL_V,
                        "failed to get stroker");
                render_priv->state.stroker = 0;
            }
        }
        if (render_priv->state.stroker)
            FT_Stroker_Set(render_priv->state.stroker, bord,
                           FT_STROKER_LINECAP_ROUND,
                           FT_STROKER_LINEJOIN_ROUND, 0);
    } else {
        FT_Stroker_Done(render_priv->state.stroker);
        render_priv->state.stroker = 0;
    }
}
Exemple #18
0
Font::Font(const int ID, Minimum *min){
	const char *Font_Path;
	if(ID==JPN)
		Font_Path = "/dev_flash/data/font/SCE-PS3-NR-R-JPN.TTF";
	else if(ID==KOR)	
		Font_Path = "/dev_flash/data/font/SCE-PS3-YG-R-KOR.TTF";
	else if(ID==CGB)
		Font_Path = "/dev_flash/data/font/SCE-PS3-DH-R-CGB.TTF";
	else if(ID==KANA)
		Font_Path =  "/dev_flash/data/font/SCE-PS3-CP-R-KANA.TTF";
	else
		Font_Path = "/dev_flash/data/font/SCE-PS3-VR-R-LATIN2.TTF";

	FontColor = COLOR_BLACK;
	FontSize = DEFAULT_FONT_SIZE;
	Lenght = 0;
	m = min;
	FT_Init_FreeType(&library);
	FT_New_Face(library,Font_Path,0,&face);
	FT_Stroker_New(library,&stroker);
	Kerning = FT_HAS_KERNING(face);
	FT_Set_Pixel_Sizes(face,0,FontSize);
	font=0;
}
Exemple #19
0
Stroker::Stroker(Library & library)
{
    FT_Stroker_New(library.id_, &id_);
}
Exemple #20
0
static av_cold int init(AVFilterContext *ctx)
{
    int err;
    DrawTextContext *s = ctx->priv;
    Glyph *glyph;

    if (!s->fontfile && !CONFIG_LIBFONTCONFIG) {
        av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
        return AVERROR(EINVAL);
    }

    if (s->textfile) {
        if (s->text) {
            av_log(ctx, AV_LOG_ERROR,
                   "Both text and text file provided. Please provide only one\n");
            return AVERROR(EINVAL);
        }
        if ((err = load_textfile(ctx)) < 0)
            return err;
    }

    if (s->reload && !s->textfile)
        av_log(ctx, AV_LOG_WARNING, "No file to reload\n");

    if (s->tc_opt_string) {
        int ret = av_timecode_init_from_string(&s->tc, s->tc_rate,
                                               s->tc_opt_string, ctx);
        if (ret < 0)
            return ret;
        if (s->tc24hmax)
            s->tc.flags |= AV_TIMECODE_FLAG_24HOURSMAX;
        if (!s->text)
            s->text = av_strdup("");
    }

    if (!s->text) {
        av_log(ctx, AV_LOG_ERROR,
               "Either text, a valid file or a timecode must be provided\n");
        return AVERROR(EINVAL);
    }

#if CONFIG_LIBFRIBIDI
    if (s->text_shaping)
        if ((err = shape_text(ctx)) < 0)
            return err;
#endif

    if ((err = FT_Init_FreeType(&(s->library)))) {
        av_log(ctx, AV_LOG_ERROR,
               "Could not load FreeType: %s\n", FT_ERRMSG(err));
        return AVERROR(EINVAL);
    }

    err = load_font(ctx);
    if (err)
        return err;
    if (!s->fontsize)
        s->fontsize = 16;
    if ((err = FT_Set_Pixel_Sizes(s->face, 0, s->fontsize))) {
        av_log(ctx, AV_LOG_ERROR, "Could not set font size to %d pixels: %s\n",
               s->fontsize, FT_ERRMSG(err));
        return AVERROR(EINVAL);
    }

    if (s->borderw) {
        if (FT_Stroker_New(s->library, &s->stroker)) {
            av_log(ctx, AV_LOG_ERROR, "Coult not init FT stroker\n");
            return AVERROR_EXTERNAL;
        }
        FT_Stroker_Set(s->stroker, s->borderw << 6, FT_STROKER_LINECAP_ROUND,
                       FT_STROKER_LINEJOIN_ROUND, 0);
    }

    s->use_kerning = FT_HAS_KERNING(s->face);

    /* load the fallback glyph with code 0 */
    load_glyph(ctx, NULL, 0);

    /* set the tabsize in pixels */
    if ((err = load_glyph(ctx, &glyph, ' ')) < 0) {
        av_log(ctx, AV_LOG_ERROR, "Could not set tabsize.\n");
        return err;
    }
    s->tabsize *= glyph->advance;

    if (s->exp_mode == EXP_STRFTIME &&
        (strchr(s->text, '%') || strchr(s->text, '\\')))
        av_log(ctx, AV_LOG_WARNING, "expansion=strftime is deprecated.\n");

    av_bprint_init(&s->expanded_text, 0, AV_BPRINT_SIZE_UNLIMITED);
    av_bprint_init(&s->expanded_fontcolor, 0, AV_BPRINT_SIZE_UNLIMITED);

    return 0;
}
Exemple #21
0
bool Font::loadFromFile(const std::string& filename)
{
    #ifndef SFML_SYSTEM_ANDROID

    // Cleanup the previous resources
    cleanup();
    m_refCount = new int(1);

    // Initialize FreeType
    // Note: we initialize FreeType for every font instance in order to avoid having a single
    // global manager that would create a lot of issues regarding creation and destruction order.
    FT_Library library;
    if (FT_Init_FreeType(&library) != 0)
    {
        err() << "Failed to load font \"" << filename << "\" (failed to initialize FreeType)" << std::endl;
        return false;
    }
    m_library = library;

    // Load the new font face from the specified file
    FT_Face face;
    if (FT_New_Face(static_cast<FT_Library>(m_library), filename.c_str(), 0, &face) != 0)
    {
        err() << "Failed to load font \"" << filename << "\" (failed to create the font face)" << std::endl;
        return false;
    }

    // Load the stroker that will be used to outline the font
    FT_Stroker stroker;
    if (FT_Stroker_New(static_cast<FT_Library>(m_library), &stroker) != 0)
    {
        err() << "Failed to load font \"" << filename << "\" (failed to create the stroker)" << std::endl;
        FT_Done_Face(face);
        return false;
    }

    // Select the unicode character map
    if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
    {
        err() << "Failed to load font \"" << filename << "\" (failed to set the Unicode character set)" << std::endl;
        FT_Stroker_Done(stroker);
        FT_Done_Face(face);
        return false;
    }

    // Store the loaded font in our ugly void* :)
    m_stroker = stroker;
    m_face = face;

    // Store the font information
    m_info.family = face->family_name ? face->family_name : std::string();

    return true;

    #else

    if (m_stream)
        delete (priv::ResourceStream*)m_stream;

    m_stream = new priv::ResourceStream(filename);
    return loadFromStream(*(priv::ResourceStream*)m_stream);

    #endif
}
Exemple #22
0
bool Font::loadFromStream(InputStream& stream)
{
    // Cleanup the previous resources
    cleanup();
    m_refCount = new int(1);

    // Initialize FreeType
    // Note: we initialize FreeType for every font instance in order to avoid having a single
    // global manager that would create a lot of issues regarding creation and destruction order.
    FT_Library library;
    if (FT_Init_FreeType(&library) != 0)
    {
        err() << "Failed to load font from stream (failed to initialize FreeType)" << std::endl;
        return false;
    }
    m_library = library;

    // Make sure that the stream's reading position is at the beginning
    stream.seek(0);

    // Prepare a wrapper for our stream, that we'll pass to FreeType callbacks
    FT_StreamRec* rec = new FT_StreamRec;
    std::memset(rec, 0, sizeof(*rec));
    rec->base               = NULL;
    rec->size               = static_cast<unsigned long>(stream.getSize());
    rec->pos                = 0;
    rec->descriptor.pointer = &stream;
    rec->read               = &read;
    rec->close              = &close;

    // Setup the FreeType callbacks that will read our stream
    FT_Open_Args args;
    args.flags  = FT_OPEN_STREAM;
    args.stream = rec;
    args.driver = 0;

    // Load the new font face from the specified stream
    FT_Face face;
    if (FT_Open_Face(static_cast<FT_Library>(m_library), &args, 0, &face) != 0)
    {
        err() << "Failed to load font from stream (failed to create the font face)" << std::endl;
        delete rec;
        return false;
    }

    // Load the stroker that will be used to outline the font
    FT_Stroker stroker;
    if (FT_Stroker_New(static_cast<FT_Library>(m_library), &stroker) != 0)
    {
        err() << "Failed to load font from stream (failed to create the stroker)" << std::endl;
        FT_Done_Face(face);
        delete rec;
        return false;
    }

    // Select the Unicode character map
    if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
    {
        err() << "Failed to load font from stream (failed to set the Unicode character set)" << std::endl;
        FT_Done_Face(face);
        FT_Stroker_Done(stroker);
        delete rec;
        return false;
    }

    // Store the loaded font in our ugly void* :)
    m_stroker = stroker;
    m_face = face;
    m_streamRec = rec;

    // Store the font information
    m_info.family = face->family_name ? face->family_name : std::string();

    return true;
}
Exemple #23
0
    // ----------------------------------------------- texture_font_load_glyphs ---
    size_t
    texture_font_load_glyphs( texture_font_t * self,
                              const wchar_t * charcodes )
    {
        size_t i, j, x, y, width, height, depth, w, h;

        FT_Library library;
        FT_Error error;
        FT_Face face;
        FT_Glyph ft_glyph;
        FT_GlyphSlot slot;
        FT_Bitmap ft_bitmap;

        FT_UInt glyph_index;
        texture_glyph_t *glyph;
        FT_Int32 flags = 0;
        int ft_glyph_top = 0;
        int ft_glyph_left = 0;

        ivec4 region;
        size_t missed = 0;
        char pass;

        assert( self );
        assert( charcodes );


        width  = self->atlas->width;
        height = self->atlas->height;
        depth  = self->atlas->depth;

        if (!texture_font_get_face(self, &library, &face))
            return wcslen(charcodes);

        /* Load each glyph */
        for( i = 0; i < wcslen(charcodes); ++i ) {
            pass = 0;
            /* Check if charcode has been already loaded */
            for( j = 0; j < self->glyphs->size; ++j ) {
                glyph = *(texture_glyph_t **) vector_get( self->glyphs, j );
                // If charcode is -1, we don't care about outline type or thickness
                // if( (glyph->charcode == charcodes[i])) {
                if( (glyph->charcode == charcodes[i]) &&
                    ((charcodes[i] == (wchar_t)(-1) ) ||
                     ((glyph->outline_type == self->outline_type) &&
                      (glyph->outline_thickness == self->outline_thickness)) ))
                {
                    pass = 1;
                    break;
                }
            }

            if(pass)
                continue;

            flags = 0;
            ft_glyph_top = 0;
            ft_glyph_left = 0;
            glyph_index = FT_Get_Char_Index( face, charcodes[i] );
            // WARNING: We use texture-atlas depth to guess if user wants
            //          LCD subpixel rendering

            if( self->outline_type > 0 )
            {
                flags |= FT_LOAD_NO_BITMAP;
            }
            else
            {
                flags |= FT_LOAD_RENDER;
            }

            if( !self->hinting )
            {
                flags |= FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
            }
            else
            {
                flags |= FT_LOAD_FORCE_AUTOHINT;
            }


            if( depth == 3 )
            {
                FT_Library_SetLcdFilter( library, FT_LCD_FILTER_LIGHT );
                flags |= FT_LOAD_TARGET_LCD;
                if( self->filtering )
                {
                    FT_Library_SetLcdFilterWeights( library, self->lcd_weights );
                }
            }

            error = FT_Load_Glyph( face, glyph_index, flags );
            if( error )
            {
                FT_Done_Face( face );
                FT_Done_FreeType( library );
                throw wcslen(charcodes)-i;
            }


            if( self->outline_type == 0 )
            {
                slot            = face->glyph;
                ft_bitmap       = slot->bitmap;
                ft_glyph_top    = slot->bitmap_top;
                ft_glyph_left   = slot->bitmap_left;
            }
            else
            {
                FT_Stroker stroker;
                FT_BitmapGlyph ft_bitmap_glyph;
                error = FT_Stroker_New( library, &stroker );
                if( error )
                {
                    FT_Done_Face( face );
                    FT_Stroker_Done( stroker );
                    FT_Done_FreeType( library );
					throw;
                }
                FT_Stroker_Set(stroker,
                                (int)(self->outline_thickness * HRES),
                                FT_STROKER_LINECAP_ROUND,
                                FT_STROKER_LINEJOIN_ROUND,
                                0);
                error = FT_Get_Glyph( face->glyph, &ft_glyph);
                if( error )
                {
                    FT_Done_Face( face );
                    FT_Stroker_Done( stroker );
                    FT_Done_FreeType( library );
					throw;
                }

                if( self->outline_type == 1 )
                {
                    error = FT_Glyph_Stroke( &ft_glyph, stroker, 1 );
                }
                else if ( self->outline_type == 2 )
                {
                    error = FT_Glyph_StrokeBorder( &ft_glyph, stroker, 0, 1 );
                }
                else if ( self->outline_type == 3 )
                {
                    error = FT_Glyph_StrokeBorder( &ft_glyph, stroker, 1, 1 );
                }
                if( error )
                {
                    FT_Done_Face( face );
                    FT_Stroker_Done( stroker );
                    FT_Done_FreeType( library );
					throw;
                }

                if( depth == 1)
                {
                    error = FT_Glyph_To_Bitmap( &ft_glyph, FT_RENDER_MODE_NORMAL, 0, 1);
                    if( error )
                    {
                        FT_Done_Face( face );
                        FT_Stroker_Done( stroker );
                        FT_Done_FreeType( library );
						throw;
                    }
                }
                else
                {
                    error = FT_Glyph_To_Bitmap( &ft_glyph, FT_RENDER_MODE_LCD, 0, 1);
                    if( error )
                    {
                        FT_Done_Face( face );
                        FT_Stroker_Done( stroker );
                        FT_Done_FreeType( library );
						throw;
                    }
                }
                ft_bitmap_glyph = (FT_BitmapGlyph) ft_glyph;
                ft_bitmap       = ft_bitmap_glyph->bitmap;
                ft_glyph_top    = ft_bitmap_glyph->top;
                ft_glyph_left   = ft_bitmap_glyph->left;
                FT_Stroker_Done(stroker);
            }


            // We want each glyph to be separated by at least one black pixel
            // (for example for shader used in demo-subpixel.c)
            w = ft_bitmap.width/depth + 1;
            h = ft_bitmap.rows + 1;
            region = texture_atlas_get_region( self->atlas, w, h );
            if ( region.x < 0 )
            {
                missed++;
                fprintf( stderr, "Texture atlas is full (line %d)\n",  __LINE__ );
                continue;
            }
            w = w - 1;
            h = h - 1;
            x = region.x;
            y = region.y;
            texture_atlas_set_region( self->atlas, x, y, w, h,
                                      ft_bitmap.buffer, ft_bitmap.pitch );

            glyph = texture_glyph_new( );
            glyph->charcode = charcodes[i];
            glyph->width    = w;
            glyph->height   = h;
            glyph->outline_type = self->outline_type;
            glyph->outline_thickness = self->outline_thickness;
            glyph->offset_x = ft_glyph_left;
            glyph->offset_y = ft_glyph_top;
            glyph->s0       = x/(float)width;
            glyph->t0       = y/(float)height;
            glyph->s1       = (x + glyph->width)/(float)width;
            glyph->t1       = (y + glyph->height)/(float)height;

            // Discard hinting to get advance
            FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING);
            slot = face->glyph;
            glyph->advance_x = slot->advance.x / HRESf;
            glyph->advance_y = slot->advance.y / HRESf;

            vector_push_back( self->glyphs, &glyph );

            if( self->outline_type > 0 )
            {
                FT_Done_Glyph( ft_glyph );
            }
        }

        FT_Done_Face( face );
        FT_Done_FreeType( library );
        texture_atlas_upload( self->atlas );
        texture_font_generate_kerning( self );
        return missed;
    }
fz_pixmap *
fz_renderftstrokedglyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_strokestate *state)
{
	FT_Face face = font->ftface;
	float expansion = fz_matrixexpansion(ctm);
	int linewidth = state->linewidth * expansion * 64 / 2;
	FT_Matrix m;
	FT_Vector v;
	FT_Error fterr;
	FT_Stroker stroker;
	FT_Glyph glyph;
	FT_BitmapGlyph bitmap;
	fz_pixmap *pix;
	int y;

	m.xx = trm.a * 64; /* should be 65536 */
	m.yx = trm.b * 64;
	m.xy = trm.c * 64;
	m.yy = trm.d * 64;
	v.x = trm.e * 64;
	v.y = trm.f * 64;

	fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
	if (fterr)
	{
		fz_warn("FT_Set_Char_Size: %s", ft_errorstring(fterr));
		return nil;
	}

	FT_Set_Transform(face, &m, &v);

	fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
	if (fterr)
	{
		fz_warn("FT_Load_Glyph(gid %d): %s", gid, ft_errorstring(fterr));
		return nil;
	}

	fterr = FT_Stroker_New(fz_ftlib, &stroker);
	if (fterr)
	{
		fz_warn("FT_Stroker_New: %s", ft_errorstring(fterr));
		return nil;
	}

	FT_Stroker_Set(stroker, linewidth, state->linecap, state->linejoin, state->miterlimit * 65536);

	fterr = FT_Get_Glyph(face->glyph, &glyph);
	if (fterr)
	{
		fz_warn("FT_Get_Glyph: %s", ft_errorstring(fterr));
		FT_Stroker_Done(stroker);
		return nil;
	}

	fterr = FT_Glyph_Stroke(&glyph, stroker, 1);
	if (fterr)
	{
		fz_warn("FT_Glyph_Stroke: %s", ft_errorstring(fterr));
		FT_Done_Glyph(glyph);
		FT_Stroker_Done(stroker);
		return nil;
	}

	fterr = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
	if (fterr)
	{
		fz_warn("FT_Glyph_To_Bitmap: %s", ft_errorstring(fterr));
		FT_Done_Glyph(glyph);
		FT_Stroker_Done(stroker);
		return nil;
	}

	bitmap = (FT_BitmapGlyph)glyph;
	pix = fz_newpixmap(NULL,
		bitmap->left,
		bitmap->top - bitmap->bitmap.rows,
		bitmap->bitmap.width,
		bitmap->bitmap.rows);

	for (y = 0; y < pix->h; y++)
	{
		memcpy(pix->samples + y * pix->w,
			bitmap->bitmap.buffer + (pix->h - y - 1) * bitmap->bitmap.pitch,
			pix->w);
	}

	FT_Done_Glyph(glyph);
	FT_Stroker_Done(stroker);

	return pix;
}
Exemple #25
0
static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want )
{
	FT_Face face;
	FT_Error error;
	FT_GlyphSlot glyph;
	FT_Glyph_Metrics* metrics;
	FT_Outline* outline;

	if ( !font || !font->face ) {
		return FT_Err_Invalid_Handle;
	}

	face = font->face;

	/* Load the glyph */
	if ( ! cached->index ) {
		cached->index = FT_Get_Char_Index( face, ch );
	}
	error = FT_Load_Glyph( face, cached->index, FT_LOAD_DEFAULT | font->hinting);
	if( error ) {
		return error;
	}

	/* Get our glyph shortcuts */
	glyph = face->glyph;
	metrics = &glyph->metrics;
	outline = &glyph->outline;

	/* Get the glyph metrics if desired */
	if ( (want & CACHED_METRICS) && !(cached->stored & CACHED_METRICS) ) {
		if ( FT_IS_SCALABLE( face ) ) {
			/* Get the bounding box */
			cached->minx = FT_FLOOR(metrics->horiBearingX);
			cached->maxx = cached->minx + FT_CEIL(metrics->width);
			cached->maxy = FT_FLOOR(metrics->horiBearingY);
			cached->miny = cached->maxy - FT_CEIL(metrics->height);
			cached->yoffset = font->ascent - cached->maxy;
			cached->advance = FT_CEIL(metrics->horiAdvance);
		} else {
			/* Get the bounding box for non-scalable format.
			 * Again, freetype2 fills in many of the font metrics
			 * with the value of 0, so some of the values we
			 * need must be calculated differently with certain
			 * assumptions about non-scalable formats.
			 * */
			cached->minx = FT_FLOOR(metrics->horiBearingX);
			cached->maxx = cached->minx + FT_CEIL(metrics->horiAdvance);
			cached->maxy = FT_FLOOR(metrics->horiBearingY);
			cached->miny = cached->maxy - FT_CEIL(face->available_sizes[font->font_size_family].height);
			cached->yoffset = 0;
			cached->advance = FT_CEIL(metrics->horiAdvance);
		}
		
		/* Adjust for bold and italic text */
		if( TTF_HANDLE_STYLE_BOLD(font) ) {
			cached->maxx += font->glyph_overhang;
		}
		if( TTF_HANDLE_STYLE_ITALIC(font) ) {
			cached->maxx += (int)ceil(font->glyph_italics);
		}
		cached->stored |= CACHED_METRICS;
	}

	if ( ((want & CACHED_BITMAP) && !(cached->stored & CACHED_BITMAP)) ||
	     ((want & CACHED_PIXMAP) && !(cached->stored & CACHED_PIXMAP)) ) {
		int mono = (want & CACHED_BITMAP);
		int i;
		FT_Bitmap* src;
		FT_Bitmap* dst;
		FT_Glyph bitmap_glyph = NULL;

		/* Handle the italic style */
		if( TTF_HANDLE_STYLE_ITALIC(font) ) {
			FT_Matrix shear;

			shear.xx = 1 << 16;
			shear.xy = (int) ( font->glyph_italics * ( 1 << 16 ) ) / font->height;
			shear.yx = 0;
			shear.yy = 1 << 16;

			FT_Outline_Transform( outline, &shear );
		}

		/* Render as outline */
		if( (font->outline > 0) && glyph->format != FT_GLYPH_FORMAT_BITMAP ) {
			FT_Stroker stroker;
			FT_Get_Glyph( glyph, &bitmap_glyph );
			error = FT_Stroker_New( library, &stroker );
			if( error ) {
				return error;
			}
			FT_Stroker_Set( stroker, font->outline * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0 ); 
			FT_Glyph_Stroke( &bitmap_glyph, stroker, 1 /* delete the original glyph */ );
			FT_Stroker_Done( stroker );
			/* Render the glyph */
			error = FT_Glyph_To_Bitmap( &bitmap_glyph, mono ? ft_render_mode_mono : ft_render_mode_normal, 0, 1 );
			if( error ) {
				FT_Done_Glyph( bitmap_glyph );
				return error;
			}
			src = &((FT_BitmapGlyph)bitmap_glyph)->bitmap;
		} else {
			/* Render the glyph */
			error = FT_Render_Glyph( glyph, mono ? ft_render_mode_mono : ft_render_mode_normal );
			if( error ) {
				return error;
			}
			src = &glyph->bitmap;
		}
		/* Copy over information to cache */
		if ( mono ) {
			dst = &cached->bitmap;
		} else {
			dst = &cached->pixmap;
		}
		memcpy( dst, src, sizeof( *dst ) );

		/* FT_Render_Glyph() and .fon fonts always generate a
		 * two-color (black and white) glyphslot surface, even
		 * when rendered in ft_render_mode_normal. */
		/* FT_IS_SCALABLE() means that the font is in outline format,
		 * but does not imply that outline is rendered as 8-bit
		 * grayscale, because embedded bitmap/graymap is preferred
		 * (see FT_LOAD_DEFAULT section of FreeType2 API Reference).
		 * FT_Render_Glyph() canreturn two-color bitmap or 4/16/256-
		 * color graymap according to the format of embedded bitmap/
		 * graymap. */
		if ( src->pixel_mode == FT_PIXEL_MODE_MONO ) {
			dst->pitch *= 8;
		} else if ( src->pixel_mode == FT_PIXEL_MODE_GRAY2 ) {
			dst->pitch *= 4;
		} else if ( src->pixel_mode == FT_PIXEL_MODE_GRAY4 ) {
			dst->pitch *= 2;
		}

		/* Adjust for bold and italic text */
		if( TTF_HANDLE_STYLE_BOLD(font) ) {
			int bump = font->glyph_overhang;
			dst->pitch += bump;
			dst->width += bump;
		}
		if( TTF_HANDLE_STYLE_ITALIC(font) ) {
			int bump = (int)ceil(font->glyph_italics);
			dst->pitch += bump;
			dst->width += bump;
		}

		if (dst->rows != 0) {
			dst->buffer = (unsigned char *)malloc( dst->pitch * dst->rows );
			if( !dst->buffer ) {
				return FT_Err_Out_Of_Memory;
			}
			memset( dst->buffer, 0, dst->pitch * dst->rows );

			for( i = 0; i < src->rows; i++ ) {
				int soffset = i * src->pitch;
				int doffset = i * dst->pitch;
				if ( mono ) {
					unsigned char *srcp = src->buffer + soffset;
					unsigned char *dstp = dst->buffer + doffset;
					int j;
					if ( src->pixel_mode == FT_PIXEL_MODE_MONO ) {
						for ( j = 0; j < src->width; j += 8 ) {
							unsigned char c = *srcp++;
							*dstp++ = (c&0x80) >> 7;
							c <<= 1;
							*dstp++ = (c&0x80) >> 7;
							c <<= 1;
							*dstp++ = (c&0x80) >> 7;
							c <<= 1;
							*dstp++ = (c&0x80) >> 7;
							c <<= 1;
							*dstp++ = (c&0x80) >> 7;
							c <<= 1;
							*dstp++ = (c&0x80) >> 7;
							c <<= 1;
							*dstp++ = (c&0x80) >> 7;
							c <<= 1;
							*dstp++ = (c&0x80) >> 7;
						}
					}  else if ( src->pixel_mode == FT_PIXEL_MODE_GRAY2 ) {
						for ( j = 0; j < src->width; j += 4 ) {
							unsigned char c = *srcp++;
							*dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0;
							c <<= 2;
							*dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0;
							c <<= 2;
							*dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0;
							c <<= 2;
							*dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0;
						}
					} else if ( src->pixel_mode == FT_PIXEL_MODE_GRAY4 ) {
						for ( j = 0; j < src->width; j += 2 ) {
							unsigned char c = *srcp++;
							*dstp++ = (((c&0xF0) >> 4) >= 0x8) ? 1 : 0;
							c <<= 4;
							*dstp++ = (((c&0xF0) >> 4) >= 0x8) ? 1 : 0;
						}
					} else {
						for ( j = 0; j < src->width; j++ ) {
const CFontGlyph *CFreetypeFontFace::PrepareChar(wchar_t character, bool& bGlyphRestFlag)
{
    bGlyphRestFlag = false;
    m_glyphMapLocker.lock();
    auto itr = m_glyphMap.find(character);
    CFreetypeFontGlyph *pGlyph = itr != m_glyphMap.end() ? down_cast<CFreetypeFontGlyph *>(itr->second) : nullptr;
    m_glyphMapLocker.unlock();

    if (!pGlyph)
    {
        float outlineWidth = GetBorderWeight() * GetScaleFactor();
        ApplyFTSize();
        FT_Face pFontFace = m_pFont->GetFontFace();
        BEATS_ASSERT(pFontFace != NULL);
        bool bFindCharacterGlyph = FT_Get_Char_Index(pFontFace, character) != 0;
        BEYONDENGINE_UNUSED_PARAM(bFindCharacterGlyph);
        BEATS_ASSERT(bFindCharacterGlyph, _T("Character %d can't be found in all font face!"), character);
        FT_Error err = FT_Load_Char(pFontFace, character, FT_LOAD_NO_BITMAP);
        BEYONDENGINE_UNUSED_PARAM(err);
        BEATS_ASSERT(!err);

        FT_GlyphSlot pGlyphSlot = pFontFace->glyph;
        BEATS_ASSERT(pGlyphSlot != NULL);
        int32_t nBorderAdvanceX = pGlyphSlot->metrics.horiAdvance >> FT_SHIFT_NUM;
        int32_t nBorderAdvanceY = m_nLineHeight + (uint32_t)ceil(outlineWidth * 2.0f);
        int32_t nFontAdvanceX = nBorderAdvanceX;
        int32_t nFontHeight = 0;
        int32_t nBorderOriginWidth = 0;
        int32_t nFontOriginWidth = 0;
        int32_t nBorderHeight = 0;
        FT_BBox borderBox;
        FT_BBox fontBox;
        int32_t x = 0, y = 0;
        if (pGlyphSlot->format == FT_GLYPH_FORMAT_OUTLINE)
        {
            FT_Library ftLib = CFont::GetLibrary();
            // Set up a stroker.
            FT_Stroker stroker;
            FT_Stroker_New(ftLib, &stroker);
            FT_Stroker_Set(stroker, (int32_t)(outlineWidth * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
            FT_Glyph pOutlineGlyph, pInnerGlyph;
            if (FT_Get_Glyph(pGlyphSlot, &pOutlineGlyph) == 0 && FT_Get_Glyph(pGlyphSlot, &pInnerGlyph) == 0)
            {
                FT_Glyph_StrokeBorder(&pOutlineGlyph, stroker, 0, 1);
                BEATS_ASSERT(pOutlineGlyph->format == FT_GLYPH_FORMAT_OUTLINE && pInnerGlyph->format == FT_GLYPH_FORMAT_OUTLINE);
                FT_Outline *pOutLine = &reinterpret_cast<FT_OutlineGlyph>(pOutlineGlyph)->outline;
                FT_Glyph_Get_CBox(pOutlineGlyph, FT_GLYPH_BBOX_GRIDFIT, &borderBox);
                FT_Glyph_Get_CBox(pInnerGlyph, FT_GLYPH_BBOX_GRIDFIT, &fontBox);

                nBorderOriginWidth = (borderBox.xMax - borderBox.xMin) >> FT_SHIFT_NUM;

                nFontOriginWidth = (fontBox.xMax - fontBox.xMin) >> FT_SHIFT_NUM;
                int32_t nBorderWidth = nextMOE(nBorderOriginWidth); // Because our GL_UNPACK_ALIGNMENT should be 8 here.
                nBorderHeight = (borderBox.yMax - borderBox.yMin) >> FT_SHIFT_NUM;
                nFontHeight = (fontBox.yMax - fontBox.yMin) >> FT_SHIFT_NUM;
                x = pGlyphSlot->metrics.horiBearingX >> FT_SHIFT_NUM;
                y = pGlyphSlot->metrics.horiBearingY >> FT_SHIFT_NUM;
                if(nBorderAdvanceX < x + nBorderOriginWidth) // It is true for most of the time, because border size always greater than nAdvanceX
                {
                    nBorderAdvanceX = x + nBorderOriginWidth;
                }
                if (nFontAdvanceX < x + nFontOriginWidth)
                {
                    nFontAdvanceX = nFontOriginWidth; 
                }
                if(m_uCurrX + x + nBorderWidth > PAGE_WIDTH)
                {
                    m_uCurrX = 0;
                    m_uCurrY += (nBorderAdvanceY + m_nBorderSpace);
                    if (m_uCurrY + nBorderAdvanceY > PAGE_HEIGHT)
                    {
                        BEATS_WARNING(false, "Freetype texture buffer overflow for %d glyphs, we will rebuild this texture buffer.", (uint32_t)m_glyphMap.size());
                        ResetGlyphs();
                        bGlyphRestFlag = true;
                        return nullptr;
                    }
                }

                int32_t nDataSize = nBorderWidth * nBorderHeight;
                float fBorderOffsetY = 1.0f; // Makes it look like a shadow.
                unsigned char* pBorderData = RenderFontDataToBmp(nBorderWidth, nBorderHeight, -borderBox.xMin, (int32_t)(-borderBox.yMin * fBorderOffsetY), pOutLine);

                FT_Outline *pInnerOutLine = &reinterpret_cast<FT_OutlineGlyph>(pInnerGlyph)->outline;
                unsigned char* pFontData = RenderFontDataToBmp(nBorderWidth, nBorderHeight, -borderBox.xMin, -borderBox.yMin, pInnerOutLine);

                unsigned char* pAllData = new unsigned char[nDataSize * 2];
                for (int32_t i = 0; i < nDataSize; ++i)
                {
                    pAllData[i * 2] = pBorderData[i];
                    pAllData[i * 2 + 1] = pFontData[i];
                }

                BEATS_ASSERT(m_pTexture.Get() != nullptr);
                GLint nX = MAX((int32_t)m_uCurrX + x, 0);
                GLint nY = MAX((int32_t)m_uCurrY + (m_nAscender - y), 0);
                SFontUpdateImageInfo* pImageInfo = new SFontUpdateImageInfo;
                pImageInfo->m_pTexture = m_pTexture;
                pImageInfo->m_nWidth = nBorderWidth;
                pImageInfo->m_nHeight = nBorderHeight;
                pImageInfo->m_x = nX;
                pImageInfo->m_y = nY;
                pImageInfo->m_pData = pAllData;
                m_fontUpdateImageCacheMutex.lock();
                m_fontUpdateImageCache.push_back(pImageInfo);
                m_fontUpdateImageCacheMutex.unlock();

                // Clean up afterwards.
                FT_Stroker_Done(stroker);
                FT_Done_Glyph(pOutlineGlyph);
                FT_Done_Glyph(pInnerGlyph);
                BEATS_SAFE_DELETE_ARRAY(pBorderData);
                BEATS_SAFE_DELETE_ARRAY(pFontData);
            }
Exemple #27
0
// ----------------------------------------------- texture_font_load_glyphs ---
size_t
texture_font_load_glyphs( texture_font_t * self,
                          const wchar_t * charcodes )
{
    assert( self );
    assert( charcodes );

    size_t i, x, y, width, height, depth, w, h;
    FT_Library library;
    FT_Error error;
    FT_Face face;
    FT_Glyph ft_glyph;
    FT_GlyphSlot slot;
    FT_Bitmap ft_bitmap;

    FT_UInt glyph_index;
    texture_glyph_t *glyph;
    ivec4 region;
    size_t missed = 0;
    width  = self->atlas->width;
    height = self->atlas->height;
    depth  = self->atlas->depth;

    region.x=1;
    region.y=1;

#ifdef RENDERSTRING
    stringwidth=0;
    stringheight=0;
    stringshift=0;
#endif

    if( !texture_font_load_face( &library, self->filename, self->size, &face ) )
    {
        return wcslen(charcodes);
    }

    /* Load each glyph */
    for( i=0; i<wcslen(charcodes); ++i )
    {
        glyph_index = FT_Get_Char_Index( face, charcodes[i] );
        // WARNING: We use texture-atlas depth to guess if user wants
        //          LCD subpixel rendering
        FT_Int32 flags = 0;

        if( self->outline_type > 0 )
        {
            flags |= FT_LOAD_NO_BITMAP;
        }
        else
        {
            flags |= FT_LOAD_RENDER;
        }

        if( !self->hinting )
        {
            flags |= FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
        }
        else
        {
            flags |= FT_LOAD_FORCE_AUTOHINT;
        }


        if( depth == 3 )
        {
            FT_Library_SetLcdFilter( library, FT_LCD_FILTER_LIGHT );
            flags |= FT_LOAD_TARGET_LCD;
            if( self->filtering )
            {
//                FT_Library_SetLcdFilterWeights( library, self->lcd_weights );
            }
        }
        error = FT_Load_Glyph( face, glyph_index, flags );

        if( error )
        {
            fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
                     __LINE__, FT_Errors[error].code, FT_Errors[error].message );
            FT_Done_FreeType( library );
            return wcslen(charcodes)-i;
        }

        int ft_bitmap_width = 0;
        int ft_bitmap_rows = 0;
        int ft_bitmap_pitch = 0;
        int ft_glyph_top = 0;
        int ft_glyph_left = 0;
        if( self->outline_type == 0 )
        {
            slot            = face->glyph;
            ft_bitmap       = slot->bitmap;
            ft_bitmap_width = slot->bitmap.width;
            ft_bitmap_rows  = slot->bitmap.rows;
            ft_bitmap_pitch = slot->bitmap.pitch;
            ft_glyph_top    = slot->bitmap_top;
            ft_glyph_left   = slot->bitmap_left;
        }
        else
        {
            FT_Stroker stroker;
            error = FT_Stroker_New( library, &stroker );
            if( error )
            {
                fprintf(stderr, "FT_Error (0x%02x) : %s\n",
                        FT_Errors[error].code, FT_Errors[error].message);
                return 0;
            }
            FT_Stroker_Set( stroker,
                            (int)(self->outline_thickness *64),
                            FT_STROKER_LINECAP_ROUND,
                            FT_STROKER_LINEJOIN_ROUND,
                            0);
            error = FT_Get_Glyph( face->glyph, &ft_glyph);
            if( error )
            {
                fprintf(stderr, "FT_Error (0x%02x) : %s\n",
                        FT_Errors[error].code, FT_Errors[error].message);
                return 0;
            }

            if( self->outline_type == 1 )
            {
                error = FT_Glyph_Stroke( &ft_glyph, stroker, 1 );
            }
            else if ( self->outline_type == 2 )
            {
                error = FT_Glyph_StrokeBorder( &ft_glyph, stroker, 0, 1 );
            }
            else if ( self->outline_type == 3 )
            {
                error = FT_Glyph_StrokeBorder( &ft_glyph, stroker, 1, 1 );
            }
            if( error )
            {
                fprintf(stderr, "FT_Error (0x%02x) : %s\n",
                        FT_Errors[error].code, FT_Errors[error].message);
                return 0;
            }
          
            if( depth == 1)
            {
                error = FT_Glyph_To_Bitmap( &ft_glyph, FT_RENDER_MODE_NORMAL, 0, 1);
                if( error )
                {
                    fprintf(stderr, "FT_Error (0x%02x) : %s\n",
                            FT_Errors[error].code, FT_Errors[error].message);
                    return 0;
                }
            }
            else
            {
                error = FT_Glyph_To_Bitmap( &ft_glyph, FT_RENDER_MODE_LCD, 0, 1);
                if( error )
                {
                    fprintf(stderr, "FT_Error (0x%02x) : %s\n",
                            FT_Errors[error].code, FT_Errors[error].message);
                    return 0;
                }
            }
            FT_BitmapGlyph ft_bitmap_glyph = (FT_BitmapGlyph) ft_glyph;
            ft_bitmap       = ft_bitmap_glyph->bitmap;
            ft_bitmap_width = ft_bitmap.width;
            ft_bitmap_rows  = ft_bitmap.rows;
            ft_bitmap_pitch = ft_bitmap.pitch;
            ft_glyph_top    = ft_bitmap_glyph->top;
            ft_glyph_left   = ft_bitmap_glyph->left;
            FT_Stroker_Done(stroker);
        }


        // We want each glyph to be separated by at least one black pixel
        // (for example for shader used in demo-subpixel.c)
        w = ft_bitmap_width/depth + 1;
        h = ft_bitmap_rows + 1;

#ifdef RENDERSTRING
        static size_t maxh=0;
        if (charcodes[i]==13) { stringshift+=maxh+1; region.x=1; }
        if (h>maxh) maxh=h;
        //region.y=stringshift+maxh-h+1+(h-ft_glyph_top);
        region.y=stringshift+maxh-ft_glyph_top+1;
       // if (stringshift+h+h-ft_glyph_top+1>stringheight) stringheight=stringshift+h+h-ft_glyph_top+1;
        if (region.y+h>stringheight) stringheight=region.y+h;
        if (region.x+w>stringwidth) stringwidth=region.x+w;
//        if (region.y>=height) { missed++; continue; }
//        if (region.x+w>=width) {missed++; continue; }
       // if (h+h-ft_glyph_top+1>=height) { missed++; continue; }
       // if (h+h-ft_glyph_top+2>=height) { missed++; continue; }
//        if (region.y+maxh>=height) { missed++; continue; }
#else
        region = texture_atlas_get_region( self->atlas, w, h );
        if ( region.x < 0 )
        {
            missed++;
        //    fprintf( stderr, "Texture atlas is full (line %d)\n",  __LINE__ );
            continue;
        }
#endif
        w = w - 1;
        h = h - 1;
        x = region.x;
        y = region.y;
        if (charcodes[i]!=13) {

#ifdef RENDERSTRING
     if (!(x<width)||!((x+w)<=width)||!(y<height)||!((y+h)<=height)) { missed++; continue; }
#endif

          texture_atlas_set_region( self->atlas, x, y, w, h,
                                  ft_bitmap.buffer, ft_bitmap.pitch );
}
        glyph = texture_glyph_new( );
        glyph->charcode = charcodes[i];
        glyph->width    = w;
        glyph->height   = h;
        glyph->outline_type = self->outline_type;
        glyph->outline_thickness = self->outline_thickness;
        glyph->offset_x = ft_glyph_left;
        glyph->offset_y = ft_glyph_top;
        glyph->s0       = x/(float)width;
        glyph->t0       = y/(float)height;
        glyph->s1       = (x + glyph->width)/(float)width;
        glyph->t1       = (y + glyph->height)/(float)height;

        // Discard hinting to get advance
        FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING);
        slot = face->glyph;
        glyph->advance_x = slot->advance.x/64.0;
        glyph->advance_y = slot->advance.y/64.0;

#ifdef RENDERSTRING
        if (charcodes[i]!=13) region.x+=(int)glyph->advance_x;
#endif

        vector_push_back( self->glyphs, &glyph );
    }
    if( self->outline_type > 0 )
    {
        FT_Done_Glyph( ft_glyph );
    }
    FT_Done_Face( face );
    FT_Done_FreeType( library );
 //   texture_atlas_upload( self->atlas );
    texture_font_generate_kerning( self );
    return missed;
}
long EMSCRIPTEN_KEEPALIVE c_Library_strokerNew(long library) {
    FT_Stroker stroker;
    FT_Error error = FT_Stroker_New((FT_Library)library, &stroker);
    if(error) return 0;
    else return (long)stroker;
}
Exemple #29
0
    Glyph::Glyph(FT_Library &library, FontFace &fontFace, int c, int outlineWidth, bool hinting) :
    mFont(fontFace)
    {
        mChar = c;
        
        FT_Face &face = fontFace.GetFTFace();

        int flags = FT_LOAD_DEFAULT;
        if (!hinting)
        {
            flags = FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING;
        }
        
        FT_Error error = FT_Load_Char(face, c, flags);
        if (error) {
            return;
        }
        
        mGlyphIndex = FT_Get_Char_Index(face, c);
        
        // Load The Glyph For Our Character.
        if(FT_Load_Glyph( face, mGlyphIndex, flags ))
            throw std::runtime_error("FT_Load_Glyph failed");
        
        // Move The Face's Glyph Into A Glyph Object.
        FT_Glyph glyph;
        if(FT_Get_Glyph( face->glyph, &glyph ))
            throw std::runtime_error("FT_Get_Glyph failed");
        
        FT_Stroker stroker;
        FT_Stroker_New(library, &stroker);
        FT_Stroker_Set(stroker, outlineWidth * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
        FT_Glyph_StrokeBorder(&glyph, stroker, false, true);
        
        FT_OutlineGlyph olglyph = reinterpret_cast<FT_OutlineGlyph>(glyph);
        
        FT_Outline outline = olglyph->outline;
        
        RenderSpans(library, &outline);
        
        FT_Stroker_Done(stroker);
        
        // Get metrics
        FT_Glyph_Metrics metrics = face->glyph->metrics;
        mAdvance.x = metrics.horiAdvance * kOneOver64;
        mAdvance.y = metrics.vertAdvance * kOneOver64;
        
        mBearing.x = metrics.horiBearingX * kOneOver64;
        mBearing.y = metrics.horiBearingY * kOneOver64;
        
        mSize.x = glm::round(metrics.width * kOneOver64);
        mSize.y = glm::round(metrics.height * kOneOver64);
        
        // Adjust for outline?
        mAdvance.x += outlineWidth;
        
        // Draw spans
        if(mSpans.size() > 0)
        {
            GlyphSpan front = mSpans.front();
            Rect bounds(front.x, front.y, front.x, front.y);
            for(int i = 0; i < mSpans.size(); i++)
            {
                bounds.Include(mSpans[i].x, mSpans[i].y + 1);
                bounds.Include(mSpans[i].x + mSpans[i].width, mSpans[i].y);
            }
            
            int width = bounds.GetWidth();
            int height = bounds.GetHeight();
            
            mDataSize.x = width;
            mDataSize.y = height;
            
            int size = width * height;
            
            mBuffer = new unsigned char[size];
            memset(mBuffer, 0, size);
            for(int i = 0; i < mSpans.size(); i++)
            {
                GlyphSpan &span = mSpans[i];
                for (int w = 0; w < span.width; ++w)
                {
                    mBuffer[(int)((height - 1 - (span.y - bounds.top)) * width
                                  + span.x - bounds.left + w)] = span.coverage;
                }
            }
        }
        FT_Done_Glyph(glyph);
    }
Exemple #30
0
int createFont(FT_Face fontFace, FT_UInt size)
{
	initFreeTypeLibrary();

	VGfloat glyphOrigin[2];
	VGfloat escapement[2];

	FT_Stroker fontStroker;
	int error = FT_Stroker_New(freeTypeLibrary, &fontStroker);
	if (error) {
		logInfo(LOG_FREETYPE, "Error FT_Stroker_New.(error=%d)\n", error);
		return -1;
	}

	FT_Stroker_Set(fontStroker,
		 2*64.0f,  // Need to get the right value based on size.
		 FT_STROKER_LINECAP_ROUND,
		 FT_STROKER_LINEJOIN_ROUND,
		 0);

	VGFont tmpFont;
	struct fontListItem *tmpFontListItem = fontExists(fontFace, size);
	if (tmpFontListItem == NULL) {
		tmpFont = vgCreateFont(fontFace->num_glyphs);
		if (tmpFont == VG_INVALID_HANDLE) {
			logInfo(LOG_FREETYPE, "Error could not create vgCreateFont.\n");
			return -1;
		}

		tmpFontListItem = malloc(sizeof(struct fontListItem));
		tmpFontListItem->fontFace = fontFace;
		tmpFontListItem->size = size;
		tmpFontListItem->font = tmpFont;
		addToFontList(tmpFontListItem);
	}
	else {
		return 0;
	}

	error = FT_Set_Char_Size( fontFace, /* handle to face object */
					0, /* char_width in 1/64th of points */
					size*64, /* char_height in 1/64th of points */
					72, /* horizontal device resolution */
					72 ); /* vertical device resolution */

	if (error) {
		logInfo(LOG_FREETYPE, "Error FT_Set_Char_Size.(error=%d)\n", error);
		return -1;
	}

	int index;
	int counter = 0;
	FT_UInt charIndex;
	VGImage image = VG_INVALID_HANDLE;
	VGImage softenedImage;
	VGfloat blustStdDev;
	int padding;
	int image_width;
	int image_height;
	VGErrorCode vg_error;
	FT_Glyph glyph;

	logInfo(LOG_FREETYPE, "This font contains %ld glyphs.\n", fontFace->num_glyphs);

	for (index = 32; (index < 256) && (counter < fontFace->num_glyphs); index++) {
		counter++;
		charIndex = FT_Get_Char_Index(fontFace, index);

		logInfo(LOG_FREETYPE, "index=0x%x, charIndex=0x%x\n", index, charIndex);

		escapement[0] = 0;
		escapement[1] = 0;

		if (charIndex == 0) {
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			logInfo(LOG_FREETYPE, "charindex== 0\n");
			continue;
		}

		error = FT_Load_Glyph(fontFace, charIndex, FT_LOAD_NO_HINTING);
		if (error) {
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			logInfo(LOG_FREETYPE, "Error FT_Load_Glyph (error:%d)\n", error);
			continue;
		}

		error = FT_Get_Glyph(fontFace->glyph, &glyph);
		if (error) {
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			logInfo(LOG_FREETYPE, "Error FT_Get_Glyph (error:%d)\n", error);
			continue;
		}

/*
		error = FT_Glyph_StrokeBorder(&glyph, fontStroker, 0, 1);
		if (error) {
			FT_Done_Glyph(glyph);
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			logInfo(LOG_FREETYPE, "Error FT_Glyph_StrokeBorder (error:%d)\n", error);
			continue;
		}
*/

		error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, NULL, 1);
		if (error) {
			FT_Done_Glyph(glyph);
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			logInfo(LOG_FREETYPE, "Error FT_Glyph_To_Bitmap (error:%d)\n", error);
			continue;
		}

		FT_BitmapGlyph bitGlyph = (FT_BitmapGlyph)glyph;
		FT_Bitmap bitmap = bitGlyph->bitmap;

		if (bitmap.width > 0 && bitmap.rows > 0) {
			blustStdDev = 0.6;
			padding = (3*blustStdDev + 0.5);
			image_width = bitmap.width + padding*2;
			image_height = bitmap.rows + padding*2;

			image = vgCreateImage(VG_A_8, image_width, image_height, VG_IMAGE_QUALITY_NONANTIALIASED);
			if (image == VG_INVALID_HANDLE) {
				FT_Done_Glyph(glyph);
				vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
				logInfo(LOG_FREETYPE, "vgCreateImage (error:%d)\n", vgGetError());
				continue;
			}

			if (bitmap.pitch > 0) {
				vgImageSubData(image,
					 bitmap.buffer + bitmap.pitch*(bitmap.rows-1),
					 -bitmap.pitch,
					 VG_A_8,
					 padding,
					 padding,
					 bitmap.width,
					 bitmap.rows);
			} else {
				vgImageSubData(image,
					 bitmap.buffer,
					 bitmap.pitch,
					 VG_A_8,
					 padding,
					 padding,
					 bitmap.width,
					 bitmap.rows);
			}
			vg_error = vgGetError();
			if (vg_error) {
				vgDestroyImage(image);
				FT_Done_Glyph(glyph);
				vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
				showVGErrorStr(vg_error, "vgImageSubData");
				continue;
			}

			softenedImage = vgCreateImage(VG_A_8,
							image_width,
							image_height,
							VG_IMAGE_QUALITY_NONANTIALIASED);
			if (softenedImage == VG_INVALID_HANDLE) {
				vgDestroyImage(image);
				FT_Done_Glyph(glyph);
				vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
				logInfo(LOG_FREETYPE, "vgCreateImage (error:%d)\n", vgGetError());
				continue;
			}

			// Even out hard and soft edges
			vgGaussianBlur(softenedImage, image, blustStdDev, blustStdDev, VG_TILE_FILL);
			vg_error = vgGetError();
			if (vg_error) {
				vgDestroyImage(softenedImage);
				vgDestroyImage(image);
				FT_Done_Glyph(glyph);
				vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
				showVGErrorStr(vg_error, "vgGaussianBlur");
				continue;
			}

			vgDestroyImage(image);
			image = softenedImage;

			glyphOrigin[0] = (VGfloat)(padding - bitGlyph->left);
			glyphOrigin[1] = (VGfloat)(padding + bitmap.rows - bitGlyph->top - 1);

		}
		else {
			logInfo(LOG_FREETYPE, "Error bitmap.width = %d, bitmap.rows = %d\n", bitmap.width, bitmap.rows);
		}

		escapement[0] = (VGfloat)((fontFace->glyph->advance.x + 32) / 64);
		escapement[1] = 0;

		vgSetGlyphToImage(tmpFont, index, image, glyphOrigin, escapement);
		vg_error = vgGetError();
		if (vg_error) {
			vgDestroyImage(softenedImage);
			vgDestroyImage(image);
			FT_Done_Glyph(glyph);
			vgSetGlyphToImage(tmpFont, index, VG_INVALID_HANDLE, escapement, escapement);
			showVGErrorStr(vg_error, "vgSetGlyphToImage");
			continue;
		}
		logInfo(LOG_FREETYPE, "Create glyph %d.\n", index);

		FT_Done_Glyph(glyph);

		if (image != VG_INVALID_HANDLE) {
			vgDestroyImage(image);
		}
	}

	return 0;
}