summaryrefslogtreecommitdiffstats
path: root/src/libnrtype
diff options
context:
space:
mode:
authorsu_v <suv-sf@users.sourceforge.net>2014-06-15 09:08:03 +0000
committer~suv <suv-sf@users.sourceforge.net>2014-06-15 09:08:03 +0000
commitccacefacda584c206625b7759001d3d8c531cfed (patch)
tree8c00cc50f5bb400b62639c06c234d11fa982502b /src/libnrtype
parentupdate to trunk (r13407) (diff)
parentAllow symbol zooming independent of icon screen size. (diff)
downloadinkscape-ccacefacda584c206625b7759001d3d8c531cfed.tar.gz
inkscape-ccacefacda584c206625b7759001d3d8c531cfed.zip
update to trunk (r13425)
(bzr r13398.1.3)
Diffstat (limited to 'src/libnrtype')
-rw-r--r--src/libnrtype/FontFactory.cpp247
-rw-r--r--src/libnrtype/FontFactory.h23
-rw-r--r--src/libnrtype/font-lister.cpp100
-rw-r--r--src/libnrtype/font-lister.h13
4 files changed, 117 insertions, 266 deletions
diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp
index 4ae408397..6859a4a5c 100644
--- a/src/libnrtype/FontFactory.cpp
+++ b/src/libnrtype/FontFactory.cpp
@@ -54,226 +54,11 @@ bool font_descr_equal::operator()( PangoFontDescription *const&a, PangoFontDesc
/////////////////// helper functions
-/**
- * A wrapper for strcasestr that also provides an implementation for Win32.
- */
-static bool
-ink_strstr(char const *haystack, char const *pneedle)
-{
- // windows has no strcasestr implementation, so here is ours...
- // stolen from nmap
- /* FIXME: This is broken for e.g. ink_strstr("aab", "ab"). Report to nmap.
- *
- * Also, suggest use of g_ascii_todown instead of buffer stuff, and g_ascii_tolower instead
- * of tolower. Given that haystack is a font name (i.e. fairly short), it should be ok to
- * do g_ascii_strdown on both haystack and pneedle, and do normal strstr.
- *
- * Rather than fixing in inkscape, consider getting rid of this routine, instead using
- * strdown and plain strstr at caller. We have control over the needle values, so we can
- * modify the callers rather than calling strdown there.
- */
- char buf[512];
- register char const *p;
- char *needle, *q, *foundto;
- if (!*pneedle) return true;
- if (!haystack) return false;
-
- needle = buf;
- p = pneedle; q = needle;
- while ((*q++ = tolower(*p++)))
- ;
- p = haystack - 1; foundto = needle;
- while (*++p) {
- if (tolower(*p) == *foundto) {
- if (!*++foundto) {
- /* Yeah, we found it */
- return true;
- }
- } else foundto = needle;
- }
- return false;
-}
-
-/**
- * Regular fonts are 'Regular', 'Roman', 'Normal', or 'Plain'
- */
-// FIXME: make this UTF8, add non-English style names
-static bool
-is_regular(char const *s)
-{
- if (ink_strstr(s, "Regular")) return true;
- if (ink_strstr(s, "Roman")) return true;
- if (ink_strstr(s, "Normal")) return true;
- if (ink_strstr(s, "Plain")) return true;
- return false;
-}
-
-/**
- * Non-bold fonts are 'Medium' or 'Book'
- */
-static bool
-is_nonbold(char const *s)
-{
- if (ink_strstr(s, "Medium")) return true;
- if (ink_strstr(s, "Book")) return true;
- return false;
-}
-
-/**
- * Italic fonts are 'Italic', 'Oblique', or 'Slanted'
- */
-static bool
-is_italic(char const *s)
-{
- if (ink_strstr(s, "Italic")) return true;
- if (ink_strstr(s, "Oblique")) return true;
- if (ink_strstr(s, "Slanted")) return true;
- return false;
-}
-
-/**
- * Bold fonts are 'Bold'
- */
-static bool
-is_bold(char const *s)
-{
- if (ink_strstr(s, "Bold")) return true;
- return false;
-}
-
-/**
- * Caps fonts are 'Caps'
- */
-static bool
-is_caps(char const *s)
-{
- if (ink_strstr(s, "Caps")) return true;
- return false;
-}
-
-#if 0 /* FIXME: These are all unused. Please delete them or use them (presumably in
-* style_name_compare). */
-/**
- * Monospaced fonts are 'Mono'
- */
-static bool
-is_mono(char const *s)
-{
- if (ink_strstr(s, "Mono")) return true;
- return false;
-}
-
-/**
- * Rounded fonts are 'Round'
- */
-static bool
-is_round(char const *s)
-{
- if (ink_strstr(s, "Round")) return true;
- return false;
-}
-
-/**
- * Outline fonts are 'Outline'
- */
-static bool
-is_outline(char const *s)
-{
- if (ink_strstr(s, "Outline")) return true;
- return false;
-}
-
-/**
- * Swash fonts are 'Swash'
- */
-static bool
-is_swash(char const *s)
-{
- if (ink_strstr(s, "Swash")) return true;
- return false;
-}
-#endif
-
-/**
- * Determines if two style names match. This allows us to match
- * based on the type of style rather than simply doing string matching,
- * because for instance 'Plain' and 'Normal' mean the same thing.
- *
- * Q: Shouldn't this include the other tests such as is_outline, etc.?
- * Q: Is there a problem with strcasecmp on Win32? Should it use stricmp?
- */
-int
-style_name_compare(char const *aa, char const *bb)
-{
- char const *a = (char const *) aa;
- char const *b = (char const *) bb;
-
- if (is_regular(a) && !is_regular(b)) return -1;
- if (is_regular(b) && !is_regular(a)) return 1;
-
- if (is_bold(a) && !is_bold(b)) return 1;
- if (is_bold(b) && !is_bold(a)) return -1;
-
- if (is_italic(a) && !is_italic(b)) return 1;
- if (is_italic(b) && !is_italic(a)) return -1;
-
- if (is_nonbold(a) && !is_nonbold(b)) return 1;
- if (is_nonbold(b) && !is_nonbold(a)) return -1;
-
- if (is_caps(a) && !is_caps(b)) return 1;
- if (is_caps(b) && !is_caps(a)) return -1;
-
- return strcasecmp(a, b);
-}
-
-/*
- defined but not used:
-
-static int
-style_record_compare(void const *aa, void const *bb)
-{
- NRStyleRecord const *a = (NRStyleRecord const *) aa;
- NRStyleRecord const *b = (NRStyleRecord const *) bb;
-
- return (style_name_compare(a->name, b->name));
-}
-
-static void font_factory_name_list_destructor(NRNameList *list)
-{
- for (unsigned int i = 0; i < list->length; i++)
- g_free(list->names[i]);
- if ( list->names ) g_free(list->names);
-}
-
-static void font_factory_style_list_destructor(NRStyleList *list)
-{
- for (unsigned int i = 0; i < list->length; i++) {
- g_free((void *) (list->records)[i].name);
- g_free((void *) (list->records)[i].descr);
- }
- if ( list->records ) g_free(list->records);
-}
-*/
-
-/**
- * On Win32 performs a stricmp(a,b), otherwise does a strcasecmp(a,b)
- */
-int
-family_name_compare(char const *a, char const *b)
-{
-#ifndef WIN32
- return strcasecmp((*((char const **) a)), (*((char const **) b)));
-#else
- return stricmp((*((char const **) a)), (*((char const **) b)));
-#endif
-}
-
static void noop(...) {}
//#define PANGO_DEBUG g_print
#define PANGO_DEBUG noop
-
///////////////////// FontFactory
#ifndef USE_PANGO_WIN32
// the substitute function to tell fontconfig to enforce outline fonts
@@ -708,9 +493,24 @@ Glib::ustring font_factory::FontSpecificationBestMatch(const Glib::ustring & fon
/////
-static bool StyleNameCompareInternal(Glib::ustring style1, Glib::ustring style2)
+// Calculate a Style "value" based on CSS values for ordering styles.
+static int StyleNameValue( const Glib::ustring &style )
+{
+
+ PangoFontDescription *pfd = pango_font_description_from_string ( style.c_str() );
+ int value =
+ pango_font_description_get_weight ( pfd ) * 1000000 +
+ pango_font_description_get_style ( pfd ) * 10000 +
+ pango_font_description_get_stretch( pfd ) * 100 +
+ pango_font_description_get_variant( pfd );
+ pango_font_description_free ( pfd );
+ return value;
+}
+
+// Determines order in which styles are presented (sorted by CSS style values)
+static bool StyleNameCompareInternal(const StyleNames &style1, const StyleNames &style2)
{
- return (style_name_compare(style1.c_str(), style2.c_str()) < 0);
+ return( StyleNameValue( style1.CssName ) < StyleNameValue( style2.CssName ) );
}
void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map)
@@ -736,7 +536,8 @@ void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map)
// If the face has a name, describe it, and then use the
// description to get the UI family and face strings
- if (pango_font_face_get_face_name(faces[currentFace]) == NULL) {
+ const gchar* displayName = pango_font_face_get_face_name(faces[currentFace]);
+ if (displayName == NULL) {
continue;
}
@@ -766,26 +567,26 @@ void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map)
// Insert new family
if (iter == map->end()) {
- map->insert(std::make_pair(familyUIName, std::list<Glib::ustring>()));
+ map->insert(std::make_pair(familyUIName, std::list<StyleNames>()));
}
// Insert into the style list and save the info in the reference maps
// only if the style does not yet exist
bool exists = false;
- std::list<Glib::ustring> &styleList = (*map)[familyUIName];
+ std::list<StyleNames> &styleList = (*map)[familyUIName];
- for (std::list<Glib::ustring>::iterator it=styleList.begin();
+ for (std::list<StyleNames>::iterator it=styleList.begin();
it != styleList.end();
++it) {
- if (*it == styleUIName) {
+ if ( (*it).CssName == styleUIName) {
exists = true;
break;
}
}
if (!exists) {
- styleList.push_back(styleUIName);
+ styleList.push_back( StyleNames(styleUIName,displayName) );
// Add the string info needed in the reference maps
fontStringMap.insert(
diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h
index 7b606d200..513ee4bf7 100644
--- a/src/libnrtype/FontFactory.h
+++ b/src/libnrtype/FontFactory.h
@@ -51,15 +51,26 @@ struct font_descr_equal : public std::binary_function<PangoFontDescription*, Pan
bool operator()(PangoFontDescription *const &a, PangoFontDescription *const &b) const;
};
-// Comparison functions for style names
-int style_name_compare(char const *aa, char const *bb);
-int family_name_compare(char const *a, char const *b);
-
// Wraps calls to pango_font_description_get_family with some name substitution
const char *sp_font_description_get_family(PangoFontDescription const *fontDescr);
-// Map type for gathering UI family and style strings
-typedef std::map<Glib::ustring, std::list<Glib::ustring> > FamilyToStylesMap;
+// Class for style strings: both CSS and as suggested by font.
+class StyleNames {
+
+public:
+ StyleNames() {};
+ StyleNames( Glib::ustring name ) :
+ CssName( name ), DisplayName( name ) {};
+ StyleNames( Glib::ustring cssname, Glib::ustring displayname ) :
+ CssName( cssname ), DisplayName( displayname ) {};
+
+public:
+ Glib::ustring CssName; // Style as Pango/CSS would write it.
+ Glib::ustring DisplayName; // Style as Font designer named it.
+};
+
+// Map type for gathering UI family and style names
+typedef std::map<Glib::ustring, std::list<StyleNames> > FamilyToStylesMap;
class font_factory {
public:
diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp
index 333c4ef5b..43c3045b1 100644
--- a/src/libnrtype/font-lister.cpp
+++ b/src/libnrtype/font-lister.cpp
@@ -25,6 +25,13 @@
//#define DEBUG_FONT
+// CSS dictates that font family names are case insensitive.
+// This should really implement full Unicode case unfolding.
+bool familyNamesAreEqual( const Glib::ustring &a, const Glib::ustring &b ) {
+
+ return( a.casefold().compare( b.casefold() ) == 0 );
+}
+
namespace Inkscape
{
FontLister::FontLister ()
@@ -57,11 +64,13 @@ namespace Inkscape
// Now go through the styles
GList *styles = NULL;
- std::list<Glib::ustring> &styleStrings = familyStyleMap[familyName];
- for (std::list<Glib::ustring>::iterator it=styleStrings.begin();
+ std::list<StyleNames> &styleStrings = familyStyleMap[familyName];
+ for (std::list<StyleNames>::iterator it=styleStrings.begin();
it != styleStrings.end();
++it) {
- styles = g_list_append(styles, g_strdup((*it).c_str()));
+ // Our own copy
+ StyleNames *copy = new StyleNames( *it );
+ styles = g_list_append(styles, copy);
}
(*treeModelIter)[FontList.styles] = styles;
@@ -74,11 +83,11 @@ namespace Inkscape
current_fontspec = "sans-serif"; // Empty style -> Normal
current_fontspec_system = "Sans";
- /* Create default styles for use when font-family is unknown on system. */
- default_styles = g_list_append( NULL, g_strdup("Normal") );
- default_styles = g_list_append( default_styles, g_strdup("Italic") );
- default_styles = g_list_append( default_styles, g_strdup("Bold") );
- default_styles = g_list_append( default_styles, g_strdup("Bold Italic") );
+ /* Create default styles for use when font-family is unknown on system. */
+ default_styles = g_list_append( NULL, new StyleNames( "Normal" ) );
+ default_styles = g_list_append( default_styles, new StyleNames( "Italic" ) );
+ default_styles = g_list_append( default_styles, new StyleNames( "Bold" ) );
+ default_styles = g_list_append( default_styles, new StyleNames( "Bold Italic" ) );
font_list_store->thaw_notify();
@@ -89,11 +98,31 @@ namespace Inkscape
style_list_store->clear();
for (GList *l=default_styles; l; l = l->next) {
Gtk::TreeModel::iterator treeModelIter = style_list_store->append();
- (*treeModelIter)[FontStyleList.styles] = (char*)l->data;
+ (*treeModelIter)[FontStyleList.cssStyle] = ((StyleNames*)l->data)->CssName;
+ (*treeModelIter)[FontStyleList.displayStyle] = ((StyleNames*)l->data)->DisplayName;
}
style_list_store->thaw_notify();
}
+ FontLister::~FontLister() {
+
+ // Delete default_styles
+ for (GList *l=default_styles; l; l = l->next) {
+ delete ((StyleNames*)l->data);
+ }
+
+ // Delete other styles
+ Gtk::TreeModel::iterator iter = font_list_store->get_iter( "0" );
+ while( iter != font_list_store->children().end() ) {
+ Gtk::TreeModel::Row row = *iter;
+ GList *styles = row[FontList.styles];
+ for (GList *l=styles; l; l = l->next) {
+ delete ((StyleNames*)l->data);
+ }
+ ++iter;
+ }
+ }
+
// Example of how to use "foreach_iter"
// bool
// FontLister::print_document_font( const Gtk::TreeModel::iterator &iter ) {
@@ -106,7 +135,6 @@ namespace Inkscape
// }
// font_list_store->foreach_iter( sigc::mem_fun(*this, &FontLister::print_document_font ));
-
/* Used to insert a font that was not in the document and not on the system into the font list. */
void
FontLister::insert_font_family( Glib::ustring new_family ) {
@@ -120,7 +148,7 @@ namespace Inkscape
Gtk::TreeModel::iterator iter2 = font_list_store->get_iter( "0" );
while( iter2 != font_list_store->children().end() ) {
Gtk::TreeModel::Row row = *iter2;
- if( row[FontList.onSystem] && tokens[0].compare( row[FontList.family] ) == 0 ) {
+ if( row[FontList.onSystem] && familyNamesAreEqual( tokens[0], row[FontList.family] ) ) {
styles = row[FontList.styles];
break;
}
@@ -197,7 +225,7 @@ namespace Inkscape
Gtk::TreeModel::iterator iter2 = font_list_store->get_iter( "0" );
while( iter2 != font_list_store->children().end() ) {
Gtk::TreeModel::Row row = *iter2;
- if( row[FontList.onSystem] && tokens[0].compare( row[FontList.family] ) == 0 ) {
+ if( row[FontList.onSystem] && familyNamesAreEqual( tokens[0], row[FontList.family] ) ) {
styles = row[FontList.styles];
break;
}
@@ -228,7 +256,7 @@ namespace Inkscape
path.push_back( row );
Gtk::TreeModel::iterator iter = font_list_store->get_iter( path );
if( iter ) {
- if( current_family.compare( (*iter)[FontList.family] ) == 0 ) {
+ if( familyNamesAreEqual( current_family, (*iter)[FontList.family] ) ) {
current_family_row = row;
break;
}
@@ -384,6 +412,7 @@ namespace Inkscape
std::pair<Glib::ustring, Glib::ustring> ui = ui_from_fontspec( current_fontspec );
set_font_family( ui.first );
+ set_font_style( ui.second );
#ifdef DEBUG_FONT
std::cout << " family_row: :" << current_family_row << ":" << std::endl;
@@ -424,7 +453,7 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
#endif
// No need to do anything if new family is same as old family.
- if ( new_family.compare( current_family ) == 0 ) {
+ if ( familyNamesAreEqual( new_family, current_family ) ) {
#ifdef DEBUG_FONT
std::cout << "FontLister::new_font_family: exit: no change in family." << std::endl;
std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl;
@@ -443,7 +472,7 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
Gtk::TreeModel::Row row = *iter;
- if( new_family.compare( row[FontList.family] ) == 0 ) {
+ if( familyNamesAreEqual( new_family, row[FontList.family] ) ) {
styles = row[FontList.styles];
break;
}
@@ -463,7 +492,8 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
for (GList *l=styles; l; l = l->next) {
Gtk::TreeModel::iterator treeModelIter = style_list_store->append();
- (*treeModelIter)[FontStyleList.styles] = (char*)l->data;
+ (*treeModelIter)[FontStyleList.cssStyle] = ((StyleNames*)l->data)->CssName;
+ (*treeModelIter)[FontStyleList.displayStyle] = ((StyleNames*)l->data)->DisplayName;
}
style_list_store->thaw_notify();
@@ -571,8 +601,15 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
Glib::ustring family = ui.first;
- sp_repr_css_set_property (css, "-inkscape-font-specification", fontspec.c_str() );
- sp_repr_css_set_property (css, "font-family", family.c_str() ); //Canonized w/ spaces
+
+ // Font spec is single quoted... for the moment
+ Glib::ustring fontspec_quoted( fontspec );
+ css_quote( fontspec_quoted );
+ sp_repr_css_set_property (css, "-inkscape-font-specification", fontspec_quoted.c_str() );
+
+ // Font families needs to be properly quoted in CSS (used unquoted in font-lister)
+ css_font_family_quote( family );
+ sp_repr_css_set_property (css, "font-family", family.c_str() );
PangoFontDescription *desc = pango_font_description_from_string( fontspec.c_str() );
PangoWeight weight = pango_font_description_get_weight( desc );
@@ -688,18 +725,19 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
fontspec = style->font_family.value;
fontspec += ",";
+ // Use weight names as defined by Pango
switch (style->font_weight.computed) {
case SP_CSS_FONT_WEIGHT_100:
- fontspec += " 100";
+ fontspec += " Thin";
break;
case SP_CSS_FONT_WEIGHT_200:
- fontspec += " 200";
+ fontspec += " Ultra-Light";
break;
case SP_CSS_FONT_WEIGHT_300:
- fontspec += " 300";
+ fontspec += " Light";
break;
case SP_CSS_FONT_WEIGHT_400:
@@ -708,24 +746,24 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
break;
case SP_CSS_FONT_WEIGHT_500:
- fontspec += " 500";
+ fontspec += " Medium";
break;
case SP_CSS_FONT_WEIGHT_600:
- fontspec += " 600";
+ fontspec += " Semi-Bold";
break;
case SP_CSS_FONT_WEIGHT_700:
case SP_CSS_FONT_WEIGHT_BOLD:
- fontspec += " bold";
+ fontspec += " Bold";
break;
case SP_CSS_FONT_WEIGHT_800:
- fontspec += " 800";
+ fontspec += " Ultra-Bold";
break;
case SP_CSS_FONT_WEIGHT_900:
- fontspec += " 900";
+ fontspec += " Heavy";
break;
case SP_CSS_FONT_WEIGHT_LIGHTER:
@@ -821,7 +859,7 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
Gtk::TreeModel::Row row = *iter;
- if( family.compare( row[FontList.family] ) == 0 ) {
+ if( familyNamesAreEqual( family, row[FontList.family] ) ) {
return row;
}
@@ -847,7 +885,7 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
Gtk::TreeModel::Row row = *iter;
- if( style.compare( row[FontStyleList.styles] ) == 0 ) {
+ if( familyNamesAreEqual( style, row[FontStyleList.cssStyle] ) ) {
return row;
}
@@ -974,10 +1012,6 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri
return best_style;
}
- FontLister::~FontLister ()
- {
- };
-
const Glib::RefPtr<Gtk::ListStore>
FontLister::get_font_list () const
{
@@ -1035,7 +1069,7 @@ void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/,
valid = gtk_tree_model_iter_next( GTK_TREE_MODEL(model), &iter ) ) {
gtk_tree_model_get(model, &iter, 0, &family, 2, &onSystem, -1);
- if( onSystem && token.compare( family ) == 0 ) {
+ if( onSystem && familyNamesAreEqual( token, family ) ) {
found = true;
break;
}
diff --git a/src/libnrtype/font-lister.h b/src/libnrtype/font-lister.h
index a460388d3..c89dab550 100644
--- a/src/libnrtype/font-lister.h
+++ b/src/libnrtype/font-lister.h
@@ -100,13 +100,18 @@ namespace Inkscape
: public Gtk::TreeModelColumnRecord
{
public:
- /** Column containing the styles
+ /** Column containing the styles as Font designer used.
*/
- Gtk::TreeModelColumn<Glib::ustring> styles;
+ Gtk::TreeModelColumn<Glib::ustring> displayStyle;
+
+ /** Column containing the styles in CSS/Pango format.
+ */
+ Gtk::TreeModelColumn<Glib::ustring> cssStyle;
FontStyleListClass ()
{
- add (styles);
+ add (cssStyle);
+ add (displayStyle);
}
};
@@ -276,7 +281,7 @@ namespace Inkscape
private:
FontLister ();
-
+
NRNameList families;
Glib::RefPtr<Gtk::ListStore> font_list_store;