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); } }
JNIEXPORT jboolean JNICALL Java_com_badlogic_gdx_graphics_g2d_freetype_FreeType_selectSize(JNIEnv* env, jclass clazz, jlong face, jint strike_index) { //@line:608 return !FT_Select_Size((FT_Face)face, strike_index); }
T42_Size_Select( T42_Size size, FT_ULong strike_index ) { T42_Face face = (T42_Face)size->root.face; FT_Error error; FT_Activate_Size( size->ttsize ); error = FT_Select_Size( face->ttf_face, (FT_Int)strike_index ); if ( !error ) ( (FT_Size)size )->metrics = face->ttf_face->size->metrics; return error; }
T42_Size_Select( FT_Size t42size, /* T42_Size */ FT_ULong strike_index ) { T42_Size size = (T42_Size)t42size; T42_Face face = (T42_Face)t42size->face; FT_Error error; FT_Activate_Size( size->ttsize ); error = FT_Select_Size( face->ttf_face, (FT_Int)strike_index ); if ( !error ) t42size->metrics = face->ttf_face->size->metrics; return error; }
FT_Error freetype_font::set_ideal_character_size(int iWidth, int iHeight) { if(font_face == nullptr) return FT_Err_Invalid_Face_Handle; if(is_monochrome() || iHeight <= 14 || iWidth <= 9) { // Look for a bitmap strike of a similar size int iBestBitmapScore = 50; FT_Int iBestBitmapIndex = -1; for(FT_Int i = 0; i < font_face->num_fixed_sizes; ++i) { if(font_face->available_sizes[i].height > iHeight) continue; int iDeltaH = iHeight - font_face->available_sizes[i].height; int iDeltaW = font_face->available_sizes[i].width - iWidth; int iScore = iDeltaH * iDeltaH * 3 + iDeltaW * iDeltaW; if(iScore < iBestBitmapScore) { iBestBitmapScore = iScore; iBestBitmapIndex = i; } } // Select the bitmap strike, if there was one if(iBestBitmapIndex != -1) return FT_Select_Size(font_face, iBestBitmapIndex); } // Go with the original size request if there was no bitmap strike, unless // the size was very small, in which case scale things up, as vector fonts // look rather poor at small sizes. if(iHeight < 14) { iWidth = iWidth * 14 / iHeight; iHeight = 14; } if(iWidth < 9) { iHeight = iHeight * 9 / iWidth; iWidth = 9; } return FT_Set_Pixel_Sizes(font_face, iWidth, iHeight); }
/** * Create a new FreeTypeFontCache. * @param fs The font size that is going to be cached. * @param face The font that has to be loaded. * @param pixels The number of pixels this font should be high. */ FreeTypeFontCache::FreeTypeFontCache(FontSize fs, FT_Face face, int pixels) : FontCache(fs), face(face), glyph_to_sprite(NULL) { assert(face != NULL); if (pixels == 0) { /* Try to determine a good height based on the minimal height recommended by the font. */ pixels = _default_font_height[this->fs]; TT_Header *head = (TT_Header *)FT_Get_Sfnt_Table(this->face, ft_sfnt_head); if (head != NULL) { /* Font height is minimum height plus the difference between the default * height for this font size and the small size. */ int diff = _default_font_height[this->fs] - _default_font_height[FS_SMALL]; pixels = Clamp(min(head->Lowest_Rec_PPEM, 20) + diff, _default_font_height[this->fs], MAX_FONT_SIZE); } } FT_Error err = FT_Set_Pixel_Sizes(this->face, 0, pixels); if (err != FT_Err_Ok) { /* Find nearest size to that requested */ FT_Bitmap_Size *bs = this->face->available_sizes; int i = this->face->num_fixed_sizes; if (i > 0) { // In pathetic cases one might get no fixed sizes at all. int n = bs->height; FT_Int chosen = 0; for (; --i; bs++) { if (abs(pixels - bs->height) >= abs(pixels - n)) continue; n = bs->height; chosen = this->face->num_fixed_sizes - i; } /* Don't use FT_Set_Pixel_Sizes here - it might give us another * error, even though the size is available (FS#5885). */ err = FT_Select_Size(this->face, chosen); } } if (err == FT_Err_Ok) { this->units_per_em = this->face->units_per_EM; this->ascender = this->face->size->metrics.ascender >> 6; this->descender = this->face->size->metrics.descender >> 6; this->height = this->ascender - this->descender; } else {
int EMSCRIPTEN_KEEPALIVE c_Face_selectSize(long face, int strike_index) { return !FT_Select_Size((FT_Face)face, strike_index); }
FT_Face ResourceTrueTypeFont::loadFace(const FT_Library& _ftLibrary, uint8*& _fontBuffer) { FT_Face result = nullptr; // Load the font file. IDataStream* datastream = DataManager::getInstance().getData(mSource); if (datastream == nullptr) return result; size_t fontBufferSize = datastream->size(); _fontBuffer = new uint8[fontBufferSize]; datastream->read(_fontBuffer, fontBufferSize); DataManager::getInstance().freeData(datastream); datastream = nullptr; // Determine how many faces the font contains. if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, -1, &result) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); FT_Long numFaces = result->num_faces; FT_Long faceIndex = 0; // Load the first face. if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); if (result->face_flags & FT_FACE_FLAG_SCALABLE) { // The font is scalable, so set the font size by first converting the requested size to FreeType's 26.6 fixed-point // format. FT_F26Dot6 ftSize = (FT_F26Dot6)(mSize * (1 << 6)); if (FT_Set_Char_Size(result, ftSize, 0, mResolution, mResolution) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not set the font size for '" << getResourceName() << "'!"); // If no code points have been specified, use the Unicode Basic Multilingual Plane by default. if (mCharMap.empty()) addCodePointRange(0, 0xFFFF); } else { // The font isn't scalable, so try to load it as a Windows FNT/FON file. FT_WinFNT_HeaderRec fnt; // Enumerate all of the faces in the font and select the smallest one that's at least as large as the requested size // (after adjusting for resolution). If none of the faces are large enough, use the largest one. std::map<float, FT_Long> faceSizes; do { if (FT_Get_WinFNT_Header(result, &fnt) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); faceSizes.insert(std::make_pair((float)fnt.nominal_point_size * fnt.vertical_resolution / mResolution, faceIndex)); FT_Done_Face(result); if (++faceIndex < numFaces) if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); } while (faceIndex < numFaces); std::map<float, FT_Long>::const_iterator iter = faceSizes.lower_bound(mSize); faceIndex = (iter != faceSizes.end()) ? iter->second : faceSizes.rbegin()->second; if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); // Select the first bitmap strike available in the selected face. This needs to be done explicitly even though Windows // FNT/FON files contain only one bitmap strike per face. if (FT_Select_Size(result, 0) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not set the font size for '" << getResourceName() << "'!"); // Windows FNT/FON files do not support Unicode, so restrict the code-point range to either ISO-8859-1 or ASCII, // depending on the font's encoding. if (mCharMap.empty()) { // No code points have been specified, so add the printable ASCII range by default. addCodePointRange(0x20, 0x7E); // Additionally, if the font's character set is CP-1252, add the range of non-ASCII 8-bit code points that are // common between CP-1252 and ISO-8859-1; i.e., everything but 0x80 through 0x9F. if (fnt.charset == FT_WinFNT_ID_CP1252) addCodePointRange(0xA0, 0xFF); } else { // Some code points have been specified, so remove anything in the non-printable ASCII range as well as anything // over 8 bits. removeCodePointRange(0, 0x1F); removeCodePointRange(0x100, std::numeric_limits<Char>::max()); // Additionally, remove non-ASCII 8-bit code points (plus ASCII DEL, 0x7F). If the font's character set is CP-1252, // remove only the code points that differ between CP-1252 and ISO-8859-1; otherwise, remove all of them. if (fnt.charset == FT_WinFNT_ID_CP1252) removeCodePointRange(0x7F, 0x9F); else removeCodePointRange(0x7F, 0xFF); } } return result; }