char_data::char_data(char ch, FT_Face face) : img(){ // Load The Glyph For Our Character. if(FT_Load_Glyph( face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT )) throw std::runtime_error("FT_Load_Glyph failed"); // Move The Face's Glyph Into A Glyph Object. FT_Glyph glyph; if(FT_Get_Glyph( face->glyph, &glyph )) throw std::runtime_error("FT_Get_Glyph failed"); // Convert The Glyph To A Bitmap. FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph; FT_Bitmap& bitmap=bitmap_glyph->bitmap; advance=face->glyph->advance.x >> 6; left= bitmap_glyph->left; w=bitmap.width; h=bitmap.rows; move_up=bitmap_glyph->top;//-bitmap.rows; data = new unsigned char[4*w*h]; for(int y=0;y<h;y++) for(int x=0;x<w;x++) { const int my=y;//h-1-y; data[4*(x+w*my)]=255; data[4*(x+w*my)+1]=255; data[4*(x+w*my)+2]=255; data[4*(x+w*my)+3]=bitmap.buffer[x+w*y]; } int old_unpack; gl_image_from_bytes(img, w, h, (char*)data, GL_BGRA); }
Py::Object FT2Font::load_char(const Py::Tuple & args) { _VERBOSE("FT2Font::load_char"); //load a char using the unsigned long charcode args.verify_length(1); long charcode = Py::Int(args[0]); int error = FT_Load_Char( face, (unsigned long)charcode, FT_LOAD_DEFAULT); if (error) throw Py::RuntimeError("Could not load charcode"); FT_Glyph thisGlyph; error = FT_Get_Glyph( face->glyph, &thisGlyph ); if (error) throw Py::RuntimeError("Could not get glyph for char"); size_t num = glyphs.size(); //the index into the glyphs list glyphs.push_back(thisGlyph); Glyph* gm = new Glyph(face, thisGlyph, num); gms.push_back(gm); Py_INCREF(gm); //todo: refcount correct? return Py::asObject( gm); }
void GetGlyphSize( FT_Face font, int numglyph, int *wi, int *hi ) { FT_Glyph glyph; FT_BitmapGlyph bmglyph; //glyph fields: /* width :: The glyph's width. */ /* height :: The glyph's height. */ /* horiBearingX :: Horizontal left side bearing. */ /* horiBearingY :: Horizontal top side bearing. */ /* horiAdvance :: Horizontal advance width. */ /* vertBearingX :: Vertical left side bearing. */ /* vertBearingY :: Vertical top side bearing. */ /* vertAdvance :: Vertical advance height. */ FT_Load_Glyph( font, FT_Get_Char_Index( font, numglyph ), FT_LOAD_DEFAULT ); FT_Get_Glyph( font->glyph, &glyph ); FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 ); bmglyph = (FT_BitmapGlyph)glyph; FT_Bitmap& bitmap = bmglyph->bitmap; //*wi = FTnext_p2( bitmap.width ); //*hi = FTnext_p2( bitmap.rows ); *wi = bitmap.width; *hi = bitmap.rows; };
static FT_Error freetype2_get_glyph_size(PFontFreetype pf, FT_Face face, int glyph_index, int *padvance, int *pascent, int *pdescent) { FT_Error error; error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); if (error) return error; if (padvance) *padvance = ROUND_26_6_TO_INT(face->glyph->advance.x); if (pascent || pdescent) { FT_Glyph glyph; FT_BBox bbox; error = FT_Get_Glyph(face->glyph, &glyph); if (error) return error; FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &bbox); FT_Done_Glyph(glyph); if (pascent) *pascent = bbox.yMax; if (pdescent) *pdescent = -bbox.yMin; } return 0; }
int test_get_cbox( btimer_t* timer, FT_Face face, void* user_data ) { FT_Glyph glyph; FT_BBox bbox; int i, done = 0; FT_UNUSED( user_data ); for ( i = 0; i < face->num_glyphs; i++ ) { if ( FT_Load_Glyph( face, i, load_flags ) ) continue; if ( FT_Get_Glyph( face->glyph, &glyph ) ) continue; TIMER_START( timer ); FT_Glyph_Get_CBox( glyph, FT_GLYPH_BBOX_PIXELS, &bbox ); TIMER_STOP( timer ); FT_Done_Glyph( glyph ); done++; } return done; }
int test_get_glyph( btimer_t* timer, FT_Face face, void* user_data ) { FT_Glyph glyph; int i, done = 0; FT_UNUSED( user_data ); for ( i = 0; i < face->num_glyphs; i++ ) { if ( FT_Load_Glyph( face, i, load_flags ) ) continue; TIMER_START( timer ); if ( !FT_Get_Glyph( face->glyph, &glyph ) ) { FT_Done_Glyph( glyph ); done++; } TIMER_STOP( timer ); } return done; }
void text_renderer::prepare_glyphs(glyph_positions const& positions) { FT_Matrix matrix; FT_Vector pen; FT_Error error; glyphs_.reserve(positions.size()); for (auto const& glyph_pos : positions) { glyph_info const& glyph = glyph_pos.glyph; glyph.face->set_character_sizes(glyph.format->text_size * scale_factor_); //TODO: Optimize this? matrix.xx = static_cast<FT_Fixed>( glyph_pos.rot.cos * 0x10000L); matrix.xy = static_cast<FT_Fixed>(-glyph_pos.rot.sin * 0x10000L); matrix.yx = static_cast<FT_Fixed>( glyph_pos.rot.sin * 0x10000L); matrix.yy = static_cast<FT_Fixed>( glyph_pos.rot.cos * 0x10000L); pixel_position pos = glyph_pos.pos + glyph.offset.rotate(glyph_pos.rot); pen.x = static_cast<FT_Pos>(pos.x * 64); pen.y = static_cast<FT_Pos>(pos.y * 64); FT_Face face = glyph.face->get_face(); FT_Set_Transform(face, &matrix, &pen); error = FT_Load_Glyph(face, glyph.glyph_index, FT_LOAD_NO_HINTING); if (error) continue; FT_Glyph image; error = FT_Get_Glyph(face->glyph, &image); if (error) continue; glyphs_.emplace_back(image, *glyph.format); } }
bool TrueTypeFont::bakeGlyphSubpixel(CodePoint _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer) { BX_CHECK(m_font != NULL, "TrueTypeFont not initialized"); _glyphInfo.glyphIndex = FT_Get_Char_Index(m_font->face, _codePoint); FT_GlyphSlot slot = m_font->face->glyph; FT_Error error = FT_Load_Glyph(m_font->face, _glyphInfo.glyphIndex, FT_LOAD_DEFAULT); if (error) { return false; } FT_Glyph glyph; error = FT_Get_Glyph(slot, &glyph); if (error) { return false; } error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_LCD, 0, 1); if (error) { return false; } FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph; glyphInfoInit(_glyphInfo, bitmap, slot, _outBuffer, 3); FT_Done_Glyph(glyph); return true; }
static void convertFT2Bitmap(FT_Face face, char c, FontBitmap& fontBitmap) { if (FT_Load_Glyph(face, FT_Get_Char_Index(face, c), FT_LOAD_DEFAULT)) { fprintf(stderr, "FT_Load_Glyph failed\n"); return ; } // Move The Face's Glyph Into A Glyph Object. FT_Glyph glyph; if (FT_Get_Glyph(face->glyph, &glyph)) { fprintf(stderr, "FT_Get_Glyph failed\n"); return ; } // Convert The Glyph To A Bitmap. FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, 0, 1); FT_BitmapGlyph glyphBitmap = (FT_BitmapGlyph)glyph; FT_Bitmap& bitmap = glyphBitmap->bitmap; fontBitmap.width = bitmap.width; fontBitmap.height = bitmap.rows; fontBitmap.offsetx = glyphBitmap->left; fontBitmap.offsety = glyphBitmap->top - bitmap.rows; fprintf(stdout, "%d\n", c); fontBitmap.data = new uint8_t [bitmap.width * bitmap.rows]; memcpy(fontBitmap.data, bitmap.buffer, bitmap.width * bitmap.rows); FT_Done_Glyph(glyph); }
bool TTBMFont::addFontGlyph(int fontnum,FT_UInt glyphIndex,wchar32_t chr) { FT_Error error; FT_Face face=fontFaces_[fontnum].face; error = FT_Load_Glyph(face, glyphIndex, FT_LOAD_DEFAULT); if (error) return false; int top, left, width, height; if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { FT_BBox bbox; if (stroker) { FT_Glyph glyph; error = FT_Get_Glyph(face->glyph, &glyph); if (error) return false; error = FT_Glyph_StrokeBorder(&glyph, stroker, false, true); if (error) return false; FT_OutlineGlyph oGlyph = reinterpret_cast<FT_OutlineGlyph>(glyph); FT_Outline_Get_CBox(&oGlyph->outline, &bbox); FT_Done_Glyph(glyph); } else FT_Outline_Get_CBox(&face->glyph->outline, &bbox); bbox.xMin &= ~63; bbox.yMin &= ~63; bbox.xMax = (bbox.xMax + 63) & ~63; bbox.yMax = (bbox.yMax + 63) & ~63; width = (bbox.xMax - bbox.xMin) >> 6; height = (bbox.yMax - bbox.yMin) >> 6; top = bbox.yMax >> 6; left = bbox.xMin >> 6; } else if (face->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
void text_renderer::prepare_glyphs(glyph_positions const& positions) { FT_Matrix matrix; FT_Vector pen; FT_Error error; glyphs_.clear(); glyphs_.reserve(positions.size()); for (auto const& glyph_pos : positions) { glyph_info const& glyph = glyph_pos.glyph; FT_Int32 load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; FT_Face face = glyph.face->get_face(); if (glyph.face->is_color()) { load_flags |= FT_LOAD_COLOR ; if (face->num_fixed_sizes > 0) { int scaled_size = static_cast<int>(glyph.format->text_size * scale_factor_); int best_match = 0; int diff = std::abs(scaled_size - face->available_sizes[0].width); for (int i = 1; i < face->num_fixed_sizes; ++i) { int ndiff = std::abs(scaled_size - face->available_sizes[i].height); if (ndiff < diff) { best_match = i; diff = ndiff; } } error = FT_Select_Size(face, best_match); } } else { glyph.face->set_character_sizes(glyph.format->text_size * scale_factor_); } double size = glyph.format->text_size * scale_factor_; matrix.xx = static_cast<FT_Fixed>( glyph_pos.rot.cos * 0x10000L); matrix.xy = static_cast<FT_Fixed>(-glyph_pos.rot.sin * 0x10000L); matrix.yx = static_cast<FT_Fixed>( glyph_pos.rot.sin * 0x10000L); matrix.yy = static_cast<FT_Fixed>( glyph_pos.rot.cos * 0x10000L); pixel_position pos = glyph_pos.pos + glyph.offset.rotate(glyph_pos.rot); pen.x = static_cast<FT_Pos>(pos.x * 64); pen.y = static_cast<FT_Pos>(pos.y * 64); FT_Set_Transform(face, &matrix, &pen); error = FT_Load_Glyph(face, glyph.glyph_index, load_flags); if (error) continue; FT_Glyph image; error = FT_Get_Glyph(face->glyph, &image); if (error) continue; box2d<double> bbox(0, glyph_pos.glyph.ymin(), glyph_pos.glyph.advance(), glyph_pos.glyph.ymax()); glyphs_.emplace_back(image, *glyph.format, pos, glyph_pos.rot, size, bbox); } }
bool font_face::glyph_dimensions(glyph_info & glyph) const { FT_Vector pen; pen.x = 0; pen.y = 0; FT_Set_Transform(face_, 0, &pen); if (FT_Load_Glyph(face_, glyph.glyph_index, FT_LOAD_NO_HINTING)) { MAPNIK_LOG_ERROR(font_face) << "FT_Load_Glyph failed"; return false; } FT_Glyph image; if (FT_Get_Glyph(face_->glyph, &image)) { MAPNIK_LOG_ERROR(font_face) << "FT_Get_Glyph failed"; return false; } FT_BBox glyph_bbox; FT_Glyph_Get_CBox(image, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox); FT_Done_Glyph(image); glyph.unscaled_ymin = glyph_bbox.yMin; glyph.unscaled_ymax = glyph_bbox.yMax; glyph.unscaled_advance = face_->glyph->advance.x; glyph.unscaled_line_height = face_->size->metrics.height; glyph.unscaled_ascender = unscaled_ascender_; return true; }
ZGlyph ZFont::create_glyph(wchar_t character) { FT_Error error = 0; FT_Face face = _impl->face; unsigned glyph_index = FT_Get_Char_Index(face, character); error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); if (error != 0) { ZException ex(ZENGINE_EXCEPTION_CODE); ex.extra_info = ZUtil::format("Font %p failed to load glyph for character '%c'", this, character); throw ex; } FT_Glyph freetype_glyph; error = FT_Get_Glyph(face->glyph, &freetype_glyph); if (error != 0) { ZException ex(ZENGINE_EXCEPTION_CODE); ex.extra_info = ZUtil::format("Font %p failed to get glyph for character '%c'", this, character); throw ex; } FT_Glyph_To_Bitmap(&freetype_glyph, FT_RENDER_MODE_NORMAL, 0, 1); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)freetype_glyph; FT_Bitmap bitmap = bitmap_glyph->bitmap; int width = bitmap.width; int height = bitmap.rows; size_t bitmap_length = width * height; ZDataRef bitmap_data = std::make_shared<ZData>(bitmap.buffer, bitmap_length); ZGlyph glyph = { .character = character, .size = { float(width), float(height) }, .advance = ZSize2D{face->glyph->advance.x / 64.f, face->glyph->advance.y / 64.f}, .insets = ZEdgeInsets{(float)bitmap_glyph->top, (float)bitmap_glyph->left, 0.f, 0.f},
//------------------------------------------------------------------------------------------------------- StringManager::BChar* StringManager::_LoadChar(wchar_t wchar) { //参考http://my.unix-center.net/~Simon_fu/?p=385 bool space = false; if( L' ' == wchar ) { space = true; wchar = L'_'; } FT_Load_Glyph(m_FT_Face, FT_Get_Char_Index( m_FT_Face, wchar ), FT_LOAD_DEFAULT);//FT_LOAD_FORCE_AUTOHINT| FT_LOAD_TARGET_NORMAL); //得到字模 FT_Glyph glyph; FT_Get_Glyph( m_FT_Face->glyph, &glyph ); //转化成位图 FT_Render_Glyph( m_FT_Face->glyph, FT_RENDER_MODE_LCD ); FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph; //取道位图数据 FT_Bitmap& bitmap=bitmap_glyph->bitmap; //重新计算数据 float scale = static_cast<float>(bitmap.rows) / static_cast<float>(m_FT_Face->glyph->metrics.height);//计算文本高宽缩放到bitmap高宽的缩放比 int beginY = Math::Ceil( m_FT_Face->glyph->metrics.horiBearingY * scale );//y偏移 //FT_Done_Glyph(glyph); vector2d size = vector2d(bitmap.width, bitmap.rows); return NEW BChar(beginY, size, glyph, space); }
void Font::Printf(u32 x, u32 y,const char *a, ...){ char text[1024]; va_list va; va_start(va, a); vsnprintf(text, sizeof text, a, va); va_end(va); size_t len = strlen(a); if(len>0){ len=strlen(text); vec.x = 0; vec.y = FontSize; FT_GlyphSlot slot = face->glyph; FT_UInt glyph_index = 0; FT_UInt previous_glyph = 0; Kerning = FT_HAS_KERNING(face); for(unsigned int i=0;i<len;i++){ glyph_index = FT_Get_Char_Index(face, text[i]); if(Kerning && previous_glyph && glyph_index){ FT_Vector delta; FT_Get_Kerning(face, previous_glyph, glyph_index, FT_KERNING_DEFAULT, &delta); vec.x += delta.x >> 6; } FT_Load_Glyph(face, glyph_index,FT_LOAD_RENDER); FT_Get_Glyph(face->glyph, &glyph); FT_Glyph_StrokeBorder(&glyph,stroker,0,0); FontDrawBitmap(&slot->bitmap,vec.x + slot->bitmap_left + x, (vec.y - slot->bitmap_top + y -FontSize)); previous_glyph = glyph_index; vec.x += slot->advance.x >> 6; vec.y += slot->advance.y >> 6; FT_Done_Glyph(glyph); }
CAMLprim value glyph_to_bitmap(value glyph) { CAMLparam1(glyph); CAMLlocal2(block, buffer); FT_GlyphSlot slot; FT_Glyph g; FT_BitmapGlyph bm; size_t pitch; size_t new_pitch; int i; slot = *(FT_GlyphSlot *)Data_custom_val(glyph); if (FT_Get_Glyph(slot, &g)) failwith("glyph_to_bitmap"); if (g->format != FT_GLYPH_FORMAT_BITMAP) { if (FT_Glyph_To_Bitmap(&g, FT_RENDER_MODE_MONO, 0, 1)) { FT_Done_Glyph(g); failwith("glyph_to_bitmap"); } } bm = (FT_BitmapGlyph)g; pitch = abs(bm->bitmap.pitch); new_pitch = (bm->bitmap.width + 7) / 8; block = alloc_tuple(6); buffer = alloc_string(bm->bitmap.rows * new_pitch); if (bm->bitmap.pitch >= 0) { for (i = 0; i < bm->bitmap.rows; i++) memcpy(String_val(buffer) + i * new_pitch, bm->bitmap.buffer + i * pitch, new_pitch); } else { for (i = 0; i < bm->bitmap.rows; i++) memcpy(String_val(buffer) + i * new_pitch, bm->bitmap.buffer + (bm->bitmap.rows - i) * pitch, new_pitch); } Store_field(block, 0, Val_int(bm->left)); Store_field(block, 1, Val_int(bm->top)); Store_field(block, 2, Val_int(bm->bitmap.rows)); Store_field(block, 3, Val_int(bm->bitmap.width)); Store_field(block, 4, Val_int(new_pitch)); Store_field(block, 5, buffer); FT_Done_Glyph(g); CAMLreturn(block); };
//http://www.freetype.org/freetype2/docs/tutorial/step2.html FT_Error measure_string(FT_Face face, std::string text, int size, Vector2i* size_out) { int pos_x = 0; bool use_kerning = FT_HAS_KERNING(face) ? true : false; FT_UInt prev_glyph_index = 0; FT_BBox text_bb; text_bb.xMax = 0; text_bb.xMin = 0; text_bb.yMax = 0; text_bb.yMin = 0; FT_Error error; error = FT_Set_Char_Size(face, 0, size * 64, 72, 72); for(unsigned int i = 0; i < text.length(); i++) { FT_UInt glyph_index = FT_Get_Char_Index(face, text.c_str()[i]); if(use_kerning && prev_glyph_index) { FT_Vector delta; FT_Get_Kerning(face, prev_glyph_index, glyph_index, FT_KERNING_DEFAULT, &delta); pos_x += delta.x >> 6; } prev_glyph_index = glyph_index; if(error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) != FT_Err_Ok) { Log::Error(__FILE__, "Unable to load glyph %d", glyph_index); return error; } FT_Glyph glyph; if(error = FT_Get_Glyph(face->glyph, &glyph) != FT_Err_Ok) { Log::Error(__FILE__, "Unable to get glyph %d", glyph_index); } FT_BBox bb; FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &bb); bb.xMax += pos_x; bb.xMin += pos_x; pos_x += glyph->advance.x >> 16; //Grow overall bounding box if(bb.xMax > text_bb.xMax) text_bb.xMax = bb.xMax; if(bb.yMax > text_bb.yMax) text_bb.yMax = bb.yMax; if(bb.xMin < text_bb.xMin) text_bb.xMin = bb.xMin; if(bb.yMin < text_bb.yMin) text_bb.yMin = bb.yMin; FT_Done_Glyph(glyph); }
Object* Font::getGlyph (char code, const Vec2 &offset) { FT_Error ftErr; FT_Glyph ftGlyph; FT_OutlineGlyph ftOutlineGlyph; //Set glyph size FT_F26Dot6 sz = ftFloatTo266( size ); ftErr = FT_Set_Char_Size( ftFace, sz, sz, 72, 72 ); if (ftErr) { std::cout << "Error while setting char size!" << std::endl; return NULL; } //Load glyph data into font face FT_UInt ftGlyphIndex = FT_Get_Char_Index( ftFace, (FT_ULong)code ); ftErr = FT_Load_Glyph( ftFace, ftGlyphIndex, FT_LOAD_DEFAULT ); if (ftErr) { std::cout << "Error while loading glyph!" << std::endl; return NULL; } //Get glyph from glyph slot of font face ftErr = FT_Get_Glyph( ftFace->glyph, &ftGlyph ); if (ftErr) { std::cout << "Error while getting glyph from slot!" << std::endl; return NULL; } //Cast glyph to outline glyph ftOutlineGlyph = (FT_OutlineGlyph) ftGlyph; if (ftGlyph->format != FT_GLYPH_FORMAT_OUTLINE) { std::cout << "Error while casting glyph to outline glyph!" << std::endl; return NULL; } //Construct outline FT_Outline_Funcs ftFuncs; ftFuncs.move_to = ftMoveTo; ftFuncs.line_to = ftLineTo; ftFuncs.conic_to = ftQuadTo; ftFuncs.cubic_to = ftCubicTo; ftFuncs.shift = 0; ftFuncs.delta = 0; Object *object = new Object; this->object = object; this->offset = offset; ftErr = FT_Outline_Decompose( &ftOutlineGlyph->outline, &ftFuncs, this ); //Cleanup FT_Done_Glyph( ftGlyph ); return object; }
void CBitmapFont::generateGlyph(U32 ch){ S32 pad = 3; FT_GlyphSlot slot = mFace->glyph; FT_Glyph glyph; FT_UInt glyph_index; glyph_index = FT_Get_Char_Index( mFace, (FT_ULong)ch ); FT_Load_Glyph( mFace, glyph_index, FT_LOAD_DEFAULT); FT_Get_Glyph( slot, &glyph); FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, 0 ,1); FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph; FT_Bitmap* source = &bitmap->bitmap; S32 srcWidth = source->width; S32 srcHeight = source->rows; S32 srcPitch = source->pitch; S32 dstWidth = srcWidth; S32 dstHeight = srcHeight; S32 dstPitch = srcPitch; FT_BBox bbox; FT_Glyph_Get_CBox( glyph, ft_glyph_bbox_pixels, &bbox); unsigned char *src = source->buffer; if(pen.x + srcWidth >= mTextureSize){ pen.x = 0; pen.y += (getFontSize() * 64.0f / dpi) + pad; } glBindTexture(GL_TEXTURE_2D, curTex);checkGLError(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);checkGLError(); glTexSubImage2D(GL_TEXTURE_2D, 0, pen.x, pen.y, srcWidth, srcHeight, GL_ALPHA, GL_UNSIGNED_BYTE, src); checkGLError(); CTexCoord start(pen); start /= mTextureSize; CTexCoord end(pen.x + srcWidth, pen.y + srcHeight); end /= mTextureSize; //CVector2 pos(slot->bitmap_left, slot->bitmap_top); CVector2 pos(bitmap->left, srcHeight - bitmap->top); CVector2 size(srcWidth, srcHeight); CVector2 advance(slot->advance.x >> 6, slot->advance.y >> 6); mGlyphs[glyph_index] = new CBitmapGlyph(curTex, start, end, pos, size, advance); pen.x += srcWidth + pad; FT_Done_Glyph(glyph); }
void draw_bezier_outline(DiaPsRenderer *renderer, int dpi_x, FT_Face face, FT_UInt glyph_index, double pos_x, double pos_y ) { FT_Int load_flags = FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP; FT_Glyph glyph; FT_Error error; gchar px_buf[G_ASCII_DTOSTR_BUF_SIZE]; gchar py_buf[G_ASCII_DTOSTR_BUF_SIZE]; gchar d1_buf[G_ASCII_DTOSTR_BUF_SIZE]; gchar d2_buf[G_ASCII_DTOSTR_BUF_SIZE]; /* Need to transform */ /* Output outline */ FT_Outline_Funcs outlinefunc = { paps_move_to, paps_line_to, paps_conic_to, paps_cubic_to }; OutlineInfo outline_info; outline_info.glyph_origin.x = pos_x; outline_info.glyph_origin.y = pos_y; outline_info.dpi = dpi_x; outline_info.OUT = renderer->file; fprintf(renderer->file, "gsave %s %s translate %s %s scale\n", g_ascii_formatd(px_buf, sizeof(px_buf), "%f", pos_x), g_ascii_formatd(py_buf, sizeof(py_buf), "%f", pos_y), g_ascii_formatd(d1_buf, sizeof(d1_buf), "%f", 2.54/72.0), g_ascii_formatd(d2_buf, sizeof(d2_buf), "%f", -2.54/72.0) ); fprintf(renderer->file, "start_ol\n"); if ((error=FT_Load_Glyph(face, glyph_index, load_flags))) { fprintf(stderr, "Can't load glyph: %d\n", error); return; } if ((error=FT_Get_Glyph (face->glyph, &glyph))) { fprintf(stderr, "Can't get glyph: %d\n", error); FT_Done_Glyph (glyph); return; } if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline), &outlinefunc, &outline_info); fprintf(renderer->file, "end_ol grestore \n"); FT_Done_Glyph (glyph); }
void loadGlyph(char letter) { int glyph_index = FT_Get_Char_Index( face, letter); FT_Load_Glyph(face,glyph_index,FT_LOAD_RENDER); FT_Render_Glyph(face->glyph,FT_RENDER_MODE_NORMAL); FT_Get_Glyph(face->glyph,(FT_Glyph *) &glyphs[letter -32]); }
//* //* Cache Readed Glyph //* byte aft_cacheglyph(AFTFACEP f, long id) { if (!aft_initialized) return 0; if (f==NULL) return 0; if (f->cache_n<id) return 0; if (!f->cache[id].init) { FT_Get_Glyph(f->face->glyph, &f->cache[id].g); f->cache[id].w = f->face->glyph->advance.x >> 6; f->cache[id].init = 1; }
int Fonts_LoadChar(wchar_t ch) { int iCallBack = Fonts_CheckExists(ch); if(iCallBack>-1) return iCallBack; if(FT_Load_Char(face, ch,FT_LOAD_FORCE_AUTOHINT| (TRUE ? FT_LOAD_TARGET_NORMAL : FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO) ) ) { return 0; } xCharTexture& charTex = Fonts_TexID[Fonts_Count]; FT_Glyph glyph; if(FT_Get_Glyph( face->glyph, &glyph )) return 0; FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD ); FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph; FT_Bitmap& bitmap=bitmap_glyph->bitmap; int width = bitmap.width; int height = bitmap.rows; face->size->metrics.y_ppem; face->glyph->metrics.horiAdvance; charTex.m_Width = width; charTex.m_Height = height; charTex.m_adv_x = face->glyph->advance.x / 64.0f; charTex.m_adv_y = face->size->metrics.y_ppem; charTex.m_delta_x = (float)bitmap_glyph->left; charTex.m_delta_y = (float)bitmap_glyph->top - height; charTex.m_texID = g_pSurface->CreateNewTextureID();/*iStartFontIndex + Fonts_Count*/; Tri_Enable(GL_TEXTURE_2D); Tri_BindTexture(GL_TEXTURE_2D,charTex.m_texID); char* pBuf = new char[width * height * 4]; for(int j=0; j < height ; j++) { for(int i=0; i < width; i++) { unsigned char _vl = (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j]; pBuf[(4*i + (height - j - 1) * width * 4) ] = 0xFF; pBuf[(4*i + (height - j - 1) * width * 4)+1] = 0xFF; pBuf[(4*i + (height - j - 1) * width * 4)+2] = 0xFF; pBuf[(4*i + (height - j - 1) * width * 4)+3] = _vl; } } Tri_TexImage2D( GL_TEXTURE_2D,0,GL_RGBA,width, height ,0,GL_RGBA,GL_UNSIGNED_BYTE,pBuf); Tri_SetTextureParam(); Tri_TexEnvf(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_REPLACE); delete[] pBuf; LogToFile("已使用字体缓存区:%d/%d[字体ID:%d分配的纹理ID:%d]",Fonts_Count,FONTS_MAX_BUFFER,65536*iWidthCheck + ch,charTex.m_texID); Fonts_Buffer[Fonts_Count] = 65536*iWidthCheck + ch; Fonts_Count ++ ; return (Fonts_Count-1); }
JNIEXPORT jlong JNICALL Java_com_badlogic_gdx_graphics_g2d_freetype_FreeType_00024GlyphSlot_getGlyph(JNIEnv* env, jclass clazz, jlong glyphSlot) { //@line:475 FT_Glyph glyph; FT_Error error = FT_Get_Glyph((FT_GlyphSlot)glyphSlot, &glyph); if(error) return 0; else return (jlong)glyph; }
ftc_image_node_init( FTC_ImageNode inode, FTC_GlyphQuery gquery, FTC_Cache cache ) { FTC_ImageFamily ifam = FTC_IMAGE_FAMILY( gquery->query.family ); FT_Error error; FT_Face face; FT_Size size; /* initialize its inner fields */ ftc_glyph_node_init( FTC_GLYPH_NODE( inode ), gquery->gindex, FTC_GLYPH_FAMILY( ifam ) ); /* we will now load the glyph image */ error = FTC_Manager_Lookup_Size( FTC_FAMILY( ifam )->cache->manager, &ifam->type.font, &face, &size ); if ( !error ) { FT_UInt gindex = FTC_GLYPH_NODE_GINDEX( inode ); error = FT_Load_Glyph( face, gindex, ifam->type.flags ); if ( !error ) { if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP || face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) { /* ok, copy it */ FT_Glyph glyph; error = FT_Get_Glyph( face->glyph, &glyph ); if ( !error ) { inode->glyph = glyph; goto Exit; } } else error = FTC_Err_Invalid_Argument; } } /* in case of error */ ftc_glyph_node_done( FTC_GLYPH_NODE(inode), cache ); Exit: return error; }
void SubtitleRenderer:: initialize_fonts(const std::string& font_path, float font_size) { ENFORCE(!FT_Init_FreeType(&ft_library_)); ENFORCE2(!FT_New_Face(ft_library_, font_path.c_str(), 0, &ft_face_), "Unable to open font"); ENFORCE(!FT_Set_Pixel_Sizes(ft_face_, 0, font_size*screen_height_)); auto get_bbox = [this](char32_t cp) { auto glyph_index = FT_Get_Char_Index(ft_face_, cp); ENFORCE(!FT_Load_Glyph(ft_face_, glyph_index, FT_LOAD_NO_HINTING)); FT_Glyph glyph; ENFORCE(!FT_Get_Glyph(ft_face_->glyph, &glyph)); SCOPE_EXIT {FT_Done_Glyph(glyph);}; FT_BBox bbox; FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox); return bbox; }; constexpr float padding_factor = 0.05f; int y_min = get_bbox('g').yMin; int y_max = get_bbox('M').yMax; y_max += -y_min*0.7f; line_height_ = y_max - y_min; const int v_padding = line_height_*padding_factor + 0.5f; line_height_ += v_padding*2; box_offset_ = y_min-v_padding; box_h_padding_ = line_height_/5.0f + 0.5f; constexpr float border_thickness = 0.045f; ENFORCE(!FT_Stroker_New(ft_library_, &ft_stroker_)); FT_Stroker_Set(ft_stroker_, line_height_*border_thickness*64.0f, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); vgSeti(VG_FILTER_FORMAT_LINEAR, VG_TRUE); assert(!vgGetError()); vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED); assert(!vgGetError()); auto create_vg_font = [](VGFont& font) { font = vgCreateFont(128); ENFORCE(font); }; create_vg_font(vg_font_); create_vg_font(vg_font_border_); }
nResult n2dFontImpl::InitText(ncTStr str, nLen lStrlen) { if (!m_pFTLib) { return NatErr_IllegalState; } GLint oldAlignment; glGetIntegerv(GL_UNPACK_ALIGNMENT, &oldAlignment); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for (nLen i = 0; i < lStrlen; ++i) { if (m_FontCache.find(str[i]) != m_FontCache.end()) continue; if (FT_Load_Char(m_pFTFace, str[i], FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_NORMAL) != 0) { return NatErr_InternalErr; } FT_Glyph tGlyph; if (FT_Get_Glyph(m_pFTFace->glyph, &tGlyph) != 0) { return NatErr_InternalErr; } FT_Render_Glyph(m_pFTFace->glyph, FT_RENDER_MODE_NORMAL); FT_Glyph_To_Bitmap(&tGlyph, FT_RENDER_MODE_NORMAL, nullptr, TRUE); FT_BitmapGlyph tBitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(tGlyph); FT_Bitmap& tBitmap = tBitmapGlyph->bitmap; auto& tCharTexture = m_FontCache[str[i]]; tCharTexture.Width = tBitmap.width; tCharTexture.Height = tBitmap.rows; tCharTexture.adv_x = m_pFTFace->glyph->advance.x >> 6; tCharTexture.adv_y = m_pFTFace->size->metrics.y_ppem; tCharTexture.bearing_x = m_pFTFace->glyph->bitmap_left; tCharTexture.bearing_y = m_pFTFace->glyph->bitmap_top; tCharTexture.delta_x = tBitmapGlyph->left; tCharTexture.delta_y = tBitmapGlyph->top - tBitmap.rows; tCharTexture.CharTexture = make_ref<n2dTexture2DImpl>(); tCharTexture.CharTexture->LoadTexture(n2dImage{ GL_RED, GL_RED, tBitmap.buffer, tCharTexture.Width * tCharTexture.Height, tCharTexture.Width, tCharTexture.Height }); } glPixelStorei(GL_UNPACK_ALIGNMENT, oldAlignment); return NatErr_OK; }
static void glyphstring_create(FT_Face face, Text *text, FT_Glyph *glyph_string, FT_Vector *pos) { const uint8_t *string = text->string; FT_Bool has_kerning; FT_UInt glyph_index, previous; FT_Vector pen, delta; uint32_t charcode; int i; has_kerning = FT_HAS_KERNING(face); previous = 0; i = 0; pen.x = pen.y = 0; while (string[0] != '\0') { charcode = utf8_next(&string); glyph_index = FT_Get_Char_Index(face, charcode); if (has_kerning && previous && glyph_index) FT_Get_Kerning(face, previous, glyph_index, FT_KERNING_DEFAULT, &delta); else delta.x = 0; if (glyph_index == 0) log_err("Glyph for character U+%X missing\n", charcode); if (FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER) != 0) { log_err("Error loading glyph for character U+%X\n", charcode); continue; } if (FT_Get_Glyph(face->glyph, &glyph_string[i]) != 0) { log_err("Error copying glyph for character U+%X\n", charcode); continue; } pen.x += delta.x; pos[i] = pen; pen.x += face->glyph->advance.x; pen.y += face->glyph->advance.y; previous = glyph_index; i++; } text->num_glyphs = i; }
void FT2Font::load_glyphs() { _VERBOSE("FT2Font::load_glyphs"); /* a small shortcut */ FT_Bool use_kerning = FT_HAS_KERNING( face ); FT_UInt previous = 0; glyphs.resize(0); pen.x = 0; pen.y = 0; for ( unsigned int n = 0; n < text.size(); n++ ) { FT_UInt glyph_index = FT_Get_Char_Index( face, text[n] ); /* retrieve kerning distance and move pen position */ if ( use_kerning && previous && glyph_index ) { FT_Vector delta; FT_Get_Kerning( face, previous, glyph_index, ft_kerning_default, &delta ); pen.x += delta.x; } error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); if ( error ) { std::cerr << "\tcould not load glyph for " << text[n] << std::endl; continue; } /* ignore errors, jump to next glyph */ /* extract glyph image and store it in our table */ FT_Glyph thisGlyph; error = FT_Get_Glyph( face->glyph, &thisGlyph ); if ( error ) { std::cerr << "\tcould not get glyph for " << text[n] << std::endl; continue; } /* ignore errors, jump to next glyph */ FT_Glyph_Transform( thisGlyph, 0, &pen); pen.x += face->glyph->advance.x; previous = glyph_index; glyphs.push_back(thisGlyph); } // now apply the rotation for (unsigned int n=0; n<glyphs.size(); n++) FT_Glyph_Transform(glyphs[n], &matrix, 0); }
/** * Load glyphs corresponding to the UTF-32 codepoint code. */ static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code) { DrawTextContext *s = ctx->priv; Glyph *glyph; struct AVTreeNode *node = NULL; int ret; /* load glyph into s->face->glyph */ if (FT_Load_Char(s->face, code, s->ft_load_flags)) return AVERROR(EINVAL); /* save glyph */ if (!(glyph = av_mallocz(sizeof(*glyph))) || !(glyph->glyph = av_mallocz(sizeof(*glyph->glyph)))) { ret = AVERROR(ENOMEM); goto error; } glyph->code = code; if (FT_Get_Glyph(s->face->glyph, glyph->glyph)) { ret = AVERROR(EINVAL); goto error; } glyph->bitmap = s->face->glyph->bitmap; glyph->bitmap_left = s->face->glyph->bitmap_left; glyph->bitmap_top = s->face->glyph->bitmap_top; glyph->advance = s->face->glyph->advance.x >> 6; /* measure text height to calculate text_height (or the maximum text height) */ FT_Glyph_Get_CBox(*glyph->glyph, ft_glyph_bbox_pixels, &glyph->bbox); /* cache the newly created glyph */ if (!(node = av_tree_node_alloc())) { ret = AVERROR(ENOMEM); goto error; } av_tree_insert(&s->glyphs, glyph, glyph_cmp, &node); if (glyph_ptr) *glyph_ptr = glyph; return 0; error: if (glyph) av_freep(&glyph->glyph); av_freep(&glyph); av_freep(&node); return ret; }