From 45922bee145584c0161fa89735da108ece53e0f5 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 28 May 2014 11:11:31 +0200 Subject: Initialize style store with default styles. Fixes Gtk-CRITICAL and GLib-Gobject-CRITICAL errors. (bzr r13341.1.40) --- src/libnrtype/font-lister.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/libnrtype') diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 98589d9d7..300273378 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -83,6 +83,15 @@ namespace Inkscape font_list_store->thaw_notify(); style_list_store = Gtk::ListStore::create (FontStyleList); + + // Initialize style store with defaults + style_list_store->freeze_notify(); + 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; + } + style_list_store->thaw_notify(); } // Example of how to use "foreach_iter" -- cgit v1.2.3 From bb0190888e9c3ce7628e4662e963d115d7855b15 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 29 May 2014 11:52:45 +0200 Subject: Use SPStyle value for 'font-family' rather than parse 'style' ourselves. This fixes the problem of a 'font-family' declared via the 'font' shorthand being ignored when creating the document font list. (bzr r13341.1.41) --- src/libnrtype/font-lister.cpp | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 300273378..333c4ef5b 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -240,37 +240,12 @@ namespace Inkscape font_list_store->thaw_notify(); } - // FIXME: why do we parse the style attribute instead of the object's SPStyle? void FontLister::update_font_list_recursive( SPObject *r, std::list *l ) { - const gchar *style = r->getRepr()->attribute("style"); - if( style != NULL ) { - - std::vector tokens = Glib::Regex::split_simple(";", style ); - for( size_t i=0; i < tokens.size(); ++i ) { - - Glib::ustring token = tokens[i]; - size_t found = token.find("font-family:"); - - if( found != Glib::ustring::npos ) { - - // Remove "font-family:" - token.erase(found,12); - - // Remove any leading single or double quote - if( token[0] == '\'' || token[0] == '"' ) { - token.erase(0,1); - } - - // Remove any trailing single or double quote - if( token[token.length()-1] == '\'' || token[token.length()-1] == '"' ) { - token.erase(token.length()-1); - } - - l->push_back( token ); - } - } + const gchar *font_family = r->style->font_family.value; + if( font_family ) { + l->push_back( Glib::ustring( font_family ) ); } for (SPObject *child = r->firstChild(); child; child = child->getNext()) { -- cgit v1.2.3 From 9b0db891ca0fc8ca0cfbfaa301c473f2ad3e6d68 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 5 Jun 2014 18:28:15 +0200 Subject: Make family-name comparisons case insensitive. Fix UI bug when SVG file does not have -inkscape-font-specification properties (Style drop-down list not properly updated.) (bzr r13341.1.47) --- src/libnrtype/font-lister.cpp | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 333c4ef5b..8ce5eccfc 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 () @@ -120,7 +127,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 +204,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 +235,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 +391,7 @@ namespace Inkscape std::pair 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 +432,7 @@ std::pair 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 +451,7 @@ std::pair 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; } @@ -688,18 +696,19 @@ std::pair 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 +717,24 @@ std::pair 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 +830,7 @@ std::pair 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 +856,7 @@ std::pair FontLister::new_font_family (Glib::ustri Gtk::TreeModel::Row row = *iter; - if( style.compare( row[FontStyleList.styles] ) == 0 ) { + if( familyNamesAreEqual( style, row[FontStyleList.styles] ) ) { return row; } @@ -1035,7 +1044,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; } -- cgit v1.2.3 From fdc7bd363b6c34bc42d246678d17faa4519323b4 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sun, 8 Jun 2014 18:16:10 +0200 Subject: Better ordering of font-face styles in UI. Rely on CSS values rather than guessing. (bzr r13341.1.53) --- src/libnrtype/FontFactory.cpp | 234 +++--------------------------------------- 1 file changed, 17 insertions(+), 217 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 4ae408397..6ab8c77b8 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 Glib::ustring &style1, const Glib::ustring &style2) { - return (style_name_compare(style1.c_str(), style2.c_str()) < 0); + return( StyleNameValue( style1 ) < StyleNameValue( style2 ) ); } void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map) -- cgit v1.2.3 From acfb5bd375ec40f1fb59b806bfb34f66a5aa5cb1 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 9 Jun 2014 10:38:18 +0200 Subject: Display name of face from font file in Text and Font dialog (as well as CSS/Pango name). Partial fix for #165521, #167353, #1008514 (bzr r13341.1.54) --- src/libnrtype/FontFactory.cpp | 17 ++++++++------- src/libnrtype/FontFactory.h | 23 ++++++++++++++------ src/libnrtype/font-lister.cpp | 50 +++++++++++++++++++++++++++++-------------- src/libnrtype/font-lister.h | 13 +++++++---- 4 files changed, 69 insertions(+), 34 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 6ab8c77b8..6859a4a5c 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -508,9 +508,9 @@ static int StyleNameValue( const Glib::ustring &style ) } // Determines order in which styles are presented (sorted by CSS style values) -static bool StyleNameCompareInternal(const Glib::ustring &style1, const Glib::ustring &style2) +static bool StyleNameCompareInternal(const StyleNames &style1, const StyleNames &style2) { - return( StyleNameValue( style1 ) < StyleNameValue( style2 ) ); + return( StyleNameValue( style1.CssName ) < StyleNameValue( style2.CssName ) ); } void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map) @@ -536,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; } @@ -566,26 +567,26 @@ void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map) // Insert new family if (iter == map->end()) { - map->insert(std::make_pair(familyUIName, std::list())); + map->insert(std::make_pair(familyUIName, std::list())); } // 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 &styleList = (*map)[familyUIName]; + std::list &styleList = (*map)[familyUIName]; - for (std::list::iterator it=styleList.begin(); + for (std::list::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 > 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 > FamilyToStylesMap; class font_factory { public: diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 8ce5eccfc..9ff4fad05 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -64,11 +64,13 @@ namespace Inkscape // Now go through the styles GList *styles = NULL; - std::list &styleStrings = familyStyleMap[familyName]; - for (std::list::iterator it=styleStrings.begin(); + std::list &styleStrings = familyStyleMap[familyName]; + for (std::list::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; @@ -81,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(); @@ -96,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 ) { @@ -113,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 ) { @@ -471,7 +492,8 @@ std::pair 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(); @@ -856,7 +878,7 @@ std::pair FontLister::new_font_family (Glib::ustri Gtk::TreeModel::Row row = *iter; - if( familyNamesAreEqual( style, row[FontStyleList.styles] ) ) { + if( familyNamesAreEqual( style, row[FontStyleList.cssStyle] ) ) { return row; } @@ -983,10 +1005,6 @@ std::pair FontLister::new_font_family (Glib::ustri return best_style; } - FontLister::~FontLister () - { - }; - const Glib::RefPtr FontLister::get_font_list () const { 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 styles; + Gtk::TreeModelColumn displayStyle; + + /** Column containing the styles in CSS/Pango format. + */ + Gtk::TreeModelColumn cssStyle; FontStyleListClass () { - add (styles); + add (cssStyle); + add (displayStyle); } }; @@ -276,7 +281,7 @@ namespace Inkscape private: FontLister (); - + NRNameList families; Glib::RefPtr font_list_store; -- cgit v1.2.3 From 3252b41582b781c90648c0ad892f45751377b57c Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 10 Jun 2014 11:40:10 +0200 Subject: Proper quoting of CSS 'font-family' fallback lists. (bzr r13341.1.56) --- src/libnrtype/font-lister.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 9ff4fad05..43c3045b1 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -601,8 +601,15 @@ std::pair 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 ); -- cgit v1.2.3 From 2a2db8af11c2e518bd7bfe520e2f88a7e439d939 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 16 Aug 2014 22:47:53 -0400 Subject: Merge in font-speedup branch to improve launch times (bzr r13341.1.140) --- src/libnrtype/FontFactory.cpp | 76 ++ src/libnrtype/FontFactory.h | 10 +- src/libnrtype/font-lister.cpp | 1697 +++++++++++++++++++++-------------------- src/libnrtype/font-lister.h | 556 +++++++------- 4 files changed, 1216 insertions(+), 1123 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 6859a4a5c..c5e68e264 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -513,6 +513,82 @@ static bool StyleNameCompareInternal(const StyleNames &style1, const StyleNames return( StyleNameValue( style1.CssName ) < StyleNameValue( style2.CssName ) ); } +static bool ustringPairSort(std::pair const& first, std::pair const& second) +{ + // well, this looks weird. + return first.second < second.second; +} + +void font_factory::GetUIFamilies(std::vector& out) +{ + // Gather the family names as listed by Pango + PangoFontFamily** families = NULL; + int numFamilies = 0; + pango_font_map_list_families(fontServer, &families, &numFamilies); + + std::vector > sorted; + + // not size_t + for (int currentFamily = 0; currentFamily < numFamilies; ++currentFamily) { + const char* displayName = pango_font_family_get_name(families[currentFamily]); + + if (displayName == 0 || *displayName == '\0') { + continue; + } + sorted.push_back(std::make_pair(families[currentFamily], displayName)); + } + + std::sort(sorted.begin(), sorted.end(), ustringPairSort); + + for (size_t i = 0; i < sorted.size(); ++i) { + out.push_back(sorted[i].first); + } +} + +GList* font_factory::GetUIStyles(PangoFontFamily * in) +{ + GList* ret = NULL; + // Gather the styles for this family + PangoFontFace** faces = NULL; + int numFaces = 0; + pango_font_family_list_faces(in, &faces, &numFaces); + + for (int currentFace = 0; currentFace < numFaces; currentFace++) { + + // If the face has a name, describe it, and then use the + // description to get the UI family and face strings + const gchar* displayName = pango_font_face_get_face_name(faces[currentFace]); + if (displayName == NULL || *displayName == '\0') { + continue; + } + + PangoFontDescription *faceDescr = pango_font_face_describe(faces[currentFace]); + if (faceDescr) { + Glib::ustring familyUIName = GetUIFamilyString(faceDescr); + Glib::ustring styleUIName = GetUIStyleString(faceDescr); + + // Disable synthesized (faux) font faces except for CSS generic faces + if (pango_font_face_is_synthesized(faces[currentFace]) ) { + if (familyUIName.compare( "sans-serif" ) != 0 && + familyUIName.compare( "serif" ) != 0 && + familyUIName.compare( "monospace" ) != 0 && + familyUIName.compare( "fantasy" ) != 0 && + familyUIName.compare( "cursive" ) != 0 ) { + continue; + } + } + + if (!familyUIName.empty() && !styleUIName.empty()) { + // Add the style information + ret = g_list_append(ret, new StyleNames(styleUIName, displayName)); + } + } + pango_font_description_free(faceDescr); + } + g_free(faces); + return ret; +} + void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map) { g_assert(map); diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h index 513ee4bf7..c48ae831a 100644 --- a/src/libnrtype/FontFactory.h +++ b/src/libnrtype/FontFactory.h @@ -23,7 +23,7 @@ #include "nr-type-primitives.h" #include "nr-type-pos-def.h" #include "font-style-to-pos.h" -#include "../style.h" +#include "style.h" /* Freetype */ #ifdef USE_PANGO_WIN32 @@ -123,7 +123,13 @@ public: // Gathers all strings needed for UI while storing pango information in // fontInstanceMap and fontStringMap + // don't use this function, it's too slow void GetUIFamiliesAndStyles(FamilyToStylesMap *map); + + // Helpfully inserts all font families into the provided vector + void GetUIFamilies(std::vector& out); + // Retrieves style information about a family in a newly allocated GList. + GList* GetUIStyles(PangoFontFamily * in); /// Retrieve a font_instance from a style object, first trying to use the font-specification, the CSS information font_instance* FaceFromStyle(SPStyle const *style); @@ -177,4 +183,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 : diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 43c3045b1..07c80054d 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -1,5 +1,5 @@ #ifdef HAVE_CONFIG_H -# include +#include #endif #include @@ -27,410 +27,432 @@ // 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 ) { +bool familyNamesAreEqual(const Glib::ustring &a, const Glib::ustring &b) +{ + return (a.casefold().compare(b.casefold()) == 0); +} - return( a.casefold().compare( b.casefold() ) == 0 ); +static const char* sp_font_family_get_name(PangoFontFamily* family) +{ + const char* name = pango_font_family_get_name(family); + if (strncmp(name, "Sans", 4) == 0 && strlen(name) == 4) + return "sans-serif"; + if (strncmp(name, "Serif", 5) == 0 && strlen(name) == 5) + return "serif"; + if (strncmp(name, "Monospace", 9) == 0 && strlen(name) == 9) + return "monospace"; + return name; } -namespace Inkscape +namespace Inkscape { + +FontLister::FontLister() { - FontLister::FontLister () - { - font_list_store = Gtk::ListStore::create (FontList); - font_list_store->freeze_notify(); - - FamilyToStylesMap familyStyleMap; - font_factory::Default()->GetUIFamiliesAndStyles(&familyStyleMap); - - // Grab the family names into a list and then sort them - std::list familyList; - for (FamilyToStylesMap::iterator iter = familyStyleMap.begin(); - iter != familyStyleMap.end(); - ++iter) { - familyList.push_back((*iter).first); + font_list_store = Gtk::ListStore::create(FontList); + font_list_store->freeze_notify(); + + /* 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")); + + // Get sorted font families from Pango + std::vector familyVector; + font_factory::Default()->GetUIFamilies(familyVector); + + // Traverse through the family names and set up the list store + for (size_t i = 0; i < familyVector.size(); ++i) { + const char* displayName = sp_font_family_get_name(familyVector[i]); + + if (displayName == 0 || *displayName == '\0') { + continue; } - familyList.sort(); - // Traverse through the family names and set up the list store (note that - // the styles list that are the map's values are already sorted) - while (!familyList.empty()) { - Glib::ustring familyName = familyList.front(); - familyList.pop_front(); - - if (!familyName.empty()) { - Gtk::TreeModel::iterator treeModelIter = font_list_store->append(); - //(*treeModelIter)[FontList.family] = reinterpret_cast(g_strdup(familyName.c_str())); - (*treeModelIter)[FontList.family] = familyName; - - // Now go through the styles - GList *styles = NULL; - std::list &styleStrings = familyStyleMap[familyName]; - for (std::list::iterator it=styleStrings.begin(); - it != styleStrings.end(); - ++it) { - // Our own copy - StyleNames *copy = new StyleNames( *it ); - styles = g_list_append(styles, copy); - } - - (*treeModelIter)[FontList.styles] = styles; - (*treeModelIter)[FontList.onSystem] = true; - } + Glib::ustring familyName = displayName; + if (!familyName.empty()) { + Gtk::TreeModel::iterator treeModelIter = font_list_store->append(); + (*treeModelIter)[FontList.family] = familyName; + + // we don't set this now (too slow) but the style will be cached if the user + // ever decides to use this font + (*treeModelIter)[FontList.styles] = NULL; + // store the pango representation for generating the style + (*treeModelIter)[FontList.pango_family] = familyVector[i]; + (*treeModelIter)[FontList.onSystem] = true; } - current_family_row = 0; - current_family = "sans-serif"; - current_style = "Normal"; - 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, 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(); - - style_list_store = Gtk::ListStore::create (FontStyleList); - - // Initialize style store with defaults - style_list_store->freeze_notify(); - style_list_store->clear(); - for (GList *l=default_styles; l; l = l->next) { - Gtk::TreeModel::iterator treeModelIter = style_list_store->append(); - (*treeModelIter)[FontStyleList.cssStyle] = ((StyleNames*)l->data)->CssName; - (*treeModelIter)[FontStyleList.displayStyle] = ((StyleNames*)l->data)->DisplayName; + } + + current_family_row = 0; + current_family = "sans-serif"; + current_style = "Normal"; + current_fontspec = "sans-serif"; // Empty style -> Normal + current_fontspec_system = "Sans"; + + font_list_store->thaw_notify(); + + style_list_store = Gtk::ListStore::create(FontStyleList); + + // Initialize style store with defaults + style_list_store->freeze_notify(); + style_list_store->clear(); + for (GList *l = default_styles; l; l = l->next) { + Gtk::TreeModel::iterator treeModelIter = style_list_store->append(); + (*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); } - style_list_store->thaw_notify(); + ++iter; } +} - FontLister::~FontLister() { +FontLister *FontLister::get_instance() +{ + static Inkscape::FontLister *instance = new Inkscape::FontLister(); + return instance; +} - // Delete default_styles - for (GList *l=default_styles; l; l = l->next) { - delete ((StyleNames*)l->data); +void FontLister::ensureRowStyles(GtkTreeModel* model, GtkTreeIter const* iterator) +{ + Gtk::TreeIter iter(model, iterator); + Gtk::TreeModel::Row row = *iter; + if (!row[FontList.styles]) { + if (row[FontList.pango_family]) { + row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]); } + } +} - // 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); +// Example of how to use "foreach_iter" +// bool +// FontLister::print_document_font( const Gtk::TreeModel::iterator &iter ) { +// Gtk::TreeModel::Row row = *iter; +// if( !row[FontList.onSystem] ) { +// std::cout << " Not on system: " << row[FontList.family] << std::endl; +// return false; +// } +// return true; +// } +// 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) +{ + GList *styles = default_styles; + + /* In case this is a fallback list, check if first font-family on system. */ + std::vector tokens = Glib::Regex::split_simple(",", new_family); + if (!tokens.empty() && !tokens[0].empty()) { + 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] && familyNamesAreEqual(tokens[0], row[FontList.family])) { + if (!row[FontList.styles]) { + row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]); + } + styles = row[FontList.styles]; + break; } - ++iter; + ++iter2; } } - // Example of how to use "foreach_iter" - // bool - // FontLister::print_document_font( const Gtk::TreeModel::iterator &iter ) { - // Gtk::TreeModel::Row row = *iter; - // if( !row[FontList.onSystem] ) { - // std::cout << " Not on system: " << row[FontList.family] << std::endl; - // return false; - // } - // return true; - // } - // 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 ) { - - GList *styles = default_styles; - - /* In case this is a fallback list, check if first font-family on system. */ - std::vector tokens = Glib::Regex::split_simple(",", new_family ); - if( !tokens.empty() && !tokens[0].empty() ) { - - 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] && familyNamesAreEqual( tokens[0], row[FontList.family] ) ) { - styles = row[FontList.styles]; + Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend(); + (*treeModelIter)[FontList.family] = new_family; + (*treeModelIter)[FontList.styles] = styles; + (*treeModelIter)[FontList.onSystem] = false; +} + +void FontLister::update_font_list(SPDocument *document) +{ + SPObject *r = document->getRoot(); + if (!r) { + return; + } + + font_list_store->freeze_notify(); + + /* Find if current row is in document or system part of list */ + gboolean row_is_system = false; + if (current_family_row > -1) { + Gtk::TreePath path; + path.push_back(current_family_row); + Gtk::TreeModel::iterator iter = font_list_store->get_iter(path); + if (iter) { + row_is_system = (*iter)[FontList.onSystem]; + // std::cout << " In: row: " << current_family_row << " " << (*iter)[FontList.family] << std::endl; + } + } + + /* Clear all old document font-family entries */ + Gtk::TreeModel::iterator iter = font_list_store->get_iter("0"); + while (iter != font_list_store->children().end()) { + Gtk::TreeModel::Row row = *iter; + if (!row[FontList.onSystem]) { + // std::cout << " Not on system: " << row[FontList.family] << std::endl; + iter = font_list_store->erase(iter); + } else { + // std::cout << " First on system: " << row[FontList.family] << std::endl; break; - } - ++iter2; } - } + } + + /* Get "font-family"s used in document. */ + std::list fontfamilies; + update_font_list_recursive(r, &fontfamilies); + + fontfamilies.sort(); + fontfamilies.unique(); + fontfamilies.reverse(); + - Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend(); - (*treeModelIter)[FontList.family] = reinterpret_cast(g_strdup(new_family.c_str())); - (*treeModelIter)[FontList.styles] = styles; - (*treeModelIter)[FontList.onSystem] = false; + /* Insert separator */ + if (!fontfamilies.empty()) { + Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend(); + (*treeModelIter)[FontList.family] = "#"; + (*treeModelIter)[FontList.onSystem] = false; } - void - FontLister::update_font_list( SPDocument* document ) { - - SPObject *r = document->getRoot(); - if( !r ) { - return; - } - - font_list_store->freeze_notify(); - - /* Find if current row is in document or system part of list */ - gboolean row_is_system = false; - if( current_family_row > -1 ) { - Gtk::TreePath path; - path.push_back( current_family_row ); - Gtk::TreeModel::iterator iter = font_list_store->get_iter( path ); - if( iter ) { - row_is_system = (*iter)[FontList.onSystem]; - // std::cout << " In: row: " << current_family_row << " " << (*iter)[FontList.family] << std::endl; - } - } - - /* Clear all old document font-family entries */ - Gtk::TreeModel::iterator iter = font_list_store->get_iter( "0" ); - while( iter != font_list_store->children().end() ) { - Gtk::TreeModel::Row row = *iter; - if( !row[FontList.onSystem] ) { - // std::cout << " Not on system: " << row[FontList.family] << std::endl; - iter = font_list_store->erase( iter ); - } else { - // std::cout << " First on system: " << row[FontList.family] << std::endl; - break; - } - } - - /* Get "font-family"s used in document. */ - std::list fontfamilies; - update_font_list_recursive( r, &fontfamilies ); - - fontfamilies.sort(); - fontfamilies.unique(); - fontfamilies.reverse(); - - /* Insert separator */ - if( !fontfamilies.empty() ) { - Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend(); - (*treeModelIter)[FontList.family] = "#"; - (*treeModelIter)[FontList.onSystem] = false; - } - - /* Insert font-family's in document. */ - std::list::iterator i; - for( i = fontfamilies.begin(); i != fontfamilies.end(); ++i) { - - GList *styles = default_styles; + /* Insert font-family's in document. */ + std::list::iterator i; + for (i = fontfamilies.begin(); i != fontfamilies.end(); ++i) { + + GList *styles = default_styles; /* See if font-family (or first in fallback list) is on system. If so, get styles. */ - std::vector tokens = Glib::Regex::split_simple(",", *i ); - if( !tokens.empty() && !tokens[0].empty() ) { - - 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] && familyNamesAreEqual( tokens[0], row[FontList.family] ) ) { - styles = row[FontList.styles]; - break; - } - ++iter2; - } - } - - Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend(); - (*treeModelIter)[FontList.family] = reinterpret_cast(g_strdup((*i).c_str())); - (*treeModelIter)[FontList.styles] = styles; - (*treeModelIter)[FontList.onSystem] = false; - } - - /* Now we do a song and dance to find the correct row as the row corresponding - * to the current_family may have changed. We can't simply search for the - * family name in the list since it can occur twice, once in the document - * font family part and once in the system font family part. Above we determined - * which part it is in. - */ - if( current_family_row > -1 ) { - int start = 0; - if( row_is_system ) start = fontfamilies.size(); - int length = font_list_store->children().size(); - for( int i = 0; i < length; ++i ) { - int row = i + start; - if( row >= length ) row -= length; - Gtk::TreePath path; - path.push_back( row ); - Gtk::TreeModel::iterator iter = font_list_store->get_iter( path ); - if( iter ) { - if( familyNamesAreEqual( current_family, (*iter)[FontList.family] ) ) { - current_family_row = row; - break; - } - } - } - } - // std::cout << " Out: row: " << current_family_row << " " << current_family << std::endl; - - font_list_store->thaw_notify(); + std::vector tokens = Glib::Regex::split_simple(",", *i); + if (!tokens.empty() && !tokens[0].empty()) { + + 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] && familyNamesAreEqual(tokens[0], row[FontList.family])) { + if (!row[FontList.styles]) { + row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]); + } + styles = row[FontList.styles]; + break; + } + ++iter2; + } + } + + Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend(); + (*treeModelIter)[FontList.family] = reinterpret_cast(g_strdup((*i).c_str())); + (*treeModelIter)[FontList.styles] = styles; + (*treeModelIter)[FontList.onSystem] = false; + } - void - FontLister::update_font_list_recursive( SPObject *r, std::list *l ) { + /* Now we do a song and dance to find the correct row as the row corresponding + * to the current_family may have changed. We can't simply search for the + * family name in the list since it can occur twice, once in the document + * font family part and once in the system font family part. Above we determined + * which part it is in. + */ + if (current_family_row > -1) { + int start = 0; + if (row_is_system) + start = fontfamilies.size(); + int length = font_list_store->children().size(); + for (int i = 0; i < length; ++i) { + int row = i + start; + if (row >= length) + row -= length; + Gtk::TreePath path; + path.push_back(row); + Gtk::TreeModel::iterator iter = font_list_store->get_iter(path); + if (iter) { + if (familyNamesAreEqual(current_family, (*iter)[FontList.family])) { + current_family_row = row; + break; + } + } + } + } + // std::cout << " Out: row: " << current_family_row << " " << current_family << std::endl; - const gchar *font_family = r->style->font_family.value; - if( font_family ) { - l->push_back( Glib::ustring( font_family ) ); - } + font_list_store->thaw_notify(); +} - for (SPObject *child = r->firstChild(); child; child = child->getNext()) { - update_font_list_recursive( child, l ); - } +void FontLister::update_font_list_recursive(SPObject *r, std::list *l) +{ + const gchar *font_family = r->style->font_family.value; + if (font_family) { + l->push_back(Glib::ustring(font_family)); } - Glib::ustring - FontLister::canonize_fontspec( Glib::ustring fontspec ) { - - // Pass fontspec to and back from Pango to get a the fontspec in - // canonical form. -inkscape-font-specification relies on the - // Pango constructed fontspec not changing form. If it does, - // this is the place to fix it. - PangoFontDescription *descr = pango_font_description_from_string( fontspec.c_str() ); - gchar* canonized = pango_font_description_to_string ( descr ); - Glib::ustring Canonized = canonized; - g_free( canonized ); - pango_font_description_free( descr ); - - // Pango canonized strings remove space after comma between family names. Put it back. - size_t i = 0; - while( (i = Canonized.find(",", i)) != std::string::npos) { - Canonized.replace(i, 1, ", "); - i += 2; - } - - return Canonized; + for (SPObject *child = r->firstChild(); child; child = child->getNext()) { + update_font_list_recursive(child, l); } +} + +Glib::ustring FontLister::canonize_fontspec(Glib::ustring fontspec) +{ - Glib::ustring - FontLister::system_fontspec( Glib::ustring fontspec ) { + // Pass fontspec to and back from Pango to get a the fontspec in + // canonical form. -inkscape-font-specification relies on the + // Pango constructed fontspec not changing form. If it does, + // this is the place to fix it. + PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str()); + gchar *canonized = pango_font_description_to_string(descr); + Glib::ustring Canonized = canonized; + g_free(canonized); + pango_font_description_free(descr); + + // Pango canonized strings remove space after comma between family names. Put it back. + size_t i = 0; + while ((i = Canonized.find(",", i)) != std::string::npos) { + Canonized.replace(i, 1, ", "); + i += 2; + } - // Find what Pango thinks is the closest match. - Glib::ustring out = fontspec; + return Canonized; +} - PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str()); - font_instance *res = (font_factory::Default())->Face(descr); - if (res->pFont) { +Glib::ustring FontLister::system_fontspec(Glib::ustring fontspec) +{ + + // Find what Pango thinks is the closest match. + Glib::ustring out = fontspec; + + PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str()); + font_instance *res = (font_factory::Default())->Face(descr); + if (res->pFont) { PangoFontDescription *nFaceDesc = pango_font_describe(res->pFont); out = sp_font_description_get_family(nFaceDesc); - } - pango_font_description_free(descr); - - return out; } + pango_font_description_free(descr); + + return out; +} - std::pair - FontLister::ui_from_fontspec( Glib::ustring fontspec ) { - - PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str()); - const gchar* family = pango_font_description_get_family(descr); - if(!family) - family = "sans-serif"; - Glib::ustring Family = family; - - // PANGO BUG... - // A font spec of Delicious, 500 Italic should result in a family of 'Delicious' - // and a style of 'Medium Italic'. It results instead with: a family of - // 'Delicious, 500' with a style of 'Medium Italic'. We chop of any weight numbers - // at the end of the family: match ",[1-9]00^". - Glib::RefPtr weight = Glib::Regex::create(",[1-9]00$"); - Family = weight->replace( Family, 0, "", Glib::REGEX_MATCH_PARTIAL ); - - // Pango canonized strings remove space after comma between family names. Put it back. - size_t i = 0; - while( (i = Family.find(",", i)) != std::string::npos) { - Family.replace(i, 1, ", "); - i += 2; - } - - pango_font_description_unset_fields(descr, PANGO_FONT_MASK_FAMILY); - gchar* style = pango_font_description_to_string( descr ); - Glib::ustring Style = style; - pango_font_description_free(descr); - g_free( style ); - - return std::make_pair( Family, Style ); +std::pair FontLister::ui_from_fontspec(Glib::ustring fontspec) +{ + PangoFontDescription *descr = pango_font_description_from_string(fontspec.c_str()); + const gchar *family = pango_font_description_get_family(descr); + if (!family) + family = "sans-serif"; + Glib::ustring Family = family; + + // PANGO BUG... + // A font spec of Delicious, 500 Italic should result in a family of 'Delicious' + // and a style of 'Medium Italic'. It results instead with: a family of + // 'Delicious, 500' with a style of 'Medium Italic'. We chop of any weight numbers + // at the end of the family: match ",[1-9]00^". + Glib::RefPtr weight = Glib::Regex::create(",[1-9]00$"); + Family = weight->replace(Family, 0, "", Glib::REGEX_MATCH_PARTIAL); + + // Pango canonized strings remove space after comma between family names. Put it back. + size_t i = 0; + while ((i = Family.find(",", i)) != std::string::npos) { + Family.replace(i, 1, ", "); + i += 2; } - std::pair - FontLister::selection_update () { + pango_font_description_unset_fields(descr, PANGO_FONT_MASK_FAMILY); + gchar *style = pango_font_description_to_string(descr); + Glib::ustring Style = style; + pango_font_description_free(descr); + g_free(style); + + return std::make_pair(Family, Style); +} + +std::pair FontLister::selection_update() +{ #ifdef DEBUG_FONT - std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; - std::cout << "FontLister::selection_update: entrance" << std::endl; + std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; + std::cout << "FontLister::selection_update: entrance" << std::endl; #endif - // Get fontspec from a selection, preferences, or thin air. - Glib::ustring fontspec; - SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); - - // Directly from stored font specification. - int result = - sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION); - - //std::cout << " Attempting selected style" << std::endl; - if( result != QUERY_STYLE_NOTHING && query->font_specification.set ) { - fontspec = query->font_specification.value; - //std::cout << " fontspec from query :" << fontspec << ":" << std::endl; - } - - // From style - if( fontspec.empty() ) { + // Get fontspec from a selection, preferences, or thin air. + Glib::ustring fontspec; + SPStyle *query = sp_style_new(SP_ACTIVE_DOCUMENT); + + // Directly from stored font specification. + int result = + sp_desktop_query_style(SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION); + + //std::cout << " Attempting selected style" << std::endl; + if (result != QUERY_STYLE_NOTHING && query->font_specification.set) { + fontspec = query->font_specification.value; + //std::cout << " fontspec from query :" << fontspec << ":" << std::endl; + } + + // From style + if (fontspec.empty()) { //std::cout << " Attempting desktop style" << std::endl; - int rfamily = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY); - int rstyle = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE); - - // Must have text in selection - if( rfamily != QUERY_STYLE_NOTHING && rstyle != QUERY_STYLE_NOTHING ) { - fontspec = fontspec_from_style( query ); - } - //std::cout << " fontspec from style :" << fontspec << ":" << std::endl; - } - - // From preferences - if( fontspec.empty() ) { + int rfamily = sp_desktop_query_style(SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY); + int rstyle = sp_desktop_query_style(SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE); + + // Must have text in selection + if (rfamily != QUERY_STYLE_NOTHING && rstyle != QUERY_STYLE_NOTHING) { + fontspec = fontspec_from_style(query); + } + //std::cout << " fontspec from style :" << fontspec << ":" << std::endl; + } + + // From preferences + if (fontspec.empty()) { //std::cout << " Attempting preferences" << std::endl; sp_style_read_from_prefs(query, "/tools/text"); - fontspec = fontspec_from_style( query ); - //std::cout << " fontspec from prefs :" << fontspec << ":" << std::endl; - } - sp_style_unref(query); + fontspec = fontspec_from_style(query); + //std::cout << " fontspec from prefs :" << fontspec << ":" << std::endl; + } + sp_style_unref(query); - // From thin air - if( fontspec.empty() ) { + // From thin air + if (fontspec.empty()) { //std::cout << " Attempting thin air" << std::endl; - fontspec = current_family + ", " + current_style; - //std::cout << " fontspec from thin air :" << fontspec << ":" << std::endl; - } - - // Do we really need? Removes spaces between font-families. - //current_fontspec = canonize_fontspec( fontspec ); - current_fontspec = fontspec; // Ignore for now + fontspec = current_family + ", " + current_style; + //std::cout << " fontspec from thin air :" << fontspec << ":" << std::endl; + } + + // Do we really need? Removes spaces between font-families. + //current_fontspec = canonize_fontspec( fontspec ); + current_fontspec = fontspec; // Ignore for now - current_fontspec_system = system_fontspec( current_fontspec ); + current_fontspec_system = system_fontspec(current_fontspec); - std::pair ui = ui_from_fontspec( current_fontspec ); - set_font_family( ui.first ); - set_font_style( ui.second ); + std::pair 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; - std::cout << " canonized: :" << current_fontspec << ":" << std::endl; - std::cout << " system: :" << current_fontspec_system << ":" << std::endl; - std::cout << " family: :" << current_family << ":" << std::endl; - std::cout << " style: :" << current_style << ":" << std::endl; - std::cout << "FontLister::selection_update: exit" << std::endl; - std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; + std::cout << " family_row: :" << current_family_row << ":" << std::endl; + std::cout << " canonized: :" << current_fontspec << ":" << std::endl; + std::cout << " system: :" << current_fontspec_system << ":" << std::endl; + std::cout << " family: :" << current_family << ":" << std::endl; + std::cout << " style: :" << current_style << ":" << std::endl; + std::cout << "FontLister::selection_update: exit" << std::endl; + std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; #endif - return std::make_pair( current_family, current_style ); - } - + return std::make_pair(current_family, current_style); +} + // Set fontspec. If check is false, best style match will not be done. -void FontLister::set_fontspec(Glib::ustring new_fontspec, gboolean /*check*/) +void FontLister::set_fontspec(Glib::ustring new_fontspec, bool /*check*/) { - std::pair ui = ui_from_fontspec( new_fontspec ); + std::pair ui = ui_from_fontspec(new_fontspec); Glib::ustring new_family = ui.first; Glib::ustring new_style = ui.second; @@ -439,13 +461,13 @@ void FontLister::set_fontspec(Glib::ustring new_fontspec, gboolean /*check*/) << " style:" << new_style << std::endl; #endif - set_font_family( new_family, false ); - set_font_style( new_style ); + set_font_family(new_family, false); + set_font_style(new_style); } // TODO: use to determine font-selector best style -std::pair FontLister::new_font_family (Glib::ustring new_family, gboolean /*check_style*/ ) +std::pair FontLister::new_font_family(Glib::ustring new_family, bool /*check_style*/) { #ifdef DEBUG_FONT std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; @@ -453,12 +475,12 @@ std::pair FontLister::new_font_family (Glib::ustri #endif // No need to do anything if new family is same as old family. - if ( familyNamesAreEqual( new_family, current_family ) ) { + 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; + std::cout << "FontLister::new_font_family: exit: no change in family." << std::endl; + std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; #endif - return std::make_pair( current_family, current_style ); + return std::make_pair(current_family, current_style); } // We need to do two things: @@ -466,596 +488,597 @@ std::pair FontLister::new_font_family (Glib::ustri // 2. Select best valid style match to old style. // For finding style list, use list of first family in font-family list. - GList* styles = NULL; - Gtk::TreeModel::iterator iter = font_list_store->get_iter( "0" ); - while( iter != font_list_store->children().end() ) { + GList *styles = NULL; + Gtk::TreeModel::iterator iter = font_list_store->get_iter("0"); + while (iter != font_list_store->children().end()) { - Gtk::TreeModel::Row row = *iter; + Gtk::TreeModel::Row row = *iter; - if( familyNamesAreEqual( new_family, row[FontList.family] ) ) { + if (familyNamesAreEqual(new_family, row[FontList.family])) { + if (!row[FontList.styles]) { + row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]); + } styles = row[FontList.styles]; break; - } - ++iter; + } + ++iter; } // Newly typed in font-family may not yet be in list... use default list. // TODO: if font-family is list, check if first family in list is on system // and set style accordingly. - if( styles == NULL ) { - styles = default_styles; + if (styles == NULL) { + styles = default_styles; } - + // Update style list. style_list_store->freeze_notify(); style_list_store->clear(); - for (GList *l=styles; l; l = l->next) { - Gtk::TreeModel::iterator treeModelIter = style_list_store->append(); - (*treeModelIter)[FontStyleList.cssStyle] = ((StyleNames*)l->data)->CssName; - (*treeModelIter)[FontStyleList.displayStyle] = ((StyleNames*)l->data)->DisplayName; + for (GList *l = styles; l; l = l->next) { + Gtk::TreeModel::iterator treeModelIter = style_list_store->append(); + (*treeModelIter)[FontStyleList.cssStyle] = ((StyleNames *)l->data)->CssName; + (*treeModelIter)[FontStyleList.displayStyle] = ((StyleNames *)l->data)->DisplayName; } style_list_store->thaw_notify(); - + // Find best match to the style from the old font-family to the // styles available with the new font. // TODO: Maybe check if an exact match exists before using Pango. - Glib::ustring best_style = get_best_style_match( new_family, current_style ); + Glib::ustring best_style = get_best_style_match(new_family, current_style); #ifdef DEBUG_FONT std::cout << "FontLister::new_font_family: exit: " << new_family << " " << best_style << std::endl; std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; #endif - return std::make_pair( new_family, best_style ); + return std::make_pair(new_family, best_style); } - - std::pair - FontLister::set_font_family (Glib::ustring new_family, gboolean check_style) { + +std::pair FontLister::set_font_family(Glib::ustring new_family, bool check_style) +{ #ifdef DEBUG_FONT - std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; - std::cout << "FontLister::set_font_family: " << new_family << std::endl; + std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; + std::cout << "FontLister::set_font_family: " << new_family << std::endl; #endif - std::pair ui = new_font_family( new_family, check_style ); - current_family = ui.first; - current_style = ui.second; - current_fontspec = canonize_fontspec( current_family + ", " + current_style ); - current_fontspec_system = system_fontspec( current_fontspec ); + std::pair ui = new_font_family(new_family, check_style); + current_family = ui.first; + current_style = ui.second; + current_fontspec = canonize_fontspec(current_family + ", " + current_style); + current_fontspec_system = system_fontspec(current_fontspec); #ifdef DEBUG_FONT - std::cout << " family_row: :" << current_family_row << ":" << std::endl; - std::cout << " canonized: :" << current_fontspec << ":" << std::endl; - std::cout << " system: :" << current_fontspec_system << ":" << std::endl; - std::cout << " family: :" << current_family << ":" << std::endl; - std::cout << " style: :" << current_style << ":" << std::endl; - std::cout << "FontLister::set_font_family: end" << std::endl; - std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; + std::cout << " family_row: :" << current_family_row << ":" << std::endl; + std::cout << " canonized: :" << current_fontspec << ":" << std::endl; + std::cout << " system: :" << current_fontspec_system << ":" << std::endl; + std::cout << " family: :" << current_family << ":" << std::endl; + std::cout << " style: :" << current_style << ":" << std::endl; + std::cout << "FontLister::set_font_family: end" << std::endl; + std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; #endif - return ui; - } - + return ui; +} - std::pair - FontLister::set_font_family (int row, gboolean check_style) { + +std::pair FontLister::set_font_family(int row, bool check_style) +{ #ifdef DEBUG_FONT - std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; - std::cout << "FontLister::set_font_family( row ): " << row << std::endl; + std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; + std::cout << "FontLister::set_font_family( row ): " << row << std::endl; #endif - current_family_row = row; - Gtk::TreePath path; - path.push_back( row ); - Glib::ustring new_family = current_family; - Gtk::TreeModel::iterator iter = font_list_store->get_iter( path ); - if( iter ) { - new_family = (*iter)[FontList.family]; - } + current_family_row = row; + Gtk::TreePath path; + path.push_back(row); + Glib::ustring new_family = current_family; + Gtk::TreeModel::iterator iter = font_list_store->get_iter(path); + if (iter) { + new_family = (*iter)[FontList.family]; + } - std::pair ui = set_font_family( new_family, check_style ); + std::pair ui = set_font_family(new_family, check_style); #ifdef DEBUG_FONT - std::cout << "FontLister::set_font_family( row ): end" << std::endl; - std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; + std::cout << "FontLister::set_font_family( row ): end" << std::endl; + std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; #endif - return ui; - } + return ui; +} - void - FontLister::set_font_style (Glib::ustring new_style) { +void FontLister::set_font_style(Glib::ustring new_style) +{ - // TODO: Validate input using Pango. If Pango doesn't recognize a style it will - // attach the "invalid" style to the font-family. +// TODO: Validate input using Pango. If Pango doesn't recognize a style it will +// attach the "invalid" style to the font-family. #ifdef DEBUG_FONT - std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; - std::cout << "FontLister:set_font_style: " << new_style << std::endl; + std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; + std::cout << "FontLister:set_font_style: " << new_style << std::endl; #endif - current_style = new_style; - current_fontspec = canonize_fontspec( current_family + ", " + current_style ); - current_fontspec_system = system_fontspec( current_fontspec ); + current_style = new_style; + current_fontspec = canonize_fontspec(current_family + ", " + current_style); + current_fontspec_system = system_fontspec(current_fontspec); #ifdef DEBUG_FONT - std::cout << " canonized: :" << current_fontspec << ":" << std::endl; - std::cout << " system: :" << current_fontspec_system << ":" << std::endl; - std::cout << " family: " << current_family << std::endl; - std::cout << " style: " << current_style << std::endl; - std::cout << "FontLister::set_font_style: end" << std::endl; - std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; + std::cout << " canonized: :" << current_fontspec << ":" << std::endl; + std::cout << " system: :" << current_fontspec_system << ":" << std::endl; + std::cout << " family: " << current_family << std::endl; + std::cout << " style: " << current_style << std::endl; + std::cout << "FontLister::set_font_style: end" << std::endl; + std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; #endif +} + + +// We do this ourselves as we can't rely on FontFactory. +void FontLister::fill_css(SPCSSAttr *css, Glib::ustring fontspec) +{ + + if (fontspec.empty()) { + fontspec = current_fontspec; + } + std::pair ui = ui_from_fontspec(fontspec); + + Glib::ustring family = ui.first; + + + // 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); + switch (weight) { + case PANGO_WEIGHT_THIN: + sp_repr_css_set_property(css, "font-weight", "100"); + break; + case PANGO_WEIGHT_ULTRALIGHT: + sp_repr_css_set_property(css, "font-weight", "200"); + break; + case PANGO_WEIGHT_LIGHT: + sp_repr_css_set_property(css, "font-weight", "300"); + break; + case PANGO_WEIGHT_BOOK: + sp_repr_css_set_property(css, "font-weight", "380"); + break; + case PANGO_WEIGHT_NORMAL: + sp_repr_css_set_property(css, "font-weight", "normal"); + break; + case PANGO_WEIGHT_MEDIUM: + sp_repr_css_set_property(css, "font-weight", "500"); + break; + case PANGO_WEIGHT_SEMIBOLD: + sp_repr_css_set_property(css, "font-weight", "600"); + break; + case PANGO_WEIGHT_BOLD: + sp_repr_css_set_property(css, "font-weight", "bold"); + break; + case PANGO_WEIGHT_ULTRABOLD: + sp_repr_css_set_property(css, "font-weight", "800"); + break; + case PANGO_WEIGHT_HEAVY: + sp_repr_css_set_property(css, "font-weight", "900"); + break; + case PANGO_WEIGHT_ULTRAHEAVY: + sp_repr_css_set_property(css, "font-weight", "1000"); + break; + } + + PangoStyle style = pango_font_description_get_style(desc); + switch (style) { + case PANGO_STYLE_NORMAL: + sp_repr_css_set_property(css, "font-style", "normal"); + break; + case PANGO_STYLE_OBLIQUE: + sp_repr_css_set_property(css, "font-style", "oblique"); + break; + case PANGO_STYLE_ITALIC: + sp_repr_css_set_property(css, "font-style", "italic"); + break; } + PangoStretch stretch = pango_font_description_get_stretch(desc); + switch (stretch) { + case PANGO_STRETCH_ULTRA_CONDENSED: + sp_repr_css_set_property(css, "font-stretch", "ultra-condensed"); + break; + case PANGO_STRETCH_EXTRA_CONDENSED: + sp_repr_css_set_property(css, "font-stretch", "extra-condensed"); + break; + case PANGO_STRETCH_CONDENSED: + sp_repr_css_set_property(css, "font-stretch", "condensed"); + break; + case PANGO_STRETCH_SEMI_CONDENSED: + sp_repr_css_set_property(css, "font-stretch", "semi-condensed"); + break; + case PANGO_STRETCH_NORMAL: + sp_repr_css_set_property(css, "font-stretch", "normal"); + break; + case PANGO_STRETCH_SEMI_EXPANDED: + sp_repr_css_set_property(css, "font-stretch", "semi-expanded"); + break; + case PANGO_STRETCH_EXPANDED: + sp_repr_css_set_property(css, "font-stretch", "expanded"); + break; + case PANGO_STRETCH_EXTRA_EXPANDED: + sp_repr_css_set_property(css, "font-stretch", "extra-expanded"); + break; + case PANGO_STRETCH_ULTRA_EXPANDED: + sp_repr_css_set_property(css, "font-stretch", "ultra-expanded"); + break; + } - // We do this ourselves as we can't rely on FontFactory. - void - FontLister::fill_css( SPCSSAttr *css, Glib::ustring fontspec ) { - - if( fontspec.empty() ) { - fontspec = current_fontspec; - } - std::pair ui = ui_from_fontspec( fontspec ); - - Glib::ustring family = ui.first; - - - // 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 ); - switch ( weight ) { - case PANGO_WEIGHT_THIN: - sp_repr_css_set_property (css, "font-weight", "100" ); - break; - case PANGO_WEIGHT_ULTRALIGHT: - sp_repr_css_set_property (css, "font-weight", "200" ); - break; - case PANGO_WEIGHT_LIGHT: - sp_repr_css_set_property (css, "font-weight", "300" ); - break; - case PANGO_WEIGHT_BOOK: - sp_repr_css_set_property (css, "font-weight", "380" ); - break; - case PANGO_WEIGHT_NORMAL: - sp_repr_css_set_property (css, "font-weight", "normal" ); - break; - case PANGO_WEIGHT_MEDIUM: - sp_repr_css_set_property (css, "font-weight", "500" ); - break; - case PANGO_WEIGHT_SEMIBOLD: - sp_repr_css_set_property (css, "font-weight", "600" ); - break; - case PANGO_WEIGHT_BOLD: - sp_repr_css_set_property (css, "font-weight", "bold" ); - break; - case PANGO_WEIGHT_ULTRABOLD: - sp_repr_css_set_property (css, "font-weight", "800" ); - break; - case PANGO_WEIGHT_HEAVY: - sp_repr_css_set_property (css, "font-weight", "900" ); - break; - case PANGO_WEIGHT_ULTRAHEAVY: - sp_repr_css_set_property (css, "font-weight", "1000" ); - break; - } - - PangoStyle style = pango_font_description_get_style( desc ); - switch ( style ) { - case PANGO_STYLE_NORMAL: - sp_repr_css_set_property (css, "font-style", "normal" ); - break; - case PANGO_STYLE_OBLIQUE: - sp_repr_css_set_property (css, "font-style", "oblique" ); - break; - case PANGO_STYLE_ITALIC: - sp_repr_css_set_property (css, "font-style", "italic" ); - break; - } - - PangoStretch stretch = pango_font_description_get_stretch( desc ); - switch ( stretch ) { - case PANGO_STRETCH_ULTRA_CONDENSED: - sp_repr_css_set_property (css, "font-stretch", "ultra-condensed" ); - break; - case PANGO_STRETCH_EXTRA_CONDENSED: - sp_repr_css_set_property (css, "font-stretch", "extra-condensed" ); - break; - case PANGO_STRETCH_CONDENSED: - sp_repr_css_set_property (css, "font-stretch", "condensed" ); - break; - case PANGO_STRETCH_SEMI_CONDENSED: - sp_repr_css_set_property (css, "font-stretch", "semi-condensed" ); - break; - case PANGO_STRETCH_NORMAL: - sp_repr_css_set_property (css, "font-stretch", "normal" ); - break; - case PANGO_STRETCH_SEMI_EXPANDED: - sp_repr_css_set_property (css, "font-stretch", "semi-expanded" ); - break; - case PANGO_STRETCH_EXPANDED: - sp_repr_css_set_property (css, "font-stretch", "expanded" ); - break; - case PANGO_STRETCH_EXTRA_EXPANDED: - sp_repr_css_set_property (css, "font-stretch", "extra-expanded" ); - break; - case PANGO_STRETCH_ULTRA_EXPANDED: - sp_repr_css_set_property (css, "font-stretch", "ultra-expanded" ); - break; - } - - PangoVariant variant = pango_font_description_get_variant( desc ); - switch ( variant ) { - case PANGO_VARIANT_NORMAL: - sp_repr_css_set_property (css, "font-variant", "normal" ); - break; - case PANGO_VARIANT_SMALL_CAPS: - sp_repr_css_set_property (css, "font-variant", "small-caps" ); - break; - } + PangoVariant variant = pango_font_description_get_variant(desc); + switch (variant) { + case PANGO_VARIANT_NORMAL: + sp_repr_css_set_property(css, "font-variant", "normal"); + break; + case PANGO_VARIANT_SMALL_CAPS: + sp_repr_css_set_property(css, "font-variant", "small-caps"); + break; } +} - // We do this ourselves as we can't rely on FontFactory. - Glib::ustring - FontLister::fontspec_from_style (SPStyle* style) { +// We do this ourselves as we can't rely on FontFactory. +Glib::ustring FontLister::fontspec_from_style(SPStyle *style) +{ - //std::cout << "FontLister:fontspec_from_style: " << std::endl; + //std::cout << "FontLister:fontspec_from_style: " << std::endl; - Glib::ustring fontspec; - if (style) { + Glib::ustring fontspec; + if (style) { - // First try to use the font specification if it is set - if (style->font_specification.set - && style->font_specification.value - && *style->font_specification.value) { + // First try to use the font specification if it is set + if (style->font_specification.set && style->font_specification.value && *style->font_specification.value) { - fontspec = style->font_specification.value; + fontspec = style->font_specification.value; } else { - fontspec = style->font_family.value; - fontspec += ","; - - // Use weight names as defined by Pango - switch (style->font_weight.computed) { + fontspec = style->font_family.value; + fontspec += ","; - case SP_CSS_FONT_WEIGHT_100: - fontspec += " Thin"; - break; - - case SP_CSS_FONT_WEIGHT_200: - fontspec += " Ultra-Light"; - break; + // Use weight names as defined by Pango + switch (style->font_weight.computed) { - case SP_CSS_FONT_WEIGHT_300: - fontspec += " Light"; - break; + case SP_CSS_FONT_WEIGHT_100: + fontspec += " Thin"; + break; - case SP_CSS_FONT_WEIGHT_400: - case SP_CSS_FONT_WEIGHT_NORMAL: - //fontspec += " normal"; - break; - - case SP_CSS_FONT_WEIGHT_500: - fontspec += " Medium"; - break; - - case SP_CSS_FONT_WEIGHT_600: - fontspec += " Semi-Bold"; - break; - - case SP_CSS_FONT_WEIGHT_700: - case SP_CSS_FONT_WEIGHT_BOLD: - fontspec += " Bold"; - break; - - case SP_CSS_FONT_WEIGHT_800: - fontspec += " Ultra-Bold"; - break; - - case SP_CSS_FONT_WEIGHT_900: - fontspec += " Heavy"; - break; - - case SP_CSS_FONT_WEIGHT_LIGHTER: - case SP_CSS_FONT_WEIGHT_BOLDER: - default: - g_warning("Unrecognized font_weight.computed value"); - break; - } - - switch (style->font_style.computed) { - case SP_CSS_FONT_STYLE_ITALIC: - fontspec += " italic"; - break; - - case SP_CSS_FONT_STYLE_OBLIQUE: - fontspec += " oblique"; - break; - - case SP_CSS_FONT_STYLE_NORMAL: - default: - //fontspec += " normal"; - break; - } - - switch (style->font_stretch.computed) { - - case SP_CSS_FONT_STRETCH_ULTRA_CONDENSED: - fontspec += " extra-condensed"; - break; - - case SP_CSS_FONT_STRETCH_EXTRA_CONDENSED: - fontspec += " extra-condensed"; - break; - - case SP_CSS_FONT_STRETCH_CONDENSED: - case SP_CSS_FONT_STRETCH_NARROWER: - fontspec += " condensed"; - break; - - case SP_CSS_FONT_STRETCH_SEMI_CONDENSED: - fontspec += " semi-condensed"; - break; - - case SP_CSS_FONT_STRETCH_NORMAL: - //fontspec += " normal"; - break; - - case SP_CSS_FONT_STRETCH_SEMI_EXPANDED: - fontspec += " semi-expanded"; - break; - - case SP_CSS_FONT_STRETCH_EXPANDED: - case SP_CSS_FONT_STRETCH_WIDER: - fontspec += " expanded"; - break; - - case SP_CSS_FONT_STRETCH_EXTRA_EXPANDED: - fontspec += " extra-expanded"; - break; - - case SP_CSS_FONT_STRETCH_ULTRA_EXPANDED: - fontspec += " ultra-expanded"; - break; - - default: - //fontspec += " normal"; - break; - } - - switch (style->font_variant.computed) { - - case SP_CSS_FONT_VARIANT_SMALL_CAPS: - fontspec += "small-caps"; - break; - - default: - //fontspec += "normal"; - break; - } - } - } - return canonize_fontspec( fontspec ); - } + case SP_CSS_FONT_WEIGHT_200: + fontspec += " Ultra-Light"; + break; + case SP_CSS_FONT_WEIGHT_300: + fontspec += " Light"; + break; - Gtk::TreeModel::Row - FontLister::get_row_for_font (Glib::ustring family) - { - Gtk::TreePath path; + case SP_CSS_FONT_WEIGHT_400: + case SP_CSS_FONT_WEIGHT_NORMAL: + //fontspec += " normal"; + break; + + case SP_CSS_FONT_WEIGHT_500: + fontspec += " Medium"; + break; + + case SP_CSS_FONT_WEIGHT_600: + fontspec += " Semi-Bold"; + break; - Gtk::TreeModel::iterator iter = font_list_store->get_iter( "0" ); - while( iter != font_list_store->children().end() ) { + case SP_CSS_FONT_WEIGHT_700: + case SP_CSS_FONT_WEIGHT_BOLD: + fontspec += " Bold"; + break; - Gtk::TreeModel::Row row = *iter; + case SP_CSS_FONT_WEIGHT_800: + fontspec += " Ultra-Bold"; + break; - if( familyNamesAreEqual( family, row[FontList.family] ) ) { - return row; - } + case SP_CSS_FONT_WEIGHT_900: + fontspec += " Heavy"; + break; - ++iter; - } + case SP_CSS_FONT_WEIGHT_LIGHTER: + case SP_CSS_FONT_WEIGHT_BOLDER: + default: + g_warning("Unrecognized font_weight.computed value"); + break; + } - throw FAMILY_NOT_FOUND; - } + switch (style->font_style.computed) { + case SP_CSS_FONT_STYLE_ITALIC: + fontspec += " italic"; + break; - Gtk::TreePath - FontLister::get_path_for_font (Glib::ustring family) - { - return font_list_store->get_path( get_row_for_font ( family ) ); + case SP_CSS_FONT_STYLE_OBLIQUE: + fontspec += " oblique"; + break; + + case SP_CSS_FONT_STYLE_NORMAL: + default: + //fontspec += " normal"; + break; + } + + switch (style->font_stretch.computed) { + + case SP_CSS_FONT_STRETCH_ULTRA_CONDENSED: + fontspec += " extra-condensed"; + break; + + case SP_CSS_FONT_STRETCH_EXTRA_CONDENSED: + fontspec += " extra-condensed"; + break; + + case SP_CSS_FONT_STRETCH_CONDENSED: + case SP_CSS_FONT_STRETCH_NARROWER: + fontspec += " condensed"; + break; + + case SP_CSS_FONT_STRETCH_SEMI_CONDENSED: + fontspec += " semi-condensed"; + break; + + case SP_CSS_FONT_STRETCH_NORMAL: + //fontspec += " normal"; + break; + + case SP_CSS_FONT_STRETCH_SEMI_EXPANDED: + fontspec += " semi-expanded"; + break; + + case SP_CSS_FONT_STRETCH_EXPANDED: + case SP_CSS_FONT_STRETCH_WIDER: + fontspec += " expanded"; + break; + + case SP_CSS_FONT_STRETCH_EXTRA_EXPANDED: + fontspec += " extra-expanded"; + break; + + case SP_CSS_FONT_STRETCH_ULTRA_EXPANDED: + fontspec += " ultra-expanded"; + break; + + default: + //fontspec += " normal"; + break; + } + + switch (style->font_variant.computed) { + + case SP_CSS_FONT_VARIANT_SMALL_CAPS: + fontspec += "small-caps"; + break; + + default: + //fontspec += "normal"; + break; + } + } } + return canonize_fontspec(fontspec); +} - Gtk::TreeModel::Row - FontLister::get_row_for_style (Glib::ustring style) - { - Gtk::TreePath path; - Gtk::TreeModel::iterator iter = style_list_store->get_iter( "0" ); - while( iter != style_list_store->children().end() ) { +Gtk::TreeModel::Row FontLister::get_row_for_font(Glib::ustring family) +{ + Gtk::TreePath path; - Gtk::TreeModel::Row row = *iter; + Gtk::TreeModel::iterator iter = font_list_store->get_iter("0"); + while (iter != font_list_store->children().end()) { - if( familyNamesAreEqual( style, row[FontStyleList.cssStyle] ) ) { - return row; - } + Gtk::TreeModel::Row row = *iter; - ++iter; - } + if (familyNamesAreEqual(family, row[FontList.family])) { + return row; + } - throw STYLE_NOT_FOUND; + ++iter; } - static gint - compute_distance (const PangoFontDescription *a, - const PangoFontDescription *b ) { - - // Weight: multiples of 100 - gint distance = abs( pango_font_description_get_weight( a ) - - pango_font_description_get_weight( b ) ); - - distance += 10000 * abs( pango_font_description_get_stretch( a ) - - pango_font_description_get_stretch( b ) ); - - PangoStyle style_a = pango_font_description_get_style( a ); - PangoStyle style_b = pango_font_description_get_style( b ); - if( style_a != style_b ) { - if( (style_a == PANGO_STYLE_OBLIQUE && style_b == PANGO_STYLE_ITALIC) || - (style_b == PANGO_STYLE_OBLIQUE && style_a == PANGO_STYLE_ITALIC) ) { - distance += 1000; // Oblique and italic are almost the same - } else { - distance += 100000; // Normal vs oblique/italic, not so similar - } - } - - // Normal vs small-caps - distance += 1000000 * abs( pango_font_description_get_variant( a ) - - pango_font_description_get_variant( b ) ); - return distance; + throw FAMILY_NOT_FOUND; +} + +Gtk::TreePath FontLister::get_path_for_font(Glib::ustring family) +{ + return font_list_store->get_path(get_row_for_font(family)); +} + +Gtk::TreeModel::Row FontLister::get_row_for_style(Glib::ustring style) +{ + Gtk::TreePath path; + + Gtk::TreeModel::iterator iter = style_list_store->get_iter("0"); + while (iter != style_list_store->children().end()) { + + Gtk::TreeModel::Row row = *iter; + + if (familyNamesAreEqual(style, row[FontStyleList.cssStyle])) { + return row; + } + + ++iter; } - // This is inspired by pango_font_description_better_match, but that routine - // always returns false if variant or stretch are different. This means, for - // example, that PT Sans Narrow with style Bold Condensed is never matched - // to another font-family with Bold style. - gboolean - font_description_better_match( PangoFontDescription* target, - PangoFontDescription* old_desc, - PangoFontDescription* new_desc ) { + throw STYLE_NOT_FOUND; +} + +static gint compute_distance(const PangoFontDescription *a, const PangoFontDescription *b) +{ - if( old_desc == NULL ) return true; - if( new_desc == NULL ) return false; + // Weight: multiples of 100 + gint distance = abs(pango_font_description_get_weight(a) - + pango_font_description_get_weight(b)); - int old_distance = compute_distance( target, old_desc ); - int new_distance = compute_distance( target, new_desc ); - //std::cout << "font_description_better_match: old: " << old_distance << std::endl; - //std::cout << " new: " << new_distance << std::endl; + distance += 10000 * abs(pango_font_description_get_stretch(a) - + pango_font_description_get_stretch(b)); - return (new_distance < old_distance ); + PangoStyle style_a = pango_font_description_get_style(a); + PangoStyle style_b = pango_font_description_get_style(b); + if (style_a != style_b) { + if ((style_a == PANGO_STYLE_OBLIQUE && style_b == PANGO_STYLE_ITALIC) || + (style_b == PANGO_STYLE_OBLIQUE && style_a == PANGO_STYLE_ITALIC)) { + distance += 1000; // Oblique and italic are almost the same + } else { + distance += 100000; // Normal vs oblique/italic, not so similar + } } - // void - // font_description_dump( PangoFontDescription* target ) { - // std::cout << " Font: " << pango_font_description_to_string( target ) << std::endl; - // std::cout << " style: " << pango_font_description_get_style( target ) << std::endl; - // std::cout << " weight: " << pango_font_description_get_weight( target ) << std::endl; - // std::cout << " variant: " << pango_font_description_get_variant( target ) << std::endl; - // std::cout << " stretch: " << pango_font_description_get_stretch( target ) << std::endl; - // std::cout << " gravity: " << pango_font_description_get_gravity( target ) << std::endl; - // } - - /* Returns style string */ - // TODO: Remove or turn into function to be used by new_font_family. - Glib::ustring - FontLister::get_best_style_match (Glib::ustring family, Glib::ustring target_style) { + // Normal vs small-caps + distance += 1000000 * abs(pango_font_description_get_variant(a) - + pango_font_description_get_variant(b)); + return distance; +} -#ifdef DEBUG_FONT - std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; - std::cout << "FontLister::get_best_style_match: " << family << " : " << target_style << std::endl; -#endif +// This is inspired by pango_font_description_better_match, but that routine +// always returns false if variant or stretch are different. This means, for +// example, that PT Sans Narrow with style Bold Condensed is never matched +// to another font-family with Bold style. +gboolean font_description_better_match(PangoFontDescription *target, PangoFontDescription *old_desc, PangoFontDescription *new_desc) +{ + if (old_desc == NULL) + return true; + if (new_desc == NULL) + return false; + + int old_distance = compute_distance(target, old_desc); + int new_distance = compute_distance(target, new_desc); + //std::cout << "font_description_better_match: old: " << old_distance << std::endl; + //std::cout << " new: " << new_distance << std::endl; - Glib::ustring fontspec = family + ", " + target_style; - - Gtk::TreeModel::Row row; - try { - row = get_row_for_font( family ); - } catch (...) { - //std::cout << " ERROR: can't find family: " << family << std::endl; - return (target_style); - } - - PangoFontDescription* target = pango_font_description_from_string( fontspec.c_str() ); - PangoFontDescription* best = NULL; - - //font_description_dump( target ); - - GList* styles = row[FontList.styles]; - for (GList *l=styles; l; l = l->next) { - Glib::ustring fontspec = family + ", " + (char*)l->data; - PangoFontDescription* candidate = pango_font_description_from_string( fontspec.c_str() ); - //font_description_dump( candidate ); - //std::cout << " " << font_description_better_match( target, best, candidate ) << std::endl; - if( font_description_better_match( target, best, candidate ) ) { - pango_font_description_free( best ); - best = candidate; - //std::cout << " ... better: " << std::endl; - } else { - pango_font_description_free( candidate ); - //std::cout << " ... not better: " << std::endl; - } - } - - Glib::ustring best_style = target_style; - if( best ) { - pango_font_description_unset_fields( best, PANGO_FONT_MASK_FAMILY ); - best_style = pango_font_description_to_string( best ); - } - - if( target ) pango_font_description_free( target ); - if( best ) pango_font_description_free( best ); + return (new_distance < old_distance); +} +// void +// font_description_dump( PangoFontDescription* target ) { +// std::cout << " Font: " << pango_font_description_to_string( target ) << std::endl; +// std::cout << " style: " << pango_font_description_get_style( target ) << std::endl; +// std::cout << " weight: " << pango_font_description_get_weight( target ) << std::endl; +// std::cout << " variant: " << pango_font_description_get_variant( target ) << std::endl; +// std::cout << " stretch: " << pango_font_description_get_stretch( target ) << std::endl; +// std::cout << " gravity: " << pango_font_description_get_gravity( target ) << std::endl; +// } + +/* Returns style string */ +// TODO: Remove or turn into function to be used by new_font_family. +Glib::ustring FontLister::get_best_style_match(Glib::ustring family, Glib::ustring target_style) +{ #ifdef DEBUG_FONT - std::cout << " Returning: " << best_style << std::endl; - std::cout << "FontLister::get_best_style_match: exit" << std::endl; - std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; + std::cout << "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; + std::cout << "FontLister::get_best_style_match: " << family << " : " << target_style << std::endl; #endif - return best_style; - } - const Glib::RefPtr - FontLister::get_font_list () const + Glib::ustring fontspec = family + ", " + target_style; + + Gtk::TreeModel::Row row; + try { - return font_list_store; + row = get_row_for_font(family); } - - const Glib::RefPtr - FontLister::get_style_list () const + catch (...) { - return style_list_store; + //std::cout << " ERROR: can't find family: " << family << std::endl; + return (target_style); } + + PangoFontDescription *target = pango_font_description_from_string(fontspec.c_str()); + PangoFontDescription *best = NULL; + + //font_description_dump( target ); + + if (!row[FontList.styles]) { + row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]); + } + GList *styles = row[FontList.styles]; + for (GList *l = styles; l; l = l->next) { + Glib::ustring fontspec = family + ", " + (char *)l->data; + PangoFontDescription *candidate = pango_font_description_from_string(fontspec.c_str()); + //font_description_dump( candidate ); + //std::cout << " " << font_description_better_match( target, best, candidate ) << std::endl; + if (font_description_better_match(target, best, candidate)) { + pango_font_description_free(best); + best = candidate; + //std::cout << " ... better: " << std::endl; + } else { + pango_font_description_free(candidate); + //std::cout << " ... not better: " << std::endl; + } + } + + Glib::ustring best_style = target_style; + if (best) { + pango_font_description_unset_fields(best, PANGO_FONT_MASK_FAMILY); + best_style = pango_font_description_to_string(best); + } + + if (target) + pango_font_description_free(target); + if (best) + pango_font_description_free(best); + + +#ifdef DEBUG_FONT + std::cout << " Returning: " << best_style << std::endl; + std::cout << "FontLister::get_best_style_match: exit" << std::endl; + std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; +#endif + return best_style; } +const Glib::RefPtr FontLister::get_font_list() const +{ + return font_list_store; +} + +const Glib::RefPtr FontLister::get_style_list() const +{ + return style_list_store; +} + +} // namespace Inkscape + // Helper functions // Separator function (if true, a separator will be drawn) -gboolean font_lister_separator_func(GtkTreeModel *model, - GtkTreeIter *iter, - gpointer /*data*/) +gboolean font_lister_separator_func(GtkTreeModel *model, GtkTreeIter *iter, gpointer /*data*/) { - gchar* text = 0; - gtk_tree_model_get(model, iter, 0, &text, -1 ); // Column 0: FontList.family - return (text && strcmp(text,"#") == 0); + gchar *text = 0; + gtk_tree_model_get(model, iter, 0, &text, -1); // Column 0: FontList.family + return (text && strcmp(text, "#") == 0); } -void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer /*data*/) +void font_lister_cell_data_func(GtkCellLayout * /*cell_layout*/, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer /*data*/) { gchar *family; gboolean onSystem = false; gtk_tree_model_get(model, iter, 0, &family, 2, &onSystem, -1); - Glib::ustring family_escaped = g_markup_escape_text(family, -1); + gchar* family_escaped = g_markup_escape_text(family, -1); //g_free(family); Glib::ustring markup; - if( !onSystem ) { + if (!onSystem) { markup = ""; /* See if font-family on system */ - std::vector tokens = Glib::Regex::split_simple("\\s*,\\s*", family_escaped ); - for( size_t i=0; i < tokens.size(); ++i ) { + std::vector tokens = Glib::Regex::split_simple("\\s*,\\s*", family_escaped); + for (size_t i = 0; i < tokens.size(); ++i) { Glib::ustring token = tokens[i]; @@ -1064,17 +1087,17 @@ void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/, gchar *family = 0; gboolean onSystem = true; gboolean found = false; - for( valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL(model), &iter ); + for (valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter); valid; - valid = gtk_tree_model_iter_next( GTK_TREE_MODEL(model), &iter ) ) { + valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter)) { gtk_tree_model_get(model, &iter, 0, &family, 2, &onSystem, -1); - if( onSystem && familyNamesAreEqual( token, family ) ) { + if (onSystem && familyNamesAreEqual(token, family)) { found = true; break; } } - if( found ) { + if (found) { markup += g_markup_escape_text(token.c_str(), -1); markup += ", "; } else { @@ -1085,13 +1108,13 @@ void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/, } } // Remove extra comma and space from end. - if( markup.size() >= 2 ) { - markup.resize( markup.size()-2 ); + if (markup.size() >= 2) { + markup.resize(markup.size() - 2); } markup += ""; // std::cout << markup << std::endl; } else { - markup = family_escaped; + markup = family_escaped; } Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -1099,7 +1122,7 @@ void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/, if (show_sample) { Glib::ustring sample = prefs->getString("/tools/text/font_sample"); - Glib::ustring sample_escaped = g_markup_escape_text(sample.data(), -1); + Glib::ustring sample_escaped = Glib::Markup::escape_text(sample); markup += " - new_font_family (Glib::ustring family, gboolean check_style = true); - - /** Sets font-family, updating style list and attempting - * to find closest style to old current_style. - * New font-family and style returned. - * Updates current_family and current_style. - * Calls new_font_family(). - * (For use in text-toolbar where update is immediate.) - */ - std::pair - set_font_family (Glib::ustring family, gboolean check_style = true); - - /** Sets font-family from row in list store. - * The row can be used to determine if we are in the - * document or system part of the font-family list. - * This is needed to handle scrolling through the - * font-family list correctly. - * Calls set_font_family(). - */ - std::pair - set_font_family (int row, gboolean check_style = true); - - Glib::ustring - get_font_family () - { - return current_family; - } - - int - get_font_family_row () - { - return current_family_row; - } - - /** Sets style. Does not validate style for family. - */ - void - set_font_style (Glib::ustring style); - - Glib::ustring - get_font_style () - { - return current_style; - } - - Glib::ustring - fontspec_from_style (SPStyle* style); - - /** Fill css using current_fontspec. - */ - void - fill_css( SPCSSAttr *css, Glib::ustring fontspec = "" ); - - Gtk::TreeModel::Row - get_row_for_font (Glib::ustring family); - - Gtk::TreePath - get_path_for_font (Glib::ustring family); - - Gtk::TreeModel::Row - get_row_for_style (Glib::ustring style); - - Gtk::TreePath - get_path_for_style (Glib::ustring style); - - std::pair - get_paths (Glib::ustring family, Glib::ustring style); - - /** Return best style match for new font given style for old font. - */ - Glib::ustring - get_best_style_match (Glib::ustring family, Glib::ustring style); - - /* Not Used */ - const NRNameList - get_name_list () const - { - return families; - } - - private: - - FontLister (); - - NRNameList families; - - Glib::RefPtr font_list_store; - Glib::RefPtr style_list_store; - - /** Info for currently selected font (what is shown in the UI). - * May include font-family lists and fonts not on system. - */ - int current_family_row; - Glib::ustring current_family; - Glib::ustring current_style; - Glib::ustring current_fontspec; - - /** fontspec of system font closest to current_fontspec. - * (What the system will use to display current_fontspec.) - */ - Glib::ustring current_fontspec_system; - - /** If a font-family is not on system, this list of styles is used. - */ - GList *default_styles; - }; -} +namespace Inkscape { + +/** + * This class enumerates fonts using libnrtype into reusable data stores and + * allows for random access to the font-family list and the font-style list. + * Setting the font-family updates the font-style list. "Style" in this case + * refers to everything but family and size (e.g. italic/oblique, weight). + * + * This class handles font-family lists and fonts that are not on the system, + * where there is not an entry in the fontInstanceMap. + * + * This class uses the idea of "font_spec". This is a plain text string as used by + * Pango. It is similar to the CSS font shorthand except that font-family comes + * first and in this class the font-size is not used. + * + * This class uses the FontFactory class to get a list of system fonts + * and to find best matches via Pango. The Pango interface is only setup + * to deal with fonts that are on the system so care must be taken. For + * example, best matches should only be done with the first font-family + * in a font-family list. If the first font-family is not on the system + * then a generic font-family should be used (sans-serif -> Sans). + * + * This class is used by the UI interface (text-toolbar, font-select, etc.). + * + * "Font" includes family and style. It should not be used when one + * means font-family. + */ + +class FontLister { +public: + enum Exceptions { + FAMILY_NOT_FOUND, + STYLE_NOT_FOUND + }; + + virtual ~FontLister(); + + /** + * GtkTreeModelColumnRecord for the font-family list Gtk::ListStore + */ + struct FontListClass : public Gtk::TreeModelColumnRecord { + /** + * Column containing the family name + */ + Gtk::TreeModelColumn family; + + /** + * Column containing the styles for each family name. + */ + Gtk::TreeModelColumn styles; + + /** + * Column containing flag if font is on system + */ + Gtk::TreeModelColumn onSystem; + + /** + * Not actually a column. + * Necessary for quick initialization of FontLister, + * we initially store the pango family and if the + * font style is actually used we'll cache it in + * %styles. + */ + Gtk::TreeModelColumn pango_family; + + FontListClass() + { + add(family); + add(styles); + add(onSystem); + add(pango_family); + } + }; + + FontListClass FontList; + + struct FontStyleListClass : public Gtk::TreeModelColumnRecord { + /** + * Column containing the styles as Font designer used. + */ + Gtk::TreeModelColumn displayStyle; + + /** + * Column containing the styles in CSS/Pango format. + */ + Gtk::TreeModelColumn cssStyle; + + FontStyleListClass() + { + add(cssStyle); + add(displayStyle); + } + }; + + FontStyleListClass FontStyleList; + + /** + * @return the ListStore with the family names + * + * The return is const and the function is declared as const. + * The ListStore is ready to be used after class instantiation + * and should not be modified. + */ + const Glib::RefPtr get_font_list() const; + + /** + * @return the ListStore with the styles + */ + const Glib::RefPtr get_style_list() const; + + /** + * Inserts a font family or font-fallback list (for use when not + * already in document or on system). + */ + void insert_font_family(Glib::ustring new_family); + + /** + * Updates font list to include fonts in document. + */ + void update_font_list(SPDocument *document); + +public: + static Inkscape::FontLister *get_instance(); + + /** + * Takes a hand written font spec and returns a Pango generated one in + * standard form. + */ + Glib::ustring canonize_fontspec(Glib::ustring fontspec); + + /** + * Find closest system font to given font. + */ + Glib::ustring system_fontspec(Glib::ustring fontspec); + + /** + * Gets font-family and style from fontspec. + * font-family and style returned. + */ + std::pair ui_from_fontspec(Glib::ustring fontspec); + + /** + * Sets font-family and style after a selection change. + * New font-family and style returned. + */ + std::pair selection_update(); + + /** + * Sets current_fontspec, etc. If check is false, won't + * try to find best style match (assumes style in fontspec + * valid for given font-family). + */ + void set_fontspec(Glib::ustring fontspec, bool check = true); + + Glib::ustring get_fontspec() + { + return current_fontspec; + } + + /** + * Changes font-family, updating style list and attempting to find + * closest style to current_style style (if check_style is true). + * New font-family and style returned. + * Does NOT update current_family and current_style. + * (For potential use in font-selector which doesn't update until + * "Apply" button clicked.) + */ + std::pair new_font_family(Glib::ustring family, bool check_style = true); + + /** + * Sets font-family, updating style list and attempting + * to find closest style to old current_style. + * New font-family and style returned. + * Updates current_family and current_style. + * Calls new_font_family(). + * (For use in text-toolbar where update is immediate.) + */ + std::pair set_font_family(Glib::ustring family, bool check_style = true); + + /** + * Sets font-family from row in list store. + * The row can be used to determine if we are in the + * document or system part of the font-family list. + * This is needed to handle scrolling through the + * font-family list correctly. + * Calls set_font_family(). + */ + std::pair set_font_family(int row, bool check_style = true); + + Glib::ustring get_font_family() + { + return current_family; + } + + int get_font_family_row() + { + return current_family_row; + } + + /** + * Sets style. Does not validate style for family. + */ + void set_font_style(Glib::ustring style); + + Glib::ustring get_font_style() + { + return current_style; + } + + Glib::ustring fontspec_from_style(SPStyle *style); + + /** + * Fill css using current_fontspec. + */ + void fill_css(SPCSSAttr *css, Glib::ustring fontspec = ""); + + Gtk::TreeModel::Row get_row_for_font(Glib::ustring family); + + Gtk::TreePath get_path_for_font(Glib::ustring family); + + Gtk::TreeModel::Row get_row_for_style(Glib::ustring style); + + Gtk::TreePath get_path_for_style(Glib::ustring style); + + std::pair get_paths(Glib::ustring family, Glib::ustring style); + + /** + * Return best style match for new font given style for old font. + */ + Glib::ustring get_best_style_match(Glib::ustring family, Glib::ustring style); + + void ensureRowStyles(GtkTreeModel* model, GtkTreeIter const* iter); + +private: + FontLister(); + + void update_font_list_recursive(SPObject *r, std::list *l); + + Glib::RefPtr font_list_store; + Glib::RefPtr style_list_store; + + /** + * Info for currently selected font (what is shown in the UI). + * May include font-family lists and fonts not on system. + */ + int current_family_row; + Glib::ustring current_family; + Glib::ustring current_style; + Glib::ustring current_fontspec; + + /** + * fontspec of system font closest to current_fontspec. + * (What the system will use to display current_fontspec.) + */ + Glib::ustring current_fontspec_system; + + /** + * If a font-family is not on system, this list of styles is used. + */ + GList *default_styles; +}; + +} // namespace Inkscape // Helper functions gboolean font_lister_separator_func(GtkTreeModel *model, - GtkTreeIter *iter, - gpointer /*data*/); + GtkTreeIter *iter, + gpointer /*data*/); -void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer /*data*/); +void font_lister_cell_data_func(GtkCellLayout * /*cell_layout*/, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer /*data*/); #endif @@ -328,4 +314,4 @@ void font_lister_cell_data_func(GtkCellLayout */*cell_layout*/, fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 : -- cgit v1.2.3 From be103a4ac9f4821db95601b84ffa70f73c49df65 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 17 Aug 2014 10:10:57 -0400 Subject: Fix gtk3 build (bzr r13341.1.141) --- src/libnrtype/font-lister.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 07c80054d..1b4d9d256 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -1122,13 +1122,14 @@ void font_lister_cell_data_func(GtkCellLayout * /*cell_layout*/, if (show_sample) { Glib::ustring sample = prefs->getString("/tools/text/font_sample"); - Glib::ustring sample_escaped = Glib::Markup::escape_text(sample); + gchar* sample_escaped = g_markup_escape_text(sample.data(), -1); markup += " "; markup += sample_escaped; markup += ""; + g_free(sample_escaped); } g_object_set(G_OBJECT(cell), "markup", markup.c_str(), NULL); -- cgit v1.2.3 From dce3466274e04364e25c47b0b71007a65c9cf9dd Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Mon, 18 Aug 2014 16:19:55 -0400 Subject: Code cleanup. (bzr r13341.1.145) --- src/libnrtype/nr-type-primitives.cpp | 151 +++++++++++++++++++---------------- src/libnrtype/nr-type-primitives.h | 21 +++-- 2 files changed, 96 insertions(+), 76 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/nr-type-primitives.cpp b/src/libnrtype/nr-type-primitives.cpp index 63a3abcc5..3ad4a3771 100644 --- a/src/libnrtype/nr-type-primitives.cpp +++ b/src/libnrtype/nr-type-primitives.cpp @@ -1,6 +1,4 @@ -#define __NR_TYPE_PRIMITIVES_C__ - -/* +/** * Typeface and script library * * Authors: @@ -12,26 +10,27 @@ /* This should be enough for approximately 10000 fonts */ #define NR_DICTSIZE 2777 -#include +#include #include #include + #include "nr-type-primitives.h" /** * An entry in a list of key->value pairs */ struct NRTDEntry { - NRTDEntry *next; - const gchar *key; - void *val; + NRTDEntry *next; + const gchar *key; + void *val; }; /** * Type Dictionary, consisting of size number of key-value entries */ struct NRTypeDict { - unsigned int size; - NRTDEntry **entries; + unsigned int size; + NRTDEntry **entries; }; static NRTDEntry *nr_td_entry_new (void); @@ -42,17 +41,17 @@ static NRTDEntry *nr_td_entry_new (void); void nr_name_list_release (NRNameList *list) { - if (list->destructor) { - list->destructor (list); - } + if (list->destructor) { + list->destructor (list); + } } void nr_style_list_release (NRStyleList *list) { - if (list->destructor) { - list->destructor (list); - } + if (list->destructor) { + list->destructor (list); + } } /** @@ -62,18 +61,18 @@ nr_style_list_release (NRStyleList *list) NRTypeDict * nr_type_dict_new (void) { - NRTypeDict *td; - int i; + NRTypeDict *td; + int i; - td = g_new (NRTypeDict, 1); + td = g_new (NRTypeDict, 1); - td->size = NR_DICTSIZE; - td->entries = g_new (NRTDEntry *, td->size); - for (i = 0; i < NR_DICTSIZE; i++) { - td->entries[i] = NULL; - } + td->size = NR_DICTSIZE; + td->entries = g_new (NRTDEntry *, td->size); + for (i = 0; i < NR_DICTSIZE; i++) { + td->entries[i] = NULL; + } - return td; + return td; } /** @@ -82,15 +81,15 @@ nr_type_dict_new (void) static unsigned int nr_str_hash (const gchar *p) { - unsigned int h; + unsigned int h; - h = *p; + h = *p; - if (h != 0) { - for (p += 1; *p; p++) h = (h << 5) - h + *p; - } + if (h != 0) { + for (p += 1; *p; p++) h = (h << 5) - h + *p; + } - return h; + return h; } /** @@ -99,25 +98,25 @@ nr_str_hash (const gchar *p) void nr_type_dict_insert (NRTypeDict *td, const gchar *key, void *val) { - if (key) { - NRTDEntry *tde; - unsigned int hval; - - hval = nr_str_hash (key) % td->size; - - for (tde = td->entries[hval]; tde; tde = tde->next) { - if (!strcmp (key, tde->key)) { - tde->val = val; - return; - } - } - - tde = nr_td_entry_new (); - tde->next = td->entries[hval]; - tde->key = key; - tde->val = val; - td->entries[hval] = tde; - } + if (key) { + NRTDEntry *tde; + unsigned int hval; + + hval = nr_str_hash (key) % td->size; + + for (tde = td->entries[hval]; tde; tde = tde->next) { + if (!strcmp (key, tde->key)) { + tde->val = val; + return; + } + } + + tde = nr_td_entry_new (); + tde->next = td->entries[hval]; + tde->key = key; + tde->val = val; + td->entries[hval] = tde; + } } /** @@ -126,16 +125,16 @@ nr_type_dict_insert (NRTypeDict *td, const gchar *key, void *val) void * nr_type_dict_lookup (NRTypeDict *td, const gchar *key) { - if (key) { - NRTDEntry *tde; - unsigned int hval; - hval = nr_str_hash (key) % td->size; - for (tde = td->entries[hval]; tde; tde = tde->next) { - if (!strcmp (key, tde->key)) return tde->val; - } - } - - return NULL; + if (key) { + NRTDEntry *tde; + unsigned int hval; + hval = nr_str_hash (key) % td->size; + for (tde = td->entries[hval]; tde; tde = tde->next) { + if (!strcmp (key, tde->key)) return tde->val; + } + } + + return NULL; } #define NR_TDE_BLOCK_SIZE 32 @@ -148,20 +147,30 @@ static NRTDEntry *nr_tde_free_list; static NRTDEntry * nr_td_entry_new (void) { - NRTDEntry *tde; + NRTDEntry *tde; - if (!nr_tde_free_list) { - int i; - nr_tde_free_list = g_new (NRTDEntry, NR_TDE_BLOCK_SIZE); - for (i = 0; i < (NR_TDE_BLOCK_SIZE - 1); i++) { - nr_tde_free_list[i].next = nr_tde_free_list + i + 1; - } - nr_tde_free_list[i].next = NULL; - } + if (!nr_tde_free_list) { + int i; + nr_tde_free_list = g_new (NRTDEntry, NR_TDE_BLOCK_SIZE); + for (i = 0; i < (NR_TDE_BLOCK_SIZE - 1); i++) { + nr_tde_free_list[i].next = nr_tde_free_list + i + 1; + } + nr_tde_free_list[i].next = NULL; + } - tde = nr_tde_free_list; - nr_tde_free_list = tde->next; + tde = nr_tde_free_list; + nr_tde_free_list = tde->next; - return tde; + return tde; } +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 : diff --git a/src/libnrtype/nr-type-primitives.h b/src/libnrtype/nr-type-primitives.h index 9bb181c4b..863803433 100644 --- a/src/libnrtype/nr-type-primitives.h +++ b/src/libnrtype/nr-type-primitives.h @@ -1,12 +1,12 @@ -#ifndef __NR_TYPE_PRIMITIVES_H__ -#define __NR_TYPE_PRIMITIVES_H__ +#ifndef SEEN_NR_TYPE_PRIMITIVES_H +#define SEEN_NR_TYPE_PRIMITIVES_H -/* +/** * Typeface and script library * * Authors: * Lauris Kaplinski - * g++ port: Nathan Hurst + * c++ port: Nathan Hurst * * This code is in public domain */ @@ -47,4 +47,15 @@ void nr_type_dict_insert (NRTypeDict *td, const gchar *key, void *val); void *nr_type_dict_lookup (NRTypeDict *td, const gchar *key); -#endif +#endif // !SEEN_NR_TYPE_PRIMITIVES_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 : -- cgit v1.2.3 From 8920e3ea655df6447e2ed6f8b0b5621442d20cb5 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sun, 24 Aug 2014 12:31:46 +0100 Subject: Fix strict build with Gtk+ 2 (bzr r13341.1.172) --- src/libnrtype/font-lister.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 1b4d9d256..6f25ab5f9 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -2,8 +2,8 @@ #include #endif -#include #include +#include #include #include -- cgit v1.2.3 From 467cf1085309d647f5410fb4a62074671c0ebce5 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Wed, 3 Sep 2014 23:32:14 +0200 Subject: libnrtype, Layout-TNG-Compute: initialize variables. fixes compiler warning (bzr r13341.1.196) --- src/libnrtype/Layout-TNG-Compute.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/libnrtype') diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index 973db0165..7eb53446f 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -854,6 +854,8 @@ void Layout::Calculator::BrokenSpan::setZero() end_glyph_index = start_glyph_index = 0; ends_with_whitespace = false; each_whitespace_width = 0.0; + letter_spacing = 0.0; + word_spacing = 0.0; } template void Layout::Calculator::ParagraphInfo::free_sequence(T &seq) -- cgit v1.2.3 From d046b5de4695a3c1ab5498a6198fe358ba069c5b Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 29 Sep 2014 09:48:36 +0200 Subject: Conditionally add 'semilight' due to changes in Pango 1.36.6. (bzr r13341.1.231) --- src/libnrtype/FontFactory.cpp | 4 ++++ src/libnrtype/FontInstance.cpp | 4 ++++ src/libnrtype/Layout-TNG-Output.cpp | 3 +++ src/libnrtype/font-lister.cpp | 5 +++++ 4 files changed, 16 insertions(+) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index c5e68e264..bc0f65346 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -933,6 +933,10 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos) pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRALIGHT); } else if ( apos.weight <= NR_POS_WEIGHT_LIGHT ) { pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_LIGHT); +#if PANGO_VERSION_CHECK(1,36,6) + } else if ( apos.weight <= NR_POS_WEIGHT_SEMILIGHT ) { + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_SEMILIGHT); +#endif } else if ( apos.weight <= NR_POS_WEIGHT_BOOK ) { pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOOK); } else if ( apos.weight <= NR_POS_WEIGHT_NORMAL ) { diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index 20eca6740..ce4c99ef7 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -311,6 +311,10 @@ unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int res=(char*)"200"; } else if ( v <= PANGO_WEIGHT_LIGHT ) { res=(char*)"300"; +#if PANGO_VERSION_CHECK(1,36,6) + } else if ( v <= PANGO_WEIGHT_SEMILIGHT ) { + res=(char*)"350"; +#endif } else if ( v <= PANGO_WEIGHT_BOOK ) { res=(char*)"380"; } else if ( v <= PANGO_WEIGHT_NORMAL ) { diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp index 77534e706..61a141cc3 100644 --- a/src/libnrtype/Layout-TNG-Output.cpp +++ b/src/libnrtype/Layout-TNG-Output.cpp @@ -511,6 +511,9 @@ static char const *weight_to_text(PangoWeight w) case PANGO_WEIGHT_THIN : return "thin"; case PANGO_WEIGHT_ULTRALIGHT: return "ultralight"; case PANGO_WEIGHT_LIGHT : return "light"; +#if PANGO_VERSION_CHECK(1,36,6) + case PANGO_WEIGHT_SEMILIGHT : return "semilight"; +#endif case PANGO_WEIGHT_BOOK : return "book"; case PANGO_WEIGHT_NORMAL : return "normalweight"; case PANGO_WEIGHT_MEDIUM : return "medium"; diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 6f25ab5f9..c6d7327f6 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -648,6 +648,11 @@ void FontLister::fill_css(SPCSSAttr *css, Glib::ustring fontspec) case PANGO_WEIGHT_LIGHT: sp_repr_css_set_property(css, "font-weight", "300"); break; +#if PANGO_VERSION_CHECK(1,36,6) + case PANGO_WEIGHT_SEMILIGHT: + sp_repr_css_set_property(css, "font-weight", "350"); + break; +#endif case PANGO_WEIGHT_BOOK: sp_repr_css_set_property(css, "font-weight", "380"); break; -- cgit v1.2.3 From 3bce99a52028adbf65309cba67a489e90ec76311 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 29 Sep 2014 10:23:07 +0200 Subject: Quick fix to unbreak build from last check in. (bzr r13341.1.232) --- src/libnrtype/nr-type-pos-def.cpp | 4 ++++ src/libnrtype/nr-type-pos-def.h | 1 + 2 files changed, 5 insertions(+) (limited to 'src/libnrtype') diff --git a/src/libnrtype/nr-type-pos-def.cpp b/src/libnrtype/nr-type-pos-def.cpp index fef04039e..ff633d5f1 100644 --- a/src/libnrtype/nr-type-pos-def.cpp +++ b/src/libnrtype/nr-type-pos-def.cpp @@ -46,6 +46,10 @@ parse_name_for_weight (char const *cc) weight = NR_POS_WEIGHT_ULTRA_LIGHT; } else if (strstr (c, "light")) { weight = NR_POS_WEIGHT_LIGHT; + } else if (strstr (c, "semi light")) { + weight = NR_POS_WEIGHT_SEMILIGHT; + } else if (strstr (c, "semilight")) { + weight = NR_POS_WEIGHT_SEMILIGHT; } else if (strstr (c, "book")) { weight = NR_POS_WEIGHT_BOOK; } else if (strstr (c, "medium")) { diff --git a/src/libnrtype/nr-type-pos-def.h b/src/libnrtype/nr-type-pos-def.h index ab9f5b45c..d4d412b21 100644 --- a/src/libnrtype/nr-type-pos-def.h +++ b/src/libnrtype/nr-type-pos-def.h @@ -9,6 +9,7 @@ #define NR_POS_WEIGHT_EXTRA_LIGHT 64 #define NR_POS_WEIGHT_ULTRA_LIGHT 64 #define NR_POS_WEIGHT_LIGHT 96 +#define NR_POS_WEIGHT_SEMILIGHT 96 #define NR_POS_WEIGHT_BOOK 128 #define NR_POS_WEIGHT_NORMAL 128 #define NR_POS_WEIGHT_MEDIUM 144 -- cgit v1.2.3 From e186cf544131e582a43316767257f199e6af986c Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 29 Sep 2014 16:21:07 +0200 Subject: Remove NRTypePosDef class and associated cruft. More direct CSS -> Pango translation. (bzr r13341.1.233) --- src/libnrtype/CMakeLists.txt | 4 - src/libnrtype/FontFactory.cpp | 196 ++++++++++++++++---------- src/libnrtype/FontFactory.h | 5 +- src/libnrtype/Makefile_insert | 4 - src/libnrtype/font-style-to-pos.cpp | 120 ---------------- src/libnrtype/font-style-to-pos.h | 21 --- src/libnrtype/nr-type-pos-def.cpp | 272 ------------------------------------ src/libnrtype/nr-type-pos-def.h | 103 -------------- 8 files changed, 127 insertions(+), 598 deletions(-) delete mode 100644 src/libnrtype/font-style-to-pos.cpp delete mode 100644 src/libnrtype/font-style-to-pos.h delete mode 100644 src/libnrtype/nr-type-pos-def.cpp delete mode 100644 src/libnrtype/nr-type-pos-def.h (limited to 'src/libnrtype') diff --git a/src/libnrtype/CMakeLists.txt b/src/libnrtype/CMakeLists.txt index 84979d7ea..05fd01a03 100644 --- a/src/libnrtype/CMakeLists.txt +++ b/src/libnrtype/CMakeLists.txt @@ -3,14 +3,12 @@ set(nrtype_SRC FontFactory.cpp FontInstance.cpp font-lister.cpp - font-style-to-pos.cpp Layout-TNG.cpp Layout-TNG-Compute.cpp Layout-TNG-Input.cpp Layout-TNG-OutIter.cpp Layout-TNG-Output.cpp Layout-TNG-Scanline-Makers.cpp - nr-type-pos-def.cpp nr-type-primitives.cpp TextWrapper.cpp @@ -25,9 +23,7 @@ set(nrtype_SRC font-glyph.h font-instance.h font-lister.h - font-style-to-pos.h font-style.h - nr-type-pos-def.h nr-type-primitives.h one-box.h one-glyph.h diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index bc0f65346..c2b3c64fe 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -712,9 +712,133 @@ font_instance* font_factory::FaceFromStyle(SPStyle const *style) // If that failed, try using the CSS information in the style if (!font) { - font = Face(style->font_family.value, font_style_to_pos(*style)); + PangoFontDescription *temp_descr = pango_font_description_new(); - // That was a hatchet job... so we need to check if this font exists!! + pango_font_description_set_family(temp_descr, style->font_family.value); + + // This duplicates Layout::EnumConversionItem... perhaps we can share code? + switch ( style->font_style.computed ) { + case SP_CSS_FONT_STYLE_ITALIC: + pango_font_description_set_style(temp_descr, PANGO_STYLE_ITALIC); + break; + + case SP_CSS_FONT_STYLE_OBLIQUE: + pango_font_description_set_style(temp_descr, PANGO_STYLE_OBLIQUE); + break; + + case SP_CSS_FONT_STYLE_NORMAL: + default: + pango_font_description_set_style(temp_descr, PANGO_STYLE_NORMAL); + break; + } + + switch( style->font_weight.computed ) { + case SP_CSS_FONT_WEIGHT_100: + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_THIN); + break; + + case SP_CSS_FONT_WEIGHT_200: + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRALIGHT); + break; + + case SP_CSS_FONT_WEIGHT_300: + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_LIGHT); + break; + + case SP_CSS_FONT_WEIGHT_400: + case SP_CSS_FONT_WEIGHT_NORMAL: + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_NORMAL); + break; + + case SP_CSS_FONT_WEIGHT_500: + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_MEDIUM); + break; + + case SP_CSS_FONT_WEIGHT_600: + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_SEMIBOLD); + break; + + case SP_CSS_FONT_WEIGHT_700: + case SP_CSS_FONT_WEIGHT_BOLD: + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOLD); + break; + + case SP_CSS_FONT_WEIGHT_800: + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRABOLD); + break; + + case SP_CSS_FONT_WEIGHT_900: + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_HEAVY); + break; + + case SP_CSS_FONT_WEIGHT_LIGHTER: + case SP_CSS_FONT_WEIGHT_BOLDER: + default: + g_warning("FaceFromStyle: Unrecognized font_weight.computed value"); + pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_NORMAL); + break; + } + // PANGO_WIEGHT_ULTRAHEAVY not used (not CSS2) + + switch (style->font_stretch.computed) { + case SP_CSS_FONT_STRETCH_ULTRA_CONDENSED: + pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_ULTRA_CONDENSED); + break; + + case SP_CSS_FONT_STRETCH_EXTRA_CONDENSED: + pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_CONDENSED); + break; + + case SP_CSS_FONT_STRETCH_CONDENSED: + pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_CONDENSED); + break; + + case SP_CSS_FONT_STRETCH_SEMI_CONDENSED: + pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_CONDENSED); + break; + + case SP_CSS_FONT_STRETCH_NORMAL: + pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_NORMAL); + break; + + case SP_CSS_FONT_STRETCH_SEMI_EXPANDED: + pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_EXPANDED); + break; + + case SP_CSS_FONT_STRETCH_EXPANDED: + pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXPANDED); + break; + + case SP_CSS_FONT_STRETCH_EXTRA_EXPANDED: + pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_EXPANDED); + break; + + case SP_CSS_FONT_STRETCH_ULTRA_EXPANDED: + pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_ULTRA_EXPANDED); + + case SP_CSS_FONT_STRETCH_WIDER: + case SP_CSS_FONT_STRETCH_NARROWER: + default: + g_warning("FaceFromStyle: Unrecognized font_stretch.computed value"); + pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_NORMAL); + break; + } + + switch ( style->font_variant.computed ) { + case SP_CSS_FONT_VARIANT_SMALL_CAPS: + pango_font_description_set_variant(temp_descr, PANGO_VARIANT_SMALL_CAPS); + break; + + case SP_CSS_FONT_VARIANT_NORMAL: + default: + pango_font_description_set_variant(temp_descr, PANGO_VARIANT_NORMAL); + break; + } + + font = Face(temp_descr); + pango_font_description_free(temp_descr); + + // We now find closest match to this font: Glib::ustring fontSpec = font_factory::Default()->ConstructFontSpecification(font); Glib::ustring newFontSpec = FontSpecificationBestMatch( fontSpec ); if( fontSpec != newFontSpec ) { @@ -907,74 +1031,6 @@ font_instance *font_factory::Face(char const *family, int variant, int style, in return res; } -font_instance *font_factory::Face(char const *family, NRTypePosDef apos) -{ - PangoFontDescription *temp_descr = pango_font_description_new(); - - pango_font_description_set_family(temp_descr, family); - - if ( apos.variant == NR_POS_VARIANT_SMALLCAPS ) { - pango_font_description_set_variant(temp_descr, PANGO_VARIANT_SMALL_CAPS); - } else { - pango_font_description_set_variant(temp_descr, PANGO_VARIANT_NORMAL); - } - - if ( apos.italic ) { - pango_font_description_set_style(temp_descr, PANGO_STYLE_ITALIC); - } else if ( apos.oblique ) { - pango_font_description_set_style(temp_descr, PANGO_STYLE_OBLIQUE); - } else { - pango_font_description_set_style(temp_descr, PANGO_STYLE_NORMAL); - } - - if ( apos.weight <= NR_POS_WEIGHT_THIN ) { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_THIN); - } else if ( apos.weight <= NR_POS_WEIGHT_ULTRA_LIGHT ) { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRALIGHT); - } else if ( apos.weight <= NR_POS_WEIGHT_LIGHT ) { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_LIGHT); -#if PANGO_VERSION_CHECK(1,36,6) - } else if ( apos.weight <= NR_POS_WEIGHT_SEMILIGHT ) { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_SEMILIGHT); -#endif - } else if ( apos.weight <= NR_POS_WEIGHT_BOOK ) { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOOK); - } else if ( apos.weight <= NR_POS_WEIGHT_NORMAL ) { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_NORMAL); - } else if ( apos.weight <= NR_POS_WEIGHT_MEDIUM ) { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_MEDIUM); - } else if ( apos.weight <= NR_POS_WEIGHT_SEMIBOLD ) { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_SEMIBOLD); - } else if ( apos.weight <= NR_POS_WEIGHT_BOLD ) { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOLD); - } else if ( apos.weight <= NR_POS_WEIGHT_ULTRA_BOLD ) { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRABOLD); - } else { - pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_HEAVY); - } - // PANGO_WIEGHT_ULTRAHEAVY not used (not CSS2) - - if ( apos.stretch <= NR_POS_STRETCH_ULTRA_CONDENSED ) { - pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_CONDENSED); - } else if ( apos.stretch <= NR_POS_STRETCH_CONDENSED ) { - pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_CONDENSED); - } else if ( apos.stretch <= NR_POS_STRETCH_SEMI_CONDENSED ) { - pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_CONDENSED); - } else if ( apos.stretch <= NR_POS_STRETCH_NORMAL ) { - pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_NORMAL); - } else if ( apos.stretch <= NR_POS_STRETCH_SEMI_EXPANDED ) { - pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_EXPANDED); - } else if ( apos.stretch <= NR_POS_STRETCH_EXPANDED ) { - pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXPANDED); - } else { - pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_EXPANDED); - } - - font_instance *res = Face(temp_descr); - pango_font_description_free(temp_descr); - return res; -} - void font_factory::UnrefFace(font_instance *who) { if ( who ) { diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h index c48ae831a..34ef36883 100644 --- a/src/libnrtype/FontFactory.h +++ b/src/libnrtype/FontFactory.h @@ -21,9 +21,7 @@ #include #include "nr-type-primitives.h" -#include "nr-type-pos-def.h" -#include "font-style-to-pos.h" -#include "style.h" +#include "../style.h" /* Freetype */ #ifdef USE_PANGO_WIN32 @@ -144,7 +142,6 @@ public: int variant=PANGO_VARIANT_NORMAL, int style=PANGO_STYLE_NORMAL, int weight=PANGO_WEIGHT_NORMAL, int stretch=PANGO_STRETCH_NORMAL, int size=10, int spacing=0); - font_instance* Face(char const *family, NRTypePosDef apos); /// Semi-private: tells the font_factory taht the font_instance 'who' has died and should be removed from loadedFaces void UnrefFace(font_instance* who); diff --git a/src/libnrtype/Makefile_insert b/src/libnrtype/Makefile_insert index 0ce8f1fd5..ab9465daa 100644 --- a/src/libnrtype/Makefile_insert +++ b/src/libnrtype/Makefile_insert @@ -2,13 +2,9 @@ ink_common_sources += \ libnrtype/boundary-type.h \ - libnrtype/font-style-to-pos.cpp \ - libnrtype/font-style-to-pos.h \ libnrtype/font-glyph.h \ libnrtype/font-instance.h \ libnrtype/font-style.h \ - libnrtype/nr-type-pos-def.cpp \ - libnrtype/nr-type-pos-def.h \ libnrtype/nr-type-primitives.cpp \ libnrtype/nr-type-primitives.h \ libnrtype/FontFactory.cpp \ diff --git a/src/libnrtype/font-style-to-pos.cpp b/src/libnrtype/font-style-to-pos.cpp deleted file mode 100644 index 02f5ef37c..000000000 --- a/src/libnrtype/font-style-to-pos.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "font-style-to-pos.h" -#include - -/* 'lighter' and 'darker' have to be resolved earlier */ -/** -Given a style struct (CSS representation), sets the corresponding fields in a NRTypePosDef. - */ -NRTypePosDef -font_style_to_pos (SPStyle const &style) -{ - NRTypePosDef ret; - - switch (style.font_weight.computed) { - case SP_CSS_FONT_WEIGHT_100: - ret.weight = NR_POS_WEIGHT_CSS100; - break; - - case SP_CSS_FONT_WEIGHT_200: - ret.weight = NR_POS_WEIGHT_CSS200; - break; - - case SP_CSS_FONT_WEIGHT_300: - ret.weight = NR_POS_WEIGHT_CSS300; - break; - - case SP_CSS_FONT_WEIGHT_400: - case SP_CSS_FONT_WEIGHT_NORMAL: - ret.weight = NR_POS_WEIGHT_CSS400; - break; - - case SP_CSS_FONT_WEIGHT_500: - ret.weight = NR_POS_WEIGHT_CSS500; - break; - - case SP_CSS_FONT_WEIGHT_600: - ret.weight = NR_POS_WEIGHT_CSS600; - break; - - case SP_CSS_FONT_WEIGHT_700: - case SP_CSS_FONT_WEIGHT_BOLD: - ret.weight = NR_POS_WEIGHT_CSS700; - break; - - case SP_CSS_FONT_WEIGHT_800: - ret.weight = NR_POS_WEIGHT_CSS800; - break; - - case SP_CSS_FONT_WEIGHT_900: - ret.weight = NR_POS_WEIGHT_CSS900; - break; - - case SP_CSS_FONT_WEIGHT_LIGHTER: - case SP_CSS_FONT_WEIGHT_BOLDER: - default: - g_warning("Unrecognized font_weight.computed value"); - ret.weight = NR_POS_WEIGHT_NORMAL; - break; - } - - switch (style.font_style.computed) { - case SP_CSS_FONT_STYLE_ITALIC: - ret.italic = 1; - break; - - case SP_CSS_FONT_STYLE_OBLIQUE: - ret.oblique = 1; - break; - - case SP_CSS_FONT_STYLE_NORMAL: - default: - ret.italic = 0; - ret.oblique = 0; - break; - } - - switch (style.font_stretch.computed) { - case SP_CSS_FONT_STRETCH_ULTRA_CONDENSED: - case SP_CSS_FONT_STRETCH_EXTRA_CONDENSED: - ret.stretch = NR_POS_STRETCH_EXTRA_CONDENSED; - break; - - case SP_CSS_FONT_STRETCH_CONDENSED: - case SP_CSS_FONT_STRETCH_NARROWER: - ret.stretch = NR_POS_STRETCH_CONDENSED; - break; - - case SP_CSS_FONT_STRETCH_SEMI_CONDENSED: - ret.stretch = NR_POS_STRETCH_SEMI_CONDENSED; - break; - - case SP_CSS_FONT_STRETCH_SEMI_EXPANDED: - ret.stretch = NR_POS_STRETCH_SEMI_EXPANDED; - break; - - case SP_CSS_FONT_STRETCH_EXPANDED: - case SP_CSS_FONT_STRETCH_WIDER: - ret.stretch = NR_POS_STRETCH_EXPANDED; - break; - - case SP_CSS_FONT_STRETCH_EXTRA_EXPANDED: - case SP_CSS_FONT_STRETCH_ULTRA_EXPANDED: - ret.stretch = NR_POS_STRETCH_EXTRA_EXPANDED; - break; - - default: - ret.stretch = NR_POS_STRETCH_NORMAL; - break; - } - - switch (style.font_variant.computed) { - case SP_CSS_FONT_VARIANT_SMALL_CAPS: - ret.variant = NR_POS_VARIANT_SMALLCAPS; - break; - default: - ret.variant = NR_POS_VARIANT_NORMAL; - break; - } - - return ret; -} diff --git a/src/libnrtype/font-style-to-pos.h b/src/libnrtype/font-style-to-pos.h deleted file mode 100644 index 41ba6cf72..000000000 --- a/src/libnrtype/font-style-to-pos.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SEEN_FONT_STYLE_TO_POS_H -#define SEEN_FONT_STYLE_TO_POS_H - -#include - -class SPStyle; - -NRTypePosDef font_style_to_pos(SPStyle const &style); - -#endif // SEEN_FONT_STYLE_TO_POS_H - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/libnrtype/nr-type-pos-def.cpp b/src/libnrtype/nr-type-pos-def.cpp deleted file mode 100644 index ff633d5f1..000000000 --- a/src/libnrtype/nr-type-pos-def.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#include "nr-type-pos-def.h" -#include -#include - -/** - * Given a font name or style name, returns a constant describing its - * apparent style (normal/italic/oblique). -*/ -int -parse_name_for_style (char const *cc) -{ - g_assert ( cc != NULL ); - gchar *c = g_ascii_strdown (cc, -1); - - gint style; - // first dab at i18n... french and german - if (strstr (c, "italic") || strstr (c, "italique") || strstr (c, "kursiv")) { - style = NR_POS_STYLE_ITALIC; - } else if (strstr (c, "oblique")) { - style = NR_POS_STYLE_OBLIQUE; - } else { - style = NR_POS_STYLE_NORMAL; - } - - g_free (c); - return style; -} - - -/** - * Given a font name or style name, returns a constant describing its - * apparent weight. -*/ -int -parse_name_for_weight (char const *cc) -{ - g_assert ( cc != NULL ); - gchar *c = g_ascii_strdown (cc, -1); - - gint weight; - if (strstr (c, "thin")) { - weight = NR_POS_WEIGHT_THIN; - } else if (strstr (c, "extra light")) { - weight = NR_POS_WEIGHT_EXTRA_LIGHT; - } else if (strstr (c, "ultra light")) { - weight = NR_POS_WEIGHT_ULTRA_LIGHT; - } else if (strstr (c, "light")) { - weight = NR_POS_WEIGHT_LIGHT; - } else if (strstr (c, "semi light")) { - weight = NR_POS_WEIGHT_SEMILIGHT; - } else if (strstr (c, "semilight")) { - weight = NR_POS_WEIGHT_SEMILIGHT; - } else if (strstr (c, "book")) { - weight = NR_POS_WEIGHT_BOOK; - } else if (strstr (c, "medium")) { - weight = NR_POS_WEIGHT_MEDIUM; - } else if (strstr (c, "semi bold")) { - weight = NR_POS_WEIGHT_SEMIBOLD; - } else if (strstr (c, "semibold")) { - weight = NR_POS_WEIGHT_SEMIBOLD; - } else if (strstr (c, "demi bold")) { - weight = NR_POS_WEIGHT_DEMIBOLD; - } else if (strstr (c, "demibold") || strstr (c, "demi")) { - weight = NR_POS_WEIGHT_DEMIBOLD; - } else if (strstr (c, "ultra bold")) { - weight = NR_POS_WEIGHT_ULTRA_BOLD; - } else if (strstr (c, "extra bold") || strstr (c, "xbold") || strstr (c, "xtrabold")) { - weight = NR_POS_WEIGHT_EXTRA_BOLD; - } else if (strstr (c, "black") || strstr (c, "heavy")) { - weight = NR_POS_WEIGHT_BLACK; - } else if (strstr (c, "bold")) { - /* Must come after the checks for `blah bold'. */ - weight = NR_POS_WEIGHT_BOLD; - } else { - weight = NR_POS_WEIGHT_NORMAL; - } - - g_free (c); - return weight; -} - -/** - * Given a font name or style name, returns a constant describing its - * apparent stretch. -*/ -int -parse_name_for_stretch (char const *cc) -{ - g_assert ( cc != NULL ); - gchar *c = g_ascii_strdown (cc, -1); - - gint stretch; - if (strstr (c, "ultra narrow") || strstr (c, "ultra condensed") || strstr (c, "extra condensed")) { - stretch = NR_POS_STRETCH_EXTRA_CONDENSED; - } else if (strstr (c, "ultra wide") || strstr (c, "ultra expanded") || strstr (c, "ultra extended") || strstr (c, "extra expanded")) { - stretch = NR_POS_STRETCH_EXTRA_EXPANDED; - } else if (strstr (c, "semi condensed") || strstr (c, "semicondensed")) { - stretch = NR_POS_STRETCH_SEMI_CONDENSED; - } else if (strstr (c, "semi extended") || strstr (c, "semiextended")) { - stretch = NR_POS_STRETCH_SEMI_EXPANDED; - } else if (strstr (c, "narrow") || strstr (c, "condensed")) { - stretch = NR_POS_STRETCH_CONDENSED; - } else if (strstr (c, "wide") || strstr (c, "expanded") || strstr (c, "extended")) { - stretch = NR_POS_STRETCH_EXPANDED; - } else { - stretch = NR_POS_STRETCH_NORMAL; - } - - g_free (c); - return stretch; -} - -/** - * Given a font name or style name, returns a constant describing its - * apparent variant (normal/smallcaps). -*/ -int -parse_name_for_variant (char const *cc) -{ - g_assert ( cc != NULL ); - gchar *c = g_ascii_strdown (cc, -1); - - gint variant; - if (strstr (c, "small caps") || strstr (c, "smallcaps") || strstr (c, "caps")) { - variant = NR_POS_VARIANT_SMALLCAPS; - } else { - variant = NR_POS_VARIANT_NORMAL; - } - - g_free (c); - return variant; -} - -/** - * Given a style constant, returns the CSS value for font-style. -*/ -const char * -style_to_css (int style) -{ - switch (style) { - case NR_POS_STYLE_NORMAL: - return "normal"; - break; - case NR_POS_STYLE_ITALIC: - return "italic"; - break; - case NR_POS_STYLE_OBLIQUE: - return "oblique"; - break; - default: - break; - } - return NULL; -} - - -/** - * Given a weight constant, returns the CSS value for font-weight. -*/ -const char * -weight_to_css (int weight) -{ - switch (weight) { - case NR_POS_WEIGHT_THIN: - return "100"; - break; - case NR_POS_WEIGHT_EXTRA_LIGHT: - return "200"; - break; - case NR_POS_WEIGHT_LIGHT: - return "300"; - break; - case NR_POS_WEIGHT_BOOK: - return "normal"; - break; - case NR_POS_WEIGHT_MEDIUM: - return "500"; - break; - case NR_POS_WEIGHT_SEMIBOLD: - return "600"; - break; - case NR_POS_WEIGHT_BOLD: - return "bold"; - break; - case NR_POS_WEIGHT_EXTRA_BOLD: - return "800"; - break; - case NR_POS_WEIGHT_BLACK: - return "900"; - break; - default: - break; - } - return NULL; -} - -/** - * Given a stretch constant, returns the CSS value for font-stretch. -*/ -const char * -stretch_to_css (int stretch) -{ - switch (stretch) { - case NR_POS_STRETCH_EXTRA_CONDENSED: - return "extra-condensed"; - break; - case NR_POS_STRETCH_CONDENSED: - return "condensed"; - break; - case NR_POS_STRETCH_SEMI_CONDENSED: - return "semi-condensed"; - break; - case NR_POS_STRETCH_NORMAL: - return "normal"; - break; - case NR_POS_STRETCH_SEMI_EXPANDED: - return "semi-expanded"; - break; - case NR_POS_STRETCH_EXPANDED: - return "expanded"; - break; - case NR_POS_STRETCH_EXTRA_EXPANDED: - return "extra-expanded"; - break; - default: - break; - } - return NULL; -} - -/** - * Given a variant constant, returns the CSS value for font-variant. -*/ -const char * -variant_to_css (int stretch) -{ - switch (stretch) { - case NR_POS_VARIANT_SMALLCAPS: - return "small-caps"; - break; - case NR_POS_VARIANT_NORMAL: - return "normal"; - break; - default: - break; - } - return NULL; -} - - -/** - * Constructor for NRTypePostDef. Sets the italic, oblique, weight, - * stretch, and variant. - */ -NRTypePosDef::NRTypePosDef(char const *description) { - // we cannot use strcasestr, it's linux only... so we must lowercase the string first - g_assert ( description != NULL ); - gchar *c = g_ascii_strdown (description, -1); - - /* copied from nr-type-directory.cpp:nr_type_calculate_position. */ - - italic = (strstr (c, "italic") != NULL); - oblique = (strstr (c, "oblique") != NULL); - - weight = parse_name_for_weight (c); - - stretch = parse_name_for_stretch (c); - - variant = parse_name_for_variant (c); - - g_free (c); -} diff --git a/src/libnrtype/nr-type-pos-def.h b/src/libnrtype/nr-type-pos-def.h deleted file mode 100644 index d4d412b21..000000000 --- a/src/libnrtype/nr-type-pos-def.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef __NR_TYPE_POS_DEF_H__ -#define __NR_TYPE_POS_DEF_H__ - -#define NR_POS_STYLE_NORMAL 0 -#define NR_POS_STYLE_ITALIC 1 -#define NR_POS_STYLE_OBLIQUE 2 - -#define NR_POS_WEIGHT_THIN 32 -#define NR_POS_WEIGHT_EXTRA_LIGHT 64 -#define NR_POS_WEIGHT_ULTRA_LIGHT 64 -#define NR_POS_WEIGHT_LIGHT 96 -#define NR_POS_WEIGHT_SEMILIGHT 96 -#define NR_POS_WEIGHT_BOOK 128 -#define NR_POS_WEIGHT_NORMAL 128 -#define NR_POS_WEIGHT_MEDIUM 144 -#define NR_POS_WEIGHT_SEMIBOLD 160 -#define NR_POS_WEIGHT_DEMIBOLD 160 -#define NR_POS_WEIGHT_BOLD 192 -#define NR_POS_WEIGHT_ULTRA_BOLD 224 -#define NR_POS_WEIGHT_EXTRA_BOLD 224 -#define NR_POS_WEIGHT_BLACK 255 - -#define NR_POS_STRETCH_ULTRA_CONDENSED 48 -#define NR_POS_STRETCH_EXTRA_CONDENSED 48 -#define NR_POS_STRETCH_CONDENSED 88 -#define NR_POS_STRETCH_SEMI_CONDENSED 108 -#define NR_POS_STRETCH_NORMAL 128 -#define NR_POS_STRETCH_SEMI_EXPANDED 148 -#define NR_POS_STRETCH_EXPANDED 168 -#define NR_POS_STRETCH_EXTRA_EXPANDED 228 -#define NR_POS_STRETCH_ULTRA_EXPANDED 228 - -// This is an enumerate, rather than on/off property, -// for I sincerely hope the vocabulary of this property will be -// extended by the W3C in the future to allow for more fancy fonts -#define NR_POS_VARIANT_NORMAL 0 -#define NR_POS_VARIANT_SMALLCAPS 1 - -/* Mapping from CSS weight numbers. - - for i in `seq 9`; do - if [ $i -le 4 ]; then w=$((32 * $i)); - elif [ $i = 5 ]; then w=144; - elif [ $i -lt 9 ]; then w=$((32 * $(($i - 1)))); - else w=255; - fi; - printf '#define NR_POS_WEIGHT_CSS%d00\t\t%3d\n' $i $w; - done - - This calculation approximately matches the old to-and-from-text code, - I don't claim it to be reasonable. ("approximately": some of the old - code wrote strings like "semi" and "heavy" that weren't being parsed - at the other end, and it had CSS100 darker than CSS200.) - */ -#define NR_POS_WEIGHT_CSS100 32 -#define NR_POS_WEIGHT_CSS200 64 -#define NR_POS_WEIGHT_CSS300 96 -#define NR_POS_WEIGHT_CSS400 128 -#define NR_POS_WEIGHT_CSS500 144 -#define NR_POS_WEIGHT_CSS600 160 -#define NR_POS_WEIGHT_CSS700 192 -#define NR_POS_WEIGHT_CSS800 224 -#define NR_POS_WEIGHT_CSS900 255 - - -class NRTypePosDef { -public: - unsigned int italic : 1; - unsigned int oblique : 1; - unsigned int weight : 8; - unsigned int stretch : 8; - unsigned int variant : 8; - /* These can probably be made sensible sizes rather than bitfields; for the moment we'll - keep the old definition. */ - -public: - NRTypePosDef() : - italic(0), - oblique(0), - weight(NR_POS_WEIGHT_NORMAL), - stretch(NR_POS_STRETCH_NORMAL), - variant(NR_POS_VARIANT_NORMAL) - { } - - NRTypePosDef(char const *description); - - bool signature() {return this->italic + - this->oblique * 255 + - this->weight * 255 * 255 + - this->stretch * 255 * 255 * 255 + - this->variant * 255 * 255 * 255 * 255;}; -}; - -int parse_name_for_style (char const *c); -int parse_name_for_weight (char const *c); -int parse_name_for_stretch (char const *c); -int parse_name_for_variant (char const *c); -const char *style_to_css (int style); -const char *weight_to_css (int weight); -const char *stretch_to_css (int stretch); -const char *variant_to_css (int variant); - -#endif /* __NR_TYPE_POS_DEF_H__ */ -- cgit v1.2.3 From 663e9d9f949a142a094270d97c5ad4fe9ffe86dc Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 2 Oct 2014 09:44:34 +0200 Subject: Fix style string while searching for best face match. Fix typo for 'ultra-condensed' face in fontspec_from_style(). (bzr r13341.1.236) --- src/libnrtype/font-lister.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index c6d7327f6..fad06cd00 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -819,7 +819,7 @@ Glib::ustring FontLister::fontspec_from_style(SPStyle *style) switch (style->font_stretch.computed) { case SP_CSS_FONT_STRETCH_ULTRA_CONDENSED: - fontspec += " extra-condensed"; + fontspec += " ultra-condensed"; break; case SP_CSS_FONT_STRETCH_EXTRA_CONDENSED: @@ -1009,7 +1009,7 @@ Glib::ustring FontLister::get_best_style_match(Glib::ustring family, Glib::ustri } GList *styles = row[FontList.styles]; for (GList *l = styles; l; l = l->next) { - Glib::ustring fontspec = family + ", " + (char *)l->data; + Glib::ustring fontspec = family + ", " + ((StyleNames *)l->data)->CssName; PangoFontDescription *candidate = pango_font_description_from_string(fontspec.c_str()); //font_description_dump( candidate ); //std::cout << " " << font_description_better_match( target, best, candidate ) << std::endl; -- cgit v1.2.3 From a7fe90319533cc4fdc79e3bc51355c3e69e341fa Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 2 Oct 2014 10:20:01 +0200 Subject: Sort styles for GUI. (Regression) (bzr r13341.1.237) --- src/libnrtype/FontFactory.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index c2b3c64fe..dd2ecddeb 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -513,6 +513,12 @@ static bool StyleNameCompareInternal(const StyleNames &style1, const StyleNames return( StyleNameValue( style1.CssName ) < StyleNameValue( style2.CssName ) ); } +static gint StyleNameCompareInternalGlib(gconstpointer a, gconstpointer b) +{ + return( StyleNameValue( ((StyleNames *)a)->CssName ) < + StyleNameValue( ((StyleNames *)b)->CssName ) ? -1 : 1 ); +} + static bool ustringPairSort(std::pair const& first, std::pair const& second) { // well, this looks weird. @@ -586,9 +592,12 @@ GList* font_factory::GetUIStyles(PangoFontFamily * in) pango_font_description_free(faceDescr); } g_free(faces); + + ret = g_list_sort( ret, StyleNameCompareInternalGlib ); return ret; } +// Used only by pdfinput/svg-builder.cpp (since rewrite to cache style) void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map) { g_assert(map); -- cgit v1.2.3 From 0aeb92afb81538139d6ad8f68b59f9a76d5e9734 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 2 Oct 2014 21:40:47 +0200 Subject: Work-around for Pango 1.36.7 which introduced 'Semi-Light' font weight, bug #1364937. (bzr r13341.1.238) --- src/libnrtype/FontFactory.cpp | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index dd2ecddeb..56fc18c7f 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -97,6 +97,7 @@ font_factory::font_factory(void) : fontSize(512), loadedPtr(new FaceMapType()) { + // std::cout << pango_version_string() << std::endl; #ifdef USE_PANGO_WIN32 #else pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fontServer), @@ -572,7 +573,7 @@ GList* font_factory::GetUIStyles(PangoFontFamily * in) if (faceDescr) { Glib::ustring familyUIName = GetUIFamilyString(faceDescr); Glib::ustring styleUIName = GetUIStyleString(faceDescr); - + // std::cout << familyUIName << " " << styleUIName << " " << displayName << std::endl; // Disable synthesized (faux) font faces except for CSS generic faces if (pango_font_face_is_synthesized(faces[currentFace]) ) { if (familyUIName.compare( "sans-serif" ) != 0 && @@ -584,6 +585,35 @@ GList* font_factory::GetUIStyles(PangoFontFamily * in) } } + // Pango breaks the 1 to 1 mapping between Pango weights and CSS weights by + // adding Semi-Light (as of 1.36.7), Book (as of 1.24), and Ultra-Heavy (as of + // 1.24). We need to map these weights to CSS weights. Book and Ultra-Heavy + // are rarely used. Semi-Light (350) is problematic as it is halfway between + // Light (300) and Normal (400) and if care is not taken it is converted to + // Normal, rather than Light. + // + // Note: The ultimate solution to handling various weight in the same + // font family is to support the @font rules from CSS. + // + // Additional notes, helpful for debugging: + // Pango's FC backend: + // Weights defined in fontconfig/fontconfig.h + // String equivalents in src/fcfreetype.c + // Weight set from os2->usWeightClass + // Use Fontforge: Element->Font Info...->OS/2->Misc->Weight Class to check font weight + size_t f = styleUIName.find( "Book" ); + if( f != Glib::ustring::npos ) { + styleUIName.replace( f, 4, "Normal" ); + } + f = styleUIName.find( "Semi-Light" ); + if( f != Glib::ustring::npos ) { + styleUIName.replace( f, 10, "Light" ); + } + f = styleUIName.find( "Ultra-Heavy" ); + if( f != Glib::ustring::npos ) { + styleUIName.replace( f, 11, "Heavy" ); + } + if (!familyUIName.empty() && !styleUIName.empty()) { // Add the style information ret = g_list_append(ret, new StyleNames(styleUIName, displayName)); -- cgit v1.2.3 From c3e0389161173d010c074d2feba7c278cfcd2401 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 3 Oct 2014 15:01:47 +0200 Subject: Removal of unused code dealing with PangoStringToDescrMap and UIStringToPangoStringMap. Removal of font_factory::GetUIFamiliesAndStyle() (unneeded after implementation of style caching). (bzr r13341.1.239) --- src/libnrtype/FontFactory.cpp | 431 +----------------------------------------- src/libnrtype/FontFactory.h | 38 ++-- 2 files changed, 28 insertions(+), 441 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 56fc18c7f..19117629a 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -130,13 +130,6 @@ font_factory::~font_factory(void) delete tmp; loadedPtr = 0; } - - // Delete the pango font pointers in the string to instance map - PangoStringToDescrMap::iterator it = fontInstanceMap.begin(); - while (it != fontInstanceMap.end()) { - pango_font_description_free((*it).second); - ++it; - } } @@ -249,248 +242,6 @@ Glib::ustring font_factory::GetUIStyleString(PangoFontDescription const *fontDes return style; } -/** - Replace font family leaving style alone (if possible). - @param fontSpec the given font - @param newFamily - @return the changed fontspec, if the property can not be set return an empty string - The routine first searches for an exact match. - If no exact match found, calls FontSpecificationBestMatch(). -*/ -Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily) -{ - Glib::ustring newFontSpec; - - // Although we are using the string from pango_font_description_to_string for the - // font specification, we definitely cannot just set the new family in the - // PangoFontDescription structure and ask for a new string. This is because - // what constitutes a "family" in our own UI may be different from how Pango - // sees it. - - // Find the PangoFontDescription associated with the old font specification string. - PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec); - - - if (it != fontInstanceMap.end()) { - // Description found! - - // Make copy - PangoFontDescription *descr = pango_font_description_copy((*it).second); - - // Grab the old UI Family string from the descr - Glib::ustring uiFamily = GetUIFamilyString(descr); - - // Replace the UI Family name with the new family name - std::size_t found = fontSpec.find(uiFamily); - if (found != Glib::ustring::npos) { - - // Add comma to end of newFamily... commas at end don't hurt but are - // required if the last part of a family name is a valid font style - // (e.g. "Arial Black"). - Glib::ustring newFamilyComma = newFamily; - if( *newFamilyComma.rbegin() != ',' ) { - newFamilyComma += ","; - } - newFontSpec = fontSpec; - newFontSpec.erase(found, uiFamily.size()); - newFontSpec.insert(found, newFamilyComma); - - // If the new font specification does not exist in the reference maps, - // search for the next best match for the faces in that style - it = fontInstanceMap.find(newFontSpec); - if (it == fontInstanceMap.end()) { - - // Search for best match, empty string returned if not found. - newFontSpec = FontSpecificationBestMatch( newFontSpec ); - - } - } - - pango_font_description_free(descr); - } - - return newFontSpec; -} - -/** - Apply style property to the given font - @param fontSpec the given font - @param turnOn true to set italic style - @return the changed fontspec, if the property can not be set return an empty string - The routine first searches for an exact match to "FontFamily Italic" or - "Font Family Oblique" (turnOn is true) or "FontFamily" (turnOn is false). - If no exact match found, calls FontSpecificationBestMatch(). -*/ -Glib::ustring font_factory::FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn) -{ - Glib::ustring newFontSpec; - - // Find the PangoFontDescription associated with the font specification string. - PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec); - - if (it != fontInstanceMap.end()) { - // Description found! - - // Make copy. - PangoFontDescription *descr = pango_font_description_copy((*it).second); - - PangoStyle style; - if (turnOn) { - // First try Oblique, we'll try Italic later - style = PANGO_STYLE_OBLIQUE; - } else { - style = PANGO_STYLE_NORMAL; - } - - pango_font_description_set_style(descr, style); - - newFontSpec = ConstructFontSpecification(descr); - - bool exactMatchFound = true; - if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) { - - exactMatchFound = false; - if (turnOn) { - // Next try Italic - style = PANGO_STYLE_ITALIC; - pango_font_description_set_style(descr, style); - - exactMatchFound = true; - if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) { - exactMatchFound = false; - } - } - } - - // Search for best match, empty string returned if not found. - if( !exactMatchFound ) { - newFontSpec = FontSpecificationBestMatch( newFontSpec ); - } - - pango_font_description_free(descr); - } - - return newFontSpec; // Empty if not found. -} - -/** - Apply weight property to the given font - @param fontSpec the given font - @param turnOn true to set bold - @return the changed fontspec, if the property can not be set return an empty string - This routine first searches for an exact match, if none found - it calls FontSpecificationBestMatch(). -*/ -Glib::ustring font_factory::FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn) -{ - Glib::ustring newFontSpec; - - // Find the PangoFontDescription associated with the font specification string. - PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec); - - if (it != fontInstanceMap.end()) { - // Description found! - - // Make copy. - PangoFontDescription *descr = pango_font_description_copy((*it).second); - - - PangoWeight weight; - if (turnOn) { - weight = PANGO_WEIGHT_BOLD; - } else { - weight = PANGO_WEIGHT_NORMAL; - } - - pango_font_description_set_weight(descr, weight); - - newFontSpec = ConstructFontSpecification(descr); - - if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) { - // Search for best match, empty string returned if not found. - newFontSpec = FontSpecificationBestMatch( newFontSpec ); - } - - pango_font_description_free(descr); - } - - return newFontSpec; // Empty if not found. -} - -/** - Use pango_font_description_better_match() to find best font match. - This handles cases like Century Schoolbook L where the "normal" - font is Century Schoolbook L Medium so just removing Italic - from the font name doesn't yield the correct name. - @param fontSpec the given font - @return the changed fontspec, if the property can not be set return an empty string -*/ -// http://library.gnome.org/devel/pango/1.28/pango-Fonts.html#pango-font-description-better-match -Glib::ustring font_factory::FontSpecificationBestMatch(const Glib::ustring & fontSpec ) -{ - - Glib::ustring newFontSpec; - - // Look for exact match - PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec); - - // If there is no exact match, look for the best match. - if (it != fontInstanceMap.end()) { - - newFontSpec = fontSpec; - - } else { - - PangoFontDescription *fontDescr = pango_font_description_from_string(fontSpec.c_str()); - PangoFontDescription *bestMatchDescr = NULL; - - // Grab the UI Family string from the descr - Glib::ustring family = GetUIFamilyString(fontDescr); - Glib::ustring bestMatchDescription; - - bool setFirstFamilyMatch = false; - for (it = fontInstanceMap.begin(); it != fontInstanceMap.end(); ++it) { - - Glib::ustring currentFontSpec = (*it).first; - Glib::ustring currentFamily = GetUIFamilyString((*it).second); - - // Save some time by only looking at the right family. - // Must use family name rather than fontSpec - // (otherwise DejaVu Sans matches DejaVu Sans Mono). - if (currentFamily == family) { - if (!setFirstFamilyMatch) { - // This ensures that the closest match is at least within the correct - // family rather than the first font in the list - bestMatchDescr = pango_font_description_copy((*it).second); - bestMatchDescription = currentFontSpec; - setFirstFamilyMatch = true; - } else { - // Get the font description that corresponds, and - // then see if we've found a better match - PangoFontDescription *possibleMatch = pango_font_description_copy((*it).second); - - if (pango_font_description_better_match( - fontDescr, bestMatchDescr, possibleMatch)) { - - pango_font_description_free(bestMatchDescr); - bestMatchDescr = possibleMatch; - bestMatchDescription = currentFontSpec; - } else { - pango_font_description_free(possibleMatch); - } - } - } - } // for - - newFontSpec = bestMatchDescription; // If NULL, then no match found - - pango_font_description_free(fontDescr); - pango_font_description_free(bestMatchDescr); - - } - - return newFontSpec; -} ///// @@ -565,6 +316,7 @@ GList* font_factory::GetUIStyles(PangoFontFamily * in) // If the face has a name, describe it, and then use the // description to get the UI family and face strings const gchar* displayName = pango_font_face_get_face_name(faces[currentFace]); + // std::cout << "Display Name: " << displayName << std::endl; if (displayName == NULL || *displayName == '\0') { continue; } @@ -627,110 +379,6 @@ GList* font_factory::GetUIStyles(PangoFontFamily * in) return ret; } -// Used only by pdfinput/svg-builder.cpp (since rewrite to cache style) -void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map) -{ - g_assert(map); - - if (map) { - - // Gather the family names as listed by Pango - PangoFontFamily** families = NULL; - int numFamilies = 0; - pango_font_map_list_families(fontServer, &families, &numFamilies); - - for (int currentFamily=0; currentFamily < numFamilies; currentFamily++) { - - // Gather the styles for this family - PangoFontFace** faces = NULL; - int numFaces = 0; - pango_font_family_list_faces(families[currentFamily], &faces, &numFaces); - - for (int currentFace=0; currentFace < numFaces; currentFace++) { - - // If the face has a name, describe it, and then use the - // description to get the UI family and face strings - - const gchar* displayName = pango_font_face_get_face_name(faces[currentFace]); - if (displayName == NULL) { - continue; - } - - PangoFontDescription *faceDescr = pango_font_face_describe(faces[currentFace]); - if (faceDescr) { - Glib::ustring familyUIName = GetUIFamilyString(faceDescr); - Glib::ustring styleUIName = GetUIStyleString(faceDescr); - - // Disable synthesized (faux) font faces except for CSS generic faces - if (pango_font_face_is_synthesized(faces[currentFace]) ) { - if( familyUIName.compare( "sans-serif" ) != 0 && - familyUIName.compare( "serif" ) != 0 && - familyUIName.compare( "monospace" ) != 0 && - familyUIName.compare( "fantasy" ) != 0 && - familyUIName.compare( "cursive" ) != 0 ) { - //std::cout << "faux: " << familyUIName << " | " << styleUIName << std::endl; - continue; - } - } - - if (!familyUIName.empty() && !styleUIName.empty()) { - - // Find the right place to put the style information, adding - // a map entry for the family name if it doesn't yet exist - - FamilyToStylesMap::iterator iter = map->find(familyUIName); - - // Insert new family - if (iter == map->end()) { - map->insert(std::make_pair(familyUIName, std::list())); - } - - // 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 &styleList = (*map)[familyUIName]; - - for (std::list::iterator it=styleList.begin(); - it != styleList.end(); - ++it) { - if ( (*it).CssName == styleUIName) { - exists = true; - break; - } - } - - if (!exists) { - styleList.push_back( StyleNames(styleUIName,displayName) ); - - // Add the string info needed in the reference maps - fontStringMap.insert( - std::make_pair( - Glib::ustring(familyUIName) + Glib::ustring(styleUIName), - ConstructFontSpecification(faceDescr))); - fontInstanceMap.insert( - std::make_pair(ConstructFontSpecification(faceDescr), faceDescr)); - - } else { - pango_font_description_free(faceDescr); - } - } else { - pango_font_description_free(faceDescr); - } - } - } - g_free(faces); - faces = 0; - } - g_free(families); - families = 0; - - // Sort the style lists - for (FamilyToStylesMap::iterator iter = map->begin() ; iter != map->end(); ++iter) { - (*iter).second.sort(StyleNameCompareInternal); - } - } -} font_instance* font_factory::FaceFromStyle(SPStyle const *style) { @@ -876,14 +524,6 @@ font_instance* font_factory::FaceFromStyle(SPStyle const *style) font = Face(temp_descr); pango_font_description_free(temp_descr); - - // We now find closest match to this font: - Glib::ustring fontSpec = font_factory::Default()->ConstructFontSpecification(font); - Glib::ustring newFontSpec = FontSpecificationBestMatch( fontSpec ); - if( fontSpec != newFontSpec ) { - font->Unref(); - font = FaceFromFontSpecification( newFontSpec.c_str() ); - } } } @@ -899,37 +539,6 @@ font_instance *font_factory::FaceFromDescr(char const *family, char const *style return res; } -font_instance* font_factory::FaceFromUIStrings(char const *uiFamily, char const *uiStyle) -{ - font_instance *fontInstance = NULL; - - g_assert(uiFamily && uiStyle); - if (uiFamily && uiStyle) { - - // If font list, take only first font in list - gchar** tokens = g_strsplit( uiFamily, ",", 0 ); - g_strstrip( tokens[0] ); - - Glib::ustring uiString = Glib::ustring(tokens[0]) + Glib::ustring(uiStyle); - - g_strfreev( tokens ); - - UIStringToPangoStringMap::iterator uiToPangoIter = fontStringMap.find(uiString); - - if (uiToPangoIter != fontStringMap.end ()) { - PangoStringToDescrMap::iterator pangoToDescrIter = fontInstanceMap.find((*uiToPangoIter).second); - if (pangoToDescrIter != fontInstanceMap.end()) { - // We found the pango description - now we can make a font_instance - PangoFontDescription *tempDescr = pango_font_description_copy((*pangoToDescrIter).second); - fontInstance = Face(tempDescr); - pango_font_description_free(tempDescr); - } - } - } - - return fontInstance; -} - font_instance* font_factory::FaceFromPangoString(char const *pangoString) { font_instance *fontInstance = NULL; @@ -937,25 +546,15 @@ font_instance* font_factory::FaceFromPangoString(char const *pangoString) g_assert(pangoString); if (pangoString) { - PangoFontDescription *descr = NULL; - - // First attempt to find the font specification in the reference map - PangoStringToDescrMap::iterator it = fontInstanceMap.find(Glib::ustring(pangoString)); - if (it != fontInstanceMap.end()) { - descr = pango_font_description_copy((*it).second); - } - // Or create a font description from the string - this may fail or + // Create a font description from the string - this may fail or // produce unexpected results if the string does not have a good format - if (!descr) { - descr = pango_font_description_from_string(pangoString); - } - - if (descr && (sp_font_description_get_family(descr) != NULL)) { - fontInstance = Face(descr); - } + PangoFontDescription *descr = pango_font_description_from_string(pangoString); if (descr) { + if (sp_font_description_get_family(descr) != NULL) { + fontInstance = Face(descr); + } pango_font_description_free(descr); } } @@ -1120,24 +719,6 @@ void font_factory::AddInCache(font_instance *who) nbEnt++; } -/* - { - std::cout << " Printing out fontInstanceMap: " << std::endl; - PangoStringToDescrMap::iterator it = fontInstanceMap.begin(); - while (it != fontInstanceMap.end()) { - - PangoFontDescription *descr = pango_font_description_copy((*it).second); - - // Grab the UI Family string from the descr - Glib::ustring uiFamily = GetUIFamilyString(descr); - Glib::ustring uiStyle = GetUIStyleString(descr); - std::cout << " " << uiFamily << " " << uiStyle << std::endl; - - it++; - } - } -*/ - /* Local Variables: mode:c++ diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h index 34ef36883..46df0181a 100644 --- a/src/libnrtype/FontFactory.h +++ b/src/libnrtype/FontFactory.h @@ -112,18 +112,6 @@ public: Glib::ustring GetUIFamilyString(PangoFontDescription const *fontDescr); Glib::ustring GetUIStyleString(PangoFontDescription const *fontDescr); - /// Modifiers for the font specification (returns new font specification) - Glib::ustring ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily); - Glib::ustring FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn); - Glib::ustring FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn); - - Glib::ustring FontSpecificationBestMatch(const Glib::ustring& fontSpec ); - - // Gathers all strings needed for UI while storing pango information in - // fontInstanceMap and fontStringMap - // don't use this function, it's too slow - void GetUIFamiliesAndStyles(FamilyToStylesMap *map); - // Helpfully inserts all font families into the provided vector void GetUIFamilies(std::vector& out); // Retrieves style information about a family in a newly allocated GList. @@ -152,19 +140,37 @@ public: private: void* loadedPtr; + + // The following two commented out maps were an attempt to allow Inkscape to use font faces + // that could not be distinguished by CSS values alone. In practice, they never were that + // useful as PangoFontDescription, which is used throughout our code, cannot distinguish + // between faces anymore than raw CSS values (with the exception of two additional weight + // values). + // + // During various works, for example to handle font-family lists and fonts that are not + // installed on the system, the code has become less reliant on these maps. And in the work to + // catch style information to speed up start up times, the maps were not being filled. + // I've removed all code that used these maps as of Oct 2014 in the experimental branch. + // The commented out maps are left here as a reminder of the path that was attempted. + // + // One possible method to keep track of font faces would be to use the 'display name', keeping + // pointers to the appropriate PangoFontFace. The font_factory loadedFaces map indexing would + // have to be changed to incorporate 'display name' (InkscapeFontDescription?). + + // These two maps are used for translating between what's in the UI and a pango // font description. This is necessary because Pango cannot always // reproduce these structures from the names it gave us in the first place. // Key: A string produced by font_factory::ConstructFontSpecification // Value: The associated PangoFontDescription - typedef std::map PangoStringToDescrMap; - PangoStringToDescrMap fontInstanceMap; + // typedef std::map PangoStringToDescrMap; + // PangoStringToDescrMap fontInstanceMap; // Key: Family name in UI + Style name in UI // Value: The associated string that should be produced with font_factory::ConstructFontSpecification - typedef std::map UIStringToPangoStringMap; - UIStringToPangoStringMap fontStringMap; + // typedef std::map UIStringToPangoStringMap; + // UIStringToPangoStringMap fontStringMap; }; -- cgit v1.2.3 From d8abd3bf6c942e0fec619ce21723c1a10b3b0bae Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 3 Oct 2014 20:04:47 +0200 Subject: Allow one style entry per unique CSS style for each family. (bzr r13341.1.240) --- src/libnrtype/FontFactory.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 19117629a..c8f5e1fef 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -260,10 +260,10 @@ static int StyleNameValue( const Glib::ustring &style ) } // Determines order in which styles are presented (sorted by CSS style values) -static bool StyleNameCompareInternal(const StyleNames &style1, const StyleNames &style2) -{ - return( StyleNameValue( style1.CssName ) < StyleNameValue( style2.CssName ) ); -} +//static bool StyleNameCompareInternal(const StyleNames &style1, const StyleNames &style2) +//{ +// return( StyleNameValue( style1.CssName ) < StyleNameValue( style2.CssName ) ); +//} static gint StyleNameCompareInternalGlib(gconstpointer a, gconstpointer b) { @@ -366,7 +366,19 @@ GList* font_factory::GetUIStyles(PangoFontFamily * in) styleUIName.replace( f, 11, "Heavy" ); } - if (!familyUIName.empty() && !styleUIName.empty()) { + bool exists = false; + for(GList *temp = ret; temp; temp = temp->next) { + if( ((StyleNames*)temp->data)->CssName.compare( styleUIName ) == 0 ) { + exists = true; + std::cerr << "Warning: Font face with same CSS values already added: " + << familyUIName << " " << styleUIName + << " (" << ((StyleNames*)temp->data)->DisplayName + << ", " << displayName << ")" << std::endl; + break; + } + } + + if (!exists && !familyUIName.empty() && !styleUIName.empty()) { // Add the style information ret = g_list_append(ret, new StyleNames(styleUIName, displayName)); } @@ -375,6 +387,7 @@ GList* font_factory::GetUIStyles(PangoFontFamily * in) } g_free(faces); + // Sort the style lists ret = g_list_sort( ret, StyleNameCompareInternalGlib ); return ret; } -- cgit v1.2.3 From 92b3e813281005a82b50aed4e168aa938575920e Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sun, 5 Oct 2014 12:21:45 +0200 Subject: Remove unused functions. (bzr r13341.1.244) --- src/libnrtype/FontInstance.cpp | 149 ----------------------------------------- src/libnrtype/font-instance.h | 6 -- 2 files changed, 155 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index ce4c99ef7..a5572c517 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -239,155 +239,6 @@ void font_instance::Unref(void) } } -unsigned int font_instance::Name(gchar *str, unsigned int size) -{ - return Attribute("name", str, size); -} - -unsigned int font_instance::Family(gchar *str, unsigned int size) -{ - return Attribute("family", str, size); -} - -unsigned int font_instance::PSName(gchar *str, unsigned int size) -{ - return Attribute("psname", str, size); -} - -unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int size) -{ - if ( descr == NULL ) { - if ( size > 0 ) { - str[0]=0; - } - return 0; - } - char* res=NULL; - bool free_res=false; - - if ( strcmp(key,"name") == 0 ) { - PangoFontDescription* td=pango_font_description_copy(descr); - pango_font_description_unset_fields (td, PANGO_FONT_MASK_SIZE); - res=pango_font_description_to_string (td); - pango_font_description_free(td); - free_res=true; - } else if ( strcmp(key,"psname") == 0 ) { -#ifndef USE_PANGO_WIN32 - res = (char *) FT_Get_Postscript_Name (theFace); // that's the main method, seems to always work -#endif - free_res=false; - if (res == NULL) { // a very limited workaround, only bold, italic, and oblique will work - PangoStyle style=pango_font_description_get_style(descr); - bool i = (style == PANGO_STYLE_ITALIC); - bool o = (style == PANGO_STYLE_OBLIQUE); - PangoWeight weight=pango_font_description_get_weight(descr); - bool b = (weight >= PANGO_WEIGHT_BOLD); - - res = g_strdup_printf ("%s%s%s%s", - sp_font_description_get_family(descr), - (b || i || o) ? "-" : "", - (b) ? "Bold" : "", - (i) ? "Italic" : ((o) ? "Oblique" : "") ); - free_res = true; - } - } else if ( strcmp(key,"family") == 0 ) { - res=(char*)sp_font_description_get_family(descr); - free_res=false; - } else if ( strcmp(key,"style") == 0 ) { - PangoStyle v=pango_font_description_get_style(descr); - if ( v == PANGO_STYLE_ITALIC ) { - res=(char*)"italic"; - } else if ( v == PANGO_STYLE_OBLIQUE ) { - res=(char*)"oblique"; - } else { - res=(char*)"normal"; - } - free_res=false; - } else if ( strcmp(key,"weight") == 0 ) { - PangoWeight v=pango_font_description_get_weight(descr); - if ( v <= PANGO_WEIGHT_THIN ) { - res=(char*)"100"; - } else if ( v <= PANGO_WEIGHT_ULTRALIGHT ) { - res=(char*)"200"; - } else if ( v <= PANGO_WEIGHT_LIGHT ) { - res=(char*)"300"; -#if PANGO_VERSION_CHECK(1,36,6) - } else if ( v <= PANGO_WEIGHT_SEMILIGHT ) { - res=(char*)"350"; -#endif - } else if ( v <= PANGO_WEIGHT_BOOK ) { - res=(char*)"380"; - } else if ( v <= PANGO_WEIGHT_NORMAL ) { - res=(char*)"normal"; - } else if ( v <= PANGO_WEIGHT_MEDIUM ) { - res=(char*)"500"; - } else if ( v <= PANGO_WEIGHT_SEMIBOLD ) { - res=(char*)"600"; - } else if ( v <= PANGO_WEIGHT_BOLD ) { - res=(char*)"bold"; - } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) { - res=(char*)"800"; - } else { // HEAVY NB: Pango defines ULTRAHEAVY = 1000 but not CSS2 - res=(char*)"900"; - } - free_res=false; - } else if ( strcmp(key,"stretch") == 0 ) { - PangoStretch v=pango_font_description_get_stretch(descr); - if ( v <= PANGO_STRETCH_EXTRA_CONDENSED ) { - res=(char*)"extra-condensed"; - } else if ( v <= PANGO_STRETCH_CONDENSED ) { - res=(char*)"condensed"; - } else if ( v <= PANGO_STRETCH_SEMI_CONDENSED ) { - res=(char*)"semi-condensed"; - } else if ( v <= PANGO_STRETCH_NORMAL ) { - res=(char*)"normal"; - } else if ( v <= PANGO_STRETCH_SEMI_EXPANDED ) { - res=(char*)"semi-expanded"; - } else if ( v <= PANGO_STRETCH_EXPANDED ) { - res=(char*)"expanded"; - } else { - res=(char*)"extra-expanded"; - } - free_res=false; - } else if ( strcmp(key,"variant") == 0 ) { - PangoVariant v=pango_font_description_get_variant(descr); - if ( v == PANGO_VARIANT_SMALL_CAPS ) { - res=(char*)"small-caps"; - } else { - res=(char*)"normal"; - } - free_res=false; - } else { - res = NULL; - free_res=false; - } - if ( res == NULL ) { - if ( size > 0 ) { - str[0] = 0; - } - return 0; - } - - if (res) { - unsigned int len=strlen(res); - unsigned int rlen=(size-1 0 ) { - memcpy(str, res, rlen); - } - if ( size > 0 ) { - str[rlen] = 0; - } - } - if (free_res) { - g_free(res); - res = 0; - } - return len; - } - return 0; -} - void font_instance::InitTheFace() { if (theFace == NULL && pFont != NULL) { diff --git a/src/libnrtype/font-instance.h b/src/libnrtype/font-instance.h index 75106617b..2c7d1ce46 100644 --- a/src/libnrtype/font-instance.h +++ b/src/libnrtype/font-instance.h @@ -65,12 +65,6 @@ public: // for generating slanted cursors for oblique fonts Geom::OptRect BBox(int glyph_id); - // attribute queries - unsigned Name(gchar *str, unsigned size); - unsigned PSName(gchar *str, unsigned size); - unsigned Family(gchar *str, unsigned size); - unsigned Attribute(gchar const *key, gchar *str, unsigned size); - private: void FreeTheFace(); -- cgit v1.2.3