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