2005-11-01 20:49:01 +03:00
|
|
|
/*
|
2008-03-18 19:52:34 +03:00
|
|
|
* Copyright 2001-2008, Haiku.
|
2005-11-01 20:49:01 +03:00
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* DarkWyrm <bpmagic@columbus.rr.com>
|
|
|
|
* Axel Dörfler, axeld@pinc-software.de
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** Classes to represent font styles and families */
|
|
|
|
|
|
|
|
|
2003-01-01 01:19:48 +03:00
|
|
|
#include "FontFamily.h"
|
|
|
|
|
2007-07-18 00:48:06 +04:00
|
|
|
#include "FontManager.h"
|
2006-04-18 19:14:10 +04:00
|
|
|
|
2005-11-01 20:49:01 +03:00
|
|
|
|
2005-11-07 19:19:40 +03:00
|
|
|
const uint32 kInvalidFamilyFlags = ~0UL;
|
2005-11-01 20:49:01 +03:00
|
|
|
|
|
|
|
|
2005-11-10 18:48:37 +03:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
// Regular fonts come first, then bold, then italics
|
|
|
|
return font_score(b) - font_score(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2003-01-01 01:19:48 +03:00
|
|
|
/*!
|
|
|
|
\brief Constructor
|
2003-01-20 02:04:58 +03:00
|
|
|
\param namestr Name of the family
|
2003-01-01 01:19:48 +03:00
|
|
|
*/
|
2005-11-01 20:49:01 +03:00
|
|
|
FontFamily::FontFamily(const char *name, uint16 id)
|
|
|
|
:
|
|
|
|
fName(name),
|
|
|
|
fID(id),
|
|
|
|
fNextID(0),
|
|
|
|
fFlags(kInvalidFamilyFlags)
|
2003-01-01 01:19:48 +03:00
|
|
|
{
|
2005-11-01 20:49:01 +03:00
|
|
|
fName.Truncate(B_FONT_FAMILY_LENGTH);
|
|
|
|
// make sure this family can be found using the Be API
|
2003-01-01 01:19:48 +03:00
|
|
|
}
|
|
|
|
|
2005-11-10 17:52:26 +03:00
|
|
|
|
2003-01-01 01:19:48 +03:00
|
|
|
/*!
|
|
|
|
\brief Destructor
|
2008-03-18 19:52:34 +03:00
|
|
|
|
2005-11-10 20:32:35 +03:00
|
|
|
Deletes all attached styles. Note that a FontFamily must only be deleted
|
|
|
|
by the font manager.
|
2003-01-01 01:19:48 +03:00
|
|
|
*/
|
2005-06-03 23:30:32 +04:00
|
|
|
FontFamily::~FontFamily()
|
2003-01-01 01:19:48 +03:00
|
|
|
{
|
2005-11-10 20:32:35 +03:00
|
|
|
for (int32 i = fStyles.CountItems(); i-- > 0;) {
|
|
|
|
FontStyle* style = fStyles.RemoveItemAt(i);
|
|
|
|
|
|
|
|
// we remove us before deleting the style, so that the font manager
|
|
|
|
// is not contacted to remove the style from us
|
|
|
|
style->_SetFontFamily(NULL, -1);
|
|
|
|
delete style;
|
|
|
|
}
|
2003-01-01 01:19:48 +03:00
|
|
|
}
|
|
|
|
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2003-01-01 01:19:48 +03:00
|
|
|
/*!
|
|
|
|
\brief Returns the name of the family
|
|
|
|
\return The family's name
|
|
|
|
*/
|
2005-06-03 23:30:32 +04:00
|
|
|
const char*
|
2005-10-20 14:01:49 +04:00
|
|
|
FontFamily::Name() const
|
2003-01-01 01:19:48 +03:00
|
|
|
{
|
2005-01-17 05:05:50 +03:00
|
|
|
return fName.String();
|
2003-01-01 01:19:48 +03:00
|
|
|
}
|
|
|
|
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2003-01-01 01:19:48 +03:00
|
|
|
/*!
|
|
|
|
\brief Adds the style to the family
|
2007-07-18 00:48:06 +04:00
|
|
|
\param style pointer to FontStyle object to be added
|
2003-01-01 01:19:48 +03:00
|
|
|
*/
|
2005-06-03 23:30:32 +04:00
|
|
|
bool
|
|
|
|
FontFamily::AddStyle(FontStyle *style)
|
2003-01-01 01:19:48 +03:00
|
|
|
{
|
2005-06-03 23:30:32 +04:00
|
|
|
if (!style)
|
2005-01-17 05:05:50 +03:00
|
|
|
return false;
|
2003-01-01 01:19:48 +03:00
|
|
|
|
2008-03-18 19:52:34 +03:00
|
|
|
// Don't add if it already is in the family.
|
2005-06-03 23:30:32 +04:00
|
|
|
int32 count = fStyles.CountItems();
|
2005-11-01 02:21:36 +03:00
|
|
|
for (int32 i = 0; i < count; i++) {
|
2005-11-01 20:49:01 +03:00
|
|
|
FontStyle *item = fStyles.ItemAt(i);
|
|
|
|
if (!strcmp(item->Name(), style->Name()))
|
2005-01-17 05:05:50 +03:00
|
|
|
return false;
|
2003-01-01 01:19:48 +03:00
|
|
|
}
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2005-11-10 18:48:37 +03:00
|
|
|
if (!fStyles.BinaryInsert(style, compare_font_styles))
|
|
|
|
return false;
|
|
|
|
|
2005-11-03 16:10:28 +03:00
|
|
|
style->_SetFontFamily(this, fNextID++);
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2005-01-17 05:05:50 +03:00
|
|
|
// force a refresh if a request for font flags is needed
|
2005-11-01 20:49:01 +03:00
|
|
|
fFlags = kInvalidFamilyFlags;
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2005-01-17 05:05:50 +03:00
|
|
|
return true;
|
2003-01-01 01:19:48 +03:00
|
|
|
}
|
|
|
|
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2005-01-17 05:05:50 +03:00
|
|
|
/*!
|
2005-11-03 16:10:28 +03:00
|
|
|
\brief Removes a style from the family.
|
|
|
|
|
2005-11-10 20:32:35 +03:00
|
|
|
The font style will not be deleted.
|
2005-01-17 05:05:50 +03:00
|
|
|
*/
|
2005-11-03 16:10:28 +03:00
|
|
|
bool
|
2005-11-10 20:32:35 +03:00
|
|
|
FontFamily::RemoveStyle(FontStyle* style)
|
2005-01-17 05:05:50 +03:00
|
|
|
{
|
2005-11-03 16:10:28 +03:00
|
|
|
if (!gFontManager->IsLocked()) {
|
|
|
|
debugger("FontFamily::RemoveStyle() called without having the font manager locked!");
|
|
|
|
return false;
|
2005-01-17 05:05:50 +03:00
|
|
|
}
|
2005-11-03 16:10:28 +03:00
|
|
|
|
|
|
|
if (!fStyles.RemoveItem(style))
|
|
|
|
return false;
|
|
|
|
|
2005-11-10 17:52:26 +03:00
|
|
|
style->_SetFontFamily(NULL, -1);
|
|
|
|
|
2005-11-10 20:32:35 +03:00
|
|
|
// force a refresh if a request for font flags is needed
|
|
|
|
fFlags = kInvalidFamilyFlags;
|
2005-11-03 16:10:28 +03:00
|
|
|
return true;
|
2005-01-17 05:05:50 +03:00
|
|
|
}
|
|
|
|
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2003-01-01 01:19:48 +03:00
|
|
|
/*!
|
|
|
|
\brief Returns the number of styles in the family
|
|
|
|
\return The number of styles in the family
|
|
|
|
*/
|
2005-06-03 23:30:32 +04:00
|
|
|
int32
|
|
|
|
FontFamily::CountStyles() const
|
2003-01-01 01:19:48 +03:00
|
|
|
{
|
2005-01-17 05:05:50 +03:00
|
|
|
return fStyles.CountItems();
|
2003-01-01 01:19:48 +03:00
|
|
|
}
|
|
|
|
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2008-03-18 19:52:34 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-01-01 01:19:48 +03:00
|
|
|
/*!
|
|
|
|
\brief Determines whether the style belongs to the family
|
2003-01-20 02:04:58 +03:00
|
|
|
\param style Name of the style being checked
|
2003-01-01 01:19:48 +03:00
|
|
|
\return True if it belongs, false if not
|
|
|
|
*/
|
2005-06-03 23:30:32 +04:00
|
|
|
bool
|
2005-11-01 02:21:36 +03:00
|
|
|
FontFamily::HasStyle(const char *styleName) const
|
2003-01-01 01:19:48 +03:00
|
|
|
{
|
2008-03-18 19:52:34 +03:00
|
|
|
return _FindStyle(styleName) != NULL;
|
2003-01-01 01:19:48 +03:00
|
|
|
}
|
|
|
|
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2008-03-18 19:52:34 +03:00
|
|
|
/*!
|
2003-01-01 01:19:48 +03:00
|
|
|
\brief Returns the name of a style in the family
|
2003-01-20 02:04:58 +03:00
|
|
|
\param index list index of the style to be found
|
2003-01-01 01:19:48 +03:00
|
|
|
\return name of the style or NULL if the index is not valid
|
|
|
|
*/
|
2005-06-03 23:30:32 +04:00
|
|
|
FontStyle*
|
2005-11-01 02:21:36 +03:00
|
|
|
FontFamily::StyleAt(int32 index) const
|
2003-01-01 01:19:48 +03:00
|
|
|
{
|
2005-11-01 02:21:36 +03:00
|
|
|
return fStyles.ItemAt(index);
|
2003-01-01 01:19:48 +03:00
|
|
|
}
|
|
|
|
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2003-01-01 01:19:48 +03:00
|
|
|
/*!
|
|
|
|
\brief Get the FontStyle object for the name given
|
2003-01-20 02:04:58 +03:00
|
|
|
\param style Name of the style to be obtained
|
2003-01-01 01:19:48 +03:00
|
|
|
\return The FontStyle object or NULL if none was found.
|
2008-03-18 19:52:34 +03:00
|
|
|
|
2003-01-01 01:19:48 +03:00
|
|
|
The object returned belongs to the family and must not be deleted.
|
|
|
|
*/
|
2005-06-03 23:30:32 +04:00
|
|
|
FontStyle*
|
2008-03-18 19:52:34 +03:00
|
|
|
FontFamily::GetStyle(const char *name) const
|
2003-01-01 01:19:48 +03:00
|
|
|
{
|
2008-03-18 19:52:34 +03:00
|
|
|
if (name == NULL || !name[0])
|
2003-01-01 01:19:48 +03:00
|
|
|
return NULL;
|
2005-06-03 23:30:32 +04:00
|
|
|
|
2008-03-18 19:52:34 +03:00
|
|
|
FontStyle* style = _FindStyle(name);
|
|
|
|
if (style != NULL)
|
|
|
|
return style;
|
|
|
|
|
|
|
|
// try alternative names
|
|
|
|
|
|
|
|
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());
|
2003-01-01 01:19:48 +03:00
|
|
|
}
|
2005-11-01 02:21:36 +03:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FontStyle*
|
2005-11-01 19:28:01 +03:00
|
|
|
FontFamily::GetStyleByID(uint16 id) const
|
2005-11-01 02:21:36 +03:00
|
|
|
{
|
2007-07-18 00:48:06 +04:00
|
|
|
int32 count = fStyles.CountItems();
|
|
|
|
for (int32 i = 0; i < count; i++) {
|
2005-11-01 02:21:36 +03:00
|
|
|
FontStyle* style = fStyles.ItemAt(i);
|
|
|
|
if (style->ID() == id)
|
|
|
|
return style;
|
|
|
|
}
|
|
|
|
|
2003-01-01 01:19:48 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
2005-01-17 05:05:50 +03:00
|
|
|
|
2005-11-01 02:21:36 +03:00
|
|
|
|
|
|
|
FontStyle*
|
2005-11-01 19:28:01 +03:00
|
|
|
FontFamily::GetStyleMatchingFace(uint16 face) const
|
2005-11-01 02:21:36 +03:00
|
|
|
{
|
2008-05-24 18:54:18 +04:00
|
|
|
// TODO: support other faces (strike through, underlined, outlines...)
|
|
|
|
face &= B_BOLD_FACE | B_ITALIC_FACE | B_REGULAR_FACE | B_CONDENSED_FACE
|
|
|
|
| B_LIGHT_FACE | B_HEAVY_FACE;
|
2005-11-01 19:28:01 +03:00
|
|
|
|
2007-07-18 00:48:06 +04:00
|
|
|
int32 count = fStyles.CountItems();
|
|
|
|
for (int32 i = 0; i < count; i++) {
|
2005-11-01 02:21:36 +03:00
|
|
|
FontStyle* style = fStyles.ItemAt(i);
|
2008-03-18 19:52:34 +03:00
|
|
|
|
2005-11-01 02:21:36 +03:00
|
|
|
if (style->Face() == face)
|
|
|
|
return style;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-07 19:19:40 +03:00
|
|
|
uint32
|
2005-11-01 02:21:36 +03:00
|
|
|
FontFamily::Flags()
|
2005-01-17 05:05:50 +03:00
|
|
|
{
|
2005-11-01 20:49:01 +03:00
|
|
|
if (fFlags == kInvalidFamilyFlags) {
|
2005-06-03 23:30:32 +04:00
|
|
|
fFlags = 0;
|
2005-11-01 02:21:36 +03:00
|
|
|
|
2007-07-18 00:48:06 +04:00
|
|
|
int32 count = fStyles.CountItems();
|
|
|
|
for (int32 i = 0; i < count; i++) {
|
2005-11-01 20:49:01 +03:00
|
|
|
FontStyle* style = fStyles.ItemAt(i);
|
|
|
|
|
|
|
|
if (style->IsFixedWidth())
|
|
|
|
fFlags |= B_IS_FIXED;
|
|
|
|
if (style->TunedCount() > 0)
|
|
|
|
fFlags |= B_HAS_TUNED_FONT;
|
2005-01-17 05:05:50 +03:00
|
|
|
}
|
|
|
|
}
|
2008-03-18 19:52:34 +03:00
|
|
|
|
2005-01-17 05:05:50 +03:00
|
|
|
return fFlags;
|
|
|
|
}
|