summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShlomi Fish <shlomif@shlomifish.org>2016-09-15 17:03:32 +0000
committerShlomi Fish <shlomif@shlomifish.org>2016-09-15 17:03:32 +0000
commit3bb19d6df3b7d4e9c2518484e62997f9150d5f5d (patch)
tree3ac3c8748744b75c468d8c55d8eec27b841cfbb0 /src
parentRefactor == true (diff)
parent[Bug #459914] Non-ascii (ja) charactors aren't displayed properly in Handle t... (diff)
downloadinkscape-3bb19d6df3b7d4e9c2518484e62997f9150d5f5d.tar.gz
inkscape-3bb19d6df3b7d4e9c2518484e62997f9150d5f5d.zip
Merged.
(bzr r15100.1.17)
Diffstat (limited to 'src')
-rw-r--r--src/display/canvas-text.cpp2
-rw-r--r--src/display/nr-svgfonts.cpp44
-rw-r--r--src/display/nr-svgfonts.h3
-rw-r--r--src/live_effects/lpe-bendpath.cpp14
-rw-r--r--src/live_effects/lpe-bendpath.h2
-rw-r--r--src/live_effects/lpe-patternalongpath.cpp26
-rw-r--r--src/live_effects/lpe-patternalongpath.h1
-rw-r--r--src/sp-font.cpp6
-rw-r--r--src/sp-item.cpp14
-rw-r--r--src/sp-pattern.cpp14
-rw-r--r--src/ui/dialog/svg-fonts-dialog.cpp182
-rw-r--r--src/ui/dialog/svg-fonts-dialog.h36
-rw-r--r--src/ui/tools/freehand-base.cpp39
-rw-r--r--src/widgets/text-toolbar.cpp10
14 files changed, 289 insertions, 104 deletions
diff --git a/src/display/canvas-text.cpp b/src/display/canvas-text.cpp
index 7c019caf5..efef018e6 100644
--- a/src/display/canvas-text.cpp
+++ b/src/display/canvas-text.cpp
@@ -84,6 +84,7 @@ sp_canvastext_render (SPCanvasItem *item, SPCanvasBuf *buf)
if (!buf->ct)
return;
+ cairo_select_font_face(buf->ct, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(buf->ct, cl->fontsize);
if (cl->background){
@@ -138,6 +139,7 @@ sp_canvastext_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned i
cairo_surface_t *tmp_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
cairo_t* tmp_buf = cairo_create(tmp_surface);
+ cairo_select_font_face(tmp_buf, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(tmp_buf, cl->fontsize);
cairo_text_extents_t extents;
cairo_text_extents(tmp_buf, cl->text, &extents);
diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp
index 53a5cba49..fd092aed8 100644
--- a/src/display/nr-svgfonts.cpp
+++ b/src/display/nr-svgfonts.cpp
@@ -197,6 +197,7 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/,
bool is_horizontal_text = true; //TODO
_utf8 = (char*) utf8;
+ double font_height = units_per_em();
while(g_utf8_get_char(_utf8)){
len = 0;
for (i=0; i < (unsigned long) this->glyphs.size(); i++){
@@ -210,13 +211,13 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/,
//apply glyph kerning if appropriate
SPHkern *hkern = dynamic_cast<SPHkern *>(&node);
if (hkern && is_horizontal_text &&
- MatchHKerningRule(hkern, this->glyphs[i], previous_unicode, previous_glyph_name)) {
- x -= (hkern->k / 1000.0);//TODO: use here the height of the font
+ MatchHKerningRule(hkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){
+ x -= (hkern->k / font_height);
}
SPVkern *vkern = dynamic_cast<SPVkern *>(&node);
if (vkern && !is_horizontal_text &&
- MatchVKerningRule(vkern, this->glyphs[i], previous_unicode, previous_glyph_name)) {
- y -= (vkern->k / 1000.0);//TODO: use here the "height" of the font
+ MatchVKerningRule(vkern, this->glyphs[i], previous_unicode, previous_glyph_name) ){
+ y -= (vkern->k / font_height);
}
}
previous_unicode = const_cast<char*>(this->glyphs[i]->unicode.c_str());//used for kerning checking
@@ -226,8 +227,15 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/,
(*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
+ if (is_horizontal_text) {
+ if (this->glyphs[i]->horiz_adv_x != 0) {
+ x+=(this->glyphs[i]->horiz_adv_x/font_height);
+ } else {
+ x+=(this->font->horiz_adv_x/font_height);
+ }
+ } else {
+ y+=(this->font->vert_adv_y/font_height);
+ }
_utf8+=len; //advance 'len' bytes in our string pointer
//continue;
goto raptorz;
@@ -240,8 +248,8 @@ SvgFont::scaled_font_text_to_glyphs (cairo_scaled_font_t */*scaled_font*/,
(*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
+ if (is_horizontal_text) x+=(this->font->horiz_adv_x/font_height);//TODO: use here the height of the font
+ else y+=(this->font->vert_adv_y/font_height);//TODO: use here the "height" of the font
_utf8 = g_utf8_next_char(_utf8); //advance 1 char in our string pointer
}
@@ -257,9 +265,7 @@ SvgFont::render_glyph_path(cairo_t* cr, Geom::PathVector* pathv){
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/1000);//TODO: use here the units-per-em attribute?
-
+ Geom::Scale s(1.0/units_per_em());
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() )
feed_pathvector_to_cairo (cr, *pathv, s, area, false, 0);
@@ -275,7 +281,7 @@ SvgFont::glyph_modified(SPObject* /* blah */, unsigned int /* bleh */){
Geom::PathVector
SvgFont::flip_coordinate_system(SPFont* spfont, Geom::PathVector pathv){
- double units_per_em = 1000;
+ double units_per_em = 1024;
for(auto& obj: spfont->children) {
if (dynamic_cast<SPFontFace *>(&obj)) {
//XML Tree being directly used here while it shouldn't be.
@@ -400,6 +406,20 @@ void SvgFont::refresh(){
this->userfont = NULL;
}
+double SvgFont::units_per_em() {
+ double units_per_em = 1024;
+ for (auto& obj: font->children) {
+ if (dynamic_cast<SPFontFace *>(&obj)) {
+ //XML Tree being directly used here while it shouldn't be.
+ sp_repr_get_double(obj.getRepr(), "units-per-em", &units_per_em);
+ }
+ }
+ if (units_per_em <= 0.0) {
+ units_per_em = 1024;
+ }
+ return units_per_em;
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/display/nr-svgfonts.h b/src/display/nr-svgfonts.h
index 21ab3ed02..d4488fb17 100644
--- a/src/display/nr-svgfonts.h
+++ b/src/display/nr-svgfonts.h
@@ -52,7 +52,8 @@ private:
SPMissingGlyph* missingglyph;
sigc::connection glyph_modified_connection;
- bool drawing_expose_cb (Gtk::Widget *widget, GdkEventExpose *event, void* data);
+ double units_per_em();
+ //bool drawing_expose_cb (Gtk::Widget *widget, GdkEventExpose *event, void* data);
};
#endif //#ifndef NR_SVGFONTS_H_SEEN
diff --git a/src/live_effects/lpe-bendpath.cpp b/src/live_effects/lpe-bendpath.cpp
index 2ba1e32b4..c24d38d7b 100644
--- a/src/live_effects/lpe-bendpath.cpp
+++ b/src/live_effects/lpe-bendpath.cpp
@@ -67,7 +67,6 @@ LPEBendPath::LPEBendPath(LivePathEffectObject *lpeobject) :
_provides_knotholder_entities = true;
apply_to_clippath_and_mask = true;
concatenate_before_pwd2 = true;
- _prop_scale_store = prop_scale;
}
LPEBendPath::~LPEBendPath()
@@ -81,9 +80,6 @@ LPEBendPath::doBeforeEffect (SPLPEItem const* lpeitem)
// get the item bounding box
original_bbox(lpeitem);
original_height = boundingbox_Y.max() - boundingbox_Y.min();
- if(_prop_scale_store != prop_scale) {
- prop_scale.param_set_value(_prop_scale_store);
- }
}
Geom::Piecewise<Geom::D2<Geom::SBasis> >
@@ -124,9 +120,9 @@ LPEBendPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd
}
if ( scale_y_rel.get_value() ) {
- y*=(scaling*_prop_scale_store);
+ y*=(scaling*prop_scale);
} else {
- if (_prop_scale_store != 1.0) y *= _prop_scale_store;
+ if (prop_scale != 1.0) y *= prop_scale;
}
Piecewise<D2<SBasis> > output = compose(uskeleton,x) + y*compose(n,x);
@@ -188,9 +184,9 @@ KnotHolderEntityWidthBendPath::knot_set(Geom::Point const &p, Geom::Point const&
Geom::Point knot_pos = this->knot->pos * item->i2dt_affine().inverse();
Geom::Coord nearest_to_ray = ray.nearestTime(knot_pos);
if(nearest_to_ray == 0){
- lpe->_prop_scale_store = -Geom::distance(s , ptA)/(lpe->original_height/2.0);
+ lpe->prop_scale.param_set_value(-Geom::distance(s , ptA)/(lpe->original_height/2.0));
} else {
- lpe->_prop_scale_store = Geom::distance(s , ptA)/(lpe->original_height/2.0);
+ lpe->prop_scale.param_set_value(Geom::distance(s , ptA)/(lpe->original_height/2.0));
}
sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
@@ -211,7 +207,7 @@ KnotHolderEntityWidthBendPath::knot_get() const
ray.setPoints(ptA,(*cubic)[1]);
}
ray.setAngle(ray.angle() + Geom::rad_from_deg(90));
- Geom::Point result_point = Geom::Point::polar(ray.angle(), (lpe->original_height/2.0) * lpe->_prop_scale_store) + ptA;
+ Geom::Point result_point = Geom::Point::polar(ray.angle(), (lpe->original_height/2.0) * lpe->prop_scale) + ptA;
bp_helper_path.clear();
Geom::Path hp(result_point);
diff --git a/src/live_effects/lpe-bendpath.h b/src/live_effects/lpe-bendpath.h
index 36789bb15..eeda86a5e 100644
--- a/src/live_effects/lpe-bendpath.h
+++ b/src/live_effects/lpe-bendpath.h
@@ -58,7 +58,7 @@ private:
BoolParam vertical_pattern;
Geom::Piecewise<Geom::D2<Geom::SBasis> > uskeleton;
Geom::Piecewise<Geom::D2<Geom::SBasis> > n;
- double _prop_scale_store;
+
void on_pattern_pasted();
LPEBendPath(const LPEBendPath&);
diff --git a/src/live_effects/lpe-patternalongpath.cpp b/src/live_effects/lpe-patternalongpath.cpp
index 0814ce0da..0785da235 100644
--- a/src/live_effects/lpe-patternalongpath.cpp
+++ b/src/live_effects/lpe-patternalongpath.cpp
@@ -11,6 +11,7 @@
#include <2geom/bezier-to-sbasis.h>
#include "knotholder.h"
+#include <algorithm>
using std::vector;
@@ -95,7 +96,7 @@ LPEPatternAlongPath::LPEPatternAlongPath(LivePathEffectObject *lpeobject) :
prop_scale.param_set_increments(0.01, 0.10);
_provides_knotholder_entities = true;
- _prop_scale_store = prop_scale;
+
}
LPEPatternAlongPath::~LPEPatternAlongPath()
@@ -111,9 +112,6 @@ LPEPatternAlongPath::doBeforeEffect (SPLPEItem const* lpeitem)
if (bbox) {
original_height = (*bbox)[Geom::Y].max() - (*bbox)[Geom::Y].min();
}
- if(_prop_scale_store != prop_scale) {
- prop_scale.param_set_value(_prop_scale_store);
- }
}
Geom::Piecewise<Geom::D2<Geom::SBasis> >
@@ -195,12 +193,12 @@ LPEPatternAlongPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > con
case PAPCT_REPEATED_STRETCHED:
// if uskeleton is closed:
if(path_i.segs.front().at0() == path_i.segs.back().at1()){
- nbCopies = static_cast<int>(std::floor((uskeleton.domain().extent() - toffset)/(pattBndsX->extent()+xspace)));
+ nbCopies = std::max(1, static_cast<int>(std::floor((uskeleton.domain().extent() - toffset)/(pattBndsX->extent()+xspace))));
pattBndsX = Interval(pattBndsX->min(),pattBndsX->max()+xspace);
scaling = (uskeleton.domain().extent() - toffset)/(((double)nbCopies)*pattBndsX->extent());
// if not closed: no space at the end
}else{
- nbCopies = static_cast<int>(std::floor((uskeleton.domain().extent() - toffset + xspace)/(pattBndsX->extent()+xspace)));
+ nbCopies = std::max(1, static_cast<int>(std::floor((uskeleton.domain().extent() - toffset + xspace)/(pattBndsX->extent()+xspace))));
pattBndsX = Interval(pattBndsX->min(),pattBndsX->max()+xspace);
scaling = (uskeleton.domain().extent() - toffset)/(((double)nbCopies)*pattBndsX->extent() - xspace);
}
@@ -216,9 +214,9 @@ LPEPatternAlongPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > con
x*=scaling;
}
if ( scale_y_rel.get_value() ) {
- y*=(scaling*_prop_scale_store);
+ y*=(scaling*prop_scale);
} else {
- if (_prop_scale_store != 1.0) y *= _prop_scale_store;
+ if (prop_scale != 1.0) y *= prop_scale;
}
x += toffset;
@@ -256,10 +254,12 @@ LPEPatternAlongPath::transform_multiply(Geom::Affine const& postmul, bool set)
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool transform_stroke = prefs ? prefs->getBool("/options/transform/stroke", true) : true;
if (transform_stroke && !scale_y_rel) {
- prop_scale.param_set_value(_prop_scale_store * ((postmul.expansionX() + postmul.expansionY()) / 2));
- }
+ prop_scale.param_set_value(prop_scale * ((postmul.expansionX() + postmul.expansionY()) / 2));
+ prop_scale.write_to_SVG();
+ }
if (postmul.isTranslation()) {
pattern.param_transform_multiply(postmul, set);
+ pattern.write_to_SVG();
}
sp_lpe_item_update_patheffect (sp_lpe_item, false, true);
}
@@ -302,9 +302,9 @@ KnotHolderEntityWidthPatternAlongPath::knot_set(Geom::Point const &p, Geom::Poin
Geom::Point knot_pos = this->knot->pos * item->i2dt_affine().inverse();
Geom::Coord nearest_to_ray = ray.nearestTime(knot_pos);
if(nearest_to_ray == 0){
- lpe->_prop_scale_store = -Geom::distance(s , ptA)/(lpe->original_height/2.0);
+ lpe->prop_scale.param_set_value(-Geom::distance(s , ptA)/(lpe->original_height/2.0));
} else {
- lpe->_prop_scale_store = Geom::distance(s , ptA)/(lpe->original_height/2.0);
+ lpe->prop_scale.param_set_value(Geom::distance(s , ptA)/(lpe->original_height/2.0));
}
}
@@ -328,7 +328,7 @@ KnotHolderEntityWidthPatternAlongPath::knot_get() const
ray.setPoints(ptA, (*cubic)[1]);
}
ray.setAngle(ray.angle() + Geom::rad_from_deg(90));
- Geom::Point result_point = Geom::Point::polar(ray.angle(), (lpe->original_height/2.0) * lpe->_prop_scale_store) + ptA;
+ Geom::Point result_point = Geom::Point::polar(ray.angle(), (lpe->original_height/2.0) * lpe->prop_scale) + ptA;
pap_helper_path.clear();
Geom::Path hp(result_point);
diff --git a/src/live_effects/lpe-patternalongpath.h b/src/live_effects/lpe-patternalongpath.h
index eedf4c172..3d7fc02bc 100644
--- a/src/live_effects/lpe-patternalongpath.h
+++ b/src/live_effects/lpe-patternalongpath.h
@@ -61,7 +61,6 @@ private:
BoolParam prop_units;
BoolParam vertical_pattern;
ScalarParam fuse_tolerance;
- double _prop_scale_store;
void on_pattern_pasted();
LPEPatternAlongPath(const LPEPatternAlongPath&);
diff --git a/src/sp-font.cpp b/src/sp-font.cpp
index 2948dece4..0d97463df 100644
--- a/src/sp-font.cpp
+++ b/src/sp-font.cpp
@@ -25,9 +25,9 @@
//I think we should have extra stuff here and in the set method in order to set default value as specified at http://www.w3.org/TR/SVG/fonts.html
// TODO determine better values and/or make these dynamic:
-double FNT_DEFAULT_ADV = 90; // TODO determine proper default
-double FNT_DEFAULT_ASCENT = 90; // TODO determine proper default
-double FNT_UNITS_PER_EM = 90; // TODO determine proper default
+double FNT_DEFAULT_ADV = 1024; // TODO determine proper default
+double FNT_DEFAULT_ASCENT = 768; // TODO determine proper default
+double FNT_UNITS_PER_EM = 1024; // TODO determine proper default
SPFont::SPFont() : SPObject() {
this->horiz_origin_x = 0;
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index 0ba74f9fd..e03b715c0 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -317,8 +317,11 @@ void SPItem::lowerOne() {
auto next_lower = find_last_if(parent->children.begin(), parent->children.iterator_to(*this), &is_item);
if (next_lower != parent->children.iterator_to(*this)) {
- next_lower--;
- Inkscape::XML::Node *ref = next_lower->getRepr();
+ Inkscape::XML::Node *ref = nullptr;
+ if (next_lower != parent->children.begin()) {
+ next_lower--;
+ ref = next_lower->getRepr();
+ }
getRepr()->parent()->changeOrder(getRepr(), ref);
}
}
@@ -326,8 +329,11 @@ void SPItem::lowerOne() {
void SPItem::lowerToBottom() {
auto bottom = std::find_if(parent->children.begin(), parent->children.iterator_to(*this), &is_item);
if (bottom != parent->children.iterator_to(*this)) {
- bottom--;
- Inkscape::XML::Node *ref = bottom->getRepr() ;
+ Inkscape::XML::Node *ref = nullptr;
+ if (bottom != parent->children.begin()) {
+ bottom--;
+ ref = bottom->getRepr();
+ }
parent->getRepr()->changeOrder(getRepr(), ref);
}
}
diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp
index 77fa9034d..9d6296a0d 100644
--- a/src/sp-pattern.cpp
+++ b/src/sp-pattern.cpp
@@ -670,10 +670,20 @@ cairo_pattern_t *SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b
dc.paint(opacity); // apply opacity
}
- cairo_pattern_t *cp = cairo_pattern_create_for_surface(pattern_surface.raw());
// Apply transformation to user space. Also compensate for oversampling.
- ink_cairo_pattern_set_matrix(cp, ps2user.inverse() * pattern_surface.drawingTransform());
+ Geom::Affine raw_transform = ps2user.inverse() * pattern_surface.drawingTransform();
+
+ // Cairo doesn't like large values of x0 and y0. We can replace x0 and y0 by equivalent
+ // values close to zero (since one tile on a grid is the same as another it doesn't
+ // matter which tile is used as the base tile).
+ int w = one_tile[Geom::X].extent();
+ int h = one_tile[Geom::Y].extent();
+ int m = raw_transform[4] / w;
+ int n = raw_transform[5] / h;
+ raw_transform *= Geom::Translate( -m*w, -n*h );
+ cairo_pattern_t *cp = cairo_pattern_create_for_surface(pattern_surface.raw());
+ ink_cairo_pattern_set_matrix(cp, raw_transform);
cairo_pattern_set_extend(cp, CAIRO_EXTEND_REPEAT);
return cp;
diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp
index 0203d9778..e55a32bd5 100644
--- a/src/ui/dialog/svg-fonts-dialog.cpp
+++ b/src/ui/dialog/svg-fonts-dialog.cpp
@@ -29,6 +29,7 @@
#include "sp-font-face.h"
#include "desktop.h"
+#include <sstream>
#include "display/nr-svgfonts.h"
#include "verbs.h"
#include "sp-glyph.h"
@@ -74,6 +75,15 @@ bool SvgFontDrawingArea::on_expose_event (GdkEventExpose */*event*/){
cr->set_font_size (_y-20);
cr->move_to (10, 10);
cr->show_text (_text.c_str());
+
+ // Draw some lines to show line area.
+ cr->set_source_rgb( 0.5, 0.5, 0.5 );
+ cr->move_to ( 0, 10);
+ cr->line_to (_x, 10);
+ cr->stroke();
+ cr->move_to ( 0, _y-10);
+ cr->line_to (_x, _y-10);
+ cr->stroke();
}
return TRUE;
}
@@ -110,6 +120,7 @@ void SvgFontsDialog::AttrEntry::set_text(char* t){
entry.set_text(t);
}
+// 'font-family' has a problem as it is also a presentation attribute for <text>
void SvgFontsDialog::AttrEntry::on_attr_changed(){
SPObject* o = NULL;
@@ -139,6 +150,74 @@ void SvgFontsDialog::AttrEntry::on_attr_changed(){
}
+SvgFontsDialog::AttrSpin::AttrSpin(SvgFontsDialog* d, gchar* lbl, const SPAttributeEnum attr) {
+
+ this->dialog = d;
+ this->attr = attr;
+ this->add(* Gtk::manage(new Gtk::Label(lbl)) );
+ this->add(spin);
+ this->show_all();
+ spin.set_range(0, 4096);
+ spin.set_increments(16, 0);
+ spin.signal_value_changed().connect(sigc::mem_fun(*this, &SvgFontsDialog::AttrSpin::on_attr_changed));
+}
+
+void SvgFontsDialog::AttrSpin::set_range(double low, double high){
+ spin.set_range(low, high);
+}
+
+void SvgFontsDialog::AttrSpin::set_value(double v){
+ spin.set_value(v);
+}
+
+void SvgFontsDialog::AttrSpin::on_attr_changed(){
+
+ SPObject* o = NULL;
+ switch (this->attr) {
+
+ // <font> attributes
+ case SP_ATTR_HORIZ_ORIGIN_X:
+ case SP_ATTR_HORIZ_ORIGIN_Y:
+ case SP_ATTR_HORIZ_ADV_X:
+ case SP_ATTR_VERT_ORIGIN_X:
+ case SP_ATTR_VERT_ORIGIN_Y:
+ case SP_ATTR_VERT_ADV_Y:
+ o = this->dialog->get_selected_spfont();
+ break;
+
+ // <font-face> attributes
+ case SP_ATTR_UNITS_PER_EM:
+ case SP_ATTR_ASCENT:
+ case SP_ATTR_DESCENT:
+ case SP_ATTR_CAP_HEIGHT:
+ case SP_ATTR_X_HEIGHT:
+ for (auto& node: dialog->get_selected_spfont()->children){
+ if (SP_IS_FONTFACE(&node)){
+ o = &node;
+ continue;
+ }
+ }
+ break;
+
+ default:
+ o = NULL;
+ }
+
+ const gchar* name = (const gchar*)sp_attribute_name(this->attr);
+ if(name && o) {
+ std::ostringstream temp;
+ temp << this->spin.get_value();
+ o->getRepr()->setAttribute((const gchar*) name, temp.str().c_str() );
+ o->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+
+ Glib::ustring undokey = "svgfonts:";
+ undokey += name;
+ DocumentUndo::maybeDone(o->document, undokey.c_str(), SP_VERB_DIALOG_SVG_FONTS,
+ _("Set SVG Font attribute"));
+ }
+
+}
+
Gtk::HBox* SvgFontsDialog::AttrCombo(gchar* lbl, const SPAttributeEnum /*attr*/){
Gtk::HBox* hbox = Gtk::manage(new Gtk::HBox());
hbox->add(* Gtk::manage(new Gtk::Label(lbl)) );
@@ -279,7 +358,6 @@ void SvgFontsDialog::update_fonts()
}
void SvgFontsDialog::on_preview_text_changed(){
- _font_da.set_text((gchar*) _preview_entry.get_text().c_str());
_font_da.set_text(_preview_entry.get_text());
}
@@ -304,9 +382,18 @@ void SvgFontsDialog::update_global_settings_tab(){
SPFont* font = get_selected_spfont();
if (!font) return;
+ _horiz_adv_x_spin->set_value(font->horiz_adv_x);
+ _horiz_origin_x_spin->set_value(font->horiz_origin_x);
+ _horiz_origin_y_spin->set_value(font->horiz_origin_y);
+
for (auto& obj: font->children) {
if (SP_IS_FONTFACE(&obj)){
_familyname_entry->set_text((SP_FONTFACE(&obj))->font_family);
+ _units_per_em_spin->set_value((SP_FONTFACE(&obj))->units_per_em);
+ _ascent_spin->set_value((SP_FONTFACE(&obj))->ascent);
+ _descent_spin->set_value((SP_FONTFACE(&obj))->descent);
+ _x_height_spin->set_value((SP_FONTFACE(&obj))->x_height);
+ _cap_height_spin->set_value((SP_FONTFACE(&obj))->cap_height);
}
}
}
@@ -321,11 +408,8 @@ void SvgFontsDialog::on_font_selection_changed(){
kerning_preview.set_svgfont(svgfont);
_font_da.set_svgfont(svgfont);
_font_da.redraw();
-
- double set_width = spfont->horiz_adv_x;
- setwidth_spin.set_value(set_width);
-
- kerning_slider->set_range(0, set_width);
+
+ kerning_slider->set_range(0, spfont->horiz_adv_x);
kerning_slider->set_draw_value(false);
kerning_slider->set_value(0);
@@ -335,17 +419,6 @@ void SvgFontsDialog::on_font_selection_changed(){
update_sensitiveness();
}
-void SvgFontsDialog::on_setfontdata_changed(){
- SPFont* spfont = this->get_selected_spfont();
- 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();
- }
-}
-
SPGlyphKerning* SvgFontsDialog::get_selected_kerning_pair()
{
Gtk::TreeModel::iterator i = _KerningPairsList.get_selection()->get_selected();
@@ -379,24 +452,37 @@ SPGlyph* SvgFontsDialog::get_selected_glyph()
}
Gtk::VBox* SvgFontsDialog::global_settings_tab(){
- _familyname_entry = new AttrEntry(this, (gchar*) _("Family Name:"), SP_PROP_FONT_FAMILY);
+ _font_label = new Gtk::Label( _("Font Attributes") );
+ _horiz_adv_x_spin = new AttrSpin( this, (gchar*) _("Horiz. Advance X"), SP_ATTR_HORIZ_ADV_X);
+ _horiz_origin_x_spin = new AttrSpin( this, (gchar*) _("Horiz. Origin X "), SP_ATTR_HORIZ_ORIGIN_X);
+ _horiz_origin_y_spin = new AttrSpin( this, (gchar*) _("Horiz. Origin Y "), SP_ATTR_HORIZ_ORIGIN_Y);
+ _font_face_label = new Gtk::Label( _("Font Face Attributes") );
+ _familyname_entry = new AttrEntry(this, (gchar*) _("Family Name:"), SP_PROP_FONT_FAMILY);
+ _units_per_em_spin = new AttrSpin( this, (gchar*) _("Units per em"), SP_ATTR_UNITS_PER_EM);
+ _ascent_spin = new AttrSpin( this, (gchar*) _("Ascent:"), SP_ATTR_ASCENT);
+ _descent_spin = new AttrSpin( this, (gchar*) _("Descent:"), SP_ATTR_DESCENT);
+ _cap_height_spin = new AttrSpin( this, (gchar*) _("Cap Height:"), SP_ATTR_CAP_HEIGHT);
+ _x_height_spin = new AttrSpin( this, (gchar*) _("x Height:"), SP_ATTR_X_HEIGHT);
+
+ //_descent_spin->set_range(-4096,0);
+
+ global_vbox.pack_start(*_font_label, false, false);
+ global_vbox.pack_start(*_horiz_adv_x_spin, false, false);
+ global_vbox.pack_start(*_horiz_origin_x_spin, false, false);
+ global_vbox.pack_start(*_horiz_origin_y_spin, false, false);
+ global_vbox.pack_start(*_font_face_label, false, false);
+ global_vbox.pack_start(*_familyname_entry, false, false);
+ global_vbox.pack_start(*_units_per_em_spin, false, false);
+ global_vbox.pack_start(*_ascent_spin, false, false);
+ global_vbox.pack_start(*_descent_spin, false, false);
+ global_vbox.pack_start(*_cap_height_spin, false, false);
+ global_vbox.pack_start(*_x_height_spin, false, false);
- global_vbox.pack_start(*_familyname_entry, false, false);
/* global_vbox->add(*AttrCombo((gchar*) _("Style:"), SP_PROP_FONT_STYLE));
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());
- 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_setfontdata_changed));
- setwidth_spin.set_range(0, 4096);
- setwidth_spin.set_increments(10, 0);
- global_vbox.pack_start(*setwidth_hbox, false, false);
-
return &global_vbox;
}
@@ -412,9 +498,10 @@ SvgFontsDialog::populate_glyphs_box()
for (auto& node: spfont->children) {
if (SP_IS_GLYPH(&node)){
Gtk::TreeModel::Row row = *(_GlyphsListStore->append());
- row[_GlyphsListColumns.glyph_node] = static_cast<SPGlyph*>(&node);
+ row[_GlyphsListColumns.glyph_node] = static_cast<SPGlyph*>(&node);
row[_GlyphsListColumns.glyph_name] = (static_cast<SPGlyph*>(&node))->glyph_name;
- row[_GlyphsListColumns.unicode] = (static_cast<SPGlyph*>(&node))->unicode;
+ row[_GlyphsListColumns.unicode] = (static_cast<SPGlyph*>(&node))->unicode;
+ row[_GlyphsListColumns.advance] = (static_cast<SPGlyph*>(&node))->horiz_adv_x;
}
}
}
@@ -487,16 +574,14 @@ void SvgFontsDialog::add_glyph(){
Geom::PathVector
SvgFontsDialog::flip_coordinate_system(Geom::PathVector pathv){
- double units_per_em = 1000;
+ double units_per_em = 1024;
for (auto& obj: get_selected_spfont()->children) {
if (SP_IS_FONTFACE(&obj)){
//XML Tree being directly used here while it shouldn't be.
sp_repr_get_double(obj.getRepr(), "units-per-em", &units_per_em);
}
}
-
double baseline_offset = units_per_em - get_selected_spfont()->horiz_origin_y;
-
//This matrix flips y-axis and places the origin at baseline
Geom::Affine m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(baseline_offset));
return pathv*m;
@@ -631,6 +716,26 @@ void SvgFontsDialog::glyph_unicode_edit(const Glib::ustring&, const Glib::ustrin
update_glyphs();
}
+void SvgFontsDialog::glyph_advance_edit(const Glib::ustring&, const Glib::ustring& str){
+ Gtk::TreeModel::iterator i = _GlyphsList.get_selection()->get_selected();
+ if (!i) return;
+
+ SPGlyph* glyph = (*i)[_GlyphsListColumns.glyph_node];
+ //XML Tree being directly used here while it shouldn't be.
+ std::istringstream is(str);
+ double value;
+ // Check if input valid
+ if ((is >> value)) {
+ glyph->getRepr()->setAttribute("horiz-adv-x", str.c_str());
+ SPDocument* doc = this->getDesktop()->getDocument();
+ DocumentUndo::done(doc, SP_VERB_DIALOG_SVG_FONTS, _("Set glyph advance"));
+
+ update_glyphs();
+ } else {
+ std::cerr << "SvgFontDialog::glyph_advance_edit: Error in input: " << str << std::endl;
+ }
+}
+
void SvgFontsDialog::remove_selected_font(){
SPFont* font = get_selected_spfont();
if (!font) return;
@@ -699,9 +804,9 @@ Gtk::VBox* SvgFontsDialog::glyphs_tab(){
_GlyphsListScroller.add(_GlyphsList);
_GlyphsListStore = Gtk::ListStore::create(_GlyphsListColumns);
_GlyphsList.set_model(_GlyphsListStore);
- _GlyphsList.append_column_editable(_("Glyph name"), _GlyphsListColumns.glyph_name);
+ _GlyphsList.append_column_editable(_("Glyph name"), _GlyphsListColumns.glyph_name);
_GlyphsList.append_column_editable(_("Matching string"), _GlyphsListColumns.unicode);
-
+ _GlyphsList.append_column_numeric_editable(_("Advance"), _GlyphsListColumns.advance, "%.2f");
Gtk::HBox* hb = Gtk::manage(new Gtk::HBox());
add_glyph_button.set_label(_("Add Glyph"));
add_glyph_button.signal_clicked().connect(sigc::mem_fun(*this, &SvgFontsDialog::add_glyph));
@@ -719,6 +824,9 @@ Gtk::VBox* SvgFontsDialog::glyphs_tab(){
dynamic_cast<Gtk::CellRendererText*>( _GlyphsList.get_column_cell_renderer(1))->signal_edited().connect(
sigc::mem_fun(*this, &SvgFontsDialog::glyph_unicode_edit));
+ dynamic_cast<Gtk::CellRendererText*>( _GlyphsList.get_column_cell_renderer(2))->signal_edited().connect(
+ sigc::mem_fun(*this, &SvgFontsDialog::glyph_advance_edit));
+
_glyphs_observer.signal_changed().connect(sigc::mem_fun(*this, &SvgFontsDialog::update_glyphs));
return &glyphs_vbox;
@@ -798,7 +906,7 @@ Gtk::VBox* SvgFontsDialog::kerning_tab(){
kerning_amount_hbox->add(*kerning_slider);
kerning_preview.set_size(300 + 20, 150 + 20);
- _font_da.set_size(150 + 20, 50 + 20);
+ _font_da.set_size(300 + 50 + 20, 60 + 20);
return &kerning_vbox;
}
diff --git a/src/ui/dialog/svg-fonts-dialog.h b/src/ui/dialog/svg-fonts-dialog.h
index 1588c0fc2..a0f1586d8 100644
--- a/src/ui/dialog/svg-fonts-dialog.h
+++ b/src/ui/dialog/svg-fonts-dialog.h
@@ -82,8 +82,9 @@ public:
void on_setfontdata_changed();
void add_font();
Geom::PathVector flip_coordinate_system(Geom::PathVector pathv);
+ bool updating;
- //TODO: AttrEntry is currently unused. Should we remove it?
+ // Used for font-family
class AttrEntry : public Gtk::HBox
{
public:
@@ -96,6 +97,20 @@ public:
SPAttributeEnum attr;
};
+ class AttrSpin : public Gtk::HBox
+ {
+ public:
+ AttrSpin(SvgFontsDialog* d, gchar* lbl, const SPAttributeEnum attr);
+ void set_value(double v);
+ void set_range(double low, double high);
+ Inkscape::UI::Widget::SpinButton* getSpin() { return &spin; }
+ private:
+ SvgFontsDialog* dialog;
+ void on_attr_changed();
+ Inkscape::UI::Widget::SpinButton spin;
+ SPAttributeEnum attr;
+ };
+
private:
void update_glyphs();
void update_sensitiveness();
@@ -107,7 +122,8 @@ private:
void reset_missing_glyph_description();
void add_glyph();
void glyph_unicode_edit(const Glib::ustring&, const Glib::ustring&);
- void glyph_name_edit(const Glib::ustring&, const Glib::ustring&);
+ void glyph_name_edit( const Glib::ustring&, const Glib::ustring&);
+ void glyph_advance_edit(const Glib::ustring&, const Glib::ustring&);
void remove_selected_glyph();
void remove_selected_font();
void remove_selected_kerning_pair();
@@ -129,7 +145,21 @@ private:
Gtk::HBox* AttrCombo(gchar* lbl, const SPAttributeEnum attr);
// Gtk::HBox* AttrSpin(gchar* lbl, const SPAttributeEnum attr);
Gtk::VBox* global_settings_tab();
+
+ // <font>
+ Gtk::Label* _font_label;
+ AttrSpin* _horiz_adv_x_spin;
+ AttrSpin* _horiz_origin_x_spin;
+ AttrSpin* _horiz_origin_y_spin;
+
+ // <font-face>
+ Gtk::Label* _font_face_label;
AttrEntry* _familyname_entry;
+ AttrSpin* _units_per_em_spin;
+ AttrSpin* _ascent_spin;
+ AttrSpin* _descent_spin;
+ AttrSpin* _cap_height_spin;
+ AttrSpin* _x_height_spin;
Gtk::VBox* kerning_tab();
Gtk::VBox* glyphs_tab();
@@ -165,11 +195,13 @@ private:
add(glyph_node);
add(glyph_name);
add(unicode);
+ add(advance);
}
Gtk::TreeModelColumn<SPGlyph*> glyph_node;
Gtk::TreeModelColumn<Glib::ustring> glyph_name;
Gtk::TreeModelColumn<Glib::ustring> unicode;
+ Gtk::TreeModelColumn<double> advance;
};
GlyphsColumns _GlyphsListColumns;
Glib::RefPtr<Gtk::ListStore> _GlyphsListStore;
diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp
index 7382c37ea..067035b97 100644
--- a/src/ui/tools/freehand-base.cpp
+++ b/src/ui/tools/freehand-base.cpp
@@ -212,19 +212,10 @@ static void spdc_paste_curve_as_freehand_shape(Geom::PathVector const &newpath,
Effect::createAndApply(PATTERN_ALONG_PATH, dc->desktop->doc(), item);
Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
static_cast<LPEPatternAlongPath*>(lpe)->pattern.set_new_value(newpath,true);
-
- // write pattern along path parameters:
- lpe->getRepr()->setAttribute("copytype", "single_stretched");
- lpe->getRepr()->setAttribute("fuse_tolerance", "0");
- lpe->getRepr()->setAttribute("is_visible", "true");
- lpe->getRepr()->setAttribute("normal_offset", "0");
- lpe->getRepr()->setAttribute("prop_scale", "1");
- lpe->getRepr()->setAttribute("prop_units", "false");
- lpe->getRepr()->setAttribute("scale_y_rel", "false");
- lpe->getRepr()->setAttribute("spacing", "0");
- lpe->getRepr()->setAttribute("tang_offset", "0");
- lpe->getRepr()->setAttribute("vertical_pattern", "false");
-
+ double scale_doc = 1 / dc->desktop->doc()->getDocumentScale()[0];
+ Inkscape::SVGOStringStream os;
+ os << scale_doc;
+ lpe->getRepr()->setAttribute("prop_scale", os.str().c_str());
}
static void spdc_apply_powerstroke_shape(const std::vector<Geom::Point> & points, FreehandBase *dc, SPItem *item)
@@ -341,7 +332,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
// "triangle in"
std::vector<Geom::Point> points(1);
points[0] = Geom::Point(0., swidth/2);
- points[0] *= i2anc_affine(static_cast<SPItem *>(item->parent), NULL).inverse();
+ //points[0] *= i2anc_affine(static_cast<SPItem *>(item->parent), NULL).inverse();
spdc_apply_powerstroke_shape(points, dc, item);
shape_applied = true;
@@ -353,7 +344,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
guint curve_length = curve->get_segment_count();
std::vector<Geom::Point> points(1);
points[0] = Geom::Point(0, swidth/2);
- points[0] *= i2anc_affine(static_cast<SPItem *>(item->parent), NULL).inverse();
+ //points[0] *= i2anc_affine(static_cast<SPItem *>(item->parent), NULL).inverse();
points[0][Geom::X] = (double)curve_length;
spdc_apply_powerstroke_shape(points, dc, item);
@@ -791,16 +782,26 @@ static void spdc_flush_white(FreehandBase *dc, SPCurve *gc)
if (!dc->white_item) {
// Attach repr
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ shapeType shape_selected = (shapeType)prefs->getInt(tool_name(dc) + "/shape", 0);
SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr));
-
- spdc_check_for_and_apply_waiting_LPE(dc, item, c);
- if(previous_shape_type != BEND_CLIPBOARD){
- dc->selection->set(repr);
+ //Bend needs the transforms applied after, Other effects best before
+ if((previous_shape_type == BEND_CLIPBOARD && shape_selected == LAST_APPLIED) ||
+ shape_selected == BEND_CLIPBOARD)
+ {
+ spdc_check_for_and_apply_waiting_LPE(dc, item, c);
+ previous_shape_type = BEND_CLIPBOARD;
}
Inkscape::GC::release(repr);
item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
item->updateRepr();
item->doWriteTransform(item->getRepr(), item->transform, NULL, true);
+ if((previous_shape_type != BEND_CLIPBOARD || shape_selected != LAST_APPLIED) &&
+ shape_selected != BEND_CLIPBOARD)
+ {
+ spdc_check_for_and_apply_waiting_LPE(dc, item, c);
+ dc->selection->set(repr);
+ }
if(previous_shape_type == BEND_CLIPBOARD){
repr->parent()->removeChild(repr);
}
diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp
index 0160bcac7..4b22c8d7e 100644
--- a/src/widgets/text-toolbar.cpp
+++ b/src/widgets/text-toolbar.cpp
@@ -565,6 +565,16 @@ static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl )
// Save for undo
if(modmade) {
+ // Call ensureUpToDate() causes rebuild of text layout (with all proper style
+ // cascading, etc.). For multi-line text with sodipodi::role="line", we must explicitly
+ // save new <tspan> 'x' and 'y' attribute values by calling updateRepr().
+ // Partial fix for bug #1590141.
+ desktop->getDocument()->ensureUpToDate();
+ for(auto i=itemlist.begin();i!=itemlist.end(); ++i){
+ if (SP_IS_TEXT (*i)) {
+ (*i)->updateRepr();
+ }
+ }
DocumentUndo::maybeDone(SP_ACTIVE_DESKTOP->getDocument(), "ttb:line-height", SP_VERB_NONE,
_("Text: Change line-height"));
}