BFont: allow loading of user fonts from disk or memory

This patch adds an API call to BFont, called LoadFont, that
takes a string path to a font file. The user fonts are managed
via a new class called AppFontManager that inherits from the base
class FontManagerBase but adds the methods to add and remove user
fonts from disk or memory. There is also a new method called UnloadFont
to remove a user font, but on exit of an app all user fonts should be
automatically cleaned up.

Global/system fonts are managed by the GlobalFontManager, which is
a new class that also inherits from the base class FontManagerBase,
replacing the old "FontManager" class.

A maximum of 128 user fonts may be loaded, and memory fonts
may not exceed 20MB.

There's also an overloaded version of LoadFont that accepts
an area_id and loads the font from memory. A size and offset may
optionally be provided to allow for an area that contains more
than just a font.

Change-Id: I6add42bdf0c0cefc0e2e2a4984fd848c3e7269e5
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4790
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
This commit is contained in:
Dale Cieslak 2022-07-19 22:45:45 -07:00 committed by Adrien Destugues
parent 65f096fd08
commit 85b82f8524
31 changed files with 2077 additions and 1023 deletions

View File

@ -282,6 +282,11 @@ public:
void PrintToStream() const; void PrintToStream() const;
status_t LoadFont(const char* path);
status_t LoadFont(const area_id fontAreaID,
uint32 size = 0, uint32 offset = 0);
status_t UnloadFont();
private: private:
friend void _init_global_fonts_(); friend void _init_global_fonts_();

View File

@ -146,6 +146,9 @@ enum {
AS_GET_TRUNCATED_STRINGS, AS_GET_TRUNCATED_STRINGS,
AS_GET_UNICODE_BLOCKS, AS_GET_UNICODE_BLOCKS,
AS_GET_HAS_UNICODE_BLOCK, AS_GET_HAS_UNICODE_BLOCK,
AS_ADD_FONT_FILE,
AS_ADD_FONT_MEMORY,
AS_REMOVE_FONT,
// Screen methods // Screen methods
AS_VALID_SCREEN_ID, AS_VALID_SCREEN_ID,

View File

@ -559,6 +559,7 @@ BFont::SetFamilyAndStyle(const font_family family, const font_style style)
link.Read<uint16>(&fFamilyID); link.Read<uint16>(&fFamilyID);
link.Read<uint16>(&fStyleID); link.Read<uint16>(&fStyleID);
link.Read<uint16>(&fFace); link.Read<uint16>(&fFace);
fHeight.ascent = kUninitializedAscent; fHeight.ascent = kUninitializedAscent;
fExtraFlags = kUninitializedExtraFlags; fExtraFlags = kUninitializedExtraFlags;
@ -943,6 +944,7 @@ BFont::GetTunedInfo(int32 index, tuned_font_info* info) const
} }
// Truncates a string to a given _pixel_ width based on the font and size
void void
BFont::TruncateString(BString* inOut, uint32 mode, float width) const BFont::TruncateString(BString* inOut, uint32 mode, float width) const
{ {
@ -1452,3 +1454,76 @@ BFont::_GetExtraFlags() const
link.Read<uint32>(&fExtraFlags); link.Read<uint32>(&fExtraFlags);
} }
status_t
BFont::LoadFont(const char* path)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_ADD_FONT_FILE);
link.AttachString(path);
status_t status = B_ERROR;
if (link.FlushWithReply(status) != B_OK || status != B_OK) {
return status;
}
link.Read<uint16>(&fFamilyID);
link.Read<uint16>(&fStyleID);
link.Read<uint16>(&fFace);
fHeight.ascent = kUninitializedAscent;
fExtraFlags = kUninitializedExtraFlags;
return B_OK;
}
status_t
BFont::LoadFont(const area_id fontAreaID, uint32 size, uint32 offset)
{
BPrivate::AppServerLink link;
link.StartMessage(AS_ADD_FONT_MEMORY);
link.Attach<int32>(fontAreaID);
link.Attach<uint32>(size);
link.Attach<uint32>(offset);
status_t status = B_ERROR;
if (link.FlushWithReply(status) != B_OK || status != B_OK) {
return status;
}
link.Read<uint16>(&fFamilyID);
link.Read<uint16>(&fStyleID);
link.Read<uint16>(&fFace);
fHeight.ascent = kUninitializedAscent;
fExtraFlags = kUninitializedExtraFlags;
return B_OK;
}
status_t
BFont::UnloadFont()
{
BPrivate::AppServerLink link;
link.StartMessage(AS_REMOVE_FONT);
link.Attach<uint16>(fFamilyID);
link.Attach<uint16>(fStyleID);
status_t status = B_ERROR;
if (link.FlushWithReply(status) != B_OK || status != B_OK) {
return status;
}
// reset to plain font
fFamilyID = 0;
fStyleID = 0;
fFace = 0;
fHeight.ascent = kUninitializedAscent;
fExtraFlags = kUninitializedExtraFlags;
return B_OK;
}

View File

@ -20,7 +20,7 @@
#include "BitmapManager.h" #include "BitmapManager.h"
#include "Desktop.h" #include "Desktop.h"
#include "FontManager.h" #include "GlobalFontManager.h"
#include "InputManager.h" #include "InputManager.h"
#include "ScreenManager.h" #include "ScreenManager.h"
#include "ServerProtocol.h" #include "ServerProtocol.h"
@ -58,7 +58,7 @@ AppServer::AppServer(status_t* status)
gInputManager = new InputManager(); gInputManager = new InputManager();
// Create the font server and scan the proper directories. // Create the font server and scan the proper directories.
gFontManager = new FontManager; gFontManager = new GlobalFontManager;
if (gFontManager->InitCheck() != B_OK) if (gFontManager->InitCheck() != B_OK)
debugger("font manager could not be initialized!"); debugger("font manager could not be initialized!");

View File

@ -46,7 +46,7 @@
#include "DecorManager.h" #include "DecorManager.h"
#include "DesktopSettingsPrivate.h" #include "DesktopSettingsPrivate.h"
#include "DrawingEngine.h" #include "DrawingEngine.h"
#include "FontManager.h" #include "GlobalFontManager.h"
#include "HWInterface.h" #include "HWInterface.h"
#include "InputManager.h" #include "InputManager.h"
#include "Screen.h" #include "Screen.h"

View File

@ -23,7 +23,9 @@
#include <ServerReadOnlyMemory.h> #include <ServerReadOnlyMemory.h>
#include "Desktop.h" #include "Desktop.h"
#include "FontManager.h" #include "FontCache.h"
#include "FontCacheEntry.h"
#include "GlobalFontManager.h"
#include "GlobalSubpixelSettings.h" #include "GlobalSubpixelSettings.h"
#include "ServerConfig.h" #include "ServerConfig.h"

View File

