Exemplo n.º 1
0
static av_cold int init(AVFilterContext *ctx)
{
    int err;
    DrawTextContext *s = ctx->priv;
    Glyph *glyph;

    if ((err = parse_font(ctx)) < 0)
        return err;

    if (s->textfile) {
        uint8_t *textbuf;
        size_t textbuf_size;

        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 = av_file_map(s->textfile, &textbuf, &textbuf_size, 0, ctx)) < 0) {
            av_log(ctx, AV_LOG_ERROR,
                   "The text file '%s' could not be read or is empty\n",
                   s->textfile);
            return err;
        }

        if (textbuf_size > SIZE_MAX - 1 ||
            !(s->text = av_malloc(textbuf_size + 1))) {
            av_file_unmap(textbuf, textbuf_size);
            return AVERROR(ENOMEM);
        }
        memcpy(s->text, textbuf, textbuf_size);
        s->text[textbuf_size] = 0;
        av_file_unmap(textbuf, textbuf_size);
    }

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

    if ((err = av_parse_color(s->fontcolor_rgba, s->fontcolor_string, -1, ctx))) {
        av_log(ctx, AV_LOG_ERROR,
               "Invalid font color '%s'\n", s->fontcolor_string);
        return err;
    }

    if ((err = av_parse_color(s->boxcolor_rgba, s->boxcolor_string, -1, ctx))) {
        av_log(ctx, AV_LOG_ERROR,
               "Invalid box color '%s'\n", s->boxcolor_string);
        return err;
    }

    if ((err = av_parse_color(s->shadowcolor_rgba, s->shadowcolor_string, -1, ctx))) {
        av_log(ctx, AV_LOG_ERROR,
               "Invalid shadow color '%s'\n", s->shadowcolor_string);
        return err;
    }

    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);
    }

    /* load the face, and set up the encoding, which is by default UTF-8 */
    if ((err = FT_New_Face(s->library, s->fontfile, 0, &s->face))) {
        av_log(ctx, AV_LOG_ERROR, "Could not load fontface from file '%s': %s\n",
               s->fontfile, FT_ERRMSG(err));
        return AVERROR(EINVAL);
    }
    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);
    }

    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 !HAVE_LOCALTIME_R
    av_log(ctx, AV_LOG_WARNING, "strftime() expansion unavailable!\n");
#endif

    return 0;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
Arquivo: font.cpp Projeto: ktj007/mmo
int DrawGlyph(
	_In_ wchar_t c,
	_In_ int pixel_size,
	_Out_ _Notnull_ int* pitch,
	_Out_ _Notnull_ int* rows,
	_Out_ _Notnull_ int* advance,
	_Out_ _Notnull_ int* horiBearingY,
	_Inout_ _Notnull_ unsigned char** ppBitmap
	)
{
	FT_Error error;
	FT_UInt glyph_index;

	glyph_index = FT_Get_Char_Index(face, c);

	error = FT_Set_Pixel_Sizes(face, 0, pixel_size);
	if (error)
	{
		return error;
	}

	error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
	if (error)
	{
		return error;
	}

	if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
	{
		FT_Pos strength = 30;
		error = FT_Outline_Embolden(&face->glyph->outline, strength);
		if (error)
		{
			//cl_debug_output("Font Embolden failed.");
            DebugBreak();
		}
	}

	/*
	FT_Matrix matrix;
	matrix.xx = 0x07FFFL;
	matrix.xy = 0;
	matrix.yx = 0;
	matrix.yy = 0x10000L;
	FT_Set_Transform(face, &matrix, 0);
	*/

	error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
	if (error)
	{
		return error;
	}

	*ppBitmap = (unsigned char*)malloc(face->glyph->bitmap.rows * face->glyph->bitmap.pitch);

	memcpy(*ppBitmap, face->glyph->bitmap.buffer,
		face->glyph->bitmap.rows * face->glyph->bitmap.pitch);

	*pitch = face->glyph->bitmap.pitch;
	*rows = face->glyph->bitmap.rows;
	*advance = face->glyph->advance.x / 64;
	*horiBearingY = face->glyph->metrics.horiBearingY / 64;

	return error;
}
Exemplo n.º 4
0
Error DynamicFontAtSize::_load() {

	int error = FT_Init_FreeType(&library);

	ERR_EXPLAIN(TTR("Error initializing FreeType."));
	ERR_FAIL_COND_V(error != 0, ERR_CANT_CREATE);

	// FT_OPEN_STREAM is extremely slow only on Android.
	if (OS::get_singleton()->get_name() == "Android" && font->font_mem == NULL && font->font_path != String()) {
		// cache font only once for each font->font_path
		if (_fontdata.has(font->font_path)) {

			font->set_font_ptr(_fontdata[font->font_path].ptr(), _fontdata[font->font_path].size());

		} else {

			FileAccess *f = FileAccess::open(font->font_path, FileAccess::READ);
			ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);

			size_t len = f->get_len();
			_fontdata[font->font_path] = Vector<uint8_t>();
			Vector<uint8_t> &fontdata = _fontdata[font->font_path];
			fontdata.resize(len);
			f->get_buffer(fontdata.ptr(), len);
			font->set_font_ptr(fontdata.ptr(), len);
			f->close();
		}
	}

	if (font->font_mem == NULL && font->font_path != String()) {

		FileAccess *f = FileAccess::open(font->font_path, FileAccess::READ);
		ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);

		memset(&stream, 0, sizeof(FT_StreamRec));
		stream.base = NULL;
		stream.size = f->get_len();
		stream.pos = 0;
		stream.descriptor.pointer = f;
		stream.read = _ft_stream_io;
		stream.close = _ft_stream_close;

		FT_Open_Args fargs;
		memset(&fargs, 0, sizeof(FT_Open_Args));
		fargs.flags = FT_OPEN_STREAM;
		fargs.stream = &stream;
		error = FT_Open_Face(library, &fargs, 0, &face);
	} else if (font->font_mem) {

		memset(&stream, 0, sizeof(FT_StreamRec));
		stream.base = (unsigned char *)font->font_mem;
		stream.size = font->font_mem_size;
		stream.pos = 0;

		FT_Open_Args fargs;
		memset(&fargs, 0, sizeof(FT_Open_Args));
		fargs.memory_base = (unsigned char *)font->font_mem;
		fargs.memory_size = font->font_mem_size;
		fargs.flags = FT_OPEN_MEMORY;
		fargs.stream = &stream;
		error = FT_Open_Face(library, &fargs, 0, &face);

	} else {
		ERR_EXPLAIN("DynamicFont uninitialized");
		ERR_FAIL_V(ERR_UNCONFIGURED);
	}

	//error = FT_New_Face( library, src_path.utf8().get_data(),0,&face );

	if (error == FT_Err_Unknown_File_Format) {
		ERR_EXPLAIN(TTR("Unknown font format."));
		FT_Done_FreeType(library);

	} else if (error) {

		ERR_EXPLAIN(TTR("Error loading font."));
		FT_Done_FreeType(library);
	}

	ERR_FAIL_COND_V(error, ERR_FILE_CANT_OPEN);

	/*error = FT_Set_Char_Size(face,0,64*size,512,512);

	if ( error ) {
		FT_Done_FreeType( library );
		ERR_EXPLAIN(TTR("Invalid font size."));
		ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER );
	}*/

	error = FT_Set_Pixel_Sizes(face, 0, id.size);

	ascent = face->size->metrics.ascender >> 6;
	descent = -face->size->metrics.descender >> 6;
	linegap = 0;
	texture_flags = 0;
	if (id.mipmaps)
		texture_flags |= Texture::FLAG_MIPMAPS;
	if (id.filter)
		texture_flags |= Texture::FLAG_FILTER;

	//print_line("ASCENT: "+itos(ascent)+" descent "+itos(descent)+" hinted: "+itos(face->face_flags&FT_FACE_FLAG_HINTER));

	valid = true;
	return OK;
}
Exemplo n.º 5
0
void InitFreeType(){
    PrintToLog("INFO: Initializing FreeType.");
    FT_Library ft;
    FT_Face face;

    if(FT_Init_FreeType(&ft)) {
        PrintToLog("ERROR: Could not init FreeType library!");
        return;
    }

    // TODO - load from some configuration file...
    const char *font_filename = "/Orbitron Bold.otf";

    PHYSFS_File *file;
    intmax_t length;
    uint8_t *font_buffer;

    file = PHYSFS_openRead(font_filename);
    if(!file){
        PrintToLog("ERROR: unable to open Font File: \"%s\"", font_filename);
        return;
    }

    length = PHYSFS_fileLength(file);
    font_buffer = new uint8_t[length];

    PHYSFS_read(file, font_buffer, 1, length);
    PHYSFS_close(file);

    FT_Error err = FT_New_Memory_Face(ft, font_buffer, length, 0, &face);

    if(err){
        PrintToLog("ERROR: Could not load font \"%s\"! error code %x!", font_filename, err);
        delete[] font_buffer;
        return;
    }

    FT_Set_Pixel_Sizes(face, 0, FONT_SIZE);

    FT_GlyphSlot g = face->glyph;
    int width = 0;
    int height = 0;

    for(unsigned char c = FONT_FIRST_CHAR; c <= FONT_LAST_CHAR; c++) {
        if(FT_Load_Char(face, c, FT_LOAD_RENDER)) {
            PrintToLog("WARNING: Loading character %c failed!", c);
            continue;
        }

        width += g->bitmap.width + 1;
        height = std::max(height, int(g->bitmap.rows));
    }

    main_atlas.width = width;

    glGenTextures(1, &main_atlas.texture);
    glBindTexture(GL_TEXTURE_2D, main_atlas.texture);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    std::vector<GLubyte> empty_image(width * height, 0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &empty_image[0]);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    uint32_t x = 0;

    for(unsigned char i = FONT_FIRST_CHAR; i <= FONT_LAST_CHAR; i++) {
        if(FT_Load_Char(face, i, FT_LOAD_RENDER))
            continue;

        glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);

        main_atlas.characters[i].advance.x = g->advance.x >> 6;
        main_atlas.characters[i].advance.y = g->advance.y >> 6;

        main_atlas.characters[i].width = g->bitmap.width;
        main_atlas.characters[i].rows = g->bitmap.rows;

        main_atlas.characters[i].left = g->bitmap_left;
        main_atlas.characters[i].top = g->bitmap_top;

        main_atlas.characters[i].x = (float)x / (float)width;

        x += g->bitmap.width + 1;
    }

    PrintToLog("INFO: Created character atlas size %ix%i", width,height);

    FT_Done_Face(face);
    delete[] font_buffer;

    // TODO - perhaps leave this open for loading other fonts and close in a GarbageCollect() function?
    FT_Done_FreeType(ft);
}
Exemplo n.º 6
0
Arquivo: font.cpp Projeto: Try/Tempest
const Tempest::FontElement::Letter&
    Tempest::FontElement::fetchLeter( char16_t ch,
                                      Tempest::SpritesHolder & res  ) const {
  Leters & leters = *lt;

  if( Letter *l = leters.find(ch) ){
    if(l->surf.w()==l->size.w && l->surf.h()==l->size.h)
      return *l;
    }

  FT_Face   face = nullptr;
  FT_Vector pen  = {0,0};
  FT_Error  err  = 0;

  char* data = nullptr;
  if(memData){
    data = memData->data;
    } else
  if(fdata[key.name]!=nullptr){
    data = fdata[key.name].get();
    } else {
    RFile file(fnames[key.name].c_str());
    size_t sz = file.size();
    data = new char[sz];
    fdata[key.name].reset(data);
    if(file.readData(data,sz)!=sz)
      fdata[key.name].reset();
    }
  Tempest::MemReader reader(data,-1);
  FT_StreamRec stream;
  ft().mkStream(stream,reader);

  err = ft().New_Face( ft().library, stream, 0, &face );
  if( err )
    return nullLeter(ch);

  err = FT_Set_Pixel_Sizes( face, key.size, key.size );
  if( err )
    return nullLeter(ch);

  FT_Set_Transform( face, 0, &pen );

  Letter letter;
  if( FT_Load_Char( face, ch, FT_LOAD_RENDER ) ){
    Letter &ref = leters[ch];
    ref = letter;
    return ref;
    }
  
  FT_GlyphSlot slot = face->glyph;
  FT_Bitmap& bmap   = slot->bitmap;

  letter.dpos = Tempest::Point( slot->bitmap_left,
                                key.size - slot->bitmap_top );
  
  if( bmap.width!=0 && bmap.rows!=0 ){
    Tempest::Pixmap pixmap( bmap.width, bmap.rows, true );

    for( int r=0; r<pixmap.height(); ++r )
      for( int i=0; i<pixmap.width(); ++i ) {
        uint8_t lum = bmap.buffer[r * bmap.width + i];
        Tempest::Pixmap::Pixel p = {255, 255, 255, lum};
        pixmap.set( i,r, p );
        }

    //pixmap.save("./l.png");
    letter.surf = res.load( pixmap );
    }

  letter.size      = Tempest::Size( bmap.width, bmap.rows );
  letter.advance   = Tempest::Point( slot->advance.x >> 6,
                                     slot->advance.y >> 6 );

  FT_Done_Face( face );

  Letter &ref = leters[ch];
  ref = letter;
  return ref;
  }
