int QueryKerning(unsigned int characterSize, char32_t first, char32_t second) const override { if (FT_HAS_KERNING(m_face)) { SetCharacterSize(characterSize); FT_Vector kerning; FT_Get_Kerning(m_face, FT_Get_Char_Index(m_face, first), FT_Get_Char_Index(m_face, second), FT_KERNING_DEFAULT, &kerning); if (!FT_IS_SCALABLE(m_face)) return kerning.x; // Taille déjà précisée en pixels dans ce cas return kerning.x >> 6; } else return 0;
bool ExtractGlyph(unsigned int characterSize, char32_t character, UInt32 style, FontGlyph* dst) override { #ifdef NAZARA_DEBUG if (!dst) { NazaraError("Glyph destination cannot be null"); return false; } #endif SetCharacterSize(characterSize); if (FT_Load_Char(m_face, character, FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_NORMAL) != 0) { NazaraError("Failed to load character"); return false; } FT_GlyphSlot& glyph = m_face->glyph; const FT_Pos boldStrength = 2 << 6; bool embolden = (style & TextStyle_Bold); dst->advance = (embolden) ? boldStrength >> 6 : 0; if (embolden && glyph->format == FT_GLYPH_FORMAT_OUTLINE) { // http://www.freetype.org/freetype2/docs/reference/ft2-outline_processing.html#FT_Outline_Embolden FT_Outline_Embolden(&glyph->outline, boldStrength); embolden = false; } // http://www.freetype.org/freetype2/docs/reference/ft2-glyph_management.html#FT_Glyph_To_Bitmap // Conversion du glyphe vers le format bitmap // Cette fonction ne fait rien dans le cas où le glyphe est déjà un bitmap if (FT_Render_Glyph(glyph, FT_RENDER_MODE_NORMAL) != 0) { NazaraError("Failed to convert glyph to bitmap"); return false; } // Dans le cas où nous voulons des caractères gras mais que nous n'avons pas pu agir plus tôt // nous demandons à FreeType d'agir directement sur le bitmap généré if (embolden) { // http://www.freetype.org/freetype2/docs/reference/ft2-bitmap_handling.html#FT_Bitmap_Embolden // "If you want to embolden the bitmap owned by a FT_GlyphSlot_Rec, you should call FT_GlyphSlot_Own_Bitmap on the slot first" FT_GlyphSlot_Own_Bitmap(glyph); FT_Bitmap_Embolden(s_library, &glyph->bitmap, boldStrength, boldStrength); } dst->advance += glyph->metrics.horiAdvance >> 6; dst->aabb.x = glyph->metrics.horiBearingX >> 6; dst->aabb.y = -(glyph->metrics.horiBearingY >> 6); // Inversion du repère dst->aabb.width = glyph->metrics.width >> 6; dst->aabb.height = glyph->metrics.height >> 6; unsigned int width = glyph->bitmap.width; unsigned int height = glyph->bitmap.rows; if (width > 0 && height > 0) { dst->image.Create(ImageType_2D, PixelFormatType_A8, width, height); UInt8* pixels = dst->image.GetPixels(); const UInt8* data = glyph->bitmap.buffer; // Selon la documentation FreeType, le glyphe peut être encodé en format A8 (huit bits d'alpha par pixel) // ou au format A1 (un bit d'alpha par pixel). // Cependant dans un cas comme dans l'autre, il nous faut gérer le pitch (les données peuvent ne pas être contigues) // ainsi que le padding dans le cas du format A1 (Chaque ligne prends un nombre fixe d'octets) if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { // Format A1 for (unsigned int y = 0; y < height; ++y) { for (unsigned int x = 0; x < width; ++x) *pixels++ = (data[x/8] & ((1 << (7 - x%8)) ? 255 : 0)); data += glyph->bitmap.pitch; } } else { // Format A8 if (glyph->bitmap.pitch == static_cast<int>(width*sizeof(UInt8))) // Pouvons-nous copier directement ? dst->image.Update(glyph->bitmap.buffer); else { for (unsigned int y = 0; y < height; ++y) { std::memcpy(pixels, data, width*sizeof(UInt8)); data += glyph->bitmap.pitch; pixels += width*sizeof(UInt8); } } } } else dst->image.Destroy(); // On s'assure que l'image ne contient alors rien return true; }
void CheckBoxObject::LoadFromXml(const TiXmlElement * elem) { if ( elem->FirstChildElement( "String" ) == NULL || elem->FirstChildElement( "String" )->Attribute("value") == NULL ) { cout << "Les informations concernant le texte d'un objet Text manquent."; } else { SetString(elem->FirstChildElement("String")->Attribute("value")); } if ( elem->FirstChildElement( "Checked" ) == NULL || elem->FirstChildElement( "Checked" )->Attribute("value") == NULL ) { cout << "Les informations concernant le texte d'un objet Text manquent."; } else { int checked = 0; elem->FirstChildElement("Checked")->QueryIntAttribute("value", &checked); SetChecked(static_cast<bool>(checked)); } if ( elem->FirstChildElement( "Font" ) == NULL || elem->FirstChildElement( "Font" )->Attribute("value") == NULL ) { cout << "Les informations concernant la police d'un objet Text manquent."; } else { SetFont(elem->FirstChildElement("Font")->Attribute("value")); } if ( elem->FirstChildElement( "CharacterSize" ) == NULL || elem->FirstChildElement( "CharacterSize" )->Attribute("value") == NULL ) { cout << "Les informations concernant la taille du texte d'un objet Text manquent."; } else { float size = 12; elem->FirstChildElement("CharacterSize")->QueryFloatAttribute("value", &size); SetCharacterSize(size); } //Background Scheme if ( elem->FirstChildElement( "BackgroundColorScheme" ) == NULL ) { cout << "Widgets Extension Warning : Unable to load background color full scheme."; } else { backgroundColor->LoadFromXml(elem->FirstChildElement( "BackgroundColorScheme" )); } //Border Scheme if ( elem->FirstChildElement( "BorderColorScheme" ) == NULL ) { cout << "Widgets Extension Warning : Unable to load border color full scheme."; } else { borderColor->LoadFromXml(elem->FirstChildElement( "BorderColorScheme" )); } //Text Scheme if ( elem->FirstChildElement( "TextColorScheme" ) == NULL ) { cout << "Widgets Extension Warning : Unable to load text color full scheme."; } else { textColor->LoadFromXml(elem->FirstChildElement( "TextColorScheme" )); } //Check Scheme if ( elem->FirstChildElement( "CheckColorScheme" ) == NULL ) { cout << "Widgets Extension Warning : Unable to load check color full scheme."; } else { checkColor->LoadFromXml(elem->FirstChildElement( "CheckColorScheme" )); } if ( elem->FirstChildElement( "BorderWidth" ) == NULL || elem->FirstChildElement( "BorderWidth" )->Attribute("value") == NULL ) { cout << "Widgets Extension Warning : Unable to load width of border"; } else { float borderW = 12; elem->FirstChildElement("BorderWidth")->QueryFloatAttribute("value", &borderW); SetBorderWidth(borderW); } if ( elem->FirstChildElement( "Padding" ) == NULL || elem->FirstChildElement( "Padding" )->Attribute("value") == NULL ) { cout << "Widgets Extension Warning : Unable to load padding"; } else { float pad = 12; elem->FirstChildElement("Padding")->QueryFloatAttribute("value", &pad); SetPadding(pad); } if ( elem->FirstChildElement( "BoxSize" ) == NULL || elem->FirstChildElement( "BoxSize" )->Attribute("value") == NULL ) { cout << "Widgets Extension Warning : Unable to load box size"; } else { int boxS = 14; elem->FirstChildElement("BoxSize")->QueryIntAttribute("value", &boxS); SetBoxSize(boxS); } if ( elem->FirstChildElement( "CheckSignSize" ) == NULL || elem->FirstChildElement( "CheckSignSize" )->Attribute("value") == NULL ) { cout << "Widgets Extension Warning : Unable to load check sign size"; } else { int checkS = 6; elem->FirstChildElement("CheckSignSize")->QueryIntAttribute("value", &checkS); SetCheckSignSize(checkS); } UpdateProperties(); }
bool CheckBoxObject::ChangeProperty(unsigned int propertyNb, string newValue) { if ( propertyNb == 1 ) { SetString(newValue); return true; } else if ( propertyNb == 3 ) { SetCharacterSize(ToInt(newValue)); } return true; }
FPSCounter::FPSCounter(sf::Font & font) : TextObject(font, "FPS: 0"), impl(new FPSCounterImpl()) { SetPosition(10, 10); SetCharacterSize(40); SetColor(sf::Color::Red); }