1 /* 2 * Copyright 2001-2008, 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 /** Classes to represent font styles and families */ 11 12 13 #include "FontFamily.h" 14 #include "ServerFont.h" 15 #include "FontManager.h" 16 17 #include <FontPrivate.h> 18 19 #include <Entry.h> 20 21 22 static BLocker sFontLock("font lock"); 23 24 25 /*! 26 \brief Constructor 27 \param filepath path to a font file 28 \param face FreeType handle for the font file after it is loaded - it will 29 be kept open until the FontStyle is destroyed 30 */ 31 FontStyle::FontStyle(node_ref& nodeRef, const char* path, FT_Face face) 32 : 33 fFreeTypeFace(face), 34 fName(face->style_name), 35 fPath(path), 36 fNodeRef(nodeRef), 37 fFamily(NULL), 38 fID(0), 39 fBounds(0, 0, 0, 0), 40 fFace(_TranslateStyleToFace(face->style_name)) 41 { 42 fName.Truncate(B_FONT_STYLE_LENGTH); 43 // make sure this style can be found using the Be API 44 45 fHeight.ascent = (double)face->ascender / face->units_per_EM; 46 fHeight.descent = (double)-face->descender / face->units_per_EM; 47 // FT2's descent numbers are negative. Be's is positive 48 49 // FT2 doesn't provide a linegap, but according to the docs, we can 50 // calculate it because height = ascending + descending + leading 51 fHeight.leading = (double)(face->height - face->ascender + face->descender) 52 / face->units_per_EM; 53 } 54 55 56 FontStyle::~FontStyle() 57 { 58 // make sure the font server is ours 59 if (fFamily != NULL && gFontManager->Lock()) { 60 gFontManager->RemoveStyle(this); 61 gFontManager->Unlock(); 62 } 63 64 FT_Done_Face(fFreeTypeFace); 65 } 66 67 68 uint32 69 FontStyle::Hash() const 70 { 71 return (ID() << 16) | fFamily->ID(); 72 } 73 74 75 bool 76 FontStyle::CompareTo(Hashable& other) const 77 { 78 // our hash values are unique (unless you have more than 65536 font 79 // families installed...) 80 return Hash() == other.Hash(); 81 } 82 83 84 bool 85 FontStyle::Lock() 86 { 87 return sFontLock.Lock(); 88 } 89 90 91 void 92 FontStyle::Unlock() 93 { 94 sFontLock.Unlock(); 95 } 96 97 98 void 99 FontStyle::GetHeight(float size, font_height& height) const 100 { 101 height.ascent = fHeight.ascent * size; 102 height.descent = fHeight.descent * size; 103 height.leading = fHeight.leading * size; 104 } 105 106 107 /*! 108 \brief Returns the path to the style's font file 109 \return The style's font file path 110 */ 111 const char* 112 FontStyle::Path() const 113 { 114 return fPath.Path(); 115 } 116 117 118 /*! 119 \brief Updates the path of the font style in case the style 120 has been moved around. 121 */ 122 void 123 FontStyle::UpdatePath(const node_ref& parentNodeRef) 124 { 125 entry_ref ref; 126 ref.device = parentNodeRef.device; 127 ref.directory = parentNodeRef.node; 128 ref.set_name(fPath.Leaf()); 129 130 fPath.SetTo(&ref); 131 } 132 133 134 /*! 135 \brief Unlike BFont::Flags() this returns the extra flags field as used 136 in the private part of BFont. 137 */ 138 uint32 139 FontStyle::Flags() const 140 { 141 uint32 flags = uint32(Direction()) << B_PRIVATE_FONT_DIRECTION_SHIFT; 142 143 if (IsFixedWidth()) 144 flags |= B_IS_FIXED; 145 if (IsFullAndHalfFixed()) 146 flags |= B_PRIVATE_FONT_IS_FULL_AND_HALF_FIXED; 147 if (TunedCount() > 0) 148 flags |= B_HAS_TUNED_FONT; 149 if (HasKerning()) 150 flags |= B_PRIVATE_FONT_HAS_KERNING; 151 152 return flags; 153 } 154 155 156 /*! 157 \brief Updates the given face to match the one from this style 158 159 The specified font face often doesn't match the exact face of 160 a style. This method will preserve the attributes of the face 161 that this style does not alter, and will only update the 162 attributes that matter to this style. 163 The font renderer could then emulate the other face attributes 164 taking this style as a base. 165 */ 166 uint16 167 FontStyle::PreservedFace(uint16 face) const 168 { 169 // TODO: make this better 170 face &= ~(B_REGULAR_FACE | B_BOLD_FACE | B_ITALIC_FACE); 171 face |= Face(); 172 173 return face; 174 } 175 176 177 status_t 178 FontStyle::UpdateFace(FT_Face face) 179 { 180 if (!sFontLock.IsLocked()) { 181 debugger("UpdateFace() called without having locked FontStyle!"); 182 return B_ERROR; 183 } 184 185 // we only accept the face if it hasn't change its style 186 187 BString name = face->style_name; 188 name.Truncate(B_FONT_STYLE_LENGTH); 189 190 if (name != fName) 191 return B_BAD_VALUE; 192 193 FT_Done_Face(fFreeTypeFace); 194 fFreeTypeFace = face; 195 return B_OK; 196 } 197 198 199 void 200 FontStyle::_SetFontFamily(FontFamily* family, uint16 id) 201 { 202 fFamily = family; 203 fID = id; 204 } 205 206 207 uint16 208 FontStyle::_TranslateStyleToFace(const char* name) const 209 { 210 if (name == NULL) 211 return 0; 212 213 BString string(name); 214 uint16 face = 0; 215 216 if (string.IFindFirst("bold") >= 0) 217 face |= B_BOLD_FACE; 218 219 if (string.IFindFirst("italic") >= 0 220 || string.IFindFirst("oblique") >= 0) 221 face |= B_ITALIC_FACE; 222 223 if (string.IFindFirst("condensed") >= 0) 224 face |= B_CONDENSED_FACE; 225 226 if (string.IFindFirst("light") >= 0 227 || string.IFindFirst("thin") >= 0) 228 face |= B_LIGHT_FACE; 229 230 if (string.IFindFirst("heavy") >= 0 231 || string.IFindFirst("black") >= 0) 232 face |= B_HEAVY_FACE; 233 234 if (face == 0) 235 return B_REGULAR_FACE; 236 237 return face; 238 } 239 240 241