#include "FontFamily.h"
#include <FontPrivate.h>
const uint32 kInvalidFamilyFlags = ~(uint32)0;
static int
font_score(const FontStyle* style)
{
int score = 0;
if (style->Face() & B_REGULAR_FACE)
score += 10;
else {
if (style->Face() & B_BOLD_FACE)
score += 5;
if (style->Face() & B_ITALIC_FACE)
score--;
}
return score;
}
static int
compare_font_styles(const FontStyle* a, const FontStyle* b)
{
return font_score(b) - font_score(a);
}
FontFamily::FontFamily(const char *name, uint16 id)
:
fName(name),
fID(id),
fNextID(0),
fFlags(kInvalidFamilyFlags)
{
fName.Truncate(B_FONT_FAMILY_LENGTH);
}
const char*
FontFamily::Name() const
{
return fName.String();
}
bool
FontFamily::AddStyle(FontStyle* style)
{
if (!style)
return false;
int32 count = fStyles.CountItems();
for (int32 i = 0; i < count; i++) {
FontStyle *item = fStyles.ItemAt(i);
if (!strcmp(item->Name(), style->Name()))
return false;
}
if (!fStyles.BinaryInsert(style, compare_font_styles))
return false;
style->_SetFontFamily(this, fNextID++);
fFlags = kInvalidFamilyFlags;
return true;
}
bool
FontFamily::RemoveStyle(FontStyle* style)
{
if (style == NULL)
return false;
if (!fStyles.RemoveItem(style))
return false;
fFlags = kInvalidFamilyFlags;
return true;
}
int32
FontFamily::CountStyles() const
{
return fStyles.CountItems();
}
FontStyle*
FontFamily::_FindStyle(const char* name) const
{
int32 count = fStyles.CountItems();
if (!name || count < 1)
return NULL;
for (int32 i = 0; i < count; i++) {
FontStyle *style = fStyles.ItemAt(i);
if (!strcmp(style->Name(), name))
return style;
}
return NULL;
}
bool
FontFamily::HasStyle(const char *styleName) const
{
return _FindStyle(styleName) != NULL;
}
FontStyle*
FontFamily::StyleAt(int32 index) const
{
return fStyles.ItemAt(index);
}
FontStyle*
FontFamily::GetStyle(const char *name) const
{
if (name == NULL || !name[0])
return NULL;
FontStyle* style = _FindStyle(name);
if (style != NULL)
return style;
if (!strcmp(name, "Roman") || !strcmp(name, "Regular")
|| !strcmp(name, "Book")) {
style = _FindStyle("Roman");
if (style == NULL) {
style = _FindStyle("Regular");
if (style == NULL)
style = _FindStyle("Book");
}
return style;
}
BString alternative = name;
if (alternative.FindFirst("Italic") >= 0) {
alternative.ReplaceFirst("Italic", "Oblique");
return _FindStyle(alternative.String());
}
if (alternative.FindFirst("Oblique") >= 0) {
alternative.ReplaceFirst("Oblique", "Italic");
return _FindStyle(alternative.String());
}
return NULL;
}
FontStyle*
FontFamily::GetStyleMatchingFace(uint16 face) const
{
face &= B_BOLD_FACE | B_ITALIC_FACE | B_REGULAR_FACE | B_CONDENSED_FACE
| B_LIGHT_FACE | B_HEAVY_FACE;
if (face == 0)
face = B_REGULAR_FACE;
int32 count = fStyles.CountItems();
for (int32 i = 0; i < count; i++) {
FontStyle* style = fStyles.ItemAt(i);
if (style->Face() == face)
return style;
}
return NULL;
}
uint32
FontFamily::Flags()
{
if (fFlags == kInvalidFamilyFlags) {
fFlags = 0;
int32 count = fStyles.CountItems();
for (int32 i = 0; i < count; i++) {
FontStyle* style = fStyles.ItemAt(i);
if (style->IsFixedWidth())
fFlags |= B_IS_FIXED;
if (style->IsFullAndHalfFixed())
fFlags |= B_PRIVATE_FONT_IS_FULL_AND_HALF_FIXED;
if (style->TunedCount() > 0)
fFlags |= B_HAS_TUNED_FONT;
}
}
return fFlags;
}