@ -145,7 +145,8 @@ DrawState::PopState()
uint16 uint16
DrawState::ReadFontFromLink(BPrivate::LinkReceiver& link) DrawState::ReadFontFromLink(BPrivate::LinkReceiver& link,
AppFontManager* fontManager)
{ {
uint16 mask; uint16 mask;
link.Read<uint16>(&mask); link.Read<uint16>(&mask);
@ -153,7 +154,7 @@ DrawState::ReadFontFromLink(BPrivate::LinkReceiver& link)
if ((mask & B_FONT_FAMILY_AND_STYLE) != 0) { if ((mask & B_FONT_FAMILY_AND_STYLE) != 0) {
uint32 fontID; uint32 fontID;
link.Read<uint32>(&fontID); link.Read<uint32>(&fontID);
fFont.SetFamilyAndStyle(fontID); fFont.SetFamilyAndStyle(fontID, fontManager);
} }
if ((mask & B_FONT_SIZE) != 0) { if ((mask & B_FONT_SIZE) != 0) {

View File

@ -22,6 +22,7 @@
#include <Referenceable.h> #include <Referenceable.h>
#include <View.h> #include <View.h>
#include "AppFontManager.h"
#include "ServerFont.h" #include "ServerFont.h"
#include "PatternHandler.h" #include "PatternHandler.h"
#include "SimpleTransform.h" #include "SimpleTransform.h"
@ -48,7 +49,8 @@ public:
DrawState* PreviousState() const DrawState* PreviousState() const
{ return fPreviousState.Get(); } { return fPreviousState.Get(); }
uint16 ReadFontFromLink(BPrivate::LinkReceiver& link); uint16 ReadFontFromLink(BPrivate::LinkReceiver& link,
AppFontManager* fontManager = NULL);
// NOTE: ReadFromLink() does not read Font state!! // NOTE: ReadFromLink() does not read Font state!!
// It was separate in ServerWindow, and I didn't // It was separate in ServerWindow, and I didn't
// want to change it without knowing implications. // want to change it without knowing implications.

View File

@ -29,6 +29,8 @@ local font_src =
FontFamily.cpp FontFamily.cpp
FontManager.cpp FontManager.cpp
FontStyle.cpp FontStyle.cpp
GlobalFontManager.cpp
AppFontManager.cpp
; ;
UseBuildFeatureHeaders freetype ; UseBuildFeatureHeaders freetype ;

View File

@ -15,7 +15,7 @@
#include <stdio.h> #include <stdio.h>
#include "DrawState.h" #include "DrawState.h"
#include "FontManager.h" #include "GlobalFontManager.h"
#include "Layer.h" #include "Layer.h"
#include "ServerApp.h" #include "ServerApp.h"
#include "ServerBitmap.h" #include "ServerBitmap.h"

View File

@ -126,6 +126,9 @@ string_for_message_code(uint32 code)
CODE(AS_GET_TRUNCATED_STRINGS); CODE(AS_GET_TRUNCATED_STRINGS);
CODE(AS_GET_UNICODE_BLOCKS); CODE(AS_GET_UNICODE_BLOCKS);
CODE(AS_GET_HAS_UNICODE_BLOCK); CODE(AS_GET_HAS_UNICODE_BLOCK);
CODE(AS_ADD_FONT_FILE);
CODE(AS_ADD_FONT_MEMORY);
CODE(AS_REMOVE_FONT);
// Screen methods // Screen methods
CODE(AS_VALID_SCREEN_ID); CODE(AS_VALID_SCREEN_ID);

View File

@ -44,6 +44,7 @@
#include <ServerProtocol.h> #include <ServerProtocol.h>
#include <WindowPrivate.h> #include <WindowPrivate.h>
#include "AppFontManager.h"
#include "AppServer.h" #include "AppServer.h"
#include "BitmapManager.h" #include "BitmapManager.h"
#include "CursorManager.h" #include "CursorManager.h"
@ -52,7 +53,7 @@
#include "DecorManager.h" #include "DecorManager.h"
#include "DrawingEngine.h" #include "DrawingEngine.h"
#include "EventStream.h" #include "EventStream.h"
#include "FontManager.h" #include "GlobalFontManager.h"
#include "HWInterface.h" #include "HWInterface.h"
#include "InputManager.h" #include "InputManager.h"
#include "OffscreenServerWindow.h" #include "OffscreenServerWindow.h"
@ -107,7 +108,8 @@ ServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort,
fViewCursor(NULL), fViewCursor(NULL),
fCursorHideLevel(0), fCursorHideLevel(0),
fIsActive(false), fIsActive(false),
fMemoryAllocator(new (std::nothrow) ClientMemoryAllocator(this), true) fMemoryAllocator(new (std::nothrow) ClientMemoryAllocator(this), true),
fAppFontManager(NULL)
{ {
if (fSignature.IsEmpty()) if (fSignature.IsEmpty())
fSignature = "application/no-signature"; fSignature = "application/no-signature";
@ -142,6 +144,9 @@ ServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort,
settings.GetDefaultFixedFont(fFixedFont); settings.GetDefaultFixedFont(fFixedFont);
desktop->UnlockSingleWindow(); desktop->UnlockSingleWindow();
fAppFontManager = new AppFontManager();
fAppFontManager->Run();
STRACE(("ServerApp %s:\n", Signature())); STRACE(("ServerApp %s:\n", Signature()));
STRACE(("\tBApp port: %" B_PRId32 "\n", fClientReplyPort)); STRACE(("\tBApp port: %" B_PRId32 "\n", fClientReplyPort));
STRACE(("\tReceiver port: %" B_PRId32 "\n", fMessagePort)); STRACE(("\tReceiver port: %" B_PRId32 "\n", fMessagePort));
@ -205,6 +210,9 @@ ServerApp::~ServerApp()
fDesktop->GetCursorManager().DeleteCursors(fClientTeam); fDesktop->GetCursorManager().DeleteCursors(fClientTeam);
fAppFontManager->Lock();
fAppFontManager->Quit();
STRACE(("ServerApp %s::~ServerApp(): Exiting\n", Signature())); STRACE(("ServerApp %s::~ServerApp(): Exiting\n", Signature()));
} }
@ -1565,6 +1573,214 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
/* font messages */ /* font messages */
case AS_ADD_FONT_FILE:
{
FTRACE(("ServerApp %s: Received BFont creation request\n",
Signature()));
// Add a font for an application from a file
// Attached Data:
// 1) char* - path to font on disk
// Returns:
// 1) uint16 - family ID of added font
// 2) uint16 - style ID of added font
// 3) uint16 - face of added font
fAppFontManager->Lock();
if (fAppFontManager->CountFamilies() > MAX_USER_FONTS) {
fLink.StartMessage(B_NOT_ALLOWED);
fAppFontManager->Unlock();
fLink.Flush();
break;
}
uint16 familyID, styleID;
char* fontPath;
link.ReadString(&fontPath);
status_t status = fAppFontManager->AddUserFontFromFile(fontPath,
familyID, styleID);
fAppFontManager->Unlock();
if (status != B_OK) {
fLink.StartMessage(status);
} else {
ServerFont* font = new(std::nothrow) ServerFont();
if (font == NULL) {
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
status = font->SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<uint16>(font->FamilyID());
fLink.Attach<uint16>(font->StyleID());
fLink.Attach<uint16>(font->Face());
} else {
fLink.StartMessage(status);
delete font;
}
}
fLink.Flush();
break;
}
case AS_ADD_FONT_MEMORY:
{
FTRACE(("ServerApp %s: Received BFont memory creation request\n",
Signature()));
// Add a font for an application from a memory area
// Attached Data:
// 1) area_id - id of memory area where font resides
// 2) uint32 - size of memory area for font
// 3) uint32 - offset to start of font memory
// Returns:
// 1) uint16 - family ID of added font
// 2) uint16 - style ID of added font
// 3) uint16 - face of added font
if (fAppFontManager->CountFamilies() > MAX_USER_FONTS) {
fLink.StartMessage(B_NOT_ALLOWED);
fLink.Flush();
break;
}
area_id fontAreaID, fontAreaCloneID;
area_info fontAreaInfo;
char* area_addr;
uint32 size, offset;
link.Read<int32>(&fontAreaID);
link.Read<uint32>(&size);
link.Read<uint32>(&offset);
fontAreaCloneID = clone_area("user font",
(void **)&area_addr,
B_ANY_ADDRESS,
B_READ_AREA,
fontAreaID);
if (fontAreaCloneID < B_OK) {
fLink.StartMessage(fontAreaCloneID);
fLink.Flush();
break;
}
status_t status = get_area_info(fontAreaCloneID, &fontAreaInfo);
if (status != B_OK) {
fLink.StartMessage(status);
fLink.Flush();
delete_area(fontAreaCloneID);
break;
}
uint32 fontMemorySize = fontAreaInfo.size - offset;
if (size == 0)
size = fontMemorySize;
// Check size of font area and reject if it's too large
if (size > MAX_FONT_DATA_SIZE_BYTES
|| size > fontMemorySize) {
fLink.StartMessage(B_BAD_DATA);
fLink.Flush();
delete_area(fontAreaCloneID);
break;
}
FT_Byte* fontData = (FT_Byte*)(malloc (sizeof(FT_Byte) * size));
if (fontData == NULL) {
delete_area(fontAreaCloneID);
fLink.StartMessage(B_BAD_DATA);
fLink.Flush();
break;
}
memcpy(fontData, (FT_Byte*)fontAreaInfo.address + offset, size);
delete_area(fontAreaCloneID);
uint16 familyID, styleID;
fAppFontManager->Lock();
status = fAppFontManager->AddUserFontFromMemory(fontData, size,
familyID, styleID);
if (status != B_OK) {
fLink.StartMessage(status);
free(fontData);
} else {
ServerFont* font = new(std::nothrow) ServerFont();
if (font == NULL) {
free(fontData);
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
status = font->SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
font->SetFontData(fontData, size);
fLink.StartMessage(B_OK);
fLink.Attach<uint16>(font->FamilyID());
fLink.Attach<uint16>(font->StyleID());
fLink.Attach<uint16>(font->Face());
} else {
fLink.StartMessage(status);
free(fontData);
delete font;
}
}
fAppFontManager->Unlock();
fLink.Flush();
break;
}
case AS_REMOVE_FONT:
{
STRACE(("ServerApp %s: Received BFont removal request\n",
Signature()));
// Remove an application-added font
// Attached Data:
// 1) uint16 - familyID of font to remove
// 2) uint16 - styleID of font to remove
uint16 familyID, styleID;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
status_t status = B_OK;
fAppFontManager->Lock();
FontStyle* style = fAppFontManager->GetStyle(familyID, styleID);
if (style != NULL) {
status = fAppFontManager->RemoveUserFont(familyID, styleID);
} else
status = B_BAD_VALUE;
fAppFontManager->Unlock();
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_SET_SYSTEM_FONT: case AS_SET_SYSTEM_FONT:
{ {
FTRACE(("ServerApp %s: AS_SET_SYSTEM_FONT\n", Signature())); FTRACE(("ServerApp %s: AS_SET_SYSTEM_FONT\n", Signature()));
@ -1708,7 +1924,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
case AS_GET_FONT_LIST_REVISION: case AS_GET_FONT_LIST_REVISION:
{ {
STRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature())); FTRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature()));
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
fLink.Attach<int32>( fLink.Attach<int32>(
@ -1739,12 +1955,19 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
gFontManager->Lock(); gFontManager->Lock();
FontFamily* family = gFontManager->FamilyAt(index); FontFamily* family = gFontManager->FamilyAt(index);
if (family == NULL) {
gFontManager->Unlock();
fAppFontManager->Lock();
family = fAppFontManager->FamilyAt(index);
}
if (family) { if (family) {
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
fLink.AttachString(family->Name()); fLink.AttachString(family->Name());
fLink.Attach<uint32>(family->Flags()); fLink.Attach<uint32>(family->Flags());
int32 count = family->CountStyles(); int32 count = family->CountStyles();
fLink.Attach<int32>(count); fLink.Attach<int32>(count);
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
@ -1757,7 +1980,11 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
} else } else
fLink.StartMessage(B_BAD_VALUE); fLink.StartMessage(B_BAD_VALUE);
gFontManager->Unlock(); if (gFontManager->IsLocked())
gFontManager->Unlock();
if (fAppFontManager->IsLocked())
fAppFontManager->Unlock();
fLink.Flush(); fLink.Flush();
break; break;
} }
@ -1780,7 +2007,13 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
gFontManager->Lock(); gFontManager->Lock();
FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle == NULL) {
gFontManager->Unlock();
fAppFontManager->Lock();
fontStyle = fAppFontManager->GetStyle(familyID, styleID);
}
if (fontStyle != NULL) { if (fontStyle != NULL) {
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
fLink.AttachString(fontStyle->Family()->Name()); fLink.AttachString(fontStyle->Family()->Name());
@ -1789,7 +2022,10 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
fLink.StartMessage(B_BAD_VALUE); fLink.StartMessage(B_BAD_VALUE);
fLink.Flush(); fLink.Flush();
gFontManager->Unlock(); if (gFontManager->IsLocked())
gFontManager->Unlock();
if (fAppFontManager->IsLocked())
fAppFontManager->Unlock();
break; break;
} }
@ -1822,8 +2058,14 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
// get the font and return IDs and face // get the font and return IDs and face
gFontManager->Lock(); gFontManager->Lock();
FontStyle *fontStyle = gFontManager->GetStyle(family, style, FontStyle* fontStyle = gFontManager->GetStyle(family, style,
familyID, styleID, face); familyID, styleID, face);
if (fontStyle == NULL) {
gFontManager->Unlock();
fAppFontManager->Lock();
fontStyle = fAppFontManager->GetStyle(family, style,
familyID, styleID, face);
}
if (fontStyle != NULL) { if (fontStyle != NULL) {
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
@ -1837,7 +2079,10 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
} else } else
fLink.StartMessage(B_NAME_NOT_FOUND); fLink.StartMessage(B_NAME_NOT_FOUND);
gFontManager->Unlock(); if (gFontManager->IsLocked())
gFontManager->Unlock();
if (fAppFontManager->IsLocked())
fAppFontManager->Unlock();
} else } else
fLink.StartMessage(B_BAD_VALUE); fLink.StartMessage(B_BAD_VALUE);
@ -1862,14 +2107,24 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
gFontManager->Lock(); gFontManager->Lock();
FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle) { if (fontStyle == NULL) {
gFontManager->Unlock();
fAppFontManager->Lock();
fontStyle = fAppFontManager->GetStyle(familyID, styleID);
}
if (fontStyle != NULL) {
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
fLink.Attach<uint16>((uint16)fontStyle->FileFormat()); fLink.Attach<uint16>((uint16)fontStyle->FileFormat());
} else } else
fLink.StartMessage(B_BAD_VALUE); fLink.StartMessage(B_BAD_VALUE);
gFontManager->Unlock(); if (gFontManager->IsLocked())
gFontManager->Unlock();
if (fAppFontManager->IsLocked())
fAppFontManager->Unlock();
fLink.Flush(); fLink.Flush();
break; break;
} }
@ -1890,12 +2145,12 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
// Returns: // Returns:
// 1) float - width of the string in pixels (numStrings times) // 1) float - width of the string in pixels (numStrings times)
uint16 family, style; uint16 familyID, styleID;
float size; float size;
uint8 spacing; uint8 spacing;
link.Read<uint16>(&family); link.Read<uint16>(&familyID);
link.Read<uint16>(&style); link.Read<uint16>(&styleID);
link.Read<float>(&size); link.Read<float>(&size);
link.Read<uint8>(&spacing); link.Read<uint8>(&spacing);
int32 numStrings; int32 numStrings;
@ -1923,7 +2178,10 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
ServerFont font; ServerFont font;
if (font.SetFamilyAndStyle(family, style) == B_OK && size > 0) { status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK && size > 0) {
font.SetSize(size); font.SetSize(size);
font.SetSpacing(spacing); font.SetSpacing(spacing);
@ -1970,7 +2228,10 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
ServerFont font; ServerFont font;
if (font.SetFamilyAndStyle(familyID, styleID) == B_OK && size > 0) { status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK && size > 0) {
font.SetSize(size); font.SetSize(size);
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
@ -1999,14 +2260,24 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
gFontManager->Lock(); gFontManager->Lock();
FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle == NULL) {
gFontManager->Unlock();
fAppFontManager->Lock();
fontStyle = fAppFontManager->GetStyle(familyID, styleID);
}
if (fontStyle != NULL) { if (fontStyle != NULL) {
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
fLink.Attach<int32>(fontStyle->TunedCount()); fLink.Attach<int32>(fontStyle->TunedCount());
} else } else
fLink.StartMessage(B_BAD_VALUE); fLink.StartMessage(B_BAD_VALUE);
gFontManager->Unlock(); if (gFontManager->IsLocked())
gFontManager->Unlock();
if (fAppFontManager->IsLocked())
fAppFontManager->Unlock();
fLink.Flush(); fLink.Flush();
break; break;
} }
@ -2048,14 +2319,24 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
gFontManager->Lock(); gFontManager->Lock();
FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle == NULL) {
gFontManager->Unlock();
fAppFontManager->Lock();
fontStyle = fAppFontManager->GetStyle(familyID, styleID);
}
if (fontStyle != NULL) { if (fontStyle != NULL) {
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
fLink.Attach<uint32>(fontStyle->Flags()); fLink.Attach<uint32>(fontStyle->Flags());
} else } else
fLink.StartMessage(B_BAD_VALUE); fLink.StartMessage(B_BAD_VALUE);
gFontManager->Unlock(); if (gFontManager->IsLocked())
gFontManager->Unlock();
if (fAppFontManager->IsLocked())
fAppFontManager->Unlock();
fLink.Flush(); fLink.Flush();
break; break;
} }
@ -2077,7 +2358,13 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
gFontManager->Lock(); gFontManager->Lock();
FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle == NULL) {
gFontManager->Unlock();
fAppFontManager->Lock();
fontStyle = fAppFontManager->GetStyle(familyID, styleID);
}
if (fontStyle != NULL) { if (fontStyle != NULL) {
font_height height; font_height height;
fontStyle->GetHeight(size, height); fontStyle->GetHeight(size, height);
@ -2087,7 +2374,11 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
} else } else
fLink.StartMessage(B_BAD_VALUE); fLink.StartMessage(B_BAD_VALUE);
gFontManager->Unlock(); if (gFontManager->IsLocked())
gFontManager->Unlock();
if (fAppFontManager->IsLocked())
fAppFontManager->Unlock();
fLink.Flush(); fLink.Flush();
break; break;
} }
@ -2108,7 +2399,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
link.Read<uint16>(&styleID); link.Read<uint16>(&styleID);
ServerFont font; ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID); status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) { if (status == B_OK) {
unicode_block blocksForFont; unicode_block blocksForFont;
font.GetUnicodeBlocks(blocksForFont); font.GetUnicodeBlocks(blocksForFont);
@ -2143,7 +2436,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
link.Read<uint32>(&end); link.Read<uint32>(&end);
ServerFont font; ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID); status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) { if (status == B_OK) {
bool hasBlock; bool hasBlock;
@ -2204,7 +2499,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
link.Read(charArray, numBytes); link.Read(charArray, numBytes);
ServerFont font; ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID); status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) { if (status == B_OK) {
font.SetSize(size); font.SetSize(size);
font.SetShear(shear); font.SetShear(shear);
@ -2259,7 +2556,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
link.Read(charArray, numBytes); link.Read(charArray, numBytes);
ServerFont font; ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID); status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) { if (status == B_OK) {
status = font.GetHasGlyphs(charArray, numBytes, numChars, status = font.GetHasGlyphs(charArray, numBytes, numChars,
hasArray); hasArray);
@ -2308,7 +2607,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
link.Read(charArray, numBytes); link.Read(charArray, numBytes);
ServerFont font; ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID); status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) { if (status == B_OK) {
status = font.GetEdges(charArray, numBytes, numChars, status = font.GetEdges(charArray, numBytes, numChars,
edgeArray); edgeArray);
@ -2386,7 +2687,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
link.Read(charArray, numBytes); link.Read(charArray, numBytes);
ServerFont font; ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID); status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) { if (status == B_OK) {
font.SetSize(size); font.SetSize(size);
font.SetSpacing(spacing); font.SetSpacing(spacing);
@ -2471,7 +2774,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
// figure out escapements // figure out escapements
ServerFont font; ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID); status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) { if (status == B_OK) {
font.SetSize(size); font.SetSize(size);
font.SetSpacing(spacing); font.SetSpacing(spacing);
@ -2558,7 +2863,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
// figure out escapements // figure out escapements
ServerFont font; ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID); status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) { if (status == B_OK) {
font.SetSize(size); font.SetSize(size);
font.SetRotation(rotation); font.SetRotation(rotation);
@ -2646,7 +2953,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
} }
ServerFont font; ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID); status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) { if (status == B_OK) {
font.SetSize(ptsize); font.SetSize(ptsize);
font.SetRotation(rotation); font.SetRotation(rotation);

View File

@ -13,6 +13,7 @@
#define SERVER_APP_H #define SERVER_APP_H
#include "AppFontManager.h"
#include "ClientMemoryAllocator.h" #include "ClientMemoryAllocator.h"
#include "MessageLooper.h" #include "MessageLooper.h"
#include "ServerFont.h" #include "ServerFont.h"
@ -96,6 +97,7 @@ public:
BPrivate::BTokenSpace& ViewTokens() { return fViewTokens; } BPrivate::BTokenSpace& ViewTokens() { return fViewTokens; }
void NotifyDeleteClientArea(area_id serverArea); void NotifyDeleteClientArea(area_id serverArea);
AppFontManager* FontManager() { return fAppFontManager; }
private: private:
virtual void _GetLooperName(char* name, size_t size); virtual void _GetLooperName(char* name, size_t size);
@ -160,6 +162,8 @@ private:
bool fIsActive; bool fIsActive;
BReference<ClientMemoryAllocator> fMemoryAllocator; BReference<ClientMemoryAllocator> fMemoryAllocator;
AppFontManager* fAppFontManager;
}; };