Exemplo n.º 7
0
rtgui_font_t *rtgui_freetype_font_create(const char *filename, int bold, int italic, rt_size_t size)
{
    FT_Error err = 0;
    struct rtgui_font *font;

    font = (struct rtgui_font *) rtgui_malloc(sizeof(struct rtgui_font));
    if (font != RT_NULL)
    {
        struct rtgui_freetype_font *freetype;

        freetype = (struct rtgui_freetype_font *) rtgui_malloc(sizeof(struct rtgui_freetype_font));
        if (freetype == RT_NULL)
        {
            rtgui_free(font);
            font = RT_NULL;
        }
        else
        {
            err = FT_Init_FreeType(&freetype->library);
            if ((err = FT_New_Face(freetype->library, filename, 0, &freetype->face)))
            {
                FT_Done_FreeType(freetype->library);

                rtgui_free(font);
                font = RT_NULL;
            }
            else
            {
                err = FT_Select_Charmap(freetype->face, ft_encoding_unicode);
                if (err)
                {
                    err = FT_Select_Charmap(freetype->face, ft_encoding_latin_1);
                }

                err = FT_Set_Pixel_Sizes(freetype->face, 0, size);
                if (err != 0)
                {
                    rtgui_free(font);
                    font = RT_NULL;

                    FT_Done_FreeType(freetype->library);
                    rtgui_free(freetype);

                    return RT_NULL;
                }

                freetype->bold = bold;
                freetype->italic = italic;

                rt_kprintf("fonfile:%s\n", filename);
                rt_kprintf("font family_name:%s\n", freetype->face->family_name);
                rt_kprintf("font style_name:%s\n", freetype->face->style_name);

                /* set user data */
                font->data = freetype;
                font->family = rt_strdup(freetype->face->family_name);
                font->height = (rt_uint16_t)size;
                font->refer_count = 0;
                font->engine = &freetype_font_engine;

                /* add to system */
                rtgui_font_system_add_font(font);
            }
        }
    }

    return font;
}
Exemplo n.º 8
0
    void find_font(font & f, std::string const& name, int height, int weight, int style)
    {
        // FIXME: shouldn't require fonts to be empty
        BOOST_ASSERT(!f);

        FcValue fcval;

        // build pattern
        FcPattern * pattern = FcPatternCreate();

        // typeface name
        fcval.type = FcTypeString;
        fcval.u.s = (FcChar8 const*) name.c_str();
        FcPatternAdd(pattern, FC_FAMILY, fcval, FcTrue);

        // pixel size
        fcval.type = FcTypeInteger;
        fcval.u.i = height;
        FcPatternAdd(pattern, FC_PIXEL_SIZE, fcval, FcTrue);

        // italic
        if (style & font_style::italic)
        {
            fcval.type = FcTypeInteger;
            fcval.u.i = FC_SLANT_ITALIC;
            FcPatternAdd(pattern, FC_SLANT, fcval, FcTrue);
        }

        // weight
        fcval.type = FcTypeInteger;
        switch (weight)
        {
        case font_weight::thin:          fcval.u.i = FC_WEIGHT_THIN; break;
        case font_weight::extra_light:   fcval.u.i = FC_WEIGHT_EXTRALIGHT; break;
        case font_weight::light:         fcval.u.i = FC_WEIGHT_LIGHT; break;
        case font_weight::normal:        fcval.u.i = FC_WEIGHT_NORMAL; break;
        case font_weight::medium:        fcval.u.i = FC_WEIGHT_MEDIUM; break;
        case font_weight::semi_bold:     fcval.u.i = FC_WEIGHT_SEMIBOLD; break;
        case font_weight::bold:          fcval.u.i = FC_WEIGHT_BOLD; break;
        case font_weight::ultra_bold:    fcval.u.i = FC_WEIGHT_ULTRABOLD; break;
        case font_weight::heavy:         fcval.u.i = FC_WEIGHT_HEAVY; break;
        default:                         fcval.u.i = FC_WEIGHT_NORMAL; break;
        };
        FcPatternAdd(pattern, FC_WEIGHT, fcval, FcTrue);

        // transform pattern
        FcConfigSubstitute(NULL, pattern, FcMatchPattern);
        FcDefaultSubstitute(pattern);

        FcResult res;
        FcPattern * real_pattern = FcFontMatch(NULL, pattern, &res);

        FcPatternDestroy(pattern);

        // get filename
        if (real_pattern)
        {
            char * fname;
            int id;

            FcPatternGetString(real_pattern, FC_FILE, 0, (FcChar8 **) &fname);
            FcPatternGetInteger(real_pattern, FC_INDEX, 0, &id);

            // load font
            FT_Face face;
            if (FT_New_Face(::ftlib, fname, id, &face))
                return;

            FcPatternDestroy(real_pattern);

            // create font
            ft_font_extra * extra = static_cast<ft_font_extra *>(f.extra_data);

            extra->face = face;

            FT_Set_Pixel_Sizes(face, 0, height);

            // get avg char width/height
            point pt = detail::font_units_to_pixels(face, face->max_advance_width, face->max_advance_height);
            extra->width = pt.x;
            extra->height = pt.y;

            pt = detail::font_units_to_pixels(face, 0, face->ascender);
            extra->ascender = pt.y;

            pt = detail::font_units_to_pixels(face, 0, face->descender);
            extra->descender = pt.y;
        }
    }
Exemplo n.º 9
0
void CFontMaterial::Load( std::string dir, FT_Library & ftLib, int fontsize ) {
    
    if( !Util::DoesFileExist( dir ) ) {
     
        Log::Error( "Attempted to load non-existant font " + dir );
        return;
        
    }
    
    m_FontSize = fontsize;
    m_LargestBearingY = 0;

    FT_Face face;
    FT_New_Face( ftLib, dir.c_str(), 0, &face );
    FT_Set_Pixel_Sizes( face, 0, fontsize );

    int sheetwidth = 0, sheetheight = 0;
    int offsetx = 0;
    
    for( int j = 0; j < FONT_ALLOC; j++ ) {
     
        FT_UInt glyphindex = FT_Get_Char_Index( face, j );
        FT_Load_Glyph( face, glyphindex, FT_LOAD_RENDER );
        FT_GlyphSlot slot = face->glyph;
        FT_Bitmap bitmap = slot->bitmap;
        
        sheetwidth += bitmap.width;
        sheetheight = ( bitmap.rows > sheetheight )? bitmap.rows : sheetheight;
        
    }

    
    m_FontSheet.InitPixels( sheetwidth, sheetheight );

    for( int j = 0; j < FONT_ALLOC; j++ )
    {
        
        FT_UInt glyphindex = FT_Get_Char_Index( face, j );
        FT_Load_Glyph( face, glyphindex, FT_LOAD_RENDER );
        FT_GlyphSlot slot = face->glyph;
        FT_Bitmap bitmap = slot->bitmap;
       
        int w = bitmap.width;
        int h = bitmap.rows;

        GLubyte * data = new GLubyte[2 * w * h];
        
        for( int y = 0; y < bitmap.rows; y++ )
        {
            
            for( int x = 0; x < bitmap.width; x++ )
            {
                
                data[2 * ( x + y * w )] = bitmap.buffer[x + bitmap.width * y] > 0? 255 : 0;
                data[2 * ( x + y * w ) + 1] = bitmap.buffer[x + bitmap.width * y];
                
            }
            
        }
       
        m_Characters[j].m_Trans = face->glyph->advance.x >> 6;
        m_Characters[j].m_Left = face->glyph->bitmap_left;
        m_Characters[j].m_Size.Set( bitmap.width, bitmap.rows );
        m_Characters[j].m_Down = slot->metrics.horiBearingY >> 6;
        m_Characters[j].m_Height = slot->metrics.height >> 6;
        
        if( m_LargestBearingY < m_Characters[j].m_Down )
            m_LargestBearingY = m_Characters[j].m_Down;
        
        m_Characters[j].m_UpperLeftST.Set( ( float )offsetx / ( float )sheetwidth, 0.0f );
        m_Characters[j].m_LowerRightST.Set( ( ( float )offsetx + ( float )w ) / ( float )sheetwidth, ( ( float )h ) / ( float )sheetheight );
        
        m_FontSheet.AddPixelDataLuminance( data, offsetx, 0, w, h );
        
        m_Characters[j].m_Offset = offsetx;
        offsetx += w;
        
        delete [] data;
   
        
    }
    
    FT_Done_Face( face );
    
    m_FontSheet.CreateGLTexture();
    
    std::stringstream log;
    log << "Successfully loaded font " << dir << " at size: " << fontsize;
    
    Log::Log( log.str() );
    
}
Exemplo n.º 10
0
/** Render a glyph for a character into bitmap and save it into the glyph page.
 *  \param c The character to be loaded.
 *  \param c \ref GlyphInfo for the character.
 */
void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
{
    assert(gi.glyph_index > 0);
    assert(gi.font_number < m_face_ttf->getTotalFaces());
    FT_Face cur_face = m_face_ttf->getFace(gi.font_number);
    FT_GlyphSlot slot = cur_face->glyph;

    // Same face may be shared across the different FontWithFace,
    // so reset dpi each time
    font_manager->checkFTError(FT_Set_Pixel_Sizes(cur_face, 0, getDPI()),
        "setting DPI");

    font_manager->checkFTError(FT_Load_Glyph(cur_face, gi.glyph_index,
        FT_LOAD_DEFAULT), "loading a glyph");

    font_manager->checkFTError(shapeOutline(&(slot->outline)),
        "shaping outline");

    font_manager->checkFTError(FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL),
        "rendering a glyph to bitmap");

    // Convert to an anti-aliased bitmap
    FT_Bitmap* bits = &(slot->bitmap);
    core::dimension2du texture_size(bits->width + 1, bits->rows + 1);
    if ((m_used_width + texture_size.Width > getGlyphPageSize() &&
        m_used_height + m_current_height + texture_size.Height >
        getGlyphPageSize())                                     ||
        m_used_height + texture_size.Height > getGlyphPageSize())
    {
        // Add a new glyph page if current one is full
        createNewGlyphPage();
    }

    // Determine the linebreak location
    if (m_used_width + texture_size.Width > getGlyphPageSize())
    {
        m_used_width  = 0;
        m_used_height += m_current_height;
        m_current_height = 0;
    }

    const unsigned int cur_tex = m_spritebank->getTextureCount() -1;
