diff options
| author | Liam P. White <inkscapebronyat-signgmaildotcom> | 2014-06-06 16:12:41 +0000 |
|---|---|---|
| committer | Liam P. White <inkscapebronyat-signgmaildotcom> | 2014-06-06 16:12:41 +0000 |
| commit | fa06e2deb21ba6d362ebd7d34b0ae59a614b5e3c (patch) | |
| tree | 84bb8f6071e403525d68a04c6589eb633176e774 /src | |
| parent | Update to trunk (r13379) (diff) | |
| parent | update clang format spec for latest clangformat version (diff) | |
| download | inkscape-fa06e2deb21ba6d362ebd7d34b0ae59a614b5e3c.tar.gz inkscape-fa06e2deb21ba6d362ebd7d34b0ae59a614b5e3c.zip | |
Update to experimental r13389
(bzr r13090.1.81)
Diffstat (limited to 'src')
| -rw-r--r-- | src/extension/internal/gdkpixbuf-input.cpp | 8 | ||||
| -rw-r--r-- | src/extension/internal/pdfinput/pdf-parser.cpp | 54 | ||||
| -rw-r--r-- | src/ink-comboboxentry-action.cpp | 28 | ||||
| -rw-r--r-- | src/libnrtype/font-lister.cpp | 81 | ||||
| -rw-r--r-- | src/live_effects/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/live_effects/Makefile_insert | 4 | ||||
| -rw-r--r-- | src/live_effects/effect-enum.h | 1 | ||||
| -rw-r--r-- | src/live_effects/effect.cpp | 6 | ||||
| -rw-r--r-- | src/live_effects/lpe-envelope-perspective.cpp | 414 | ||||
| -rw-r--r-- | src/live_effects/lpe-envelope-perspective.h | 76 | ||||
| -rw-r--r-- | src/style-internal.cpp | 17 | ||||
| -rw-r--r-- | src/style.cpp | 52 | ||||
| -rw-r--r-- | src/style.h | 4 | ||||
| -rw-r--r-- | src/ui/dialog/spellcheck.cpp | 74 | ||||
| -rw-r--r-- | src/widgets/text-toolbar.cpp | 1 | ||||
| -rw-r--r-- | src/xml/repr-css.cpp | 20 |
16 files changed, 705 insertions, 138 deletions
diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp index a384c7bde..da179bee0 100644 --- a/src/extension/internal/gdkpixbuf-input.cpp +++ b/src/extension/internal/gdkpixbuf-input.cpp @@ -87,11 +87,11 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) ir = new ImageResolution(uri); } if (ir && ir->ok()) { - xscale = 900.0 / floor(10.*ir->x() + .5); // round-off to 0.1 dpi - yscale = 900.0 / floor(10.*ir->y() + .5); + xscale = 960.0 / floor(10.*ir->x() + .5); // round-off to 0.1 dpi + yscale = 960.0 / floor(10.*ir->y() + .5); } else { - xscale = 90.0 / defaultxdpi; - yscale = 90.0 / defaultxdpi; + xscale = 96.0 / defaultxdpi; + yscale = 96.0 / defaultxdpi; } width *= xscale; diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index b398486e6..c5f03e5aa 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -866,7 +866,9 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/) GBool isolated = gFalse; GBool knockout = gFalse; if (!obj4.dictLookup(const_cast<char*>("CS"), &obj5)->isNull()) { -#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) +#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) + blendingColorSpace = GfxColorSpace::parse(&obj5, NULL, NULL); +#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) blendingColorSpace = GfxColorSpace::parse(&obj5, NULL); #else blendingColorSpace = GfxColorSpace::parse(&obj5); @@ -1100,7 +1102,13 @@ void PdfParser::opSetFillColorSpace(Object args[], int /*numArgs*/) res->lookupColorSpace(args[0].getName(), &obj); GfxColorSpace *colorSpace = 0; -#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) +#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) + if (obj.isNull()) { + colorSpace = GfxColorSpace::parse(&args[0], NULL, NULL); + } else { + colorSpace = GfxColorSpace::parse(&obj, NULL, NULL); + } +#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) if (obj.isNull()) { colorSpace = GfxColorSpace::parse(&args[0], NULL); } else { @@ -1137,7 +1145,13 @@ void PdfParser::opSetStrokeColorSpace(Object args[], int /*numArgs*/) state->setStrokePattern(NULL); res->lookupColorSpace(args[0].getName(), &obj); -#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) +#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) + if (obj.isNull()) { + colorSpace = GfxColorSpace::parse(&args[0], NULL, NULL); + } else { + colorSpace = GfxColorSpace::parse(&obj, NULL, NULL); + } +#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) if (obj.isNull()) { colorSpace = GfxColorSpace::parse(&args[0], NULL); } else { @@ -1231,7 +1245,13 @@ void PdfParser::opSetFillColorN(Object args[], int numArgs) { builder->updateStyle(state); } GfxPattern *pattern; -#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) +#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) + if (args[numArgs-1].isName() && + (pattern = res->lookupPattern(args[numArgs-1].getName(), NULL, NULL))) { + state->setFillPattern(pattern); + builder->updateStyle(state); + } +#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) if (args[numArgs-1].isName() && (pattern = res->lookupPattern(args[numArgs-1].getName(), NULL))) { state->setFillPattern(pattern); @@ -1291,7 +1311,13 @@ void PdfParser::opSetStrokeColorN(Object args[], int numArgs) { builder->updateStyle(state); } GfxPattern *pattern; -#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) +#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) + if (args[numArgs-1].isName() && + (pattern = res->lookupPattern(args[numArgs-1].getName(), NULL, NULL))) { + state->setStrokePattern(pattern); + builder->updateStyle(state); + } +#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) if (args[numArgs-1].isName() && (pattern = res->lookupPattern(args[numArgs-1].getName(), NULL))) { state->setStrokePattern(pattern); @@ -1746,7 +1772,11 @@ void PdfParser::opShFill(Object args[], int /*numArgs*/) double *matrix = NULL; GBool savedState = gFalse; -#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) +#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) + if (!(shading = res->lookupShading(args[0].getName(), NULL, NULL))) { + return; + } +#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) if (!(shading = res->lookupShading(args[0].getName(), NULL))) { return; } @@ -2817,7 +2847,9 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) } } if (!obj1.isNull()) { -#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) +#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) + colorSpace = GfxColorSpace::parse(&obj1, NULL, NULL); +#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) colorSpace = GfxColorSpace::parse(&obj1, NULL); #else colorSpace = GfxColorSpace::parse(&obj1); @@ -2909,7 +2941,9 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) obj2.free(); } } -#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) +#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) + GfxColorSpace *maskColorSpace = GfxColorSpace::parse(&obj1, NULL, NULL); +#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) GfxColorSpace *maskColorSpace = GfxColorSpace::parse(&obj1, NULL); #else GfxColorSpace *maskColorSpace = GfxColorSpace::parse(&obj1); @@ -3099,7 +3133,9 @@ void PdfParser::doForm(Object *str) { if (obj1.dictLookup(const_cast<char*>("S"), &obj2)->isName(const_cast<char*>("Transparency"))) { transpGroup = gTrue; if (!obj1.dictLookup(const_cast<char*>("CS"), &obj3)->isNull()) { -#if defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) +#if defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) + blendingColorSpace = GfxColorSpace::parse(&obj3, NULL, NULL); +#elif defined(POPPLER_NEW_COLOR_SPACE_API) || defined(POPPLER_NEW_ERRORAPI) blendingColorSpace = GfxColorSpace::parse(&obj3, NULL); #else blendingColorSpace = GfxColorSpace::parse(&obj3); diff --git a/src/ink-comboboxentry-action.cpp b/src/ink-comboboxentry-action.cpp index 06ccc3739..ebd238edc 100644 --- a/src/ink-comboboxentry-action.cpp +++ b/src/ink-comboboxentry-action.cpp @@ -38,7 +38,7 @@ static GtkWidget* create_tool_item( GtkAction* action ); static GtkWidget* create_menu_item( GtkAction* action ); // Internal -static gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, gboolean exclude = false ); +static gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, gboolean exclude = false, gboolean ignore_case = false ); static Glib::ustring check_comma_separated_text( Ink_ComboBoxEntry_Action* action ); // Callbacks @@ -732,7 +732,8 @@ void ink_comboboxentry_action_set_altx_name( Ink_ComboBoxEntry_Action* actio // use 3d colunm if available to exclude row from checking (useful to // skip rows added for font-families included in doc and not on // system) -gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, gboolean exclude ) { +gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, + gboolean exclude, gboolean ignore_case ) { // Check if text in list gint row = 0; @@ -752,10 +753,23 @@ gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* ta gchar* text = 0; gtk_tree_model_get( action->model, &iter, 0, &text, -1 ); // Column 0 - // Check for match - if( strcmp( target_text, text ) == 0 ){ - found = true; - break; + if( !ignore_case ) { + // Case sensitive compare + if( strcmp( target_text, text ) == 0 ){ + found = true; + break; + } + } else { + // Case insensitive compare + gchar* target_text_casefolded = g_utf8_casefold( target_text, -1 ); + gchar* text_casefolded = g_utf8_casefold( text, -1 ); + gboolean equal = (strcmp( target_text_casefolded, text_casefolded ) == 0 ); + g_free( text_casefolded ); + g_free( target_text_casefolded ); + if( equal ) { + found = true; + break; + } } } @@ -794,7 +808,7 @@ static Glib::ustring check_comma_separated_text( Ink_ComboBoxEntry_Action* actio // Remove any surrounding white space. g_strstrip( tokens[i] ); - if( get_active_row_from_text( action, tokens[i], true ) == -1 ) { + if( get_active_row_from_text( action, tokens[i], true, true ) == -1 ) { missing += tokens[i]; missing += ", "; } diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 98589d9d7..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 () @@ -83,6 +90,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" @@ -111,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; } @@ -188,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; } @@ -219,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; } @@ -231,37 +247,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<Glib::ustring> *l ) { - const gchar *style = r->getRepr()->attribute("style"); - if( style != NULL ) { - - std::vector<Glib::ustring> 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()) { @@ -400,6 +391,7 @@ namespace Inkscape std::pair<Glib::ustring, Glib::ustring> ui = ui_from_fontspec( current_fontspec ); set_font_family( ui.first ); + set_font_style( ui.second ); #ifdef DEBUG_FONT std::cout << " family_row: :" << current_family_row << ":" << std::endl; @@ -440,7 +432,7 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri #endif // No need to do anything if new family is same as old family. - if ( new_family.compare( current_family ) == 0 ) { + if ( familyNamesAreEqual( new_family, current_family ) ) { #ifdef DEBUG_FONT std::cout << "FontLister::new_font_family: exit: no change in family." << std::endl; std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" << std::endl; @@ -459,7 +451,7 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri Gtk::TreeModel::Row row = *iter; - if( new_family.compare( row[FontList.family] ) == 0 ) { + if( familyNamesAreEqual( new_family, row[FontList.family] ) ) { styles = row[FontList.styles]; break; } @@ -704,18 +696,19 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri fontspec = style->font_family.value; fontspec += ","; + // Use weight names as defined by Pango switch (style->font_weight.computed) { case SP_CSS_FONT_WEIGHT_100: - fontspec += " 100"; + fontspec += " Thin"; break; case SP_CSS_FONT_WEIGHT_200: - fontspec += " 200"; + fontspec += " Ultra-Light"; break; case SP_CSS_FONT_WEIGHT_300: - fontspec += " 300"; + fontspec += " Light"; break; case SP_CSS_FONT_WEIGHT_400: @@ -724,24 +717,24 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri break; case SP_CSS_FONT_WEIGHT_500: - fontspec += " 500"; + fontspec += " Medium"; break; case SP_CSS_FONT_WEIGHT_600: - fontspec += " 600"; + fontspec += " Semi-Bold"; break; case SP_CSS_FONT_WEIGHT_700: case SP_CSS_FONT_WEIGHT_BOLD: - fontspec += " bold"; + fontspec += " Bold"; break; case SP_CSS_FONT_WEIGHT_800: - fontspec += " 800"; + fontspec += " Ultra-Bold"; break; case SP_CSS_FONT_WEIGHT_900: - fontspec += " 900"; + fontspec += " Heavy"; break; case SP_CSS_FONT_WEIGHT_LIGHTER: @@ -837,7 +830,7 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri Gtk::TreeModel::Row row = *iter; - if( family.compare( row[FontList.family] ) == 0 ) { + if( familyNamesAreEqual( family, row[FontList.family] ) ) { return row; } @@ -863,7 +856,7 @@ std::pair<Glib::ustring, Glib::ustring> FontLister::new_font_family (Glib::ustri Gtk::TreeModel::Row row = *iter; - if( style.compare( row[FontStyleList.styles] ) == 0 ) { + if( familyNamesAreEqual( style, row[FontStyleList.styles] ) ) { return row; } @@ -1051,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; } diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt index c7547ded3..c3ce31cfc 100644 --- a/src/live_effects/CMakeLists.txt +++ b/src/live_effects/CMakeLists.txt @@ -15,6 +15,7 @@ set(live_effects_SRC lpe-dynastroke.cpp lpe-ellipse-5pts.cpp lpe-envelope.cpp + lpe-envelope-perspective.cpp lpe-extrude.cpp lpe-fill-between-many.cpp lpe-fill-between-strokes.cpp @@ -43,6 +44,7 @@ set(live_effects_SRC lpe-bspline.cpp lpe-text_label.cpp lpe-vonkoch.cpp + lpe-envelope-perspective.cpp lpegroupbbox.cpp lpeobject-reference.cpp lpeobject.cpp @@ -113,6 +115,7 @@ set(live_effects_SRC lpe-bspline.h lpe-text_label.h lpe-vonkoch.h + lpe-envelope-perspective.h lpegroupbbox.h lpeobject-reference.h lpeobject.h diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert index 922a4a966..3d474d00c 100644 --- a/src/live_effects/Makefile_insert +++ b/src/live_effects/Makefile_insert @@ -104,4 +104,6 @@ ink_common_sources += \ live_effects/lpe-jointype.cpp \ live_effects/lpe-jointype.h \ live_effects/lpe-taperstroke.cpp \ - live_effects/lpe-taperstroke.h + live_effects/lpe-taperstroke.h \ + live_effects/lpe-envelope-perspective.cpp \ + live_effects/lpe-envelope-perspective.h diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h index 82ce36225..92f35fc72 100644 --- a/src/live_effects/effect-enum.h +++ b/src/live_effects/effect-enum.h @@ -60,6 +60,7 @@ enum EffectType { BOUNDING_BOX, JOIN_TYPE, TAPER_STROKE, + ENVELOPE_PERSPECTIVE, INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan) }; diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 3c13ee9a9..4157e14d7 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -57,6 +57,7 @@ #include "live_effects/lpe-bounding-box.h" #include "live_effects/lpe-jointype.h" #include "live_effects/lpe-taperstroke.h" +#include "live_effects/lpe-envelope-perspective.h" #include "xml/node-event-vector.h" #include "sp-object.h" @@ -144,6 +145,7 @@ const Util::EnumData<EffectType> LPETypeData[] = { /* 0.91 */ {SIMPLIFY, N_("Simplify"), "simplify"}, {LATTICE2, N_("Lattice Deformation 2"), "lattice2"}, + {ENVELOPE_PERSPECTIVE, N_("Envelope-Perspective"), "envelope-perspective"}, }; const Util::EnumDataConverter<EffectType> LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData)); @@ -290,12 +292,16 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj) break; case TAPER_STROKE: neweffect = static_cast<Effect*> ( new LPETaperStroke(lpeobj) ); + break; case SIMPLIFY: neweffect = static_cast<Effect*> ( new LPESimplify(lpeobj) ); break; case LATTICE2: neweffect = static_cast<Effect*> ( new LPELattice2(lpeobj) ); break; + case ENVELOPE_PERSPECTIVE: + neweffect = static_cast<Effect*> ( new LPEEnvelopePerspective(lpeobj) ); + break; default: g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr); neweffect = NULL; diff --git a/src/live_effects/lpe-envelope-perspective.cpp b/src/live_effects/lpe-envelope-perspective.cpp new file mode 100644 index 000000000..bfd6e56d7 --- /dev/null +++ b/src/live_effects/lpe-envelope-perspective.cpp @@ -0,0 +1,414 @@ +/** \file + * LPE <envelope-perspective> implementation + + */ +/* + * Authors: + * Jabiertxof Code migration from python extensions envelope and perspective + * Aaron Spike, aaron@ekips.org from envelope and perspective phyton code + * Dmitry Platonov, shadowjack@mail.ru, 2006 perspective approach & math + * Jose Hevia (freon) Transform algorithm from envelope + * + * Copyright (C) 2007-2014 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/lpe-envelope-perspective.h" +#include "helper/geom.h" +#include "display/curve.h" +#include "svg/svg.h" +#include <gtkmm/separator.h> +#include <gtkmm/stock.h> +#include <tools-switch.h> +#include <gsl/gsl_linalg.h> +#include "desktop.h" + +using namespace Geom; + +namespace Inkscape { +namespace LivePathEffect { + +LPEEnvelopePerspective::LPEEnvelopePerspective(LivePathEffectObject *lpeobject) : + Effect(lpeobject), + // initialise your parameters here: + perspective(_("Perspective"), _("Perspective"), "Perspective", &wr, this, false), + Up_Left_Point(_("Top Left:"), _("Top Left - Ctrl+Alt+Click to reset"), "Up_Left_Point", &wr, this), + Up_Right_Point(_("Top Right:"), _("Top Right - Ctrl+Alt+Click to reset"), "Up_Right_Point", &wr, this), + Down_Left_Point(_("Down Left:"), _("Down Left - Ctrl+Alt+Click to reset"), "Down_Left_Point", &wr, this), + Down_Right_Point(_("Down Right:"), _("Down Right - Ctrl+Alt+Click to reset"), "Down_Right_Point", &wr, this) +{ + // register all your parameters here, so Inkscape knows which parameters this effect has: + registerParameter( dynamic_cast<Parameter *>(&perspective)); + registerParameter( dynamic_cast<Parameter *>(&Up_Left_Point) ); + registerParameter( dynamic_cast<Parameter *>(&Up_Right_Point) ); + registerParameter( dynamic_cast<Parameter *>(&Down_Left_Point) ); + registerParameter( dynamic_cast<Parameter *>(&Down_Right_Point) ); +} + +LPEEnvelopePerspective::~LPEEnvelopePerspective() +{ +} + +void LPEEnvelopePerspective::doEffect(SPCurve *curve) { + using Geom::X; + using Geom::Y; + double projmatrix[3][3]; + if(perspective){ + std::vector<Geom::Point> handles(4); + handles[0] = Down_Left_Point; + handles[1] = Up_Left_Point; + handles[2] = Up_Right_Point; + handles[3] = Down_Right_Point; + std::vector<Geom::Point> sourceHandles(4); + sourceHandles[0] = Geom::Point(boundingbox_X.min(), boundingbox_Y.max()); + sourceHandles[1] = Geom::Point(boundingbox_X.min(), boundingbox_Y.min()); + sourceHandles[2] = Geom::Point(boundingbox_X.max(), boundingbox_Y.min()); + sourceHandles[3] = Geom::Point(boundingbox_X.max(), boundingbox_Y.max()); + double solmatrix[8][8] = {{0}}; + double free_term[8] = {0}; + double gslSolmatrix[64]; + for(unsigned int i = 0; i < 4; ++i){ + solmatrix[i][0] = sourceHandles[i][X]; + solmatrix[i][1] = sourceHandles[i][Y]; + solmatrix[i][2] = 1; + solmatrix[i][6] = -handles[i][X] * sourceHandles[i][X]; + solmatrix[i][7] = -handles[i][X] * sourceHandles[i][Y]; + solmatrix[i+4][3] = sourceHandles[i][X]; + solmatrix[i+4][4] = sourceHandles[i][Y]; + solmatrix[i+4][5] = 1; + solmatrix[i+4][6] = -handles[i][Y] * sourceHandles[i][X]; + solmatrix[i+4][7] = -handles[i][Y] * sourceHandles[i][Y]; + free_term[i] = handles[i][X]; + free_term[i+4] = handles[i][Y]; + } + int h = 0; + for( int i = 0; i < 8; i++ ) { + for( int j = 0; j < 8; j++ ) { + gslSolmatrix[h] = solmatrix[i][j]; + h++; + } + } + //this is get by this page: + //http://www.gnu.org/software/gsl/manual/html_node/Linear-Algebra-Examples.html#Linear-Algebra-Examples + gsl_matrix_view m = gsl_matrix_view_array (gslSolmatrix, 8, 8); + gsl_vector_view b = gsl_vector_view_array (free_term, 8); + gsl_vector *x = gsl_vector_alloc (8); + int s; + gsl_permutation * p = gsl_permutation_alloc (8); + gsl_linalg_LU_decomp (&m.matrix, p, &s); + gsl_linalg_LU_solve (&m.matrix, p, &b.vector, x); + h = 0; + for( int i = 0; i < 3; i++ ) { + for( int j = 0; j < 3; j++ ) { + if(h==8){ + projmatrix[2][2] = 1.0; + continue; + } + projmatrix[i][j] = gsl_vector_get(x, h); + h++; + } + } + gsl_permutation_free (p); + gsl_vector_free (x); + } + Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(curve->get_pathvector()); + curve->reset(); + Geom::CubicBezier const *cubic = NULL; + Geom::Point pointAt1(0, 0); + Geom::Point pointAt2(0, 0); + Geom::Point pointAt3(0, 0); + for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { + //Si está vacío... + if (path_it->empty()) + continue; + //Itreadores + SPCurve *nCurve = new SPCurve(); + Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve + Geom::Path::const_iterator curve_it2 = + ++(path_it->begin()); // outgoing curve + Geom::Path::const_iterator curve_endit = + path_it->end_default(); // this determines when the loop has to stop + + if (path_it->closed()) { + // if the path is closed, maybe we have to stop a bit earlier because the + // closing line segment has zerolength. + const Geom::Curve &closingline = + path_it->back_closed(); // the closing line segment is always of type + // Geom::LineSegment. + if (are_near(closingline.initialPoint(), closingline.finalPoint())) { + // closingline.isDegenerate() did not work, because it only checks for + // *exact* zero length, which goes wrong for relative coordinates and + // rounding errors... + // the closing line segment has zero-length. So stop before that one! + curve_endit = path_it->end_open(); + } + } + if(perspective){ + nCurve->moveto(project_point(curve_it1->initialPoint(),projmatrix)); + }else{ + nCurve->moveto(project_point(curve_it1->initialPoint())); + } + while (curve_it2 != curve_endit) { + cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1); + if (cubic) { + pointAt1 = (*cubic)[1]; + pointAt2 = (*cubic)[2]; + } else { + pointAt1 = curve_it1->initialPoint(); + pointAt2 = curve_it1->finalPoint(); + } + pointAt3 = curve_it1->finalPoint(); + if(perspective){ + pointAt1 = project_point(pointAt1,projmatrix); + pointAt2 = project_point(pointAt2,projmatrix); + pointAt3 = project_point(pointAt3,projmatrix); + }else{ + pointAt1 = project_point(pointAt1); + pointAt2 = project_point(pointAt2); + pointAt3 = project_point(pointAt3); + } + nCurve->curveto(pointAt1, pointAt2, pointAt3); + ++curve_it1; + ++curve_it2; + } + cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1); + if (cubic) { + pointAt1 = (*cubic)[1]; + pointAt2 = (*cubic)[2]; + } else { + pointAt1 = curve_it1->initialPoint(); + pointAt2 = curve_it1->finalPoint(); + } + pointAt3 = curve_it1->finalPoint(); + if(perspective){ + pointAt1 = project_point(pointAt1,projmatrix); + pointAt2 = project_point(pointAt2,projmatrix); + pointAt3 = project_point(pointAt3,projmatrix); + }else{ + pointAt1 = project_point(pointAt1); + pointAt2 = project_point(pointAt2); + pointAt3 = project_point(pointAt3); + } + nCurve->curveto(pointAt1, pointAt2, pointAt3); + if(perspective){ + nCurve->move_endpoints(project_point(path_it->begin()->initialPoint(),projmatrix), pointAt3); + }else{ + nCurve->move_endpoints(project_point(path_it->begin()->initialPoint()), pointAt3); + } + //y cerramos la curva + if (path_it->closed()) { + nCurve->closepath_current(); + } + curve->append(nCurve, false); + nCurve->reset(); + delete nCurve; + } +} + +Geom::Point +LPEEnvelopePerspective::project_point(Geom::Point p){ + double width = boundingbox_X.extent(); + double height = boundingbox_Y.extent(); + Geom::Coord xratio = abs(Geom::Point(boundingbox_X.min(), boundingbox_Y.max())[X]-p[X])/width; + Geom::Coord yratio = abs(Geom::Point(boundingbox_X.min(), boundingbox_Y.max())[Y]-p[Y])/height; + Geom::Line* horiz = new Geom::Line(); + Geom::Line* vert = new Geom::Line(); + vert->setPoints (pointAtRatio(yratio,Down_Left_Point,Up_Left_Point),pointAtRatio(yratio,Down_Right_Point,Up_Right_Point)); + horiz->setPoints (pointAtRatio(xratio,Down_Left_Point,Down_Right_Point),pointAtRatio(xratio,Up_Left_Point,Up_Right_Point)); + + OptCrossing crossPoint = intersection(*horiz,*vert); + if(crossPoint){ + return horiz->pointAt(Geom::Coord(crossPoint->ta)); + }else{ + return p; + } +} + +Geom::Point +LPEEnvelopePerspective::project_point(Geom::Point p, double m[][3]){ + Geom::Coord x = p[0]; + Geom::Coord y = p[1]; + return Geom::Point( + Geom::Coord((x*m[0][0] + y*m[0][1] + m[0][2])/(x*m[2][0]+y*m[2][1]+m[2][2])), + Geom::Coord((x*m[1][0] + y*m[1][1] + m[1][2])/(x*m[2][0]+y*m[2][1]+m[2][2]))); +} + +Geom::Point +LPEEnvelopePerspective::pointAtRatio(Geom::Coord ratio,Geom::Point A, Geom::Point B){ + Geom::Coord x = A[X] + (ratio * (B[X]-A[X])); + Geom::Coord y = A[Y]+ (ratio * (B[Y]-A[Y])); + return Point(x, y); +} + + +Gtk::Widget * +LPEEnvelopePerspective::newWidget() +{ + // use manage here, because after deletion of Effect object, others might still be pointing to this widget. + Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget()) ); + + vbox->set_border_width(5); + vbox->set_homogeneous(false); + vbox->set_spacing(6); + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0)); + + Gtk::Button* resetButton = Gtk::manage(new Gtk::Button(Gtk::Stock::CLEAR)); + resetButton->signal_clicked().connect(sigc::mem_fun (*this,&LPEEnvelopePerspective::resetGrid)); + resetButton->set_size_request(140,45); + vbox->pack_start(*hbox, true,true,2); + hbox->pack_start(*resetButton, false, false,2); + std::vector<Parameter *>::iterator it = param_vector.begin(); + Gtk::HBox * hboxUpHandles = Gtk::manage(new Gtk::HBox(false,0)); + Gtk::HBox * hboxDownHandles = Gtk::manage(new Gtk::HBox(false,0)); + while (it != param_vector.end()) { + if ((*it)->widget_is_visible) { + Parameter * param = *it; + Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget()); + if (param->param_key == "Up_Left_Point" || + param->param_key == "Up_Right_Point" || + param->param_key == "Down_Left_Point" || + param->param_key == "Down_Right_Point") + { + Gtk::HBox * pointParameter = dynamic_cast<Gtk::HBox *>(widg); + std::vector< Gtk::Widget* > childList = pointParameter->get_children(); + Gtk::HBox * pointParameterHBox = dynamic_cast<Gtk::HBox *>(childList[0]); + std::vector< Gtk::Widget* > childList2 = pointParameterHBox->get_children(); + pointParameterHBox->remove(childList2[0][0]); + Glib::ustring * tip = param->param_getTooltip(); + if (widg) { + if(param->param_key == "Up_Left_Point"){ + Gtk::Label* handles = Gtk::manage(new Gtk::Label(Glib::ustring(_("Handles:")),Gtk::ALIGN_START)); + vbox->pack_start(*handles, false, false, 2); + hboxUpHandles->pack_start(*widg, true, true, 2); + hboxUpHandles->pack_start(*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_EXPAND_WIDGET); + }else if(param->param_key == "Up_Right_Point"){ + hboxUpHandles->pack_start(*widg, true, true, 2); + }else if(param->param_key == "Down_Left_Point"){ + hboxDownHandles->pack_start(*widg, true, true, 2); + hboxDownHandles->pack_start(*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_EXPAND_WIDGET); + }else{ + hboxDownHandles->pack_start(*widg, true, true, 2); + } + if (tip) { + widg->set_tooltip_text(*tip); + } else { + widg->set_tooltip_text(""); + widg->set_has_tooltip(false); + } + } + }else{ + Glib::ustring * tip = param->param_getTooltip(); + if (widg) { + vbox->pack_start(*widg, true, true, 2); + if (tip) { + widg->set_tooltip_text(*tip); + } else { + widg->set_tooltip_text(""); + widg->set_has_tooltip(false); + } + } + } + } + + ++it; + } + vbox->pack_start(*hboxUpHandles,true, true, 2); + Gtk::HBox * hboxMiddle = Gtk::manage(new Gtk::HBox(true,2)); + hboxMiddle->pack_start(*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET); + hboxMiddle->pack_start(*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET); + vbox->pack_start(*hboxMiddle, false, true, 2); + vbox->pack_start(*hboxDownHandles, true, true, 2); + return dynamic_cast<Gtk::Widget *>(vbox); +} + +void +LPEEnvelopePerspective::doBeforeEffect (SPLPEItem const* lpeitem) +{ + original_bbox(lpeitem); + setDefaults(); +} + +void +LPEEnvelopePerspective::setDefaults() +{ + Geom::Point Up_Left(boundingbox_X.min(), boundingbox_Y.min()); + Geom::Point Up_Right(boundingbox_X.max(), boundingbox_Y.min()); + Geom::Point Down_Left(boundingbox_X.min(), boundingbox_Y.max()); + Geom::Point Down_Right(boundingbox_X.max(), boundingbox_Y.max()); + + Up_Left_Point.param_update_default(Up_Left); + Up_Right_Point.param_update_default(Up_Right); + Down_Right_Point.param_update_default(Down_Right); + Down_Left_Point.param_update_default(Down_Left); +} + +void +LPEEnvelopePerspective::resetGrid() +{ + Up_Left_Point.param_set_and_write_default(); + Up_Right_Point.param_set_and_write_default(); + Down_Right_Point.param_set_and_write_default(); + Down_Left_Point.param_set_and_write_default(); + //todo:this hack is only to reposition the knots on reser grid button + //Better update path effect in LPEITEM + SPDesktop * desktop = inkscape_active_desktop(); + tools_switch(desktop, TOOLS_SELECT); + tools_switch(desktop, TOOLS_NODES); +} + +void +LPEEnvelopePerspective::resetDefaults(SPItem const* item) +{ + Effect::resetDefaults(item); + original_bbox(SP_LPE_ITEM(item)); + setDefaults(); + resetGrid(); +} + +void +LPEEnvelopePerspective::calculateCurve(Geom::Point a,Geom::Point b, SPCurve* c, bool horizontal, bool move) +{ + using Geom::X; + using Geom::Y; + if(move) c->moveto(a); + Geom::Point cubic1 = a + (1./3)* (b - a); + Geom::Point cubic2 = b + (1./3)* (a - b); + if(horizontal) c->curveto(Geom::Point(cubic1[X],a[Y]),Geom::Point(cubic2[X],b[Y]),b); + else c->curveto(Geom::Point(a[X],cubic1[Y]),Geom::Point(b[X],cubic2[Y]),b); +} + +void +LPEEnvelopePerspective::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) +{ + hp_vec.clear(); + + SPCurve *c = new SPCurve(); + c->reset(); + c->moveto(Up_Left_Point); + c->lineto(Up_Right_Point); + c->lineto(Down_Right_Point); + c->lineto(Down_Left_Point); + c->lineto(Up_Left_Point); + hp_vec.push_back(c->get_pathvector()); +} + + +/* ######################## */ + +} //namespace LivePathEffect +} /* namespace Inkscape */ + + + + +/* + 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 : diff --git a/src/live_effects/lpe-envelope-perspective.h b/src/live_effects/lpe-envelope-perspective.h new file mode 100644 index 000000000..6aae33936 --- /dev/null +++ b/src/live_effects/lpe-envelope-perspective.h @@ -0,0 +1,76 @@ +#ifndef INKSCAPE_LPE_ENVELOPE_PERSPECTIVE_H +#define INKSCAPE_LPE_ENVELOPE_PERSPECTIVE_H + +/** \file + * LPE <envelope-perspective> implementation , see lpe-envelope-perspective.cpp. + + */ +/* + * Authors: + * Jabiertxof Code migration from python extensions envelope and perspective + * Aaron Spike, aaron@ekips.org from envelope and perspective phyton code + * Dmitry Platonov, shadowjack@mail.ru, 2006 perspective approach & math + * Jose Hevia (freon) Transform algorithm from envelope + * + * Copyright (C) 2007-2014 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/parameter/enum.h" +#include "live_effects/effect.h" +#include "live_effects/parameter/pointreseteable.h" +#include "live_effects/lpegroupbbox.h" + +namespace Inkscape { +namespace LivePathEffect { + +class LPEEnvelopePerspective : public Effect, GroupBBoxEffect { +public: + + LPEEnvelopePerspective(LivePathEffectObject *lpeobject); + virtual ~LPEEnvelopePerspective(); + + virtual void doEffect(SPCurve *curve); + + virtual Geom::Point project_point(Geom::Point p); + + virtual Geom::Point project_point(Geom::Point p, double m[][3]); + + Geom::Point pointAtRatio(Geom::Coord ratio,Geom::Point A, Geom::Point B); + + virtual void resetDefaults(SPItem const* item); + + virtual void doBeforeEffect(SPLPEItem const* lpeitem); + + virtual Gtk::Widget * newWidget(); + + virtual void calculateCurve(Geom::Point a,Geom::Point b, SPCurve *c, bool horizontal, bool move); + + virtual void setDefaults(); + + virtual void resetGrid(); + + //virtual void original_bbox(SPLPEItem const* lpeitem, bool absolute = false); + + //virtual void addCanvasIndicators(SPLPEItem const*/*lpeitem*/, std::vector<Geom::PathVector> &/*hp_vec*/); + + //virtual std::vector<Geom::PathVector> getHelperPaths(SPLPEItem const* lpeitem); +protected: + void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec); +private: + + BoolParam perspective; + PointReseteableParam Up_Left_Point; + PointReseteableParam Up_Right_Point; + PointReseteableParam Down_Left_Point; + PointReseteableParam Down_Right_Point; + + LPEEnvelopePerspective(const LPEEnvelopePerspective&); + LPEEnvelopePerspective& operator=(const LPEEnvelopePerspective&); +}; + +} //namespace LivePathEffect +} //namespace Inkscape + +#endif diff --git a/src/style-internal.cpp b/src/style-internal.cpp index b15892128..8b4f3c1cd 100644 --- a/src/style-internal.cpp +++ b/src/style-internal.cpp @@ -648,9 +648,6 @@ SPIString::read( gchar const *str ) { if( !str ) return; - // libcroco puts quotes around some strings... remove - gchar *str_unquoted = attribute_unquote(str); - if (!strcmp(str, "inherit")) { set = true; inherit = true; @@ -658,10 +655,18 @@ SPIString::read( gchar const *str ) { } else { set = true; inherit = false; - value = g_strdup(str_unquoted); - } - g_free( str_unquoted ); + // libcroco puts quotes around some strings... remove + Glib::ustring str_unquoted(str); + css_unquote( str_unquoted ); + + // Unquote individual family names, Pango always uses unquoted names. + if( name.compare( "font-family" ) == 0 ) { + css_font_family_unquote( str_unquoted ); + } + + value = g_strdup(str_unquoted.c_str()); + } } diff --git a/src/style.cpp b/src/style.cpp index 11b1dc440..8e4c89839 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -58,6 +58,8 @@ #include <2geom/math-utils.h> +#include <glibmm/regex.h> + using Inkscape::CSSOStringStream; using std::vector; @@ -1824,31 +1826,43 @@ sp_css_attr_scale(SPCSSAttr *css, double ex) } -// Called in style.cpp, xml/repr-css.cpp +// Called in style-internal.cpp, xml/repr-css.cpp /** - * Remove quotes and escapes from a string. Returned value must be g_free'd. + * Remove paired single and double quotes from a string, changing string in place. * Note: in CSS (in style= and in stylesheets), unquoting and unescaping is done * by libcroco, our CSS parser, though it adds a new pair of "" quotes for the strings - * it parsed for us. So this function is only used to remove those quotes and for - * presentation attributes, without any unescaping. (XML unescaping - * (& etc) is done by XML parser.) + * it parsed for us. */ -gchar * -attribute_unquote(gchar const *val) +void +css_unquote(Glib::ustring &val) { - if (val) { - if (*val == '\'' || *val == '"') { - int l = strlen(val); - if (l >= 2) { - if ( ( val[0] == '"' && val[l - 1] == '"' ) || - ( val[0] == '\'' && val[l - 1] == '\'' ) ) { - return (g_strndup (val+1, l-2)); - } - } - } - } + if( val.size() > 1 && + ( (val[0] == '"' && val[val.size()-1] == '"' ) || + (val[0] == '\'' && val[val.size()-1] == '\'' ) ) ) { - return (val? g_strdup (val) : NULL); + val.erase( 0, 1 ); + val.erase( val.size()-1 ); + } +} + +// Called in style-internal.cpp, text-toolbar.cpp +/** + * Remove paired single and double quotes from font names in font-family lists, + * changing string in place. + * Pango expects unquoted font family names. We use unquoted names in interface. + */ +void +css_font_family_unquote(Glib::ustring &val) +{ + std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s*,\\s*", val ); + + val.erase(); + for( unsigned i=0; i < tokens.size(); ++i ) { + css_unquote( tokens[i] ); + val += tokens[i] + ", "; + } + if( val.size() > 1 ) + val.erase( val.size() - 2 ); // Remove trailing ", " } // Called in style.cpp, xml/repr-css.cpp diff --git a/src/style.h b/src/style.h index 9e592b78f..506b90b44 100644 --- a/src/style.h +++ b/src/style.h @@ -292,7 +292,9 @@ void sp_style_unset_property_attrs(SPObject *o); void sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *linked, bool recursive); -gchar *attribute_unquote(gchar const *val); +void css_unquote( Glib::ustring &val ); // Remove quotes from CSS values (style-internal.cpp, xml/repr-css.cpp) +void css_font_family_unquote( Glib::ustring &val ); // style-internal.cpp, text-toolbar.cpp + Glib::ustring css2_escape_quote(gchar const *val); #endif // SEEN_SP_STYLE_H diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp index 8a4ddc57e..a887a7355 100644 --- a/src/ui/dialog/spellcheck.cpp +++ b/src/ui/dialog/spellcheck.cpp @@ -347,7 +347,7 @@ SpellCheck::init(SPDesktop *d) char *slashPos = strrchr(exeName, '\\'); if (slashPos) *slashPos = '\0'; - g_print ("%s\n", exeName); + //g_print ("Aspell prefix path: %s\n", exeName); #endif _stops = 0; @@ -356,54 +356,54 @@ SpellCheck::init(SPDesktop *d) #ifdef HAVE_ASPELL { - AspellConfig *config = new_aspell_config(); + AspellConfig *config = new_aspell_config(); #ifdef WIN32 - aspell_config_replace(config, "prefix", exeName); + aspell_config_replace(config, "prefix", exeName); #endif - aspell_config_replace(config, "lang", _lang.c_str()); - aspell_config_replace(config, "encoding", "UTF-8"); - AspellCanHaveError *ret = new_aspell_speller(config); - delete_aspell_config(config); - if (aspell_error(ret) != 0) { - g_warning("Error: %s\n", aspell_error_message(ret)); - delete_aspell_can_have_error(ret); - return false; - } - _speller = to_aspell_speller(ret); + aspell_config_replace(config, "lang", _lang.c_str()); + aspell_config_replace(config, "encoding", "UTF-8"); + AspellCanHaveError *ret = new_aspell_speller(config); + delete_aspell_config(config); + if (aspell_error(ret) != 0) { + g_warning("Error: %s\n", aspell_error_message(ret)); + delete_aspell_can_have_error(ret); + return false; + } + _speller = to_aspell_speller(ret); } if (_lang2 != "") { - AspellConfig *config = new_aspell_config(); + AspellConfig *config = new_aspell_config(); #ifdef WIN32 - aspell_config_replace(config, "prefix", exeName); + aspell_config_replace(config, "prefix", exeName); #endif - aspell_config_replace(config, "lang", _lang2.c_str()); - aspell_config_replace(config, "encoding", "UTF-8"); - AspellCanHaveError *ret = new_aspell_speller(config); - delete_aspell_config(config); - if (aspell_error(ret) != 0) { - g_warning("Error: %s\n", aspell_error_message(ret)); - delete_aspell_can_have_error(ret); - return false; - } - _speller2 = to_aspell_speller(ret); + aspell_config_replace(config, "lang", _lang2.c_str()); + aspell_config_replace(config, "encoding", "UTF-8"); + AspellCanHaveError *ret = new_aspell_speller(config); + delete_aspell_config(config); + if (aspell_error(ret) != 0) { + g_warning("Error: %s\n", aspell_error_message(ret)); + delete_aspell_can_have_error(ret); + return false; + } + _speller2 = to_aspell_speller(ret); } if (_lang3 != "") { - AspellConfig *config = new_aspell_config(); + AspellConfig *config = new_aspell_config(); #ifdef WIN32 - aspell_config_replace(config, "prefix", exeName); + aspell_config_replace(config, "prefix", exeName); #endif - aspell_config_replace(config, "lang", _lang3.c_str()); - aspell_config_replace(config, "encoding", "UTF-8"); - AspellCanHaveError *ret = new_aspell_speller(config); - delete_aspell_config(config); - if (aspell_error(ret) != 0) { - g_warning("Error: %s\n", aspell_error_message(ret)); - delete_aspell_can_have_error(ret); - return false; - } - _speller3 = to_aspell_speller(ret); + aspell_config_replace(config, "lang", _lang3.c_str()); + aspell_config_replace(config, "encoding", "UTF-8"); + AspellCanHaveError *ret = new_aspell_speller(config); + delete_aspell_config(config); + if (aspell_error(ret) != 0) { + g_warning("Error: %s\n", aspell_error_message(ret)); + delete_aspell_can_have_error(ret); + return false; + } + _speller3 = to_aspell_speller(ret); } #endif /* HAVE_ASPELL */ diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index 3a4f315da..64a7cd5e7 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -134,6 +134,7 @@ static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GOb g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); Glib::ustring new_family = ink_comboboxentry_action_get_active_text( act ); + css_font_family_unquote( new_family ); // Remove quotes around font family names. // TODO: Think about how to handle handle multiple selections. While // the font-family may be the same for all, the styles might be different. diff --git a/src/xml/repr-css.cpp b/src/xml/repr-css.cpp index 32a1e7f5d..e462f70da 100644 --- a/src/xml/repr-css.cpp +++ b/src/xml/repr-css.cpp @@ -12,7 +12,7 @@ * changing an item in the List. Utility functions are provided to go back and forth between the * two ways of representing properties (by a string or by a list). * - * Use sp_repr_write_string to go from a property list to a style string. + * Use sp_repr_css_write_string to go from a property list to a style string. * */ @@ -350,9 +350,10 @@ void sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src) static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *const decl) { guchar *const str_value_unsigned = cr_term_to_string(decl->value); - gchar *const str_value = reinterpret_cast<gchar *>(str_value_unsigned); - gchar *value_unquoted = attribute_unquote (str_value); // libcroco returns strings quoted in "" - Glib::ustring value_unquoted2 = value_unquoted ? value_unquoted : Glib::ustring(); + + Glib::ustring value_unquoted( reinterpret_cast<gchar *>(str_value_unsigned ) ); + css_unquote( value_unquoted ); // libcroco returns strings quoted in "", remove + Glib::ustring units; /* @@ -362,11 +363,11 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con * * HACK for now is to strip off em and ex units and add them back at the end */ - int le = value_unquoted2.length(); + int le = value_unquoted.length(); if (le > 2) { - units = value_unquoted2.substr(le-2, 2); + units = value_unquoted.substr(le-2, 2); if ((units == "em") || (units == "ex")) { - value_unquoted2 = value_unquoted2.substr(0, le-2); + value_unquoted = value_unquoted.substr(0, le-2); } else { units.clear(); @@ -377,7 +378,7 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con // CSSOStringStream is used here to write valid CSS (as in sp_style_write_string). This has // the additional benefit of respecting the numerical precission set in the SVG Output // preferences. We assume any numerical part comes first (if not, the whole string is copied). - std::stringstream ss( value_unquoted2 ); + std::stringstream ss( value_unquoted ); double number = 0; std::string characters; std::string temp; @@ -399,8 +400,7 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con //g_message("sp_repr_css_merge_from_decl looks like em or ex units %s --> %s", str_value, os.str().c_str()); } ((Node *) css)->setAttribute(decl->property->stryng->str, os.str().c_str(), false); - g_free(value_unquoted); - g_free(str_value); + g_free(str_value_unsigned); } /** |
