xref: /haiku/src/servers/app/font/AppFontManager.cpp (revision 52c4471a3024d2eb81fe88e2c3982b9f8daa5e56)
1 /*
2  * Copyright 2001-2016, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  *		Axel Dörfler, axeld@pinc-software.de
8  */
9 
10 
11 /*!	Manages user font families and styles */
12 
13 
14 #include "AppFontManager.h"
15 
16 #include <new>
17 #include <stdint.h>
18 #include <syslog.h>
19 
20 #include <Autolock.h>
21 #include <Debug.h>
22 #include <Directory.h>
23 #include <Entry.h>
24 #include <File.h>
25 #include <FindDirectory.h>
26 #include <Message.h>
27 #include <NodeMonitor.h>
28 #include <Path.h>
29 #include <String.h>
30 
31 #include "FontFamily.h"
32 #include "FontManager.h"
33 #include "ServerConfig.h"
34 #include "ServerFont.h"
35 
36 
37 #define TRACE_FONT_MANAGER
38 #ifdef TRACE_FONT_MANAGER
39 #	define FTRACE(x) debug_printf x
40 #else
41 #	define FTRACE(x) ;
42 #endif
43 
44 
45 //	#pragma mark -
46 
47 
48 /*! Sets high id number to avoid collisions with GlobalFontManager
49 	The result of a collision would be that the global font is selected
50 	rather than the application font.
51 */
52 AppFontManager::AppFontManager()
53 	: FontManagerBase(false, "AppFontManager")
54 {
55 	fNextID = UINT16_MAX;
56 }
57 
58 
59 //! Frees all families and styles loaded by the application
60 AppFontManager::~AppFontManager()
61 {
62 	while (fFamilies.CountItems() > 0) {
63 		FontFamily* family = fFamilies.ItemAt(0);
64 		while (family->CountStyles() > 0) {
65 			uint16 familyID = family->ID();
66 			uint16 styleID = family->StyleAt(0)->ID();
67 			FontKey fKey(familyID, styleID);
68 			FontStyle* styleRef = fStyleHashTable.Get(fKey);
69 			family->RemoveStyle(styleRef, this);
70 			styleRef->ReleaseReference();
71 		}
72 
73 		fFamilies.RemoveItem(family);
74 		delete family;
75 	}
76 }
77 
78 
79 void
80 AppFontManager::MessageReceived(BMessage* message)
81 {
82 	FontManagerBase::MessageReceived(message);
83 }
84 
85 
86 status_t
87 AppFontManager::_AddUserFont(FT_Face face, node_ref nodeRef, const char* path,
88 	uint16& familyID, uint16& styleID)
89 {
90 	FontFamily* family = _FindFamily(face->family_name);
91 	if (family != NULL
92 		&& family->HasStyle(face->style_name)) {
93 		// prevent adding the same style twice
94 		// (this indicates a problem with the installed fonts maybe?)
95 		FT_Done_Face(face);
96 		return B_NAME_IN_USE;
97 	}
98 
99 	if (family == NULL) {
100 		family = new (std::nothrow) FontFamily(face->family_name, fNextID--);
101 
102 		if (family == NULL
103 			|| !fFamilies.BinaryInsert(family, compare_font_families)) {
104 			delete family;
105 			FT_Done_Face(face);
106 			return B_NO_MEMORY;
107 		}
108 	}
109 
110 	FTRACE(("\tadd style: %s, %s\n", face->family_name, face->style_name));
111 
112 	// the FontStyle takes over ownership of the FT_Face object
113 	FontStyle* style = new (std::nothrow) FontStyle(nodeRef, path, face);
114 
115 	if (style == NULL || !family->AddStyle(style, this)) {
116 		delete style;
117 		delete family;
118 		return B_NO_MEMORY;
119 	}
120 
121 	familyID = style->Family()->ID();
122 	styleID = style->ID();
123 
124 	fStyleHashTable.Put(FontKey(familyID, styleID), style);
125 
126 	return B_OK;
127 }
128 
129 
130 /*!	\brief Adds the FontFamily/FontStyle that is represented by this path.
131 */
132 status_t
133 AppFontManager::AddUserFontFromFile(const char* path,
134 	uint16& familyID, uint16& styleID)
135 {
136 	ASSERT(IsLocked());
137 
138 	BEntry entry;
139 	status_t status = entry.SetTo(path);
140 	if (status != B_OK)
141 		return status;
142 
143 	node_ref nodeRef;
144 	status = entry.GetNodeRef(&nodeRef);
145 	if (status < B_OK)
146 		return status;
147 
148 	FT_Face face;
149 	FT_Error error = FT_New_Face(gFreeTypeLibrary, path, 0, &face);
150 	if (error != 0)
151 		return error;
152 
153 	status = _AddUserFont(face, nodeRef, path, familyID, styleID);
154 
155 	return status;
156 }
157 
158 
159 /*!	\brief Adds the FontFamily/FontStyle that is represented by the area in memory.
160 */
161 status_t
162 AppFontManager::AddUserFontFromMemory(const FT_Byte* fontAddress, uint32 size,
163 	uint16& familyID, uint16& styleID)
164 {
165 	ASSERT(IsLocked());
166 
167 	node_ref nodeRef;
168 	status_t status;
169 
170 	FT_Face face;
171 	FT_Error error = FT_New_Memory_Face(gFreeTypeLibrary, fontAddress, size, 0,
172 		&face);
173 	if (error != 0)
174 		return error;
175 
176 	status = _AddUserFont(face, nodeRef, "", familyID, styleID);
177 
178 	return status;
179 }
180 
181 
182 /*!	\brief Removes the FontFamily/FontStyle from the font manager.
183 */
184 status_t
185 AppFontManager::RemoveUserFont(uint16 familyID, uint16 styleID)
186 {
187 	ASSERT(IsLocked());
188 
189 	FontKey fKey(familyID, styleID);
190 	FontStyle* styleRef = fStyleHashTable.Get(fKey);
191 	fStyleHashTable.Remove(fKey);
192 
193 	FontFamily* family = styleRef->Family();
194 	bool removed = family->RemoveStyle(styleRef, this);
195 
196 	if (!removed)
197 		syslog(LOG_DEBUG, "AppFontManager::RemoveUserFont style not removed from family\n");
198 
199 	fFamilies.RemoveItem(family);
200 	delete family;
201 
202 	styleRef->ReleaseReference();
203 
204 	return B_OK;
205 }
206