#ifndef SERVER_ONLY
    if (bits->buffer != NULL)
    {
        video::ITexture* tex = m_spritebank->getTexture(cur_tex);
        glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName());
        assert(bits->pixel_mode == FT_PIXEL_MODE_GRAY);
        if (CVS->isARBTextureSwizzleUsable())
        {
            glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
                bits->width, bits->rows, GL_RED, GL_UNSIGNED_BYTE,
                bits->buffer);
        }
        else
        {
            const unsigned int size = bits->width * bits->rows;
            uint8_t* image_data = new uint8_t[size * 4];
            memset(image_data, 255, size * 4);
            for (unsigned int i = 0; i < size; i++)
                image_data[4 * i + 3] = bits->buffer[i];
            glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
                bits->width, bits->rows, GL_RGBA, GL_UNSIGNED_BYTE,
                image_data);
            delete[] image_data;
        }
        if (tex->hasMipMaps())
            glGenerateMipmap(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, 0);
    }
#endif

    // Store the rectangle of current glyph
    gui::SGUISpriteFrame f;
    gui::SGUISprite s;
    core::rect<s32> rectangle(m_used_width, m_used_height,
        m_used_width + bits->width, m_used_height + bits->rows);
    f.rectNumber = m_spritebank->getPositions().size();
    f.textureNumber = cur_tex;

    // Add frame to sprite
    s.Frames.push_back(f);
    s.frameTime = 0;
    m_spritebank->getPositions().push_back(rectangle);
    m_spritebank->getSprites().push_back(s);

    // Save glyph metrics
    FontArea a;
    a.advance_x = cur_face->glyph->advance.x / BEARING;
    a.bearing_x = cur_face->glyph->metrics.horiBearingX / BEARING;
    const int cur_height = (cur_face->glyph->metrics.height / BEARING);
    const int cur_offset_y = cur_height -
        (cur_face->glyph->metrics.horiBearingY / BEARING);
    a.offset_y = m_glyph_max_height - cur_height + cur_offset_y;
    a.offset_y_bt = -cur_offset_y;
    a.spriteno = f.rectNumber;
    m_character_area_map[c] = a;

    // Store used area
    m_used_width += texture_size.Width;
    if (m_current_height < texture_size.Height)
        m_current_height = texture_size.Height;
}   // insertGlyph
Exemplo n.º 11
0
  TextRenderer::TextRenderer (const std::string &font,
                              unsigned height,
                              boost::shared_ptr<GLExtensionProxy> proxy)
    : priv (new Private (proxy))
  {
    priv->height = 0;

    FT_Error err;
    err = FT_New_Face (priv->lib,
                       font.c_str (),
                       0,
                       &priv->ft_face);

    if (err)
    {
      throw std::logic_error ("Failed to load font");
    }

    err = FT_Set_Pixel_Sizes (priv->ft_face,
                              0,
                              height);

    if (err)
    {
      throw std::logic_error ("Failed to set font height");
    }

    priv->glyphs.resize (256);
    priv->kern = FT_HAS_KERNING (priv->ft_face);

    FT_UInt glyph_index;
    for (FT_ULong char_code = FT_Get_First_Char (priv->ft_face, &glyph_index);
          glyph_index != 0;
          char_code = FT_Get_Next_Char (priv->ft_face, char_code, &glyph_index))
    {
      err = FT_Load_Glyph (priv->ft_face, glyph_index, FT_LOAD_DEFAULT);

      if (err)
      {
        SS_WARN ("Ignoring char %c because of Freetype error: %d", (char) char_code, err);
        continue;
      }

      if (char_code >= 256)
        continue;

      FT_Glyph tmp;
      err = FT_Get_Glyph (priv->ft_face->glyph, &tmp);

      if (err)
      {
        SS_WARN ("Ignoring char %c because of Freetype error: %d", (char) char_code, err);
        continue;
      }

      err = FT_Glyph_To_Bitmap (&tmp,
          FT_RENDER_MODE_LIGHT, 0, 1);

      if (err)
      {
        SS_WARN ("Ignoring char %c because of Freetype error: %d", (char) char_code, err);
        continue;
      }

      priv->glyphs[char_code].ft_glyph = tmp;
      priv->glyphs[char_code].glyph_index = glyph_index;
    }
  }
