2 * Copyright 2001-2008, Haiku.
3 * Distributed under the terms of the MIT License.
6 * DarkWyrm <bpmagic@columbus.rr.com>
7 * Axel Dörfler, axeld@pinc-software.de
10 /** Classes to represent font styles and families */
13 #include "FontFamily.h"
15 #include "FontManager.h"
17 #include <FontPrivate.h>
20 const uint32 kInvalidFamilyFlags
= ~(uint32
)0;
24 font_score(const FontStyle
* style
)
27 if (style
->Face() & B_REGULAR_FACE
)
30 if (style
->Face() & B_BOLD_FACE
)
32 if (style
->Face() & B_ITALIC_FACE
)
41 compare_font_styles(const FontStyle
* a
, const FontStyle
* b
)
43 // Regular fonts come first, then bold, then italics
44 return font_score(b
) - font_score(a
);
53 \param namestr Name of the family
55 FontFamily::FontFamily(const char *name
, uint16 id
)
60 fFlags(kInvalidFamilyFlags
)
62 fName
.Truncate(B_FONT_FAMILY_LENGTH
);
63 // make sure this family can be found using the Be API
70 Deletes all attached styles. Note that a FontFamily must only be deleted
73 FontFamily::~FontFamily()
75 for (int32 i
= fStyles
.CountItems(); i
-- > 0;) {
76 FontStyle
* style
= fStyles
.RemoveItemAt(i
);
78 // we remove us before deleting the style, so that the font manager
79 // is not contacted to remove the style from us
80 style
->_SetFontFamily(NULL
, -1);
87 \brief Returns the name of the family
88 \return The family's name
91 FontFamily::Name() const
93 return fName
.String();
98 \brief Adds the style to the family
99 \param style pointer to FontStyle object to be added
102 FontFamily::AddStyle(FontStyle
*style
)
107 // Don't add if it already is in the family.
108 int32 count
= fStyles
.CountItems();
109 for (int32 i
= 0; i
< count
; i
++) {
110 FontStyle
*item
= fStyles
.ItemAt(i
);
111 if (!strcmp(item
->Name(), style
->Name()))
115 if (!fStyles
.BinaryInsert(style
, compare_font_styles
))
118 style
->_SetFontFamily(this, fNextID
++);
120 // force a refresh if a request for font flags is needed
121 fFlags
= kInvalidFamilyFlags
;
128 \brief Removes a style from the family.
130 The font style will not be deleted.
133 FontFamily::RemoveStyle(FontStyle
* style
)
135 if (!gFontManager
->IsLocked()) {
136 debugger("FontFamily::RemoveStyle() called without having the font manager locked!");
140 if (!fStyles
.RemoveItem(style
))
143 style
->_SetFontFamily(NULL
, -1);
145 // force a refresh if a request for font flags is needed
146 fFlags
= kInvalidFamilyFlags
;
152 \brief Returns the number of styles in the family
153 \return The number of styles in the family
156 FontFamily::CountStyles() const
158 return fStyles
.CountItems();
163 FontFamily::_FindStyle(const char* name
) const
165 int32 count
= fStyles
.CountItems();
166 if (!name
|| count
< 1)
169 for (int32 i
= 0; i
< count
; i
++) {
170 FontStyle
*style
= fStyles
.ItemAt(i
);
171 if (!strcmp(style
->Name(), name
))
180 \brief Determines whether the style belongs to the family
181 \param style Name of the style being checked
182 \return True if it belongs, false if not
185 FontFamily::HasStyle(const char *styleName
) const
187 return _FindStyle(styleName
) != NULL
;
192 \brief Returns the name of a style in the family
193 \param index list index of the style to be found
194 \return name of the style or NULL if the index is not valid
197 FontFamily::StyleAt(int32 index
) const
199 return fStyles
.ItemAt(index
);
204 \brief Get the FontStyle object for the name given
205 \param style Name of the style to be obtained
206 \return The FontStyle object or NULL if none was found.
208 The object returned belongs to the family and must not be deleted.
211 FontFamily::GetStyle(const char *name
) const
213 if (name
== NULL
|| !name
[0])
216 FontStyle
* style
= _FindStyle(name
);
220 // try alternative names
222 if (!strcmp(name
, "Roman") || !strcmp(name
, "Regular")
223 || !strcmp(name
, "Book")) {
224 style
= _FindStyle("Roman");
226 style
= _FindStyle("Regular");
228 style
= _FindStyle("Book");
233 BString alternative
= name
;
234 if (alternative
.FindFirst("Italic") >= 0) {
235 alternative
.ReplaceFirst("Italic", "Oblique");
236 return _FindStyle(alternative
.String());
238 if (alternative
.FindFirst("Oblique") >= 0) {
239 alternative
.ReplaceFirst("Oblique", "Italic");
240 return _FindStyle(alternative
.String());
248 FontFamily::GetStyleByID(uint16 id
) const
250 int32 count
= fStyles
.CountItems();
251 for (int32 i
= 0; i
< count
; i
++) {
252 FontStyle
* style
= fStyles
.ItemAt(i
);
253 if (style
->ID() == id
)
262 FontFamily::GetStyleMatchingFace(uint16 face
) const
264 // TODO: support other faces (strike through, underlined, outlines...)
265 face
&= B_BOLD_FACE
| B_ITALIC_FACE
| B_REGULAR_FACE
| B_CONDENSED_FACE
266 | B_LIGHT_FACE
| B_HEAVY_FACE
;
268 int32 count
= fStyles
.CountItems();
269 for (int32 i
= 0; i
< count
; i
++) {
270 FontStyle
* style
= fStyles
.ItemAt(i
);
272 if (style
->Face() == face
)
283 if (fFlags
== kInvalidFamilyFlags
) {
286 int32 count
= fStyles
.CountItems();
287 for (int32 i
= 0; i
< count
; i
++) {
288 FontStyle
* style
= fStyles
.ItemAt(i
);
290 if (style
->IsFixedWidth())
291 fFlags
|= B_IS_FIXED
;
292 if (style
->IsFullAndHalfFixed())
293 fFlags
|= B_PRIVATE_FONT_IS_FULL_AND_HALF_FIXED
;
294 if (style
->TunedCount() > 0)
295 fFlags
|= B_HAS_TUNED_FONT
;