From f30962b5be812756040de0376091042fc151153b Mon Sep 17 00:00:00 2001 From: JucaBlues Date: Mon, 5 Jan 2009 23:49:00 +0000 Subject: [PATCH] Another week coding offline... * Adding Set Width (horiz-adv-x attribute) slider to the SVGFonts dialog. * Fixed the order of some language options at the i18n preferences page. * Fixed parsing and handling of u1 and u2 (CSS2 unicode range) attributes for kerning pair nodes * Fixed a warning in helper-fns.h * commented out unused variable in sp-font.cpp * refactoring of nr-svgfonts.cpp * using 1000 instead of horiz-adv-x when scaling the glyph coordinates. Probably should use a value based on units-per-em in the future. Or maybe accent-height, cap-height, x-height... I don't know. I should study this subject a bit more first. --- share/examples/svgfont.svg | 14 +-- src/display/nr-svgfonts.cpp | 133 +++++++++++++------------ src/helper-fns.h | 2 +- src/sp-font.cpp | 2 +- src/ui/dialog/inkscape-preferences.cpp | 8 +- src/ui/dialog/svg-fonts-dialog.cpp | 13 ++- src/unicoderange.cpp | 31 +++--- 7 files changed, 107 insertions(+), 96 deletions(-) diff --git a/share/examples/svgfont.svg b/share/examples/svgfont.svg index edf96f19a..c5ff179fa 100644 --- a/share/examples/svgfont.svg +++ b/share/examples/svgfont.svg @@ -10,16 +10,16 @@ - + - + - + @@ -30,10 +30,10 @@ - - - - + + + + diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp index 633f4cddd..86da5b7a1 100644 --- a/src/display/nr-svgfonts.cpp +++ b/src/display/nr-svgfonts.cpp @@ -104,6 +104,17 @@ unsigned int size_of_substring(const char* substring, gchar* str){ return 0; } +//TODO: in these macros, verify what happens when using unicode strings. +#define Match_VKerning_Rule (((SPVkern*)node)->u1->contains(previous_unicode[0])\ + || ((SPVkern*)node)->g1->contains(previous_glyph_name)) &&\ + (((SPVkern*)node)->u2->contains(this->glyphs[i]->unicode[0])\ + || ((SPVkern*)node)->g2->contains(this->glyphs[i]->glyph_name.c_str())) + +#define Match_HKerning_Rule (((SPHkern*)node)->u1->contains(previous_unicode[0])\ + || ((SPHkern*)node)->g1->contains(previous_glyph_name)) &&\ + (((SPHkern*)node)->u2->contains(this->glyphs[i]->unicode[0])\ + || ((SPHkern*)node)->g2->contains(this->glyphs[i]->glyph_name.c_str())) + cairo_status_t SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, const char *utf8, @@ -126,22 +137,22 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, bool missing; //First we findout whats the number of glyphs needed. - while(g_utf8_get_char(_utf8) != 0){ - missing = true; - for (i=0; i < (unsigned long) this->glyphs.size(); i++){ - if ( (len = size_of_substring(this->glyphs[i]->unicode.c_str(), _utf8)) ){ - //TODO: store this cluster - _utf8+=len; - count++; - missing=false; - break; - } - } - if (missing){ - //TODO: store this cluster - _utf8++; - count++; - } + while(g_utf8_get_char(_utf8)){ + missing = true; + for (i=0; i < (unsigned long) this->glyphs.size(); i++){ + if ( (len = size_of_substring(this->glyphs[i]->unicode.c_str(), _utf8)) ){ + //TODO: store this cluster + _utf8+=len; + count++; + missing=false; + break; + } + } + if (missing){ + //TODO: store this cluster + _utf8++; + count++; + } } @@ -155,54 +166,48 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, double x=0, y=0;//These vars store the position of the glyph within the rendered string bool is_horizontal_text = true; //TODO _utf8 = (char*) utf8; - while(g_utf8_get_char(_utf8) != 0){ - len = 0; + + while(g_utf8_get_char(_utf8)){ + len = 0; for (i=0; i < (unsigned long) this->glyphs.size(); i++){ - if ( (len = size_of_substring(this->glyphs[i]->unicode.c_str(), _utf8)) ){ - //check whether is there a glyph declared on the SVG document - // that matches with the text string in its current position - for(SPObject* node = this->font->children;previous_unicode && node;node=node->next){ - //apply glyph kerning if appropriate - if (SP_IS_HKERN(node) && is_horizontal_text){ - if ( (((SPHkern*)node)->u1->contains(previous_unicode[0]) - || ((SPHkern*)node)->g1->contains(previous_glyph_name)) && - (((SPHkern*)node)->u2->contains(this->glyphs[i]->unicode[0]) - || ((SPHkern*)node)->g2->contains(this->glyphs[i]->glyph_name.c_str())) - )//TODO: verify what happens when using unicode strings. - x -= (((SPHkern*)node)->k / this->font->horiz_adv_x); - } - if (SP_IS_VKERN(node) && !is_horizontal_text){ - if ( (((SPVkern*)node)->u1->contains(previous_unicode[0]) - || ((SPVkern*)node)->g1->contains(previous_glyph_name)) && - (((SPVkern*)node)->u2->contains(this->glyphs[i]->unicode[0]) - || ((SPVkern*)node)->g2->contains(this->glyphs[i]->glyph_name.c_str())) - )//TODO: idem - y -= (((SPVkern*)node)->k / this->font->vert_adv_y); - } - } - previous_unicode = (char*) this->glyphs[i]->unicode.c_str();//used for kerning checking - previous_glyph_name = (char*) this->glyphs[i]->glyph_name.c_str();//used for kerning checking - (*glyphs)[count].index = i; - (*glyphs)[count].x = x; - (*glyphs)[count++].y = y; - //advance glyph coordinates: - if (is_horizontal_text) x++; - else y++; - _utf8+=len; //advance 'len' bytes in our string pointer - //continue; - goto dirty; + //check whether is there a glyph declared on the SVG document + // that matches with the text string in its current position + if ( (len = size_of_substring(this->glyphs[i]->unicode.c_str(), _utf8)) ){ + for(SPObject* node = this->font->children;previous_unicode && node;node=node->next){ + //apply glyph kerning if appropriate + if (SP_IS_HKERN(node) && is_horizontal_text && Match_HKerning_Rule ){ + x -= (((SPHkern*)node)->k / 1000.0);//TODO: use here the height of the font + } + if (SP_IS_VKERN(node) && !is_horizontal_text && Match_VKerning_Rule ){ + y -= (((SPVkern*)node)->k / 1000.0);//TODO: use here the "height" of the font + } + } + previous_unicode = (char*) this->glyphs[i]->unicode.c_str();//used for kerning checking + previous_glyph_name = (char*) this->glyphs[i]->glyph_name.c_str();//used for kerning checking + (*glyphs)[count].index = i; + (*glyphs)[count].x = x; + (*glyphs)[count++].y = y; + + //advance glyph coordinates: + if (is_horizontal_text) x+=(this->font->horiz_adv_x/1000.0);//TODO: use here the height of the font + else y+=(this->font->vert_adv_y/1000.0);//TODO: use here the "height" of the font + _utf8+=len; //advance 'len' bytes in our string pointer + //continue; + goto raptorz; } } -dirty: - if (!len){ - (*glyphs)[count].index = i; - (*glyphs)[count].x = x; - (*glyphs)[count++].y = y; - //advance glyph coordinates: - if (is_horizontal_text) x++; - else y++; - _utf8 = g_utf8_next_char(_utf8); //advance 1 char in our string pointer - } +raptorz: + if (len==0){ + (*glyphs)[count].index = i; + (*glyphs)[count].x = x; + (*glyphs)[count++].y = y; + + //advance glyph coordinates: + if (is_horizontal_text) x+=(this->font->horiz_adv_x/1000.0);//TODO: use here the height of the font + else y+=(this->font->vert_adv_y/1000.0);//TODO: use here the "height" of the font + + _utf8 = g_utf8_next_char(_utf8); //advance 1 char in our string pointer + } } *num_glyphs = count; return CAIRO_STATUS_SUCCESS; @@ -246,11 +251,13 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t *scaled_font, //This glyph has a path description on its d attribute, so we render it: cairo_new_path(cr); //adjust scale of the glyph - Geom::Scale s(1.0/((SPFont*) node->parent)->horiz_adv_x); +// Geom::Scale s(1.0/((SPFont*) node->parent)->horiz_adv_x); + Geom::Scale s(1.0/1000);//TODO: use here the units-per-em attribute? //This matrix flips the glyph vertically Geom::Matrix m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0)); //then we offset it - pathv += Geom::Point(Geom::Coord(0),Geom::Coord(-((SPFont*) node->parent)->horiz_adv_x)); +// pathv += Geom::Point(Geom::Coord(0),Geom::Coord(-((SPFont*) node->parent)->horiz_adv_x)); + pathv += Geom::Point(Geom::Coord(0),Geom::Coord(-1000));//TODO: use here the units-per-em attribute? Geom::Rect area( Geom::Point(0,0), Geom::Point(1,1) ); //I need help here! (reaction: note that the 'area' parameter is an *optional* rect, so you can pass an empty Geom::OptRect() ) diff --git a/src/helper-fns.h b/src/helper-fns.h index 39d919aa7..43c90063b 100644 --- a/src/helper-fns.h +++ b/src/helper-fns.h @@ -57,7 +57,7 @@ inline bool helperfns_read_bool(gchar const *value, bool default_value){ inline std::vector helperfns_read_vector(const gchar* value, int size){ std::vector v(size, (gdouble) 0); std::istringstream is(value); - for(int i = 0; i < size && (is >> v[i]); i++); + for(int i = 0; i < size && (is >> v[i]); i++){}; return v; } diff --git a/src/sp-font.cpp b/src/sp-font.cpp index f2d37f3bf..07aeaabf4 100644 --- a/src/sp-font.cpp +++ b/src/sp-font.cpp @@ -144,7 +144,7 @@ sp_font_remove_child(SPObject *object, Inkscape::XML::Node *child) static void sp_font_release(SPObject *object) { - SPFont *font = SP_FONT(object); + //SPFont *font = SP_FONT(object); sp_document_remove_resource(SP_OBJECT_DOCUMENT(object), "font", object); if (((SPObjectClass *) parent_class)->release) { diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index e8a1e539c..0d97c0b77 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -1044,14 +1044,14 @@ void InkscapePreferences::initPageUI() _("sv Swedish"), _("th Thai"), _("tr Turkish"), _("uk Ukrainian"), _("vi Vietnamese"), _("zh_CN Chinese, as spoken in China"), _("zh_TW Chinese, as spoken in Taiwan")}; Glib::ustring langValues[] = {"", "am", "ar", "az", "be", "bg", "bn", "br", "ca", "ca@valencia", "cs", "da", "de", - "dz", "el", "en", "en_AU", "en_CA", "en_GB", "en_US@piglatin", "eo", "es_MX", "es", "et", "eu", "fi", "fr", "ga", + "dz", "el", "en", "en_AU", "en_CA", "en_GB", "en_US@piglatin", "eo", "es", "es_MX", "et", "eu", "fi", "fr", "ga", "gl", "he", "hr", "hu", "hy", "id", "it", "ja", "km", "ko", "lt", "mk", "mn", "nb", "ne", "nl", "nn", "pa", - "pl", "pt_BR", "pt", "ro", "ru", "rw", "sk", "sl", "sq", "sr@latin", "sr", "sv", "th", "tr", "uk", "vi", + "pl", "pt", "pt_BR", "ro", "ru", "rw", "sk", "sl", "sq", "sr", "sr@latin", "sv", "th", "tr", "uk", "vi", "zh_CN", "zh_TW"}; - _ui_languages.init( "/ui/language", languages, langValues, G_N_ELEMENTS(languages), languages[0]); + _ui_languages.init( "/ui/language", languages, langValues, G_N_ELEMENTS(languages), languages[0]); _page_ui.add_line( false, _("Language (requires restart):"), _ui_languages, "", - _("Set the language for menues and number-formats"), false); + _("Set the language for menus and number-formats"), false); Glib::ustring sizeLabels[] = {_("Normal"), _("Medium"), _("Small")}; int sizeValues[] = {0, 1, 2}; diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp index a29a01510..abdf4c3ae 100644 --- a/src/ui/dialog/svg-fonts-dialog.cpp +++ b/src/ui/dialog/svg-fonts-dialog.cpp @@ -321,6 +321,9 @@ void SvgFontsDialog::on_setwidth_changed(){ if (spfont){ spfont->horiz_adv_x = setwidth_spin.get_value(); //TODO: tell cairo that the glyphs cache has to be invalidated + // The current solution is to recreate the whole cairo svgfont. + // This is not a good solution to the issue because big fonts will result in poor performance. + update_glyphs(); } } @@ -364,16 +367,17 @@ Gtk::VBox* SvgFontsDialog::global_settings_tab(){ global_vbox->add(*AttrCombo((gchar*) _("Variant:"), SP_PROP_FONT_VARIANT)); global_vbox->add(*AttrCombo((gchar*) _("Weight:"), SP_PROP_FONT_WEIGHT)); */ + //Set Width (horiz_adv_x): -/* Gtk::HBox* setwidth_hbox = Gtk::manage(new Gtk::HBox()); + Gtk::HBox* setwidth_hbox = Gtk::manage(new Gtk::HBox()); setwidth_hbox->add(*Gtk::manage(new Gtk::Label(_("Set width:")))); setwidth_hbox->add(setwidth_spin); setwidth_spin.signal_changed().connect(sigc::mem_fun(*this, &SvgFontsDialog::on_setwidth_changed)); setwidth_spin.set_range(0, 4096); setwidth_spin.set_increments(10, 100); - global_vbox->add(*setwidth_hbox); -*/ + global_vbox.pack_start(*setwidth_hbox, false, false); + return &global_vbox; } @@ -498,7 +502,8 @@ void SvgFontsDialog::missing_glyph_description_from_selected_path(){ Geom::Matrix m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0)); pathv*=m; //then we offset it - pathv+=Geom::Point(Geom::Coord(0),Geom::Coord(get_selected_spfont()->horiz_adv_x)); +// pathv+=Geom::Point(Geom::Coord(0),Geom::Coord(get_selected_spfont()->horiz_adv_x)); + pathv+=Geom::Point(Geom::Coord(0),Geom::Coord(1000));//TODO: use here the units-per-em attribute? SPObject* obj; for (obj = get_selected_spfont()->children; obj; obj=obj->next){ diff --git a/src/unicoderange.cpp b/src/unicoderange.cpp index 72df25b5c..688969207 100644 --- a/src/unicoderange.cpp +++ b/src/unicoderange.cpp @@ -9,8 +9,9 @@ static unsigned int hex2int(char* s){ while(s[i+1]!='\0') i++; while(i>=0){ - if (s[i] > '9') res += mul * (s[i]-'A'+10); - else res += mul * (s[i]-'0'); + if (s[i] >= 'A' && s[i] <= 'F') res += mul * (s[i]-'A'+10); + if (s[i] >= 'a' && s[i] <= 'f') res += mul * (s[i]-'a'+10); + if (s[i] >= '0' && s[i] <= '9') res += mul * (s[i]-'0'); i--; mul*=16; } @@ -22,9 +23,8 @@ UnicodeRange::UnicodeRange(const gchar* value){ gchar* val = (gchar*) value; while(val[0] != '\0'){ if (val[0]=='U' && val[1]=='+'){ - val += add_range(val); + val += add_range(val+2); } else { -// g_warning("adding unichar. unichar=%c", g_utf8_get_char(&val[0])); this->unichars.push_back(g_utf8_get_char(&val[0])); val++; } @@ -36,9 +36,7 @@ UnicodeRange::UnicodeRange(const gchar* value){ int UnicodeRange::add_range(gchar* val){ Urange r; - //U+ - val+=2; - int i=0, count=2; + int i=0, count=0; while(val[i]!='\0' && val[i]!='-' && val[i]!=' ' && val[i]!=',') i++; r.start = (gchar*) malloc((i+1)*sizeof(gchar*)); strncpy(r.start, val, i); @@ -57,7 +55,6 @@ UnicodeRange::add_range(gchar* val){ } else { r.end=NULL; } -// g_warning("adding range. from %s to %s", r.start, r.end); this->range.push_back(r); return count+1; } @@ -69,7 +66,6 @@ bool UnicodeRange::contains(gchar unicode){ unsigned int unival; unival = g_utf8_get_char (&unicode); -// g_warning("unival=%d", unival); char uni[9] = "00000000"; uni[8]= '\0'; unsigned char val; @@ -79,19 +75,21 @@ bool UnicodeRange::contains(gchar unicode){ if (val < 10) uni[i] = '0' + val; else uni[i] = 'A'+ val - 10; } -// g_warning("uni=%s", uni); bool found; for(unsigned int i=0;irange.size();i++){ Urange r = this->range[i]; if (r.end){ -// g_warning("hex2int: start=%d", hex2int(r.start)); -// g_warning("hex2int: end=%d", hex2int(r.end)); if (unival >= hex2int(r.start) && unival <= hex2int(r.end)) return true; } else { found = true; - for (int pos=0;pos<8;pos++){ - if (uni[pos]!='?' && uni[pos]!=r.start[pos]) found = false; + + int p=0; + while (r.start[p]!='\0') p++; + p--; + + for (int pos=8;p>=0;pos--,p--){ + if (uni[pos]!='?' && uni[pos]!=r.start[p]) found = false; } if (found) return true; } @@ -108,8 +106,9 @@ Glib::ustring UnicodeRange::attribute_string(){ } for(i=0; irange.size(); i++){ - result += "U+" + Glib::ustring(this->range[i].start) + "-" + Glib::ustring(this->range[i].end); - if (i!=this->range.size()-1) result += ","; + result += "U+" + Glib::ustring(this->range[i].start); + if (this->range[i].end) result += "-" + Glib::ustring(this->range[i].end); + if (i!=this->range.size()-1) result += ", "; } return result; -- 2.30.2