Exemplo n.º 12
0
void			Text::LoadFont(GLfloat width, GLfloat height)
{
	shader = new Shader( (pathToShaders + "Text.vert").c_str(),
				  		 (pathToShaders + "Text.frag").c_str());
	shader->Use();
    glm::mat4 projection = glm::ortho(0.0f, width, 0.0f, height);
    glUniformMatrix4fv(glGetUniformLocation(shader->Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));

	if(FT_Init_FreeType(&freetype))
		throw DError() << msg("Could not init freetype library");
	if(FT_New_Face(freetype, (pathToFont + font).c_str(), 0, &face))
		throw DError() << msg("Could not open font: " + font);
	
	FT_Set_Pixel_Sizes(face, 0, size);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 

	for (GLubyte c = 0; c < 128; c++)
    {
        // Load character glyph 
        if (FT_Load_Char(face, c, FT_LOAD_RENDER))
        {
            std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
            continue;
        }
        // Generate texture
        GLuint texture;
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexImage2D(
            GL_TEXTURE_2D,
            0,
            GL_RED,
            face->glyph->bitmap.width,
            face->glyph->bitmap.rows,
            0,
            GL_RED,
            GL_UNSIGNED_BYTE,
            face->glyph->bitmap.buffer
        );
        // Set texture options
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        // Now store character for later use
        Character character = {
            texture,
            glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
            glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
            (GLuint)face->glyph->advance.x
        };
        Characters.insert(std::pair<GLchar, Character>(c, character));
    }
    glBindTexture(GL_TEXTURE_2D, 0);
    // Destroy FreeType once we're finished
    FT_Done_Face(face);
    FT_Done_FreeType(freetype);

    
    // Configure VAO/VBO for texture quads
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}
Exemplo n.º 13
0
console* Create_console(console_attribute attr)
{
    console* cons;
    int i;

    cons = (console*) malloc(sizeof(console));
    if(cons==NULL)
        return NULL;

    cons->attr = attr;	// make a copy of attributes
    // Init of members
    cons->line_current = 0;
    cons->line_next = 0;
    cons->car_current = 0;
    cons->nb_line = attr.height / attr.textsize;
    cons->nb_car_per_line = attr.width / attr.textsize;
    cons->line_top = -1;
    cons->ft_library	= NULL;
    cons->ft_face		= NULL;

    // Construction of buffer :
    // -> buffer[line][row]
    cons->buffer = (char**) malloc(sizeof(char*) * cons->nb_line);
    if(cons->buffer == NULL)
    {
        Delete_console(cons);
        return NULL;
    }
    for(i=0; i<(cons->nb_line) ; i++)
    {
        cons->buffer[i] = (char*) malloc(sizeof(char) * (cons->nb_car_per_line + 1));	// +1 for '\0'
        if(cons->buffer[i] == NULL)
        {
            Delete_console(cons);
            return NULL;
        }
        cons->buffer[i][0]='\0'; // first caracter NULL for no printing at the begining
        cons->buffer[i][cons->nb_car_per_line]='\0'; // should always be NULL
    }

    if ( attr.ft_library != NULL && attr.ft_face != NULL)	// library and face specifed in attributes
    {
        // use library and face from attributes
        cons->ft_library = attr.ft_library;
        cons->ft_face = attr.ft_face;
    }
    else
    {
        if ( FT_Init_FreeType( &(cons->ft_library) ) )
        {
            Delete_console(cons);
            return NULL;
        }
        // Load Face "/dev_hdd0/tmp/arial.ttf"
        // Not a good way, this default Face will be on memory
        if ( FT_New_Face( cons->ft_library, "/dev_hdd0/tmp/arial.ttf", 0, &(cons->ft_face) ) )
        {
            Delete_console(cons);
            return NULL;
        }
    }
    // Set font size
    if( FT_Set_Pixel_Sizes( cons->ft_face, 0, cons->attr.textsize) )
    {
        Delete_console(cons);
        return NULL;
    }

    return cons;
}
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
Error DynamicFontAtSize::_load() {


	int error = FT_Init_FreeType( &library );

	ERR_EXPLAIN(TTR("Error initializing FreeType."));
	ERR_FAIL_COND_V( error !=0, ERR_CANT_CREATE );

	if (font->font_path!=String()) {

		FileAccess *f=FileAccess::open(font->font_path,FileAccess::READ);
		ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);

		memset(&stream,0,sizeof(FT_StreamRec));
		stream.base=NULL;
		stream.size=f->get_len();
		stream.pos=0;
		stream.descriptor.pointer=f;
		stream.read=_ft_stream_io;
		stream.close=_ft_stream_close;

		FT_Open_Args fargs;
		memset(&fargs,0,sizeof(FT_Open_Args));
		fargs.flags=FT_OPEN_STREAM;
		fargs.stream=&stream;
		error = FT_Open_Face( library,&fargs,0,&face);
	} else if (font->font_mem) {

		memset(&stream,0,sizeof(FT_StreamRec));
		stream.base=(unsigned char*)font->font_mem;
		stream.size=font->font_mem_size;
		stream.pos=0;

		FT_Open_Args fargs;
		memset(&fargs,0,sizeof(FT_Open_Args));
		fargs.memory_base=(unsigned char*)font->font_mem;
		fargs.memory_size=font->font_mem_size;
		fargs.flags= FT_OPEN_MEMORY;
		fargs.stream=&stream;
		error = FT_Open_Face( library,&fargs,0,&face);

	} else {
		ERR_EXPLAIN("DynamicFont uninitialized");
		ERR_FAIL_V(ERR_UNCONFIGURED);
	}

	//error = FT_New_Face( library, src_path.utf8().get_data(),0,&face );

	if ( error == FT_Err_Unknown_File_Format ) {
		ERR_EXPLAIN(TTR("Unknown font format."));
		FT_Done_FreeType( library );

	} else if ( error ) {

		ERR_EXPLAIN(TTR("Error loading font."));
		FT_Done_FreeType( library );

	}

	ERR_FAIL_COND_V(error,ERR_FILE_CANT_OPEN);


	/*error = FT_Set_Char_Size(face,0,64*size,512,512);

	if ( error ) {
		FT_Done_FreeType( library );
		ERR_EXPLAIN(TTR("Invalid font size."));
		ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER );
	}*/

	error = FT_Set_Pixel_Sizes(face,0,size);

	ascent=face->size->metrics.ascender>>6;
	descent=-face->size->metrics.descender>>6;
	linegap=0;

	//print_line("ASCENT: "+itos(ascent)+" descent "+itos(descent)+" hinted: "+itos(face->face_flags&FT_FACE_FLAG_HINTER));

	valid=true;
	return OK;
}
Exemplo n.º 16
0
gboolean draw_overview_glyph (cairo_t* context, const char* font_file, gdouble width, gdouble height, gunichar character) {
	FT_Face face;
	int error;
	gdouble units_per_em;
	gdouble units;
	gdouble advance;
	int gid;

	// private use area
	if (0xe000 <= character && character <= 0xf8ff) {
		return FALSE;
	}
	
	// control characters
	if (character <= 0x001f || (0x007f <= character && character <= 0x008d)) {
		return FALSE;
	}

	if (font_file == NULL) {
		g_warning("font_file is null");
		return FALSE;
	}
	
	gchar text[7];
	int length = g_unichar_to_utf8 (character, text);
	text[length] = '\0';
	
	if (freetype_library == NULL) {
		error = FT_Init_FreeType (&freetype_library);
		if (error) {
			g_warning ("Freetype init error %d.\n", error);
			return FALSE;
		}
	}

	error = FT_New_Face (freetype_library, font_file, 0, &face);
	if (error) {
		g_warning ("Freetype font face error %d\n", error);
		return FALSE;
	}
	
	units_per_em = face->units_per_EM;
	units = (height * 0.5) / units_per_em;
	
	error = FT_Select_Charmap (face , FT_ENCODING_UNICODE);
	if (error) {
		g_warning ("Freetype can not use Unicode, error: %d\n", error);
		FT_Done_Face (face);
		return FALSE;
	}

	error = FT_Set_Char_Size (face, 0, 64, (int) height, (int) height);
	if (error) {
		g_warning ("FT_Set_Char_Size, error: %d.\n", error);
		FT_Done_Face (face);
		return FALSE;
	}
	
	error = FT_Set_Pixel_Sizes (face, 0, (int) (height * 0.5));
	if (error) {
		g_warning ("FT_Set_Pixel_Sizes, error: %d.\n", error);
		FT_Done_Face (face);
		return FALSE;
	}

	gid = FT_Get_Char_Index (face, character);
	advance = 0;
	if (gid != 0) {
		FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE);
		advance = face->glyph->metrics.horiAdvance;
		advance *= units;
	} else {
		FT_Done_Face (face);
		return FALSE;
	}

	static const cairo_user_data_key_t key;

	cairo_save (context);
	
	cairo_font_face_t* cairo_face = cairo_ft_font_face_create_for_ft_face (face, 0);
	
	if (cairo_face == NULL) {
		g_warning("cairo font face is null");
		FT_Done_Face (face);
		return FALSE;
	}
	
	int status = cairo_font_face_set_user_data (cairo_face, &key, face, (cairo_destroy_func_t) FT_Done_Face);
	
	if (status != CAIRO_STATUS_SUCCESS) {		
		cairo_font_face_destroy (cairo_face);
		FT_Done_Face (face);
		return FALSE;
	}

	cairo_set_font_face (context, cairo_face);
	cairo_set_font_size (context, height * 0.5);
	
	gdouble x = (width - advance) / 2;
	
	if (x < 0) {
		x = 0;
	}
	
	cairo_move_to (context, x, height - 30);
	cairo_show_text (context, text);
	
	cairo_font_face_destroy (cairo_face);
	cairo_restore (context);
	
	// cairo closes the font face and the library must be kept open
	
	return TRUE;
}
//------------------------------------------------------------------------------
APP::TextureAtlas::TextureAtlas(const std::string& font, unsigned int fontSize)
{
    // INIT FREETYPE AND CREATE FONT ATLAS

    // check if we have and OpenGL context
    ERROR_ASSERT(APP::IsInitialized())

    FT_Library library;

    // load the library
    FT_Error err = FT_Init_FreeType(&library);

    ERROR_ASSERT(err == 0)

    FT_Face face;

    // load the font (face)
    err = FT_New_Face(
            library,
            font.c_str(),
            0,
            &face 
        );

    ERROR_ASSERT(err == 0)

    FT_Set_Pixel_Sizes(face, 0, fontSize);    

    FT_GlyphSlot g = face->glyph;
    int atlasWidth = 0;
    int atlasHeight = 0;

    
    // compute the dimensions of the atlas
    for (unsigned int i = 32; i < 128; i++) 
    {
        if(FT_Load_Char(face, i, FT_LOAD_RENDER)) 
        {
            ERROR_WARNING("Loading character %c failed!")
            continue;
        }

        atlasWidth += g->bitmap.width;
        atlasHeight = std::max(atlasHeight, g->bitmap.rows);
    }

    unsigned char* atlas = new unsigned char[atlasWidth*atlasHeight];
    
    for (unsigned int i = 0; i < atlasHeight*atlasWidth; i++)
    {
        atlas[i] = 0;
    }

    int marker = 0;

    for (unsigned int i = 32; i < 128; i++) 
    {
        if(FT_Load_Char(face, i, FT_LOAD_RENDER)) 
        {
            continue;
        }
        
        int w = g->bitmap.width;
        int h = g->bitmap.rows;
        
        unsigned char* buffer = g->bitmap.buffer;
        
        // copy character to atlas
        for (unsigned int v = 0; v < h; v++)
        {
            for (unsigned int u = 0; u < w; u++)
            {
                int y = atlasHeight - 1 - v;
                int x = marker + u;
                atlas[y*atlasWidth + x] = buffer[v*w + u];
            }
        }

        // save character info
        bitmapWidth_[i]  = w;
        atlasOffX_[i] = marker;
        advances_[i] = Math::Vector2I(g->advance.x >> 6, g->advance.y >> 6);
        bearings_[i] = Math::Vector2I(g->bitmap_left, g->bitmap_top);

        // increase marker
        marker += w;
    }


    // initialize member
    atlas_ = new GL::Tex2DR8FR8UI(
            atlasWidth, 
            atlasHeight, 
            static_cast<void*>(atlas)
        );   

    width_ = atlasWidth;
    height_ = atlasHeight;


    // clean up
    delete[] atlas;
    FT_Done_FreeType(library);
}
Exemplo n.º 18
0
FT_Error
TA_sfnt_build_glyph_instructions(SFNT* sfnt,
                                 FONT* font,
                                 FT_Long idx)
{
  FT_Face face = sfnt->face;
  FT_Error error;

  FT_Byte* ins_buf;
  FT_UInt ins_len;
  FT_Byte* bufp;
  FT_Byte* p;

  SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
  glyf_Data* data = (glyf_Data*)glyf_table->data;
  /* `idx' is never negative */
  GLYPH* glyph = &data->glyphs[idx];

  TA_GlyphHints hints;

  FT_UInt num_hints_records;
  Hints_Record* hints_records;

  Recorder recorder;

  FT_Int32 load_flags;
  FT_UInt size;


  /* XXX: right now, we abuse this flag to control */
  /*      the global behaviour of the auto-hinter */
  load_flags = font->fallback_script << 30;
  load_flags |= 1 << 28; /* vertical hinting only */
  if (font->increase_x_height)
    load_flags |= 1 << 29;
  if (!font->pre_hinting)
    load_flags |= FT_LOAD_NO_SCALE;

  /* computing the segments is resolution independent, */
  /* thus the pixel size in this call is arbitrary */
  error = FT_Set_Pixel_Sizes(face, 20, 20);
  if (error)
    return error;

  ta_loader_register_hints_recorder(font->loader, NULL, NULL);
  error = ta_loader_load_glyph(font->loader, face, (FT_UInt)idx, load_flags);
  if (error)
    return error;

  /* do nothing if we have an empty glyph */
  if (!face->glyph->outline.n_contours)
    return FT_Err_Ok;

  hints = &font->loader->hints;

  /* do nothing if the setup delivered the dummy module only */
  if (!hints->num_points)
    return FT_Err_Ok;

  /* we allocate a buffer which is certainly large enough */
  /* to hold all of the created bytecode instructions; */
  /* later on it gets reallocated to its real size */
  ins_len = hints->num_points * 1000;
  ins_buf = (FT_Byte*)malloc(ins_len);
  if (!ins_buf)
    return FT_Err_Out_Of_Memory;

  /* initialize array with an invalid bytecode */
  /* so that we can easily find the array length at reallocation time */
  memset(ins_buf, INS_A0, ins_len);

  num_hints_records = 0;
  hints_records = NULL;

  /* handle composite glyph */
  if (font->loader->gloader->base.num_subglyphs)
  {
    bufp = TA_font_build_subglyph_shifter(font, ins_buf);
    if (!bufp)
    {
      error = FT_Err_Out_Of_Memory;
      goto Err;
    }

    goto Done1;
  }

  /* only scale the glyph if the dummy hinter has been used */
  if (font->loader->metrics->clazz == &ta_dummy_script_class)
  {
    /* since `TA_init_recorder' hasn't been called yet, */
    /* we manually initialize the `glyph' field */
    recorder.glyph = glyph;

    bufp = TA_sfnt_build_glyph_scaler(sfnt, &recorder, ins_buf);
    if (!bufp)
    {
      error = FT_Err_Out_Of_Memory;
      goto Err;
    }

    goto Done1;
  }

  error = TA_init_recorder(&recorder, face->glyph->outline.n_contours,
                           font, glyph, hints);
  if (error)
    goto Err;

  bufp = TA_sfnt_build_glyph_segments(sfnt, &recorder, ins_buf);
  if (!bufp)
  {
    error = FT_Err_Out_Of_Memory;
    goto Err;
  }

  /* now we loop over a large range of pixel sizes */
  /* to find hints records which get pushed onto the bytecode stack */

#ifdef DEBUGGING
  {
    int num_chars, i;


    num_chars = fprintf(stderr, "glyph %ld\n", idx);
    for (i = 0; i < num_chars - 1; i++)
      putc('=', stderr);
    fprintf(stderr, "\n\n");

  }
#endif

  /* we temporarily use `ins_buf' to record the current glyph hints, */
  /* leaving two bytes at the beginning so that the number of actions */
  /* can be inserted later on */
  ta_loader_register_hints_recorder(font->loader,
                                    TA_hints_recorder,
                                    (void*)&recorder);

  for (size = font->hinting_range_min;
       size <= font->hinting_range_max;
       size++)
  {
    TA_rewind_recorder(&recorder, bufp, size);

    error = FT_Set_Pixel_Sizes(face, size, size);
    if (error)
      goto Err;

    /* calling `ta_loader_load_glyph' uses the */
    /* `TA_hints_recorder' function as a callback, */
    /* modifying `hints_record' */
    error = ta_loader_load_glyph(font->loader, face, idx, load_flags);
    if (error)
      goto Err;

    /* append the point hints data collected in `TA_hints_recorder' */
    TA_build_point_hints(&recorder, hints);

    /* store the number of actions in `ins_buf' */
    *bufp = HIGH(recorder.hints_record.num_actions);
    *(bufp + 1) = LOW(recorder.hints_record.num_actions);

    if (TA_hints_record_is_different(hints_records,
                                     num_hints_records,
                                     bufp, recorder.hints_record.buf))
    {
#ifdef DEBUGGING
      {
        fprintf(stderr, "  size %d:\n", size);

        ta_glyph_hints_dump_edges(_ta_debug_hints);
        ta_glyph_hints_dump_segments(_ta_debug_hints);
        ta_glyph_hints_dump_points(_ta_debug_hints);

        fprintf(stderr, "  hints record:\n");
        for (p = bufp; p < recorder.hints_record.buf; p += 2)
          fprintf(stderr, " %2d", *p * 256 + *(p + 1));
        fprintf(stderr, "\n");
      }
#endif

      error = TA_add_hints_record(&hints_records,
                                  &num_hints_records,
                                  bufp, recorder.hints_record);
      if (error)
        goto Err;
    }
  }

  if (num_hints_records == 1 && !hints_records[0].num_actions)
  {
    /* since we only have a single empty record we just scale the glyph, */
    /* overwriting the data from `TA_sfnt_build_glyph_segments' */
    bufp = TA_sfnt_build_glyph_scaler(sfnt, &recorder, ins_buf);
    if (!bufp)
    {
      error = FT_Err_Out_Of_Memory;
      goto Err;
    }

    /* clear the rest of the temporarily used part of `ins_buf' */
    p = bufp;
    while (*p != INS_A0)
      *(p++) = INS_A0;

    goto Done;
  }

  /* in most cases, the output of `TA_sfnt_build_glyph_segments' */
  /* is shorter than the previously stored data, */
  /* so clear the rest of the temporarily used part of `ins_buf' */
  /* before appending the hints records */
  p = bufp;
  while (*p != INS_A0)
    *(p++) = INS_A0;

  bufp = TA_sfnt_emit_hints_records(sfnt,
                                    hints_records, num_hints_records,
                                    bufp);

Done:
  TA_free_hints_records(hints_records, num_hints_records);
  TA_free_recorder(&recorder);

  /* we are done, so reallocate the instruction array to its real size */
  if (*bufp == INS_A0)
  {
    /* search backwards */
    while (*bufp == INS_A0)
      bufp--;
    bufp++;
  }
  else
  {
    /* search forwards */
    while (*bufp != INS_A0)
      bufp++;
  }

Done1:
  ins_len = bufp - ins_buf;

  if (ins_len > sfnt->max_instructions)
    sfnt->max_instructions = ins_len;

  glyph->ins_buf = (FT_Byte*)realloc(ins_buf, ins_len);
  glyph->ins_len = ins_len;

  return FT_Err_Ok;

Err:
  TA_free_hints_records(hints_records, num_hints_records);
  TA_free_recorder(&recorder);
  free(ins_buf);

  return error;
}
Exemplo n.º 19
0
Arquivo: font.cpp Projeto: Try/Tempest
Tempest::FontElement::LetterGeometry Tempest::FontElement::letterGeometry( char16_t ch ) const {
  Leters & letters = *lt;

  if( Letter *l = letters.find(ch) ){
    LetterGeometry r;
    r.advance = l->advance;
    r.dpos    = l->dpos;
    r.size    = l->size;
    return r;
    }

  FT_Face       face;
  FT_Vector     pen = {0,0};
  FT_Error err = 0;

  if(fdata[key.name]==nullptr){
    RFile file(fnames[key.name].c_str());
    size_t sz = file.size();
    char * ch = new char[sz];
    fdata[key.name].reset(ch);
    if(file.readData(ch,sz)!=sz)
      fdata[key.name].reset();
    }
  Tempest::MemReader reader(fdata[key.name].get(),size_t(-1));
  FT_StreamRec stream;
  ft().mkStream(stream, reader);

  err = ft().New_Face( ft().library, stream, 0, &face );
  if( err )
    return LetterGeometry();

  err = FT_Set_Pixel_Sizes( face, key.size, key.size );
  if( err ){
    return LetterGeometry();
    }

  FT_Set_Transform( face, 0, &pen );

  LetterGeometry letter;
  if( FT_Load_Char( face, ch, FT_LOAD_RENDER ) ){
    return letter;
    }

  FT_GlyphSlot slot = face->glyph;
  FT_Bitmap& bmap = slot->bitmap;

  letter.dpos = Tempest::Point( slot->bitmap_left,
                                 key.size - slot->bitmap_top );

  letter.size      = Tempest::Size( bmap.width, bmap.rows );
  letter.advance   = Tempest::Point( slot->advance.x >> 6,
                                     slot->advance.y >> 6 );

  FT_Done_Face( face );

  Letter &ref = letters[ch];
  ref.size   =letter.size;
  ref.dpos   =letter.dpos;
  ref.advance=letter.advance;

  return letter;
  }
