app_server FontManager: load all fonts and named-variants from a file

BFont::LoadFont can now use an index (0-based) and an optional named-instance (1-based)
to select the font variant from a file.
BFont::LoadFont can also use an index when loading from memory.

Change-Id: I0ce3eb6cc77d32cf43847416561eafe3063ca693
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7402
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
Reviewed-by: Máximo Castañeda <antiswen@yahoo.es>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
Jérôme Duval 2024-02-14 16:40:20 +01:00 committed by Máximo Castañeda
parent fe8f7e314e
commit d0f06357f5
8 changed files with 74 additions and 24 deletions

View File

@ -283,8 +283,11 @@ public:
void PrintToStream() const;
status_t LoadFont(const char* path);
status_t LoadFont(const char* path, uint16 index, uint16 instance);
status_t LoadFont(const area_id fontAreaID,
size_t size = 0, size_t offset = 0);
status_t LoadFont(const area_id fontAreaID,
size_t size = 0, size_t offset = 0, uint16 index = 0);
status_t UnloadFont();
private:

View File

@ -1458,10 +1458,19 @@ BFont::_GetExtraFlags() const
status_t
BFont::LoadFont(const char* path)
{
return LoadFont(path, 0, 0);
}
status_t
BFont::LoadFont(const char* path, uint16 index, uint16 instance)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_ADD_FONT_FILE);
link.AttachString(path);
link.Attach<uint16>(index);
link.Attach<uint16>(instance);
status_t status = B_ERROR;
if (link.FlushWithReply(status) != B_OK || status != B_OK) {
return status;
@ -1479,6 +1488,13 @@ BFont::LoadFont(const char* path)
status_t
BFont::LoadFont(const area_id fontAreaID, size_t size, size_t offset)
{
return LoadFont(fontAreaID, size, offset, 0);
}
status_t
BFont::LoadFont(const area_id fontAreaID, size_t size, size_t offset, uint16 index)
{
BPrivate::AppServerLink link;
@ -1487,6 +1503,7 @@ BFont::LoadFont(const area_id fontAreaID, size_t size, size_t offset)
link.Attach<int32>(fontAreaID);
link.Attach<size_t>(size);
link.Attach<size_t>(offset);
link.Attach<uint16>(index);
status_t status = B_ERROR;
if (link.FlushWithReply(status) != B_OK || status != B_OK) {

View File

@ -1581,6 +1581,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
// Attached Data:
// 1) char* - path to font on disk
// 2) uint16 - index in font file
// 3) uint16 - instance
// Returns:
// 1) uint16 - family ID of added font
@ -1597,9 +1599,12 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
uint16 familyID, styleID;
char* fontPath;
uint16 index, instance;
link.ReadString(&fontPath);
link.Read<uint16>(&index);
link.Read<uint16>(&instance);
status_t status = fAppFontManager->AddUserFontFromFile(fontPath,
status_t status = fAppFontManager->AddUserFontFromFile(fontPath, index, instance,
familyID, styleID);
if (status != B_OK) {
@ -1632,6 +1637,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
// 1) area_id - id of memory area where font resides
// 2) size_t - size of memory area for font
// 3) size_t - offset to start of font memory
// 4) uint16 - index in font buffer
// Returns:
// 1) uint16 - family ID of added font
@ -1650,10 +1656,12 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
area_info fontAreaInfo;
char* area_addr;
size_t size, offset;
uint16 index;
link.Read<int32>(&fontAreaID);
link.Read<size_t>(&size);
link.Read<size_t>(&offset);
link.Read<uint16>(&index);
fontAreaCloneID = clone_area("user font",
(void **)&area_addr,
B_ANY_ADDRESS,
@ -1702,7 +1710,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
uint16 familyID, styleID;
status = fAppFontManager->AddUserFontFromMemory(fontData, size,
status = fAppFontManager->AddUserFontFromMemory(fontData, size, index,
familyID, styleID);
if (status != B_OK) {

View File

@ -68,6 +68,8 @@ class ServerFont {
const char* Family() const;
const char* Path() const
{ return fStyle->Path(); }
long FaceIndex() const
{ return fStyle->FreeTypeFace()->face_index; }
void SetStyle(FontStyle* style);
status_t SetFamilyAndStyle(uint16 familyID,

View File

@ -50,7 +50,7 @@ AppFontManager::AppFontManager()
/*! \brief Adds the FontFamily/FontStyle that is represented by this path.
*/
status_t
AppFontManager::AddUserFontFromFile(const char* path,
AppFontManager::AddUserFontFromFile(const char* path, uint16 index, uint16 instance,
uint16& familyID, uint16& styleID)
{
ASSERT(IsLocked());
@ -66,12 +66,11 @@ AppFontManager::AddUserFontFromFile(const char* path,
return status;
FT_Face face;
FT_Error error = FT_New_Face(gFreeTypeLibrary, path, 0, &face);
FT_Error error = FT_New_Face(gFreeTypeLibrary, path, index | (instance << 16), &face);
if (error != 0)
return B_ERROR;
status = _AddFont(face, nodeRef, path, familyID, styleID);
return status;
}
@ -79,7 +78,7 @@ AppFontManager::AddUserFontFromFile(const char* path,
/*! \brief Adds the FontFamily/FontStyle that is represented by the area in memory.
*/
status_t
AppFontManager::AddUserFontFromMemory(const FT_Byte* fontAddress, size_t size,
AppFontManager::AddUserFontFromMemory(const FT_Byte* fontAddress, size_t size, uint16 index,
uint16& familyID, uint16& styleID)
{
ASSERT(IsLocked());
@ -88,7 +87,7 @@ AppFontManager::AddUserFontFromMemory(const FT_Byte* fontAddress, size_t size,
status_t status;
FT_Face face;
FT_Error error = FT_New_Memory_Face(gFreeTypeLibrary, fontAddress, size, 0,
FT_Error error = FT_New_Memory_Face(gFreeTypeLibrary, fontAddress, size, index,
&face);
if (error != 0)
return B_ERROR;

View File

@ -37,10 +37,10 @@ public:
void Unlock() { BLocker::Unlock(); }
bool IsLocked() const { return BLocker::IsLocked(); }
status_t AddUserFontFromFile(const char* path,
status_t AddUserFontFromFile(const char* path, uint16 index, uint16 instance,
uint16& familyID, uint16& styleID);
status_t AddUserFontFromMemory(const FT_Byte* fontAddress,
size_t size, uint16& familyID, uint16& styleID);
status_t AddUserFontFromMemory(const FT_Byte* fontAddress, size_t size,
uint16 index, uint16& familyID, uint16& styleID);
status_t RemoveUserFont(uint16 familyID, uint16 styleID);
private:

View File

@ -160,10 +160,10 @@ FontCacheEntry::Init(const ServerFont& font, bool forceVector)
bool success;
if (font.FontData() != NULL)
success = fEngine.Init(NULL, 0, font.Size(), charMap,
success = fEngine.Init(NULL, font.FaceIndex(), font.Size(), charMap,
renderingType, hinting, (const void*)font.FontData(), font.FontDataSize());
else
success = fEngine.Init(font.Path(), 0, font.Size(), charMap,
success = fEngine.Init(font.Path(), font.FaceIndex(), font.Size(), charMap,
renderingType, hinting);
if (!success) {

View File

@ -239,8 +239,8 @@ GlobalFontManager::MessageReceived(BMessage* message)
if (fromDirectory != NULL) {
// find style in source and move it to the target
nodeRef.node = node;
FontStyle* style = fromDirectory->FindStyle(nodeRef);
if (style != NULL) {
FontStyle* style;
while ((style = fromDirectory->FindStyle(nodeRef)) != NULL) {
fromDirectory->styles.RemoveItem(style, false);
directory->styles.AddItem(style);
style->UpdatePath(directory->directory);
@ -505,8 +505,8 @@ GlobalFontManager::_RemoveStyle(dev_t device, uint64 directoryNode, uint64 node)
if (directory != NULL) {
// find style in directory and remove it
nodeRef.node = node;
FontStyle* style = directory->FindStyle(nodeRef);
if (style != NULL)
FontStyle* style;
while ((style = directory->FindStyle(nodeRef)) != NULL)
_RemoveStyle(*directory, style);
}
}
@ -711,18 +711,39 @@ GlobalFontManager::_AddFont(font_directory& directory, BEntry& entry)
return status;
FT_Face face;
FT_Error error = FT_New_Face(gFreeTypeLibrary, path.Path(), 0, &face);
FT_Error error = FT_New_Face(gFreeTypeLibrary, path.Path(), -1, &face);
if (error != 0)
return B_ERROR;
FT_Long count = face->num_faces;
FT_Done_Face(face);
uint16 familyID, styleID;
status = FontManager::_AddFont(face, nodeRef, path.Path(), familyID, styleID);
if (status == B_NAME_IN_USE)
return B_OK;
if (status < B_OK)
return status;
for (FT_Long i = 0; i < count; i++) {
FT_Error error = FT_New_Face(gFreeTypeLibrary, path.Path(), -(i + 1), &face);
if (error != 0)
return B_ERROR;
uint32 variableCount = (face->style_flags & 0x7fff0000) >> 16;
FT_Done_Face(face);
directory.styles.AddItem(GetStyle(familyID, styleID));
uint32 j = variableCount == 0 ? 0 : 1;
do {
FT_Long faceIndex = i | (j << 16);
error = FT_New_Face(gFreeTypeLibrary, path.Path(), faceIndex, &face);
if (error != 0)
return B_ERROR;
uint16 familyID, styleID;
status = FontManager::_AddFont(face, nodeRef, path.Path(), familyID, styleID);
if (status == B_NAME_IN_USE) {
status = B_OK;
j++;
continue;
}
if (status < B_OK)
return status;
directory.styles.AddItem(GetStyle(familyID, styleID));
j++;
} while (j <= variableCount);
}
if (directory.AlreadyScanned())
directory.revision++;