Localizable font families, start font name with ui to get a \n-separated font list from uxt, close ryzom/ryzomcore#623

develop
kaetemi 4 years ago
parent 5bb21d7aa0
commit be60cf8978

@ -36,7 +36,7 @@ typedef struct FT_FaceRec_* FT_Face;
#include "nel/misc/types_nl.h" #include "nel/misc/types_nl.h"
#include <string> #include <string>
#include <vector>
namespace NL3D { namespace NL3D {
@ -88,6 +88,7 @@ private:
static uint32 _FontGeneratorCounterUID; static uint32 _FontGeneratorCounterUID;
uint32 _UID; uint32 _UID;
std::string _FontFileName; std::string _FontFileName;
std::vector<std::string> _FontFileNames;
#ifndef NL_DONT_USE_EXTERNAL_CODE #ifndef NL_DONT_USE_EXTERNAL_CODE
const char *getFT2Error(FT_Error fte); const char *getFT2Error(FT_Error fte);
@ -95,7 +96,7 @@ private:
static FT_Library _Library; static FT_Library _Library;
static uint _LibraryInit; static uint _LibraryInit;
FT_Face _Face; std::vector<FT_Face> _Faces;
#else // NL_DONT_USE_EXTERNAL_CODE #else // NL_DONT_USE_EXTERNAL_CODE
#endif // NL_DONT_USE_EXTERNAL_CODE #endif // NL_DONT_USE_EXTERNAL_CODE

@ -26,6 +26,7 @@
#include "nel/misc/common.h" #include "nel/misc/common.h"
#include "nel/misc/path.h" #include "nel/misc/path.h"
#include "nel/misc/file.h" #include "nel/misc/file.h"
#include "nel/misc/i18n.h"
#include "nel/3d/font_generator.h" #include "nel/3d/font_generator.h"
@ -190,6 +191,20 @@ CFontGenerator::CFontGenerator (const std::string &fontFileName, const std::stri
_FontGeneratorCounterUID++; _FontGeneratorCounterUID++;
_FontFileName = fontFileName; _FontFileName = fontFileName;
if (NLMISC::startsWith(fontFileName, "ui"))
{
std::string nameList = CI18N::get(fontFileName);
NLMISC::explode(nameList, string("\n"), _FontFileNames, true);
for (std::vector<std::string>::iterator it(_FontFileNames.begin()), end(_FontFileNames.end()); it != end; ++it)
{
*it = CPath::lookup(*it);
}
}
else
{
_FontFileNames.push_back(fontFileName);
}
FT_Error error; FT_Error error;
if (!_LibraryInit) if (!_LibraryInit)
@ -202,49 +217,66 @@ CFontGenerator::CFontGenerator (const std::string &fontFileName, const std::stri
} }
++_LibraryInit; ++_LibraryInit;
for (std::vector<std::string>::iterator it(_FontFileNames.begin()), end(_FontFileNames.end()); it != end; ++it)
{
FT_Open_Args args; FT_Open_Args args;
const std::string &fileName = *it;
if (!createFreetypeStream(fontFileName, args)) if (!createFreetypeStream(fileName, args))
{ {
nlerror ("createFreetypeStream failed with file '%s'", fontFileName.c_str()); nlerror("createFreetypeStream failed with file '%s'", fileName.c_str());
} }
error = FT_Open_Face(_Library, &args, 0, &_Face); FT_Face face;
error = FT_Open_Face(_Library, &args, 0, &face);
if (error) if (error)
{ {
nlerror ("FT_New_Face() failed with file '%s': %s", fontFileName.c_str(), getFT2Error(error)); nlerror("FT_New_Face() failed with file '%s': %s", fileName.c_str(), getFT2Error(error));
} }
string fontEx = fontExFileName; string fontEx = fontExFileName;
if (fontEx.empty()) if (fontEx.empty())
{ {
// try to see if the ex filename exists based on the fontExFileName // try to see if the ex filename exists based on the fontExFileName
fontEx = CPath::lookup(CFile::getFilenameWithoutExtension (fontFileName)+".afm", false, false); fontEx = CPath::lookup(CFile::getFilenameWithoutExtension(fileName) + ".afm", false, false);
} }
if (!fontEx.empty()) if (!fontEx.empty())
{ {
if (!createFreetypeStream(fontEx, args)) if (!createFreetypeStream(fontEx, args))
{ {
nlerror ("createFreetypeStream failed with file '%s'", fontFileName.c_str()); nlerror("createFreetypeStream failed with file '%s'", fileName.c_str());
FT_Done_Face(face);
continue;
} }
error = FT_Attach_Stream(_Face, &args); error = FT_Attach_Stream(face, &args);
if (error) if (error)
{ {
nlwarning("FT_Attach_File() failed with file '%s': %s", fontEx.c_str(), getFT2Error(error)); nlwarning("FT_Attach_File() failed with file '%s': %s", fontEx.c_str(), getFT2Error(error));
FT_Done_Face(face);
continue;
} }
} }
error = FT_Select_Charmap (_Face, ft_encoding_unicode); error = FT_Select_Charmap(face, ft_encoding_unicode);
if (error) if (error)
{ {
nlerror ("FT_Select_Charmap() failed with file '%s': %s", fontFileName.c_str(), getFT2Error(error)); nlerror("FT_Select_Charmap() failed with file '%s': %s", fileName.c_str(), getFT2Error(error));
FT_Done_Face(face);
continue;
}
_Faces.push_back(face);
} }
} }
CFontGenerator::~CFontGenerator () CFontGenerator::~CFontGenerator ()
{ {
for (std::vector<FT_Face>::iterator it(_Faces.begin()), end(_Faces.end()); it != end; ++it)
FT_Done_Face(*it);
_Faces.clear();
// important: destroying and creating your last font generator // important: destroying and creating your last font generator
// will also reload the freetype library // will also reload the freetype library
nlassert(_LibraryInit); nlassert(_LibraryInit);
@ -259,30 +291,41 @@ CFontGenerator::~CFontGenerator ()
void CFontGenerator::getSizes (u32char c, uint32 size, uint32 &width, uint32 &height) void CFontGenerator::getSizes (u32char c, uint32 size, uint32 &width, uint32 &height)
{ {
FT_Error error; FT_Error error;
FT_Face face;
FT_UInt glyph_index = 0;
if (!_Faces.size())
{
nlerror("No faces loaded");
return;
}
error = FT_Set_Pixel_Sizes (_Face, size, size); for (std::vector<FT_Face>::iterator it(_Faces.begin()), end(_Faces.end()); it != end; ++it)
{
face = *it;
error = FT_Set_Pixel_Sizes(face, size, size);
if (error) if (error)
{ {
nlerror("FT_Set_Pixel_Sizes() failed: %s", getFT2Error(error)); nlerror("FT_Set_Pixel_Sizes() failed: %s", getFT2Error(error));
continue;
} }
// retrieve glyph index from character code // retrieve glyph index from character code
FT_UInt glyph_index = FT_Get_Char_Index (_Face, c); glyph_index = FT_Get_Char_Index(face, c);
if (glyph_index == 0) // found glyph
{ if (glyph_index)
// no glyph available, replace with a dot break;
glyph_index = FT_Get_Char_Index (_Face, u32char('.'));
} }
// load glyph image into the slot (erase previous one) // load glyph image into the slot (erase previous one)
error = FT_Load_Glyph (_Face, glyph_index, FT_LOAD_DEFAULT); error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error) if (error)
{ {
// use fallback for glyph/character errors (composite char limit for example) // use fallback for glyph/character errors (composite char limit for example)
nlwarning ("FT_Load_Glyph() failed: %s", getFT2Error(error)); nlwarning ("FT_Load_Glyph() failed: %s", getFT2Error(error));
error = FT_Load_Glyph (_Face, 0, FT_LOAD_DEFAULT); error = FT_Load_Glyph(face, 0, FT_LOAD_DEFAULT);
if (error) if (error)
{ {
nlerror("FT_Load_Glyph() fallback failed: %s", getFT2Error(error)); nlerror("FT_Load_Glyph() fallback failed: %s", getFT2Error(error));
@ -290,39 +333,48 @@ void CFontGenerator::getSizes (u32char c, uint32 size, uint32 &width, uint32 &he
} }
// convert 24.6 fixed point into integer // convert 24.6 fixed point into integer
width = _Face->glyph->metrics.width >> 6; width = face->glyph->metrics.width >> 6;
height = _Face->glyph->metrics.height >> 6; height = face->glyph->metrics.height >> 6;
} }
uint8 *CFontGenerator::getBitmap (u32char c, uint32 size, bool embolden, bool oblique, uint32 &width, uint32 &height, uint32 &pitch, sint32 &left, sint32 &top, sint32 &advx, uint32 &glyphIndex) uint8 *CFontGenerator::getBitmap (u32char c, uint32 size, bool embolden, bool oblique, uint32 &width, uint32 &height, uint32 &pitch, sint32 &left, sint32 &top, sint32 &advx, uint32 &glyphIndex)
{ {
FT_Error error; FT_Error error;
FT_Face face;
FT_UInt glyph_index = 0;
if (!_Faces.size())
{
nlerror("No faces loaded");
return NULL;
}
error = FT_Set_Pixel_Sizes (_Face, size, size); for (std::vector<FT_Face>::iterator it(_Faces.begin()), end(_Faces.end()); it != end; ++it)
{
face = *it;
error = FT_Set_Pixel_Sizes(face, size, size);
if (error) if (error)
{ {
nlerror("FT_Set_Pixel_Sizes() failed: %s", getFT2Error(error)); nlerror("FT_Set_Pixel_Sizes() failed: %s", getFT2Error(error));
continue;
} }
// retrieve glyph index from character code // retrieve glyph index from character code
FT_UInt glyph_index = FT_Get_Char_Index (_Face, c); glyph_index = FT_Get_Char_Index(face, c);
/* // found glyph
if (glyph_index == 0) if (glyph_index)
{ break;
// no glyph available, replace with a dot
glyph_index = FT_Get_Char_Index (_Face, u32char('.'));
} }
*/
// load glyph image into the slot (erase previous one) // load glyph image into the slot (erase previous one)
error = FT_Load_Glyph (_Face, glyph_index, FT_LOAD_DEFAULT); error = FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT);
if (error) if (error)
{ {
// use fallback for glyph/character errors (composite char limit for example) // use fallback for glyph/character errors (composite char limit for example)
nlwarning ("FT_Load_Glyph() failed: %s", getFT2Error(error)); nlwarning ("FT_Load_Glyph() failed: %s", getFT2Error(error));
error = FT_Load_Glyph (_Face, 0, FT_LOAD_DEFAULT); error = FT_Load_Glyph (face, 0, FT_LOAD_DEFAULT);
if (error) if (error)
{ {
nlerror("FT_Load_Glyph() fallback failed: %s", getFT2Error(error)); nlerror("FT_Load_Glyph() fallback failed: %s", getFT2Error(error));
@ -343,47 +395,49 @@ uint8 *CFontGenerator::getBitmap (u32char c, uint32 size, bool embolden, bool ob
if (embolden) if (embolden)
{ {
FT_GlyphSlot_Embolden(_Face->glyph); FT_GlyphSlot_Embolden(face->glyph);
} }
if (oblique) if (oblique)
{ {
FT_GlyphSlot_Oblique(_Face->glyph); FT_GlyphSlot_Oblique(face->glyph);
} }
// convert to an anti-aliased bitmap // convert to an anti-aliased bitmap
error = FT_Render_Glyph (_Face->glyph, ft_render_mode_normal); error = FT_Render_Glyph (face->glyph, ft_render_mode_normal);
if (error) if (error)
{ {
nlerror ("FT_Render_Glyph() failed: %s", getFT2Error(error)); nlerror ("FT_Render_Glyph() failed: %s", getFT2Error(error));
} }
width = _Face->glyph->bitmap.width; width = face->glyph->bitmap.width;
height = _Face->glyph->bitmap.rows; height = face->glyph->bitmap.rows;
pitch = _Face->glyph->bitmap.pitch; pitch = face->glyph->bitmap.pitch;
left = _Face->glyph->bitmap_left; left = face->glyph->bitmap_left;
top = _Face->glyph->bitmap_top; top = face->glyph->bitmap_top;
advx = _Face->glyph->advance.x >> 6; advx = face->glyph->advance.x >> 6;
glyphIndex = glyph_index; glyphIndex = glyph_index;
return (uint8 *) _Face->glyph->bitmap.buffer; return (uint8 *) face->glyph->bitmap.buffer;
} }
void CFontGenerator::getKerning (u32char left, u32char right, sint32 &kernx) void CFontGenerator::getKerning (u32char left, u32char right, sint32 &kernx)
{ {
if (!FT_HAS_KERNING(_Face)) if (!FT_HAS_KERNING(_Faces[0]))
{ {
kernx = 0; kernx = 0;
} }
else else
{ {
// This is currently not used...
FT_Vector kerning; FT_Vector kerning;
FT_Error error = FT_Get_Kerning (_Face, left, right, ft_kerning_default, &kerning); FT_Error error = FT_Get_Kerning (_Faces[0], left, right, ft_kerning_default, &kerning);
if (error) if (error)
{ {
nlerror ("FT_Get_Kerning() failed: %s", getFT2Error(error)); nlerror ("FT_Get_Kerning() failed: %s", getFT2Error(error));
@ -396,12 +450,14 @@ void CFontGenerator::getKerning (u32char left, u32char right, sint32 &kernx)
uint32 CFontGenerator::getCharIndex (u32char c) uint32 CFontGenerator::getCharIndex (u32char c)
{ {
uint32 ret = FT_Get_Char_Index(_Face, c); // This is currently not used...
uint32 ret = FT_Get_Char_Index(_Faces[0], c);
if (ret == 0) if (ret == 0)
{ {
// no glyph available, replace with a dot // no glyph available, replace with a dot
ret = FT_Get_Char_Index (_Face, u32char('.')); ret = FT_Get_Char_Index (_Faces[0], u32char('.'));
} }
return ret; return ret;

@ -312,7 +312,7 @@ namespace NLGUI
if (fonts.count(name) > 0) if (fonts.count(name) > 0)
driver->deleteTextContext(fonts[name]); driver->deleteTextContext(fonts[name]);
std::string fontFile = CPath::lookup(font, false); std::string fontFile = NLMISC::startsWith(font, "ui") ? font : CPath::lookup(font, false);
if (fontFile.empty()) if (fontFile.empty())
{ {
nlwarning("Font file '%s' not found", font.c_str()); nlwarning("Font file '%s' not found", font.c_str());

@ -49,6 +49,7 @@ mkPath(log, fontExportDir)
for dir in FontSourceDirectories: for dir in FontSourceDirectories:
mkPath(log, DatabaseDirectory + "/" + dir) mkPath(log, DatabaseDirectory + "/" + dir)
copyFilesExtNoTreeIfNeeded(log, DatabaseDirectory + "/" + dir, fontExportDir, ".ttf") copyFilesExtNoTreeIfNeeded(log, DatabaseDirectory + "/" + dir, fontExportDir, ".ttf")
copyFilesExtNoTreeIfNeeded(log, DatabaseDirectory + "/" + dir, fontExportDir, ".otf")
copyFilesExtNoTreeIfNeeded(log, DatabaseDirectory + "/" + dir, fontExportDir, ".afm") copyFilesExtNoTreeIfNeeded(log, DatabaseDirectory + "/" + dir, fontExportDir, ".afm")
copyFilesExtNoTreeIfNeeded(log, DatabaseDirectory + "/" + dir, fontExportDir, ".pfb") copyFilesExtNoTreeIfNeeded(log, DatabaseDirectory + "/" + dir, fontExportDir, ".pfb")
copyFilesExtNoTreeIfNeeded(log, DatabaseDirectory + "/" + dir, fontExportDir, ".pfm") copyFilesExtNoTreeIfNeeded(log, DatabaseDirectory + "/" + dir, fontExportDir, ".pfm")

@ -50,6 +50,7 @@ mkPath(log, fontExportDir)
printLog(log, ">>> Install font <<<") printLog(log, ">>> Install font <<<")
copyFilesExtNoTreeIfNeeded(log, fontExportDir, installPath, ".ttf") copyFilesExtNoTreeIfNeeded(log, fontExportDir, installPath, ".ttf")
copyFilesExtNoTreeIfNeeded(log, fontExportDir, installPath, ".otf")
copyFilesExtNoTreeIfNeeded(log, fontExportDir, installPath, ".afm") copyFilesExtNoTreeIfNeeded(log, fontExportDir, installPath, ".afm")
copyFilesExtNoTreeIfNeeded(log, fontExportDir, installPath, ".pfb") copyFilesExtNoTreeIfNeeded(log, fontExportDir, installPath, ".pfb")
copyFilesExtNoTreeIfNeeded(log, fontExportDir, installPath, ".pfm") copyFilesExtNoTreeIfNeeded(log, fontExportDir, installPath, ".pfm")

@ -90,7 +90,7 @@ void resetTextContext (const char *font, bool resetInterfaceManager)
{ {
if (TextContext != NULL) if (TextContext != NULL)
Driver->deleteTextContext(TextContext); Driver->deleteTextContext(TextContext);
TextContext = Driver->createTextContext(CPath::lookup(font)); TextContext = Driver->createTextContext(NLMISC::startsWith(font, "ui") ? font : CPath::lookup(font));
if (TextContext != NULL) if (TextContext != NULL)
TextContext->setKeep800x600Ratio(false); TextContext->setKeep800x600Ratio(false);
else else

Loading…
Cancel
Save