Exemplo n.º 20
0
Arquivo: main.cpp Projeto: jokoon/eio
void inittext(Shader &shader)
{
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    // Compile and setup the shader
    /*Shader shader("shaders/text.vs", "shaders/text.frag");*/
    glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(WIDTH), 0.0f, static_cast<GLfloat>(HEIGHT));
    shader.Use();
    glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));

    // FreeType
    FT_Library ft;
    // All functions return a value different than 0 whenever an error occurred
    if (FT_Init_FreeType(&ft))
        std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;

    // Load font as face
    FT_Face face;
    if (FT_New_Face(ft, "DejaVuSansMono.ttf", 0, &face))
        std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;

    // Set size to load glyphs as
    int fontsize;
    cfg.SET(fontsize);
    
    FT_Set_Pixel_Sizes(face, 0, fontsize);
    //FT_Set_Pixel_Sizes(face, 0, 48);

    // Disable byte-alignment restriction
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    // Load first 128 characters of ASCII set
    for (GLubyte c = 0; c < 128; c++)
    {
        // Load character glyph 
        if (FT_Load_Char(face, c, FT_LOAD_RENDER))
        {
            std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
            continue;
        }
        // Generate texture
        GLuint texture;
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexImage2D(
            GL_TEXTURE_2D,
            0,
            GL_RED,
            face->glyph->bitmap.width,
            face->glyph->bitmap.rows,
            0,
            GL_RED,
            GL_UNSIGNED_BYTE,
            face->glyph->bitmap.buffer
            );
        // Set texture options
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        // Now store character for later use
        Character character = {
            texture,
            glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
            glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
            face->glyph->advance.x
        };
        Characters.insert(std::pair<GLchar, Character>(c, character));
    }
    glBindTexture(GL_TEXTURE_2D, 0);
    // Destroy FreeType once we're finished
    FT_Done_Face(face);
    FT_Done_FreeType(ft);


    // Configure VAO/VBO for texture quads
    glGenVertexArrays(1, &VAO_text);
    glGenBuffers(1, &VBO_text);
    glBindVertexArray(VAO_text);
    glBindBuffer(GL_ARRAY_BUFFER, VBO_text);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

}
Exemplo n.º 21
0
	void FreetypeFont::SetFontSize(const U32 fontSize)
	{
		FT_Set_Pixel_Sizes(m_FontFace, 0, fontSize);
	}