View File

@ -13,8 +13,9 @@
#include "ServerFont.h" #include "ServerFont.h"
#include "Angle.h" #include "Angle.h"
#include "AppFontManager.h"
#include "GlyphLayoutEngine.h" #include "GlyphLayoutEngine.h"
#include "FontManager.h" #include "GlobalFontManager.h"
#include "truncate_string.h" #include "truncate_string.h"
#include "utf8_functions.h" #include "utf8_functions.h"
@ -272,8 +273,10 @@ ServerFont::SetStyle(FontStyle* style)
\return B_OK if successful, B_ERROR if not \return B_OK if successful, B_ERROR if not
*/ */
status_t status_t
ServerFont::SetFamilyAndStyle(uint16 familyID, uint16 styleID) ServerFont::SetFamilyAndStyle(uint16 familyID, uint16 styleID,
AppFontManager* fontManager)
{ {
BReference<FontStyle> style; BReference<FontStyle> style;
if (gFontManager->Lock()) { if (gFontManager->Lock()) {
@ -282,8 +285,16 @@ ServerFont::SetFamilyAndStyle(uint16 familyID, uint16 styleID)
gFontManager->Unlock(); gFontManager->Unlock();
} }
if (style == NULL) if (style == NULL) {
return B_ERROR; if (fontManager != NULL && fontManager->Lock()) {
style.SetTo(fontManager->GetStyle(familyID, styleID), false);
fontManager->Unlock();
}
if (style == NULL)
return B_ERROR;
}
SetStyle(style); SetStyle(style);
@ -300,12 +311,12 @@ ServerFont::SetFamilyAndStyle(uint16 familyID, uint16 styleID)
\return B_OK if successful, B_ERROR if not \return B_OK if successful, B_ERROR if not
*/ */
status_t status_t
ServerFont::SetFamilyAndStyle(uint32 fontID) ServerFont::SetFamilyAndStyle(uint32 fontID, AppFontManager* fontManager)
{ {
uint16 style = fontID & 0xFFFF; uint16 style = fontID & 0xFFFF;
uint16 family = (fontID & 0xFFFF0000) >> 16; uint16 family = (fontID & 0xFFFF0000) >> 16;
return SetFamilyAndStyle(family, style); return SetFamilyAndStyle(family, style, fontManager);
} }
@ -369,6 +380,9 @@ ServerFont::SetFace(uint16 face)
uint32 uint32
ServerFont::GetFamilyAndStyle() const ServerFont::GetFamilyAndStyle() const
{ {
if (fStyle == NULL || fStyle->Family() == NULL)
return 0;
return (FamilyID() << 16) | StyleID(); return (FamilyID() << 16) | StyleID();
} }
@ -1188,3 +1202,10 @@ ServerFont::EmbeddedTransformation() const
return transform; return transform;
} }
void
ServerFont::SetFontData(FT_Byte* location, uint32 size)
{
if (fStyle != NULL)
fStyle->SetFontData(location, size);
}

