1f4f30311SClemens Zeidler /*
2f4f30311SClemens Zeidler * Copyright 2001-2008, Haiku.
3f4f30311SClemens Zeidler * Distributed under the terms of the MIT License.
4f4f30311SClemens Zeidler *
5f4f30311SClemens Zeidler * Authors:
6f4f30311SClemens Zeidler * DarkWyrm <bpmagic@columbus.rr.com>
7f4f30311SClemens Zeidler * Axel Dörfler, axeld@pinc-software.de
8f4f30311SClemens Zeidler */
9f4f30311SClemens Zeidler
10f4f30311SClemens Zeidler /** Classes to represent font styles and families */
11f4f30311SClemens Zeidler
12f4f30311SClemens Zeidler
13f4f30311SClemens Zeidler #include "FontFamily.h"
14f4f30311SClemens Zeidler
15f4f30311SClemens Zeidler #include <FontPrivate.h>
16f4f30311SClemens Zeidler
17f4f30311SClemens Zeidler
183fed1a15SAlex Smith const uint32 kInvalidFamilyFlags = ~(uint32)0;
19f4f30311SClemens Zeidler
20f4f30311SClemens Zeidler
21f4f30311SClemens Zeidler static int
font_score(const FontStyle * style)22f4f30311SClemens Zeidler font_score(const FontStyle* style)
23f4f30311SClemens Zeidler {
24f4f30311SClemens Zeidler int score = 0;
25f4f30311SClemens Zeidler if (style->Face() & B_REGULAR_FACE)
26f4f30311SClemens Zeidler score += 10;
27f4f30311SClemens Zeidler else {
28f4f30311SClemens Zeidler if (style->Face() & B_BOLD_FACE)
29f4f30311SClemens Zeidler score += 5;
30f4f30311SClemens Zeidler if (style->Face() & B_ITALIC_FACE)
31f4f30311SClemens Zeidler score--;
32f4f30311SClemens Zeidler }
33f4f30311SClemens Zeidler
34f4f30311SClemens Zeidler return score;
35f4f30311SClemens Zeidler }
36f4f30311SClemens Zeidler
37f4f30311SClemens Zeidler
38f4f30311SClemens Zeidler static int
compare_font_styles(const FontStyle * a,const FontStyle * b)39f4f30311SClemens Zeidler compare_font_styles(const FontStyle* a, const FontStyle* b)
40f4f30311SClemens Zeidler {
41f4f30311SClemens Zeidler // Regular fonts come first, then bold, then italics
42f4f30311SClemens Zeidler return font_score(b) - font_score(a);
43f4f30311SClemens Zeidler }
44f4f30311SClemens Zeidler
45f4f30311SClemens Zeidler
46f4f30311SClemens Zeidler // #pragma mark -
47f4f30311SClemens Zeidler
48f4f30311SClemens Zeidler
49f4f30311SClemens Zeidler /*!
50f4f30311SClemens Zeidler \brief Constructor
51f4f30311SClemens Zeidler \param namestr Name of the family
52f4f30311SClemens Zeidler */
FontFamily(const char * name,uint16 id)53f4f30311SClemens Zeidler FontFamily::FontFamily(const char *name, uint16 id)
54f4f30311SClemens Zeidler :
55f4f30311SClemens Zeidler fName(name),
56f4f30311SClemens Zeidler fID(id),
57f4f30311SClemens Zeidler fNextID(0),
58f4f30311SClemens Zeidler fFlags(kInvalidFamilyFlags)
59f4f30311SClemens Zeidler {
60f4f30311SClemens Zeidler fName.Truncate(B_FONT_FAMILY_LENGTH);
61f4f30311SClemens Zeidler // make sure this family can be found using the Be API
62f4f30311SClemens Zeidler }
63f4f30311SClemens Zeidler
64f4f30311SClemens Zeidler
65f4f30311SClemens Zeidler /*!
66f4f30311SClemens Zeidler \brief Returns the name of the family
67f4f30311SClemens Zeidler \return The family's name
68f4f30311SClemens Zeidler */
69f4f30311SClemens Zeidler const char*
Name() const70f4f30311SClemens Zeidler FontFamily::Name() const
71f4f30311SClemens Zeidler {
72f4f30311SClemens Zeidler return fName.String();
73f4f30311SClemens Zeidler }
74f4f30311SClemens Zeidler
75f4f30311SClemens Zeidler
76f4f30311SClemens Zeidler /*!
77f4f30311SClemens Zeidler \brief Adds the style to the family
78f4f30311SClemens Zeidler \param style pointer to FontStyle object to be added
79f4f30311SClemens Zeidler */
80f4f30311SClemens Zeidler bool
AddStyle(FontStyle * style)81*85d52d33SMáximo Castañeda FontFamily::AddStyle(FontStyle* style)
82f4f30311SClemens Zeidler {
83f4f30311SClemens Zeidler if (!style)
84f4f30311SClemens Zeidler return false;
85f4f30311SClemens Zeidler
86f4f30311SClemens Zeidler // Don't add if it already is in the family.
87f4f30311SClemens Zeidler int32 count = fStyles.CountItems();
88f4f30311SClemens Zeidler for (int32 i = 0; i < count; i++) {
89f4f30311SClemens Zeidler FontStyle *item = fStyles.ItemAt(i);
90f4f30311SClemens Zeidler if (!strcmp(item->Name(), style->Name()))
91f4f30311SClemens Zeidler return false;
92f4f30311SClemens Zeidler }
93f4f30311SClemens Zeidler
94f4f30311SClemens Zeidler if (!fStyles.BinaryInsert(style, compare_font_styles))
95f4f30311SClemens Zeidler return false;
96f4f30311SClemens Zeidler
97f4f30311SClemens Zeidler style->_SetFontFamily(this, fNextID++);
98f4f30311SClemens Zeidler
99f4f30311SClemens Zeidler // force a refresh if a request for font flags is needed
100f4f30311SClemens Zeidler fFlags = kInvalidFamilyFlags;
101f4f30311SClemens Zeidler
102f4f30311SClemens Zeidler return true;
103f4f30311SClemens Zeidler }
104f4f30311SClemens Zeidler
105f4f30311SClemens Zeidler
106f4f30311SClemens Zeidler /*!
107f4f30311SClemens Zeidler \brief Removes a style from the family.
108f4f30311SClemens Zeidler
109f4f30311SClemens Zeidler The font style will not be deleted.
110f4f30311SClemens Zeidler */
111f4f30311SClemens Zeidler bool
RemoveStyle(FontStyle * style)112*85d52d33SMáximo Castañeda FontFamily::RemoveStyle(FontStyle* style)
113f4f30311SClemens Zeidler {
1144f52a155SDale Cieslak if (style == NULL)
1154f52a155SDale Cieslak return false;
1164f52a155SDale Cieslak
117f4f30311SClemens Zeidler if (!fStyles.RemoveItem(style))
118f4f30311SClemens Zeidler return false;
119f4f30311SClemens Zeidler
120f4f30311SClemens Zeidler // force a refresh if a request for font flags is needed
121f4f30311SClemens Zeidler fFlags = kInvalidFamilyFlags;
122f4f30311SClemens Zeidler return true;
123f4f30311SClemens Zeidler }
124f4f30311SClemens Zeidler
125f4f30311SClemens Zeidler
126f4f30311SClemens Zeidler /*!
127f4f30311SClemens Zeidler \brief Returns the number of styles in the family
128f4f30311SClemens Zeidler \return The number of styles in the family
129f4f30311SClemens Zeidler */
130f4f30311SClemens Zeidler int32
CountStyles() const131f4f30311SClemens Zeidler FontFamily::CountStyles() const
132f4f30311SClemens Zeidler {
133f4f30311SClemens Zeidler return fStyles.CountItems();
134f4f30311SClemens Zeidler }
135f4f30311SClemens Zeidler
136f4f30311SClemens Zeidler
137f4f30311SClemens Zeidler FontStyle*
_FindStyle(const char * name) const138f4f30311SClemens Zeidler FontFamily::_FindStyle(const char* name) const
139f4f30311SClemens Zeidler {
140f4f30311SClemens Zeidler int32 count = fStyles.CountItems();
141f4f30311SClemens Zeidler if (!name || count < 1)
142f4f30311SClemens Zeidler return NULL;
143f4f30311SClemens Zeidler
144f4f30311SClemens Zeidler for (int32 i = 0; i < count; i++) {
145f4f30311SClemens Zeidler FontStyle *style = fStyles.ItemAt(i);
146f4f30311SClemens Zeidler if (!strcmp(style->Name(), name))
147f4f30311SClemens Zeidler return style;
148f4f30311SClemens Zeidler }
149f4f30311SClemens Zeidler
150f4f30311SClemens Zeidler return NULL;
151f4f30311SClemens Zeidler }
152f4f30311SClemens Zeidler
153f4f30311SClemens Zeidler
154f4f30311SClemens Zeidler /*!
155f4f30311SClemens Zeidler \brief Determines whether the style belongs to the family
156f4f30311SClemens Zeidler \param style Name of the style being checked
157f4f30311SClemens Zeidler \return True if it belongs, false if not
158f4f30311SClemens Zeidler */
159f4f30311SClemens Zeidler bool
HasStyle(const char * styleName) const160f4f30311SClemens Zeidler FontFamily::HasStyle(const char *styleName) const
161f4f30311SClemens Zeidler {
162f4f30311SClemens Zeidler return _FindStyle(styleName) != NULL;
163f4f30311SClemens Zeidler }
164f4f30311SClemens Zeidler
165f4f30311SClemens Zeidler
166f4f30311SClemens Zeidler /*!
167f4f30311SClemens Zeidler \brief Returns the name of a style in the family
168f4f30311SClemens Zeidler \param index list index of the style to be found
169f4f30311SClemens Zeidler \return name of the style or NULL if the index is not valid
170f4f30311SClemens Zeidler */
171f4f30311SClemens Zeidler FontStyle*
StyleAt(int32 index) const172f4f30311SClemens Zeidler FontFamily::StyleAt(int32 index) const
173f4f30311SClemens Zeidler {
174f4f30311SClemens Zeidler return fStyles.ItemAt(index);
175f4f30311SClemens Zeidler }
176f4f30311SClemens Zeidler
177f4f30311SClemens Zeidler
178f4f30311SClemens Zeidler /*!
179f4f30311SClemens Zeidler \brief Get the FontStyle object for the name given
180f4f30311SClemens Zeidler \param style Name of the style to be obtained
181f4f30311SClemens Zeidler \return The FontStyle object or NULL if none was found.
182f4f30311SClemens Zeidler
183f4f30311SClemens Zeidler The object returned belongs to the family and must not be deleted.
184f4f30311SClemens Zeidler */
185f4f30311SClemens Zeidler FontStyle*
GetStyle(const char * name) const186f4f30311SClemens Zeidler FontFamily::GetStyle(const char *name) const
187f4f30311SClemens Zeidler {
188f4f30311SClemens Zeidler if (name == NULL || !name[0])
189f4f30311SClemens Zeidler return NULL;
190f4f30311SClemens Zeidler
191f4f30311SClemens Zeidler FontStyle* style = _FindStyle(name);
192f4f30311SClemens Zeidler if (style != NULL)
193f4f30311SClemens Zeidler return style;
194f4f30311SClemens Zeidler
195f4f30311SClemens Zeidler // try alternative names
196f4f30311SClemens Zeidler
197f4f30311SClemens Zeidler if (!strcmp(name, "Roman") || !strcmp(name, "Regular")
198f4f30311SClemens Zeidler || !strcmp(name, "Book")) {
199f4f30311SClemens Zeidler style = _FindStyle("Roman");
200f4f30311SClemens Zeidler if (style == NULL) {
201f4f30311SClemens Zeidler style = _FindStyle("Regular");
202f4f30311SClemens Zeidler if (style == NULL)
203f4f30311SClemens Zeidler style = _FindStyle("Book");
204f4f30311SClemens Zeidler }
205f4f30311SClemens Zeidler return style;
206f4f30311SClemens Zeidler }
207f4f30311SClemens Zeidler
208f4f30311SClemens Zeidler BString alternative = name;
209f4f30311SClemens Zeidler if (alternative.FindFirst("Italic") >= 0) {
210f4f30311SClemens Zeidler alternative.ReplaceFirst("Italic", "Oblique");
211f4f30311SClemens Zeidler return _FindStyle(alternative.String());
212f4f30311SClemens Zeidler }
213f4f30311SClemens Zeidler if (alternative.FindFirst("Oblique") >= 0) {
214f4f30311SClemens Zeidler alternative.ReplaceFirst("Oblique", "Italic");
215f4f30311SClemens Zeidler return _FindStyle(alternative.String());
216f4f30311SClemens Zeidler }
217f4f30311SClemens Zeidler
218f4f30311SClemens Zeidler return NULL;
219f4f30311SClemens Zeidler }
220f4f30311SClemens Zeidler
221f4f30311SClemens Zeidler
222f4f30311SClemens Zeidler FontStyle*
GetStyleMatchingFace(uint16 face) const223f4f30311SClemens Zeidler FontFamily::GetStyleMatchingFace(uint16 face) const
224f4f30311SClemens Zeidler {
225ef83008eSKacper Kasper // Other face flags do not impact the font selection (they are applied
226ef83008eSKacper Kasper // during drawing)
227f4f30311SClemens Zeidler face &= B_BOLD_FACE | B_ITALIC_FACE | B_REGULAR_FACE | B_CONDENSED_FACE
228f4f30311SClemens Zeidler | B_LIGHT_FACE | B_HEAVY_FACE;
229ef83008eSKacper Kasper if (face == 0)
230ef83008eSKacper Kasper face = B_REGULAR_FACE;
231f4f30311SClemens Zeidler
232f4f30311SClemens Zeidler int32 count = fStyles.CountItems();
233f4f30311SClemens Zeidler for (int32 i = 0; i < count; i++) {
234f4f30311SClemens Zeidler FontStyle* style = fStyles.ItemAt(i);
235f4f30311SClemens Zeidler
236f4f30311SClemens Zeidler if (style->Face() == face)
237f4f30311SClemens Zeidler return style;
238f4f30311SClemens Zeidler }
239f4f30311SClemens Zeidler
240f4f30311SClemens Zeidler return NULL;
241f4f30311SClemens Zeidler }
242f4f30311SClemens Zeidler
243f4f30311SClemens Zeidler
244f4f30311SClemens Zeidler uint32
Flags()245f4f30311SClemens Zeidler FontFamily::Flags()
246f4f30311SClemens Zeidler {
247f4f30311SClemens Zeidler if (fFlags == kInvalidFamilyFlags) {
248f4f30311SClemens Zeidler fFlags = 0;
249f4f30311SClemens Zeidler
250f4f30311SClemens Zeidler int32 count = fStyles.CountItems();
251f4f30311SClemens Zeidler for (int32 i = 0; i < count; i++) {
252f4f30311SClemens Zeidler FontStyle* style = fStyles.ItemAt(i);
253f4f30311SClemens Zeidler
254f4f30311SClemens Zeidler if (style->IsFixedWidth())
255f4f30311SClemens Zeidler fFlags |= B_IS_FIXED;
256f4f30311SClemens Zeidler if (style->IsFullAndHalfFixed())
257f4f30311SClemens Zeidler fFlags |= B_PRIVATE_FONT_IS_FULL_AND_HALF_FIXED;
258f4f30311SClemens Zeidler if (style->TunedCount() > 0)
259f4f30311SClemens Zeidler fFlags |= B_HAS_TUNED_FONT;
260f4f30311SClemens Zeidler }
261f4f30311SClemens Zeidler }
262f4f30311SClemens Zeidler
263f4f30311SClemens Zeidler return fFlags;
264f4f30311SClemens Zeidler }
265