Exemplo n.º 22
0
int generateFontMetadata (const char* ttfFilePath,
                          const char* outputPNG,
                          const char* outputMETADATA) {
   //fprintf(stderr, "TTF file %s \n", ttfFilePath);
   //fprintf(stderr, "PNG file %s \n", outputPNG);
   //fprintf(stderr, "META file %s \n", outputMETADATA);
	// Now we can initialise FreeType

   /* Check if the files are already there */
   FILE* fpMeta = fopen(outputMETADATA, "r");
   FILE* fpPng = fopen(outputPNG, "r");
   if (fpMeta) {
      fclose (fpMeta);
      if (fpPng) {
         fclose (fpPng);
         return 0;
      }
   }

	FT_Library ft;
	if (FT_Init_FreeType (&ft)) {
		fprintf (stderr, "Could not init FreeType library\n");
		return 1;
	}
	// load a font face from a file
	FT_Face face;
	if (FT_New_Face (ft, ttfFilePath, 0, &face)) {
		fprintf(stderr, "Could not open .ttf file\n");
		return 1;
	}

	int atlas_dimension_px = 1024; // atlas size in pixels
	int atlas_columns = 16; // number of glyphs across atlas
	int padding_px = 6; // total space in glyph size for outlines
	int slot_glyph_size = 64; // glyph maximum size in pixels
	int atlas_glyph_px = 64 - padding_px; // leave some padding for outlines
	
	// Next we can open a file stream to write our atlas image to
	unsigned char* atlas_buffer = (unsigned char*)malloc (
		atlas_dimension_px * atlas_dimension_px * 4 * sizeof (unsigned char)
	);
	unsigned int atlas_buffer_index = 0;

	// I'll tell FreeType the maximum size of each glyph in pixels
	int grows[256]; // glyph height in pixels
	int gwidth[256]; // glyph width in pixels
	int gpitch[256]; // bytes per row of pixels
	int gymin[256]; // offset for letters that dip below baseline like g and y
	unsigned char* glyph_buffer[256] = { NULL }; // stored glyph images
	// set height in pixels width 0 height 48 (48x48)
	FT_Set_Pixel_Sizes (face, 0, atlas_glyph_px);
	for (int i = 33; i < 256; i++) {
		if (FT_Load_Char (face, i, FT_LOAD_RENDER)) {
			fprintf(stderr, "Could not load character %i\n", i);
			return 1;
		}
		// draw glyph image anti-aliased
		FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL);
		// get dimensions of bitmap
		grows[i] = face->glyph->bitmap.rows;
		gwidth[i] = face->glyph->bitmap.width;
		gpitch[i] = face->glyph->bitmap.pitch;
		// copy glyph data into memory because it seems to be overwritten/lost later
		glyph_buffer[i] = (unsigned char*)malloc (grows[i] * gpitch[i]);
		memcpy (
			glyph_buffer[i],
			face->glyph->bitmap.buffer,
			face->glyph->bitmap.rows * face->glyph->bitmap.pitch
		);

		// get y-offset to place glyphs on baseline. this is in the bounding box
		FT_Glyph glyph; // a handle to the glyph image
		if (FT_Get_Glyph (face->glyph, &glyph)) {
			fprintf(stderr, "Could not get glyph handle %i\n", i);
			return 1;
		}
		// get bbox. "truncated" mode means get dimensions in pixels
		FT_BBox bbox;
		FT_Glyph_Get_CBox (glyph, FT_GLYPH_BBOX_TRUNCATE, &bbox);
		gymin[i] = bbox.yMin;
	}

	for (int y = 0; y < atlas_dimension_px; y++) {
		for (int x = 0; x < atlas_dimension_px; x++) {
			// work out which grid slot[col][row] we are in e.g out of 16x16
			int col = x / slot_glyph_size;
			int row = y / slot_glyph_size;
			int order = row * atlas_columns + col;
			int glyph_index = order + 32;

			// an actual glyph bitmap exists for these indices
			if (glyph_index > 32 && glyph_index < 256) {
				// pixel indices within padded glyph slot area
				int x_loc = x % slot_glyph_size - padding_px / 2;
				int y_loc = y % slot_glyph_size - padding_px / 2;
				// outside of glyph dimensions use a transparent, black pixel (0,0,0,0)
				if (x_loc < 0 || y_loc < 0 ||
					x_loc >= gwidth[glyph_index] || y_loc >= grows[glyph_index]) {
					atlas_buffer[atlas_buffer_index++] = 0;
					atlas_buffer[atlas_buffer_index++] = 0;
					atlas_buffer[atlas_buffer_index++] = 0;
					atlas_buffer[atlas_buffer_index++] = 0;
				} else {
					// this is 1, but it's safer to put it in anyway
					//int bytes_per_pixel = gwidth[glyph_index] / gpitch[glyph_index];
					//int bytes_in_glyph = grows[glyph_index] * gpitch[glyph_index];
					int byte_order_in_glyph = y_loc * gwidth[glyph_index] + x_loc;
					unsigned char colour[4];
					colour[0] = colour[1] = colour[2] = colour[3] =
						glyph_buffer[glyph_index][byte_order_in_glyph];
					// print byte from glyph
					atlas_buffer[atlas_buffer_index++] =
						glyph_buffer[glyph_index][byte_order_in_glyph];
					atlas_buffer[atlas_buffer_index++] =
						glyph_buffer[glyph_index][byte_order_in_glyph];
					atlas_buffer[atlas_buffer_index++] =
						glyph_buffer[glyph_index][byte_order_in_glyph];
					atlas_buffer[atlas_buffer_index++] =
						glyph_buffer[glyph_index][byte_order_in_glyph];
				}
			// write black in non-graphical ASCII boxes
			} else {
				atlas_buffer[atlas_buffer_index++] = 0;
				atlas_buffer[atlas_buffer_index++] = 0;
				atlas_buffer[atlas_buffer_index++] = 0;
				atlas_buffer[atlas_buffer_index++] = 0;
			} //endif
		} // endfor
	} // endfor

	// write meta-data file to go with atlas image
	std::ofstream myfile;

   myfile.open (outputMETADATA, std::ios::in | std::ios::out | std::ios::app | std::ios::binary);

   if (!myfile.is_open()) {
      free (atlas_buffer);
      return 1;
   }

   myfile << "// ascii_code prop_xMin prop_width prop_yMin prop_height prop_y_offset" << std::endl;

	// write an unique line for the 'space' character
	myfile << "32" << " " << std::fixed << std::setprecision( 6 ) << 0.0f << " " << 0.5 << " " << 0.0f << " " << 1.0 << " " << 0.0f << std::endl;

	// write a line for each regular character
	for (int i = 33; i < 256; i++) {
		int order = i - 32;
		int col = order % atlas_columns;
		int row = order / atlas_columns;
		float x_min = (float)(col * slot_glyph_size) / (float)atlas_dimension_px;
		float y_min = (float)(row * slot_glyph_size) / (float)atlas_dimension_px;
		myfile << std::fixed << std::setprecision( 6 ) << i << " "
		      << x_min << " "
	         << (float)(gwidth[i] + padding_px) / 64.0f << " "
		      << y_min << " "
		      << (grows[i] + padding_px)  / 64.0f << " "
		      << -((float)padding_px - (float)gymin[i]) / 64.0f
		      << std::endl;
	}
   myfile.close();

   // free that buffer of glyph info
	for (int i = 0; i < 256; i++) {
		if (NULL != glyph_buffer[i]) {
			free (glyph_buffer[i]);
		}
	}
	
	// use stb_image_write to write directly to png
	if (!stbi_write_png (
		outputPNG,
		atlas_dimension_px,
		atlas_dimension_px,
		4,
		atlas_buffer,
		0
	)) {
		fprintf (stderr, "ERROR: could not write file %s\n", outputPNG);
	}
	free (atlas_buffer);
	return 0;
}
Exemplo n.º 23
0
static Font_Info *
_font_slave_int_load(const Slave_Msg_Font_Load *msg, Font_Source_Info *fsi)
{
   int error;
   int val, dv;
   int ret;
   Font_Info *fi = calloc(1, sizeof(*fi));

   error = FT_New_Size(fsi->face, &(fi->size));
   if (!error)
     FT_Activate_Size(fi->size);

   fi->fsize = msg->size;
   fi->dpi = msg->dpi;
   fi->real_size = msg->size * 64;
   fi->fsi = fsi;
   error = FT_Set_Char_Size(fsi->face, 0, fi->real_size, msg->dpi, msg->dpi);
   if (error)
     error = FT_Set_Pixel_Sizes(fsi->face, 0, fi->real_size);

   if (error)
     {
        int i, maxd = 0x7fffffff;
        int chosen_size = 0;
        int chosen_size2 = 0;

        for (i = 0; i < fsi->face->num_fixed_sizes; i++)
          {
             int s, cd;

             s = fsi->face->available_sizes[i].size;
             cd = chosen_size - fi->real_size;
             if (cd < 0) cd = -cd;
             if (cd < maxd)
               {
                  maxd = cd;
                  chosen_size = s;
                  chosen_size2 = fsi->face->available_sizes[i].y_ppem;
                  if (maxd == 0) break;
               }
          }
        fi->real_size = chosen_size;
        error = FT_Set_Pixel_Sizes(fsi->face, 0, fi->real_size);

        if (error)
          {
             error = FT_Set_Char_Size(fsi->face, 0, fi->real_size, fi->dpi, fi->dpi);
             if (error)
               {
                  /* hack around broken fonts */
                  fi->real_size = (chosen_size2 / 64) * 60;
                  error = FT_Set_Char_Size(fsi->face, 0, fi->real_size, fi->dpi, fi->dpi);
                  if (error)
                    {
                       ERR("Could not choose the font size for font: '%s:%s'.",
                           msg->file, msg->name);
                       FT_Done_Size(fi->size);
                       free(fi);
                       return NULL;
                    }
               }
          }
     }

   fi->max_h = 0;
   val = (int)fsi->face->bbox.yMax;
   if (fsi->face->units_per_EM != 0)
     {
        dv = (fsi->orig_upem * 2048) / fsi->face->units_per_EM;
        ret = (val * fsi->face->size->metrics.y_scale) / (dv * dv);
     }
   else ret = val;
   fi->max_h += ret;
   val = -(int)fsi->face->bbox.yMin;
   if (fsi->face->units_per_EM != 0)
     {
        dv = (fsi->orig_upem * 2048) / fsi->face->units_per_EM;
        ret = (val * fsi->face->size->metrics.y_scale) / (dv * dv);
     }
   else ret = val;
   fi->max_h += ret;

   fi->runtime_rend = FONT_REND_REGULAR;
   if ((msg->rend_flags & FONT_REND_SLANT) &&
       !(fsi->face->style_flags & FT_STYLE_FLAG_ITALIC))
     fi->runtime_rend |= FONT_REND_SLANT;
   if ((msg->rend_flags & FONT_REND_WEIGHT) &&
       !(fsi->face->style_flags & FT_STYLE_FLAG_BOLD))
     fi->runtime_rend |= FONT_REND_WEIGHT;

   return fi;
}
Exemplo n.º 24
0
int main(int argc, char** argv)
{
    if(argc < 2)
    {
        printf("Error! No Font Specified!\n");
        return 1;
    }
    std::string filename(argv[1]);
const size_t last_slash_idx = filename.find_last_of("\\/");
if (std::string::npos != last_slash_idx)
{
    filename.erase(0, last_slash_idx + 1);
}

    // Remove extension if present.
    const size_t period_idx = filename.rfind('.');
    if (std::string::npos != period_idx)
    {
         filename.erase(period_idx);
    }

    FIBITMAP* bitmap = FreeImage_Allocate(4096, 4096, 32);

    FreeImage_SetTransparent(bitmap, true);
    FT_Library library;

    FT_Init_FreeType(&library);

    FT_Face face;

    FT_New_Face(library, argv[1], 0, &face);

    rapidjson::StringBuffer s;
    rapidjson::Writer<rapidjson::StringBuffer> writer(s);

    writer.StartObject();
    writer.String("glyphs");
    writer.StartArray();
    int tileSize = 64;
    int tileCount = 64;
    FT_Set_Pixel_Sizes(face, 0, tileSize);
    for (int c = 32, id = 0; c < 4096; ++c, ++id)
    {
        FT_Load_Char(face, c, FT_LOAD_RENDER);

        FT_Bitmap bmp = face->glyph->bitmap;

        FT_Glyph_Metrics metrics = face->glyph->metrics;

        int i = 0, j = 0;
        for (j = 0; j < bmp.rows; ++j)
        {
            for (i = 0; i < bmp.width; ++i)
            {
                RGBQUAD value = {bmp.buffer[j * bmp.width + i],
                                 bmp.buffer[j * bmp.width + i],
                                 bmp.buffer[j * bmp.width + i],
                                 bmp.buffer[j * bmp.width + i]};
                FreeImage_SetPixelColor(
                    bitmap, (id % tileCount) * tileSize + i,
                    (id / tileCount) * tileSize + bmp.rows - j, &value);
            }
        }

        double x = (id % tileCount) * tileSize;
        double y = (id / tileCount) * tileSize;

        writer.StartObject();
        {
            writer.String("id");
            writer.Uint(c);
            writer.String("char");
            writer.String((const char*)&c);
            writer.String("metrics");
            writer.StartObject();
            {
                writer.String("width");
                writer.Int(metrics.width / 64);
                writer.String("height");
                writer.Int(metrics.height / 64);
                writer.String("horiBearingX");
                writer.Int(metrics.horiBearingX / 64);
                writer.String("horiBearingY");
                writer.Int(metrics.horiBearingY / 64);
                writer.String("horiAdvance");
                writer.Int(metrics.horiAdvance / 64);
                writer.String("vertBearingX");
                writer.Int(metrics.vertBearingX / 64);
                writer.String("vertBearingY");
                writer.Int(metrics.vertBearingY / 64);
                writer.String("vertAdvance");
                writer.Int(metrics.vertAdvance / 64);
            }
            writer.EndObject();
            writer.String("uv");
            writer.StartArray();
            writer.StartArray();
            writer.Double(x / 4096.0);
            writer.Double((y - metrics.height / 64) / 4096.0);
            writer.EndArray();
            writer.StartArray();
            writer.Double(x / 4096.0);
            writer.Double(y / 4096.0);
            writer.EndArray();
            writer.StartArray();
            writer.Double((x + metrics.width / 64) / 4096.0);
            writer.Double(y / 4096.0);
            writer.EndArray();
            writer.StartArray();
            writer.Double((x + metrics.width / 64) / 4096.0);
            writer.Double((y - metrics.height / 64) / 4096.0);
            writer.EndArray();
            writer.EndArray();
        }
        writer.EndObject();
    }

    writer.EndArray();
    writer.EndObject();

    FILE* fp = fopen((filename + ".json").c_str(), "w");

    fputs(s.GetString(), fp);

    fclose(fp);

    if (FreeImage_Save(FIF_PNG, bitmap, (filename + ".png").c_str(), BMP_DEFAULT))
    {
        printf("Saved file to %s\n", (filename + ".png").c_str());
    }

    FreeImage_Unload(bitmap);

    return 0;
}
Exemplo n.º 25
0
//--------------------------------------------------------------
void ofxFreeType2::loadFont(string filepath, int size, bool _bAntiAlias, bool _bFullCharacterSet, bool _bMakeContours) {
	//Init vars
	fontSize			=  size;
	lineHeight			= fontSize;
	bAntiAlias			= _bAntiAlias;
	bFullCharacterSet	= _bFullCharacterSet;
	bMakeContours		= _bMakeContours;
	
	
	//Clear chars if a font has already been loaded
	if (bFaceLoaded){
		if (chars != NULL){
			delete[] chars;
		}
		
		if (charTextures != NULL){
			for (int i = 0; i < nChars; i++){
				glDeleteTextures(1, &charTextures[i]);
			}
			delete[] charTextures;
		}
	}
	
	bFaceLoaded = false;
	
	
	//FreeType Vars
	FT_Library	library;
	FT_Face		face;
	FT_Error error;
	
	//Init library
	if (FT_Init_FreeType(&library)) { 
		ofLog(OF_LOG_ERROR,"Freetype Error: Unable to Initialize Library");
		return;
	}
	
	
	
	//Load Font Face
	error = FT_New_Face(library,
						ofToDataPath(filepath).c_str(),
						0,
						&face );
	
	if (error == FT_Err_Unknown_File_Format) { //Font opened but unsupported
		ofLog(OF_LOG_ERROR,"Freetype Error: Unknown Format");
		return;
	} else if (error) { //Font can not be read/is broken
		ofLog(OF_LOG_ERROR,"Freetype Error: Couldn't open font.");
		return;
	}
	
	
	//Set Size (pts or pixels)
	if(resolution) error = FT_Set_Char_Size(face, 0,  (float(size) * (72.0/float(resolution)))*64.0, resolution, resolution);	  
	else error = FT_Set_Pixel_Sizes(face, size, size);
	
	if(error) {
		ofLog(OF_LOG_ERROR,"Freetype Error: Couldn't set font size. Font may be fixed width?");
		return;
	}
	
	//Get total Chars from Face
	nChars	= bFullCharacterSet ? 256 : 128;
	nChars -= START_CHAR;
	
	//Init arrays, generate textures
	chars			= new charInfo[nChars];
	charTextures	= new GLuint[nChars];
	glGenTextures(nChars, charTextures);
	
	//Clear/Create contour array if necessary
	if(bMakeContours){
		charOutlines.clear();
		charOutlines.assign(nChars, ofTTCharacter());
	}
	
	
	//Create Characters
	FT_Glyph glyph;
	FT_BBox	bbox;
	
	for(int i=START_CHAR; i<nChars+START_CHAR; i++) {
		//Load Glyph
		int charIndex	= i - START_CHAR;
		
		if(bAntiAlias) {
			error = FT_Load_Char(face, i, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT);
		} else {
			error = FT_Load_Char(face, i, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
		}
		
		if(error) {
			ofLog(OF_LOG_ERROR,"Freetype Error: Couldn't load glyph.");
			return;
		}
		
		
		
		//Create Outline if necessary
		if(bMakeContours){
			if( printVectorInfo )printf("\n\ncharacter %c: \n", char( i ) );
			
			//int character = i + NUM_CHARACTER_TO_START;
			charOutlines[charIndex] = makeContoursForCharacter( face );
		}
		
		
		//Get Size of Bitmap, convert from fractional pixel format
		float bmpW	= face->glyph->metrics.width >> 6;
		float bmpH	= face->glyph->metrics.height >> 6;
		
		
		//Create Texture Sizes
		//Add 2px to avoid edges on either side
		
		int width  = ofNextPow2(bmpW+1);
		int height = ofNextPow2(bmpH+1);
		if (width == 1) width = 2;
		if (height == 1) height = 2;
		
		//Set Info for This Glyph
		FT_Get_Glyph(face->glyph, &glyph );
		FT_Glyph_Get_CBox(glyph, 0, &bbox );
		
		float xMin = bbox.xMin >> 6;
		float xMax = bbox.xMax >> 6;
		float yMin = bbox.yMin >> 6;
		float yMax = bbox.yMax >> 6;
		
		chars[charIndex].value 			= i;
		chars[charIndex].width 			= xMax - xMin;
		chars[charIndex].height 		= yMax - yMin;
		chars[charIndex].left			= face->glyph->bitmap_left;
		chars[charIndex].top			= yMax;
		chars[charIndex].bottom			= yMin;
		chars[charIndex].advance		= face->glyph->metrics.horiAdvance >> 6;
		
		//Set the position of the texture, centered with pow2 tex
		chars[charIndex].texWidth 		= bmpW;
		chars[charIndex].texHeight 		= bmpH;
		chars[charIndex].texXDiff	= (float)bmpW/(float)width;
		chars[charIndex].texYDiff	= (float)bmpH/(float)height;
		
		// Allocate Memory For The Texture Data.
		unsigned char* expanded_data = new unsigned char[2 * width * height];
		
		//Clear Texture Data
		for(int j=0; j <height;j++) {
			for(int k=0; k < width; k++){
				expanded_data[2*(k+(j*width))] = 255;   // every luminance pixel = 255
				expanded_data[2*(k+(j*width))+1] = 0;
			}
		}
		
		
		//Create texture from bitmap of glyph
		FT_Bitmap& bitmap= face->glyph->bitmap;
		
		if (bAntiAlias){
			//-----------------------------------
			for(int j=0; j <height; j++) {
				for(int k=0; k < width; k++){
					if ((k<bitmap.width) && (j<bitmap.rows)){
						//Offset pixels into texture by 1px to avoid edges
						//expanded_data[2*(((j+1)*width)+k +1) + 1] = bitmap.buffer[k + bitmap.width*(j)];
						int thisPixel = (((j * width) + k) * 2) + 1;
						expanded_data[thisPixel] = bitmap.buffer[k + bitmap.width*(j)];
					}
				}
			}
			//-----------------------------------
		} else {
			//-----------------------------------
			// true type packs monochrome info in a
			// 1-bit format, hella funky
			// here we unpack it:
			unsigned char *src =  bitmap.buffer;
			for(int j=0; j <bitmap.rows;j++) {
				unsigned char b=0;
				unsigned char *bptr =  src;
				for(int k=0; k < bitmap.width ; k++){
					if (k%8==0) b=(*bptr++);
					
					//Offset pixels into texture by 1px to avoid edges
					expanded_data[2*(k+j*width)+1] = b&0x80 ? 255 : 0;
					
				    b <<= 1;
				}
				src += bitmap.pitch;
			}
			//-----------------------------------
		}
		
		//Now we just setup some texture paramaters.
		glBindTexture( GL_TEXTURE_2D, charTextures[charIndex]);
		
		if (bAntiAlias){
			glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
			glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		} else {
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
		}
		
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		
		//Here we actually create the texture itself, notice
		//that we are using GL_LUMINANCE_ALPHA to indicate that
		//we are using 2 channel data.
		
		glTexImage2D(	GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height,
						0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data );
		
		
		//Clear Expanded Data
		delete [] expanded_data;
	}
	
	bFaceLoaded = true;
}
Exemplo n.º 26
0
Font::Font(const std::string filename, size_t size) {
	// These are the characters that get stored to texture.
	// Margins around characters to prevent them from 'bleeding' into each other.
	const size_t margin = 1;
	size_t image_height = 0, image_width = 512;

	// Initialize FreeType
	FT_Library library;
	if (FT_Init_FreeType(&library)) {
		LOG_FATAL("FreeType initializing failed");
	} else {
		LOG_STRING("FreeType initialized");
	}

	// Load the font
	LOG_STRING("Loading font '" + filename + "'");

	FT_Face face;
	int error = FT_New_Face(library, filename.c_str(), 0, &face);
	if (error == FT_Err_Unknown_File_Format) {
		LOG_FATAL("Font loading failed: Unknown format of a file.");
	} else if (error) {
		LOG_FATAL("Font loading failed: The file could not be opened or read, or is broken, or else.");
	}
	LOG_STRING("Font loaded");

	// Some checks
	if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {
		LOG_FATAL("The font is not scalable)");
	}
	if (!(face->face_flags & FT_FACE_FLAG_HORIZONTAL)) {
		LOG_FATAL("The font is not horizontal)");
	}

	// Set the font size
	FT_Set_Pixel_Sizes(face, size, 0);
	pixel_height = size;

	int max_height = 0;
	size_t x = margin, y = margin;
	// Rasterize all the characters

	int total_chars = 0;
	uint32_t gindex; // glyph index
	uint32_t unicode = FT_Get_First_Char(face, &gindex);

	while (gindex != 0) {
		char buf[100];
		FT_Get_Glyph_Name(face, gindex, buf, 100);
		//LOG_STRING("Available character: " + stringify<uint32_t>(unicode) + " (" + buf + ")");
		// Look up the character in the font file.

		if (glyphs.find(gindex) != glyphs.end()) {
			unicode2glyph[unicode] = glyphs[gindex];
			continue;
		}

		// Render the current glyph.
		FT_Load_Glyph(face, gindex, FT_LOAD_RENDER | FT_LOAD_NO_HINTING);

		// Save character metrics
		Glyph *g = glyphs[gindex] = unicode2glyph[unicode] = new Glyph; // shortcut
		g->advance = face->glyph->metrics.horiAdvance / 64;
		g->width = face->glyph->bitmap.width;
		g->height = face->glyph->bitmap.rows;
		g->bearingX = face->glyph->metrics.horiBearingX / 64;
		g->bearingY = face->glyph->metrics.horiBearingY / 64;

		// Compute kerning
		//for (int j = 0; j < 256; j++) {
		//	// Look up the second character in the font file.
		//	int char2_index = FT_Get_Char_Index(face, j);
		//	FT_Vector akerning;
		//	FT_Get_Kerning(face, char_index, char2_index, FT_KERNING_DEFAULT, &akerning);
		//	kerning[i][j] = static_cast<float>(akerning.x) / 64;
		//}

		// Save glyph bitmap
		g->data = new unsigned char[g->width * g->height];
		memcpy(g->data, face->glyph->bitmap.buffer, g->width * g->height);

		// If the line is full, go to the next line
		if (g->width + margin > image_width - x) {
			x = margin;
			y += max_height + margin;
			max_height = 0;
		}
		g->x = x;
		g->y = y;
		max_height = std::max(g->height, max_height);
		x += g->width + margin;

		total_chars += 1;
		unicode = FT_Get_Next_Char(face, unicode, &gindex);
	}
	LOG_STRING("Total chars in atlas: " + stringify<int>(total_chars));
	FT_Done_FreeType(library);

	LOG_STRING("Generating font texture atlas");
	// Compute how high the texture has to be.
	int needed_image_height = y + max_height + margin;
	// Get the first power of two in which it fits.
	image_height = 16;
	while (image_height < needed_image_height) {
		image_height *= 2;
	}

	// Allocate memory for the texture, and set it to 0.
	unsigned char *image = new unsigned char[image_height * image_width];
	for (int i = 0; i < image_height * image_width; i++) {
		image[i] = 0;
	}

	// Drawing loop
	for (std::map<uint32_t, Glyph*>::iterator gindex = glyphs.begin(); gindex != glyphs.end(); gindex++) {
		Glyph *g = gindex->second; // shortcut

		if (g->data != NULL) {
			// Fill in the texture coords
			g->tex_left = static_cast<float>(g->x) / image_width;
			g->tex_right = static_cast<float>(g->x + g->width) / image_width;
			g->tex_top = static_cast<float>(g->y) / image_height;
			g->tex_bottom = static_cast<float>(g->y + g->height) / image_height;

			// Copy the glyph bitmap to the texture atlas
			for (size_t row = 0; row < g->height; ++row) {
				memcpy(&image[g->x + (g->y + row) * image_width], &g->data[row * g->width], g->width);
			}

			delete[] g->data;
			g->data = NULL;
		}
	}
	LOG_STRING("Font texture atlas generated");

	// Create OpenGL texture from the image.
	glDeleteTextures(1, &texture);
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, image_width, image_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, image);
	// Free the image memory.
	delete[] image;
	LOG_STRING("Font texture loaded");
}
Exemplo n.º 27
0
int
main(int argc,
     char** argv)
{
  FT_Face     face;
  long        max_bytes = CACHE_SIZE * 1024;
  char*       test_string = NULL;
  int         size = FACE_SIZE;
  int         max_iter = 0;
  double      max_time = BENCH_TIME;
  int         compare_cached = 0;
  int         i;

  while ( 1 )
  {
    int  opt;


    opt = getopt( argc, argv, "Cc:f:m:pr:s:t:b:" );

    if ( opt == -1 )
      break;

    switch ( opt )
    {
    case 'C':
      compare_cached = 1;
      break;
    case 'c':
      max_iter = atoi( optarg );
      break;
    case 'f':
      load_flags = strtol( optarg, NULL, 16 );
      break;
    case 'm':
      max_bytes = atoi( optarg );
      max_bytes *= 1024;
      break;
    case 'p':
      preload = 1;
      break;
    case 'r':
      render_mode = (FT_Render_Mode)atoi( optarg );
      if ( render_mode >= FT_RENDER_MODE_MAX )
        render_mode = FT_RENDER_MODE_NORMAL;
      break;
    case 's':
      size = atoi( optarg );
      if ( size <= 0 )
        size = 1;
      else if ( size > 500 )
        size = 500;
      break;
    case 't':
      max_time = atof( optarg );
      break;
    case 'b':
      test_string = optarg;
      break;
    default:
      usage();
      break;
    }
  }

  argc -= optind;
  argv += optind;

  if ( argc != 1 )
    usage();

  if ( FT_Init_FreeType( &lib ) )
  {
    fprintf( stderr, "could not initialize font library\n" );

    return 1;
  }

  filename = *argv;

  if ( get_face( &face ) )
    goto Exit;

  if ( FT_IS_SCALABLE( face ) )
  {

    if ( FT_Set_Pixel_Sizes( face, size, size ) )
    {
      fprintf( stderr, "failed to set pixel size to %d\n", size );

      return 1;
    }
  }
  else
    size = face->available_sizes[0].width;

  FTC_Manager_New( lib, 0, 0, max_bytes, face_requester, face, &cache_man );

  font_type.face_id = (FTC_FaceID) 1;
  font_type.width   = (short) size;
  font_type.height  = (short) size;
  font_type.flags   = load_flags;

  for ( i = 0; i < N_FT_BENCH; i++ )
  {
    btest_t   test;
    FT_ULong  flags;


    if ( !TEST( 'a' + i ) )
      continue;

    test.title       = NULL;
    test.bench       = NULL;
    test.cache_first = 0;
    test.user_data   = NULL;

    switch ( i )
    {
    case FT_BENCH_LOAD_GLYPH:
      test.title = "Load";
      test.bench = test_load;
      benchmark( face, &test, max_iter, max_time );

      if ( compare_cached )
      {
        test.cache_first = 1;

        test.title = "Load (image cached)";
        test.bench = test_image_cache;
        benchmark( face, &test, max_iter, max_time );

        test.title = "Load (sbit cached)";
        test.bench = test_sbit_cache;
        benchmark( face, &test, max_iter, max_time );
      }
      break;
    case FT_BENCH_LOAD_ADVANCES:
      test.user_data = &flags;

      test.title = "Load_Advances (Normal)";
      test.bench = test_load_advances;
      flags      = FT_LOAD_DEFAULT;
      benchmark( face, &test, max_iter, max_time );

      test.title  = "Load_Advances (Fast)";
      test.bench  = test_load_advances;
      flags       = FT_LOAD_TARGET_LIGHT;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_RENDER:
      test.title = "Render";
      test.bench = test_render;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_GET_GLYPH:
      test.title = "Get_Glyph";
      test.bench = test_get_glyph;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_GET_CBOX:
      test.title = "Get_CBox";
      test.bench = test_get_cbox;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_CMAP:
      {
        bcharset_t  charset;


        get_charset( face, &charset );
        if ( charset.code )
        {
          test.user_data = (void*)&charset;


          test.title = "Get_Char_Index";
          test.bench = test_get_char_index;

          benchmark( face, &test, max_iter, max_time );

          if ( compare_cached )
          {
            test.cache_first = 1;

            test.title = "Get_Char_Index (cached)";
            test.bench = test_cmap_cache;
            benchmark( face, &test, max_iter, max_time );
          }

          free( charset.code );
        }
      }
      break;
    case FT_BENCH_CMAP_ITER:
      test.title = "Iterate CMap";
      test.bench = test_cmap_iter;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_NEW_FACE:
      test.title = "New_Face";
      test.bench = test_new_face;
      benchmark( face, &test, max_iter, max_time );
      break;
    case FT_BENCH_EMBOLDEN:
      test.title = "Embolden";
      test.bench = test_embolden;
      benchmark( face, &test, max_iter, max_time );
      break;
    }
  }

Exit:
  /* The following is a bit subtle: When we call FTC_Manager_Done, this
   * normally destroys all FT_Face objects that the cache might have created
   * by calling the face requester.
   *
   * However, this little benchmark uses a tricky face requester that
   * doesn't create a new FT_Face through FT_New_Face but simply pass a
   * pointer to the one that was previously created.
   *
   * If the cache manager has been used before, the call to FTC_Manager_Done
   * discards our single FT_Face.
   *
   * In the case where no cache manager is in place, or if no test was run,
   * the call to FT_Done_FreeType releases any remaining FT_Face object
   * anyway.
   */
  if ( cache_man )
    FTC_Manager_Done( cache_man );

  FT_Done_FreeType( lib );

  return 0;
}
Exemplo n.º 28
0
int main(int argc, char **argv)
{
	SDL_Init(SDL_INIT_VIDEO);
	SDL_Surface *screen = SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);

   int error = FT_Init_FreeType( &library );
   if ( error )
	  {
		printf("Failed initialising freetype\n");
      exit(0);
   }
   error = FT_New_Face( library, "Vera.ttf", 0, &face );
   if ( error == FT_Err_Unknown_File_Format )
   {
		printf("Failed loading arial.ttf :O unsupported :O\n");
      exit(0);
   } else if ( error )
   {
		printf("File not found probably\n");
      exit(0);
   }

   error = FT_Set_Pixel_Sizes( face, 0, 32 );
	if(error)
	{
		printf("Failed setting size\n");
		exit(0);
	}


	int quit = 0;
	char cchar = 0;
	for(;!quit;)
	{
		SDL_Event ev;
		while(SDL_PollEvent(&ev))
		{
			if(ev.type == SDL_QUIT)
			{
				quit = 1;
			}
			if(ev.type == SDL_KEYDOWN)
			{
				if(ev.key.keysym.sym == SDLK_LEFT)
				{
					if(cchar>0)
						cchar--;
					else
						cchar = 255;
				}
				if(ev.key.keysym.sym == SDLK_RIGHT)
				{
					if(cchar<255)
						cchar++;
					else
						cchar = 0;
				}
			}
		}

		renderGlyph(screen, cchar);
		char info[32] = { 0 };
		sprintf(info, "Char Num: %d",cchar);
		renderString(screen, info, 50,100);
		SDL_Flip(screen);
	}

	SDL_Quit();
	return 0;
}
Exemplo n.º 29
0
void FTEnvironment::loadFont()
{
    checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
                                (FileManager::TTF, stk_config->m_font_default.c_str(), true)).c_str(),
                                0, &m_ft_face[F_DEFAULT]), "loading F_DEFAULT");

    checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
                                (FileManager::TTF, stk_config->m_font_default_fallback.c_str(), true)).c_str(),
                                0, &m_ft_face[F_DEFAULT_FALLBACK]), "loading F_DEFAULT_FALLBACK");

    checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
                                (FileManager::TTF, stk_config->m_font_cjk.c_str(), true)).c_str(),
                                 0, &m_ft_face[F_CJK]), "loading F_CJK");

    checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
                                (FileManager::TTF, stk_config->m_font_ar.c_str(), true)).c_str(),
                                 0, &m_ft_face[F_AR]), "loading F_AR");

    checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
                                (FileManager::TTF, stk_config->m_font_bold.c_str(), true)).c_str(),
                                0, &m_ft_face[F_BOLD]), "loading F_BOLD");

    checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
                                (FileManager::TTF, stk_config->m_font_bold_fallback.c_str(), true)).c_str(),
                                0, &m_ft_face[F_BOLD_FALLBACK]), "loading F_BOLD_FALLBACK");

    checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
                                (FileManager::TTF, stk_config->m_font_digit.c_str(),true)).c_str(),
                                 0, &m_ft_face[F_DIGIT]), "loading F_DIGIT");

    //Set charmap
    for (int h = 0; h < F_COUNT; ++h)
    {
        for (int i = 0; i < m_ft_face[h]->num_charmaps; ++i)
        {
            FT_UShort pid = m_ft_face[h]->charmaps[i]->platform_id;
            FT_UShort eid = m_ft_face[h]->charmaps[i]->encoding_id;
            if (((pid == 0) && (eid == 3)) || ((pid == 3) && (eid == 1)))
                checkError(FT_Set_Charmap(m_ft_face[h], m_ft_face[h]->charmaps[i]), "setting charmaps");
        }
    }

    // Set face dpi
    // font size is resolution-dependent.
    // normal text will range from 0.8, in 640x* resolutions (won't scale
    // below that) to 1.0, in 1024x* resolutions, and linearly up
    // normal text will range from 0.2, in 640x* resolutions (won't scale
    // below that) to 0.4, in 1024x* resolutions, and linearly up
    const s32 screen_width = irr_driver->getFrameSize().Width;
    const s32 screen_height = irr_driver->getFrameSize().Height;
    float scale = std::max(0, screen_width - 640)/564.0f;

    // attempt to compensate for small screens
    if (screen_width < 1200) scale = std::max(0, screen_width - 640) / 750.0f;
    if (screen_width < 900 || screen_height < 700) scale = std::min(scale, 0.05f);

    const u32 normal_dpi = u32((0.7f + 0.2f*scale)*27);
    const u32 title_dpi  = u32((0.2f + 0.2f*scale)*120);
    const u32 digit_dpi  = u32((0.7f + 0.2f*scale)*40);

    Log::info("Freetype Environment", "DPI for Normal Font is %d.", normal_dpi);
    Log::info("Freetype Environment", "DPI for Title Font is %d.", title_dpi);
    Log::info("Freetype Environment", "DPI for Digit Font is %d.", digit_dpi);

    checkError(FT_Set_Pixel_Sizes(m_ft_face[F_DEFAULT], 0, normal_dpi), "setting F_DEFAULT size");
    checkError(FT_Set_Pixel_Sizes(m_ft_face[F_DEFAULT_FALLBACK], 0, normal_dpi), "setting F_DEFAULT_FALLBACK size");
    checkError(FT_Set_Pixel_Sizes(m_ft_face[F_CJK], 0, normal_dpi), "setting F_CJK size");
    checkError(FT_Set_Pixel_Sizes(m_ft_face[F_AR], 0, normal_dpi), "setting F_AR size");
    checkError(FT_Set_Pixel_Sizes(m_ft_face[F_BOLD], 0, title_dpi), "setting F_BOLD size");
    checkError(FT_Set_Pixel_Sizes(m_ft_face[F_BOLD_FALLBACK], 0, title_dpi), "setting F_BOLD_FALLBACK size");
    checkError(FT_Set_Pixel_Sizes(m_ft_face[F_DIGIT], 0, digit_dpi), "setting F_DIGIT size");

}
//------------------------------------------------------------------------------
void createAtlasData(const std::string &font, unsigned int fontSize)
{
    // INIT FREETYPE AND CREATE FONT ATLAS

    ERROR_ASSERT(APP::IsInitialized())

    // load the library
    FT_Error err = FT_Init_FreeType(&library_);

    ERROR_ASSERT(err == 0)

    FT_Face face;

    // load the font (face)
    err = FT_New_Face(
            library_,
            font.c_str(),
            0,
            &face 
        );

    ERROR_ASSERT(err == 0)

    FT_Set_Pixel_Sizes(face, 0, fontSize);    

    FT_GlyphSlot g = face->glyph;
    int atlasWidth = 0;
    int atlasHeight = 0;
    int blMin = 0;
    int blMax = -1;
    
    // compute the dimensions of the atlas
    for (unsigned int i = 32; i < 128; i++) 
    {
        if(FT_Load_Char(face, i, FT_LOAD_RENDER)) 
        {
            ERROR_WARNING("Loading character %c failed!")
            continue;
        }
        
        atlasWidth += (g->bitmap.width + std::abs(g->bitmap_left));
        blMin = std::min(blMin, g->bitmap_top);

        if (g->bitmap_top > 0)
        {
            blMin = std::min(blMin, g->bitmap_top - g->bitmap.rows);
        }

        blMax = std::max(blMax, g->bitmap_top);

        atlasHeight = std::max(atlasHeight, g->bitmap.rows);
    }

    atlasHeight = blMax - blMin;

    int baseline = 0 - blMin;
    unsigned char* atlas = new unsigned char[atlasWidth*atlasHeight];
    int marker = 0;
    
    for (unsigned int i = 32; i < 128; i++) 
    {
        if(FT_Load_Char(face, i, FT_LOAD_RENDER)) 
        {
            continue;
        }
        
        int w = g->bitmap.width;
        int h = g->bitmap.rows;
        
        unsigned char* buffer = g->bitmap.buffer;
        
        // copy character to atlas
        for (unsigned int v = 0; v < h; v++)
        {
            for (unsigned int u = 0; u < w; u++)
            {
                int y = atlasHeight - (baseline + g->bitmap_top) + v;
                int x = marker + u  + std::abs(g->bitmap_left);
                atlas[y*atlasWidth + x] = buffer[v*w + u];
            }
        }

        // save character info
        characterInfo_[i].Width = w + std::abs(g->bitmap_left);
        characterInfo_[i].XOff0 = marker;

        // increase marker
        marker += (w + std::abs(g->bitmap_left));
    }

    // initialize the atlas
    atlas_.Atlas = new GL::Texture2DA(
        atlasWidth, 
        atlasHeight, 
        static_cast<void*>(atlas)
    );

    atlas_.Width = atlasWidth;
    atlas_.Height = atlasHeight;

    vertexArray_ = new GL::VertexArray();
    
    // clean up
    delete[] atlas;
    FT_Done_FreeType(library_);
}