View File

@ -15,7 +15,9 @@
#include <Font.h> #include <Font.h>
#include <Rect.h> #include <Rect.h>
#include "AppFontManager.h"
#include "FontFamily.h" #include "FontFamily.h"
#include "FontManager.h"
#include "GlobalSubpixelSettings.h" #include "GlobalSubpixelSettings.h"
#include "Transformable.h" #include "Transformable.h"
@ -69,8 +71,10 @@ class ServerFont {
void SetStyle(FontStyle* style); void SetStyle(FontStyle* style);
status_t SetFamilyAndStyle(uint16 familyID, status_t SetFamilyAndStyle(uint16 familyID,
uint16 styleID); uint16 styleID,
status_t SetFamilyAndStyle(uint32 fontID); AppFontManager* fontManager = NULL);
status_t SetFamilyAndStyle(uint32 fontID,
AppFontManager* fontManager = NULL);
uint16 StyleID() const uint16 StyleID() const
{ return fStyle->ID(); } { return fStyle->ID(); }
@ -167,8 +171,15 @@ class ServerFont {
status_t IncludesUnicodeBlock(uint32 start, uint32 end, status_t IncludesUnicodeBlock(uint32 start, uint32 end,
bool &hasBlock); bool &hasBlock);
void SetFontData(FT_Byte* location, uint32 size);
uint32 FontDataSize() const
{ return fStyle->FontDataSize(); }
FT_Byte* FontData() const
{ return fStyle->FontData(); }
protected: protected:
friend class FontStyle; friend class FontStyle;
FT_Face GetTransformedFace(bool rotate, FT_Face GetTransformedFace(bool rotate,
bool shear) const; bool shear) const;
void PutTransformedFace(FT_Face face) const; void PutTransformedFace(FT_Face face) const;

View File

@ -19,7 +19,7 @@
#include "AlphaMask.h" #include "AlphaMask.h"
#include "DrawingEngine.h" #include "DrawingEngine.h"
#include "DrawState.h" #include "DrawState.h"
#include "FontManager.h" #include "GlobalFontManager.h"
#include "Layer.h" #include "Layer.h"
#include "ServerApp.h" #include "ServerApp.h"
#include "ServerBitmap.h" #include "ServerBitmap.h"

View File

@ -1299,7 +1299,8 @@ fDesktop->LockSingleWindow();
DTRACE(("ServerWindow %s: Message AS_VIEW_SET_FONT_STATE: " DTRACE(("ServerWindow %s: Message AS_VIEW_SET_FONT_STATE: "
"View name: %s\n", fTitle, fCurrentView->Name())); "View name: %s\n", fTitle, fCurrentView->Name()));
fCurrentView->CurrentState()->ReadFontFromLink(link); fCurrentView->CurrentState()->ReadFontFromLink(link,
fServerApp->FontManager());
fWindow->GetDrawingEngine()->SetFont( fWindow->GetDrawingEngine()->SetFont(
fCurrentView->CurrentState()); fCurrentView->CurrentState());
break; break;

View File

@ -0,0 +1,205 @@
/*
* Copyright 2001-2016, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Axel Dörfler, axeld@pinc-software.de
*/
/*! Manages user font families and styles */
#include "AppFontManager.h"
#include <new>
#include <stdint.h>
#include <syslog.h>
#include <Autolock.h>
#include <Debug.h>
#include <Directory.h>
#include <Entry.h>
#include <File.h>
#include <FindDirectory.h>
#include <Message.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <String.h>
#include "FontFamily.h"
#include "FontManager.h"
#include "ServerConfig.h"
#include "ServerFont.h"
#define TRACE_FONT_MANAGER
#ifdef TRACE_FONT_MANAGER
# define FTRACE(x) debug_printf x
#else
# define FTRACE(x) ;
#endif
// #pragma mark -
/*! Sets high id number to avoid collisions with GlobalFontManager
The result of a collision would be that the global font is selected
rather than the application font.
*/
AppFontManager::AppFontManager()
: FontManagerBase(false, "AppFontManager")
{
fNextID = UINT16_MAX;
}
//! Frees all families and styles loaded by the application
AppFontManager::~AppFontManager()
{
while (fFamilies.CountItems() > 0) {
FontFamily* family = fFamilies.ItemAt(0);
while (family->CountStyles() > 0) {
uint16 familyID = family->ID();
uint16 styleID = family->StyleAt(0)->ID();
FontKey fKey(familyID, styleID);
FontStyle* styleRef = fStyleHashTable.Get(fKey);
family->RemoveStyle(styleRef, this);
styleRef->ReleaseReference();
}
fFamilies.RemoveItem(family);
delete family;
}
}
void
AppFontManager::MessageReceived(BMessage* message)
{
FontManagerBase::MessageReceived(message);
}
status_t
AppFontManager::_AddUserFont(FT_Face face, node_ref nodeRef, const char* path,
uint16& familyID, uint16& styleID)
{
FontFamily* family = _FindFamily(face->family_name);
if (family != NULL
&& family->HasStyle(face->style_name)) {
// prevent adding the same style twice
// (this indicates a problem with the installed fonts maybe?)
FT_Done_Face(face);
return B_NAME_IN_USE;
}
if (family == NULL) {
family = new (std::nothrow) FontFamily(face->family_name, fNextID--);
if (family == NULL
|| !fFamilies.BinaryInsert(family, compare_font_families)) {
delete family;
FT_Done_Face(face);
return B_NO_MEMORY;
}
}
FTRACE(("\tadd style: %s, %s\n", face->family_name, face->style_name));
// the FontStyle takes over ownership of the FT_Face object
FontStyle* style = new (std::nothrow) FontStyle(nodeRef, path, face);
if (style == NULL || !family->AddStyle(style, this)) {
delete style;
delete family;
return B_NO_MEMORY;
}
familyID = style->Family()->ID();
styleID = style->ID();
fStyleHashTable.Put(FontKey(familyID, styleID), style);
return B_OK;
}
/*! \brief Adds the FontFamily/FontStyle that is represented by this path.
*/
status_t
AppFontManager::AddUserFontFromFile(const char* path,
uint16& familyID, uint16& styleID)
{
ASSERT(IsLocked());
BEntry entry;
status_t status = entry.SetTo(path);
if (status != B_OK)
return status;
node_ref nodeRef;
status = entry.GetNodeRef(&nodeRef);
if (status < B_OK)
return status;
FT_Face face;
FT_Error error = FT_New_Face(gFreeTypeLibrary, path, 0, &face);
if (error != 0)
return error;
status = _AddUserFont(face, nodeRef, path, familyID, styleID);
return status;
}
/*! \brief Adds the FontFamily/FontStyle that is represented by the area in memory.
*/
status_t
AppFontManager::AddUserFontFromMemory(const FT_Byte* fontAddress, uint32 size,
uint16& familyID, uint16& styleID)
{
ASSERT(IsLocked());
node_ref nodeRef;
status_t status;
FT_Face face;
FT_Error error = FT_New_Memory_Face(gFreeTypeLibrary, fontAddress, size, 0,
&face);
if (error != 0)
return error;
status = _AddUserFont(face, nodeRef, "", familyID, styleID);
return status;
}
/*! \brief Removes the FontFamily/FontStyle from the font manager.
*/
status_t
AppFontManager::RemoveUserFont(uint16 familyID, uint16 styleID)
{
ASSERT(IsLocked());
FontKey fKey(familyID, styleID);
FontStyle* styleRef = fStyleHashTable.Get(fKey);
fStyleHashTable.Remove(fKey);
FontFamily* family = styleRef->Family();
bool removed = family->RemoveStyle(styleRef, this);
if (!removed)
syslog(LOG_DEBUG, "AppFontManager::RemoveUserFont style not removed from family\n");
fFamilies.RemoveItem(family);
delete family;
styleRef->ReleaseReference();
return B_OK;
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2001-2009, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef APP_FONT_MANAGER_H
#define APP_FONT_MANAGER_H
#include "FontManager.h"
#include <AutoDeleter.h>
#include <HashMap.h>
#include <Looper.h>
#include <ObjectList.h>
#include <Referenceable.h>
#include <ft2build.h>
#include FT_FREETYPE_H
class BEntry;
class BPath;
struct node_ref;
class FontFamily;
class FontStyle;
class ServerFont;
// font areas should be less than 20MB
#define MAX_FONT_DATA_SIZE_BYTES 20 * 1024 * 1024
#define MAX_USER_FONTS 128
/*!
\class AppFontManager AppFontManager.h
\brief Manager for application-added fonts in the font subsystem
*/
class AppFontManager : public FontManagerBase {
public:
AppFontManager();
virtual ~AppFontManager();
virtual void MessageReceived(BMessage* message);
status_t AddUserFontFromFile(const char* path,
uint16& familyID, uint16& styleID);
status_t AddUserFontFromMemory(const FT_Byte* fontAddress,
uint32 size, uint16& familyID, uint16& styleID);
status_t RemoveUserFont(uint16 familyID, uint16 styleID);
private:
status_t _AddUserFont(FT_Face face, node_ref nodeRef,
const char* path,
uint16& familyID, uint16& styleID);
private:
int32 fNextID;
};
#endif /* APP_FONT_MANAGER_H */

View File

@ -158,12 +158,20 @@ FontCacheEntry::Init(const ServerFont& font, bool forceVector)
FT_Encoding charMap = FT_ENCODING_NONE; FT_Encoding charMap = FT_ENCODING_NONE;
bool hinting = font.Hinting(); bool hinting = font.Hinting();
if (!fEngine.Init(font.Path(), 0, font.Size(), charMap, bool success;
renderingType, hinting)) { if (font.FontData() != NULL)
success = fEngine.Init(NULL, 0, font.Size(), charMap,
renderingType, hinting, (const void*)font.FontData(), font.FontDataSize());
else
success = fEngine.Init(font.Path(), 0, font.Size(), charMap,
renderingType, hinting);
if (!success) {
fprintf(stderr, "FontCacheEntry::Init() - some error loading font " fprintf(stderr, "FontCacheEntry::Init() - some error loading font "
"file %s\n", font.Path()); "file %s\n", font.Path());
return false; return false;
} }
if (fGlyphCache->Init() != B_OK) { if (fGlyphCache->Init() != B_OK) {
fprintf(stderr, "FontCacheEntry::Init() - failed to allocate " fprintf(stderr, "FontCacheEntry::Init() - failed to allocate "
"GlyphCache table for font file %s\n", font.Path()); "GlyphCache table for font file %s\n", font.Path());

View File

@ -638,7 +638,7 @@ FontEngine::GetKerning(uint32 first, uint32 second, double* x, double* y)
bool bool
FontEngine::Init(const char* fontFilePath, unsigned faceIndex, double size, FontEngine::Init(const char* fontFilePath, unsigned faceIndex, double size,
FT_Encoding charMap, glyph_rendering ren_type, bool hinting, FT_Encoding charMap, glyph_rendering ren_type, bool hinting,
const char* fontFileBuffer, const long fontFileBufferSize) const void* fontFileBuffer, const long fontFileBufferSize)
{ {
if (!fLibraryInitialized) if (!fLibraryInitialized)
return false; return false;

View File

@ -82,7 +82,7 @@ class FontEngine {
FT_Encoding char_map, FT_Encoding char_map,
glyph_rendering ren_type, glyph_rendering ren_type,
bool hinting, bool hinting,
const char* fontFileBuffer = NULL, const void* fontFileBuffer = NULL,
const long fontFileBufferSize = 0); const long fontFileBufferSize = 0);
int LastError() const int LastError() const

View File

@ -12,7 +12,7 @@
#include "FontFamily.h" #include "FontFamily.h"
#include "FontManager.h" #include "GlobalFontManager.h"
#include <FontPrivate.h> #include <FontPrivate.h>
@ -78,6 +78,8 @@ FontFamily::~FontFamily()
// we remove us before deleting the style, so that the font manager // we remove us before deleting the style, so that the font manager
// is not contacted to remove the style from us // is not contacted to remove the style from us
style->_SetFontFamily(NULL, -1); style->_SetFontFamily(NULL, -1);
style->ReleaseReference();
} }
} }
@ -98,7 +100,7 @@ FontFamily::Name() const
\param style pointer to FontStyle object to be added \param style pointer to FontStyle object to be added
*/ */
bool bool
FontFamily::AddStyle(FontStyle *style) FontFamily::AddStyle(FontStyle* style, AppFontManager* fontManager)
{ {
if (!style) if (!style)
return false; return false;
@ -115,6 +117,7 @@ FontFamily::AddStyle(FontStyle *style)
return false; return false;
style->_SetFontFamily(this, fNextID++); style->_SetFontFamily(this, fNextID++);
style->_SetFontManager(fontManager);
// force a refresh if a request for font flags is needed // force a refresh if a request for font flags is needed
fFlags = kInvalidFamilyFlags; fFlags = kInvalidFamilyFlags;
@ -129,9 +132,9 @@ FontFamily::AddStyle(FontStyle *style)
The font style will not be deleted. The font style will not be deleted.
*/ */
bool bool
FontFamily::RemoveStyle(FontStyle* style) FontFamily::RemoveStyle(FontStyle* style, AppFontManager* fontManager)
{ {
if (!gFontManager->IsLocked()) { if (!gFontManager->IsLocked() && fontManager == NULL) {
debugger("FontFamily::RemoveStyle() called without having the font manager locked!"); debugger("FontFamily::RemoveStyle() called without having the font manager locked!");
return false; return false;
} }

View File

@ -13,6 +13,7 @@
#include <ObjectList.h> #include <ObjectList.h>
#include <String.h> #include <String.h>
#include "AppFontManager.h"
#include "FontStyle.h" #include "FontStyle.h"
@ -30,8 +31,10 @@ public:
const char* Name() const; const char* Name() const;
bool AddStyle(FontStyle* style); bool AddStyle(FontStyle* style,
bool RemoveStyle(FontStyle* style); AppFontManager* fontManager = NULL);
bool RemoveStyle(FontStyle* style,
AppFontManager* fontManager = NULL);
FontStyle* GetStyle(const char* style) const; FontStyle* GetStyle(const char* style) const;
FontStyle* GetStyleMatchingFace(uint16 face) const; FontStyle* GetStyleMatchingFace(uint16 face) const;

File diff suppressed because it is too large Load Diff

View File

@ -31,89 +31,55 @@ class ServerFont;
/*! /*!
\class FontManager FontManager.h \class FontManager FontManager.h
\brief Manager for the largest part of the font subsystem \brief Base class interface used by GlobalFontManager and AppFontManager
*/ */
class FontManager : public BLooper { class FontManagerBase : public BLooper {
public: public:
FontManager(); FontManagerBase(bool init_freetype,
virtual ~FontManager(); const char* className = "FontManagerBase");
virtual ~FontManagerBase();
status_t InitCheck() { return fInitStatus; } status_t InitCheck() { return fInitStatus; }
void SaveRecentFontMappings(); void SetInitStatus(status_t new_status)
{ fInitStatus = new_status; }
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
int32 CheckRevision(uid_t user); virtual int32 CountFamilies();
int32 CountFamilies();
int32 CountStyles(const char* family); virtual int32 CountStyles(const char* family);
int32 CountStyles(uint16 familyID); virtual int32 CountStyles(uint16 familyID);
FontFamily* FamilyAt(int32 index) const; FontFamily* FamilyAt(int32 index) const;
FontFamily* GetFamily(uint16 familyID) const; virtual FontFamily* GetFamily(uint16 familyID) const;
FontFamily* GetFamily(const char* name); virtual FontFamily* GetFamily(const char* name);
FontStyle* GetStyleByIndex(const char* family, FontStyle* GetStyleByIndex(const char* family,
int32 index); int32 index);
FontStyle* GetStyleByIndex(uint16 familyID, int32 index); FontStyle* GetStyleByIndex(uint16 familyID, int32 index);
FontStyle* GetStyle(const char* family, const char* style,
uint16 familyID = 0xffff, virtual FontStyle* GetStyle(uint16 familyID,
uint16 styleID = 0xffff, uint16 face = 0);
FontStyle* GetStyle(const char *family, uint16 styleID);
FontStyle* GetStyle(uint16 familyID,
uint16 styleID) const; uint16 styleID) const;
virtual FontStyle* GetStyle(const char* familyName,
const char* styleName,
uint16 familyID = 0xffff,
uint16 styleID = 0xffff,
uint16 face = 0);
FontStyle* FindStyleMatchingFace(uint16 face) const; FontStyle* FindStyleMatchingFace(uint16 face) const;
void RemoveStyle(FontStyle* style); void RemoveStyle(FontStyle* style);
// This call must not be used by anything else than class // This call must not be used by anything else than class
// FontStyle. // FontStyle.
const ServerFont* DefaultPlainFont() const;
const ServerFont* DefaultBoldFont() const;
const ServerFont* DefaultFixedFont() const;
void AttachUser(uid_t userID);
void DetachUser(uid_t userID);
private:
struct font_directory;
struct font_mapping;
void _AddDefaultMapping(const char* family,
const char* style, const char* path);
bool _LoadRecentFontMappings();
status_t _AddMappedFont(const char* family,
const char* style = NULL);
FontStyle* _GetDefaultStyle(const char* familyName,
const char* styleName,
const char* fallbackFamily,
const char* fallbackStyle,
uint16 fallbackFace);
status_t _SetDefaultFonts();
void _PrecacheFontFile(const ServerFont* font);
void _AddSystemPaths();
font_directory* _FindDirectory(node_ref& nodeRef);
void _RemoveDirectory(font_directory* directory);
status_t _CreateDirectories(const char* path);
status_t _AddPath(const char* path);
status_t _AddPath(BEntry& entry,
font_directory** _newDirectory = NULL);
void _RemoveStyle(font_directory& directory,
FontStyle* style);
void _RemoveStyle(dev_t device, uint64 directory,
uint64 node);
FontFamily* _FindFamily(const char* family) const;
void _ScanFontsIfNecessary();
void _ScanFonts();
status_t _ScanFontDirectory(font_directory& directory);
status_t _AddFont(font_directory& directory,
BEntry& entry);
FT_CharMap _GetSupportedCharmap(const FT_Face& face); FT_CharMap _GetSupportedCharmap(const FT_Face& face);
private: protected:
FontFamily* _FindFamily(const char* family) const;
static int compare_font_families(const FontFamily* a,
const FontFamily* b);
struct FontKey { struct FontKey {
FontKey(uint16 family, uint16 style) FontKey(uint16 family, uint16 style)
: familyID(family), styleID(style) {} : familyID(family), styleID(style) {}
@ -132,31 +98,17 @@ private:
uint16 familyID, styleID; uint16 familyID, styleID;
}; };
private:
status_t fInitStatus; status_t fInitStatus;
typedef BObjectList<font_directory> DirectoryList;
typedef BObjectList<font_mapping> MappingList;
typedef BObjectList<FontFamily> FamilyList; typedef BObjectList<FontFamily> FamilyList;
DirectoryList fDirectories;
MappingList fMappings;
FamilyList fFamilies; FamilyList fFamilies;
HashMap<FontKey, BReference<FontStyle> > fStyleHashTable; HashMap<FontKey, BReference<FontStyle> > fStyleHashTable;
ObjectDeleter<ServerFont> uint16 fNextID;
fDefaultPlainFont; bool fHasFreetypeLibrary;
ObjectDeleter<ServerFont>
fDefaultBoldFont;
ObjectDeleter<ServerFont>
fDefaultFixedFont;
bool fScanned;
int32 fNextID;
}; };
extern FT_Library gFreeTypeLibrary; extern FT_Library gFreeTypeLibrary;
extern FontManager* gFontManager;
#endif /* FONT_MANAGER_H */ #endif /* FONT_MANAGER_H */

View File

@ -12,7 +12,7 @@
#include "FontFamily.h" #include "FontFamily.h"
#include "ServerFont.h" #include "ServerFont.h"
#include "FontManager.h" #include "GlobalFontManager.h"
#include <FontPrivate.h> #include <FontPrivate.h>
@ -38,7 +38,8 @@ FontStyle::FontStyle(node_ref& nodeRef, const char* path, FT_Face face)
fID(0), fID(0),
fBounds(0, 0, 0, 0), fBounds(0, 0, 0, 0),
fFace(_TranslateStyleToFace(face->style_name)), fFace(_TranslateStyleToFace(face->style_name)),
fFullAndHalfFixed(false) fFullAndHalfFixed(false),
fFontData(NULL)
{ {
fName.Truncate(B_FONT_STYLE_LENGTH); fName.Truncate(B_FONT_STYLE_LENGTH);
// make sure this style can be found using the Be API // make sure this style can be found using the Be API
@ -93,12 +94,20 @@ FontStyle::FontStyle(node_ref& nodeRef, const char* path, FT_Face face)
FontStyle::~FontStyle() FontStyle::~FontStyle()
{ {
// make sure the font server is ours // make sure the font server is ours
if (fFamily != NULL && gFontManager->Lock()) { if (fFamily != NULL) {
gFontManager->RemoveStyle(this); if (fFontManager != NULL && fFontManager->Lock()) {
gFontManager->Unlock(); fFontManager->RemoveStyle(this);
fFontManager->Unlock();
} else if (gFontManager->Lock()) {
gFontManager->RemoveStyle(this);
gFontManager->Unlock();
}
} }
FT_Done_Face(fFreeTypeFace); FT_Done_Face(fFreeTypeFace);
if (fFontData != NULL)
free(fFontData);
} }
@ -260,3 +269,13 @@ FontStyle::_TranslateStyleToFace(const char* name) const
} }
void
FontStyle::SetFontData(FT_Byte* location, uint32 size)
{
// if memory was already allocated here, we should free it so it's not leaked
if (fFontData != NULL)
free(fFontData);
fFontDataSize = size;
fFontData = location;
}

View File

@ -22,8 +22,11 @@
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include "AppFontManager.h"
struct node_ref; struct node_ref;
class AppFontManager;
class FontFamily; class FontFamily;
class ServerFont; class ServerFont;
@ -131,11 +134,19 @@ class FontStyle : public BReferenceable {
status_t UpdateFace(FT_Face face); status_t UpdateFace(FT_Face face);
uint32 FontDataSize() const
{ return fFontDataSize; }
void SetFontData(FT_Byte* location, uint32 size);
FT_Byte* FontData() const
{ return fFontData; }
private: private:
friend class FontFamily; friend class FontFamily;
uint16 _TranslateStyleToFace(const char *name) const; uint16 _TranslateStyleToFace(const char *name) const;
void _SetFontFamily(FontFamily* family, uint16 id); void _SetFontFamily(FontFamily* family, uint16 id);
void _SetFontManager(AppFontManager* fontManager)
{ fFontManager = fontManager; }
private: private:
FT_Face fFreeTypeFace; FT_Face fFreeTypeFace;
BString fName; BString fName;
@ -150,6 +161,10 @@ class FontStyle : public BReferenceable {
font_height fHeight; font_height fHeight;
uint16 fFace; uint16 fFace;
bool fFullAndHalfFixed; bool fFullAndHalfFixed;
FT_Byte* fFontData;
uint32 fFontDataSize;
AppFontManager* fFontManager;
}; };
#endif // FONT_STYLE_H_ #endif // FONT_STYLE_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
/*
* Copyright 2001-2009, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef GLOBAL_FONT_MANAGER_H
#define GLOBAL_FONT_MANAGER_H
#include "FontManager.h"
#include <AutoDeleter.h>
#include <HashMap.h>
#include <Looper.h>
#include <ObjectList.h>
#include <Referenceable.h>
#include <ft2build.h>
#include FT_FREETYPE_H
class BEntry;
class BPath;
struct node_ref;
class FontFamily;
class FontStyle;
class ServerFont;
/*!
\class GlobalFontManager GlobalFontManager.h
\brief Manager for system fonts within the font subsystem
*/
class GlobalFontManager : public FontManagerBase {
public:
GlobalFontManager();
virtual ~GlobalFontManager();
void SaveRecentFontMappings();
virtual void MessageReceived(BMessage* message);
virtual int32 CountFamilies();
virtual int32 CountStyles(const char* family);
virtual int32 CountStyles(uint16 familyID);
int32 CheckRevision(uid_t user);
const ServerFont* DefaultPlainFont() const;
const ServerFont* DefaultBoldFont() const;
const ServerFont* DefaultFixedFont() const;
void AttachUser(uid_t userID);
void DetachUser(uid_t userID);
virtual FontFamily* GetFamily(uint16 familyID) const;
virtual FontFamily* GetFamily(const char* name);
virtual FontStyle* GetStyle(uint16 familyID,
uint16 styleID) const;
virtual FontStyle* GetStyle(const char* familyName,
const char* styleName,
uint16 familyID = 0xffff,
uint16 styleID = 0xffff,
uint16 face = 0);
private:
struct font_directory;
struct font_mapping;
void _AddDefaultMapping(const char* family,
const char* style, const char* path);
bool _LoadRecentFontMappings();
status_t _AddMappedFont(const char* family,
const char* style = NULL);
void _PrecacheFontFile(const ServerFont* font);
void _AddSystemPaths();
font_directory* _FindDirectory(node_ref& nodeRef);
void _RemoveDirectory(font_directory* directory);
status_t _CreateDirectories(const char* path);
status_t _AddPath(const char* path);
status_t _AddPath(BEntry& entry,
font_directory** _newDirectory = NULL);
void _ScanFontsIfNecessary();
void _ScanFonts();
status_t _ScanFontDirectory(font_directory& directory);
status_t _AddFont(font_directory& directory,
BEntry& entry);
void _RemoveStyle(font_directory& directory,
FontStyle* style);
void _RemoveStyle(dev_t device, uint64 directory,
uint64 node);
FontStyle* _GetDefaultStyle(const char* familyName,
const char* styleName,
const char* fallbackFamily,
const char* fallbackStyle,
uint16 fallbackFace);
status_t _SetDefaultFonts();
private:
status_t fInitStatus;
typedef BObjectList<font_directory> DirectoryList;
typedef BObjectList<font_mapping> MappingList;
DirectoryList fDirectories;
MappingList fMappings;
ObjectDeleter<ServerFont>
fDefaultPlainFont;
ObjectDeleter<ServerFont>
fDefaultBoldFont;
ObjectDeleter<ServerFont>
fDefaultFixedFont;
bool fScanned;
};
extern GlobalFontManager* gFontManager;
extern FT_Library gFreeTypeLibrary;
#endif /* GLOBAL_FONT_MANAGER_H */

View File

@ -13,7 +13,7 @@
#include "FontCache.h" #include "FontCache.h"
#include "FontCacheEntry.h" #include "FontCacheEntry.h"
#include "FontManager.h" #include "GlobalFontManager.h"
#include "ServerFont.h" #include "ServerFont.h"
#include <Autolock.h> #include <Autolock.h>