diff options
| author | Matthew Petroff <matthew@mpetroff.net> | 2013-09-20 17:05:24 +0000 |
|---|---|---|
| committer | Matthew Petroff <matthew@mpetroff.net> | 2013-09-20 17:05:24 +0000 |
| commit | 48b4ee48e518d65c3c5e49369a747c2aa4b0081b (patch) | |
| tree | 7159f8bc67d3f96ae43c42c32cacec6f7813f6fa /src/sp-flowtext.cpp | |
| parent | Fix bug in rectangle toolbar. (diff) | |
| parent | Fix grids after C++ification. Patch from Markus Engel (diff) | |
| download | inkscape-48b4ee48e518d65c3c5e49369a747c2aa4b0081b.tar.gz inkscape-48b4ee48e518d65c3c5e49369a747c2aa4b0081b.zip | |
Merge from trunk.
(bzr r12475.1.29)
Diffstat (limited to 'src/sp-flowtext.cpp')
| -rw-r--r-- | src/sp-flowtext.cpp | 308 |
1 files changed, 125 insertions, 183 deletions
diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index 4fc922a82..d46a644cf 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -34,112 +34,62 @@ #include "display/drawing-text.h" +#include "sp-factory.h" -static void sp_flowtext_dispose(GObject *object); +namespace { + SPObject* createFlowtext() { + return new SPFlowtext(); + } -static void sp_flowtext_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref); -static void sp_flowtext_remove_child(SPObject *object, Inkscape::XML::Node *child); -static void sp_flowtext_update(SPObject *object, SPCtx *ctx, guint flags); -static void sp_flowtext_modified(SPObject *object, guint flags); -static Inkscape::XML::Node *sp_flowtext_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static void sp_flowtext_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); -static void sp_flowtext_set(SPObject *object, unsigned key, gchar const *value); - -static Geom::OptRect sp_flowtext_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type); -static void sp_flowtext_print(SPItem *item, SPPrintContext *ctx); -static gchar *sp_flowtext_description(SPItem *item); -static void sp_flowtext_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); -static Inkscape::DrawingItem *sp_flowtext_show(SPItem *item, Inkscape::Drawing &drawing, unsigned key, unsigned flags); -static void sp_flowtext_hide(SPItem *item, unsigned key); -static Geom::Affine sp_flowtext_set_transform(SPItem *item, Geom::Affine const &xform); - -G_DEFINE_TYPE(SPFlowtext, sp_flowtext, SP_TYPE_ITEM); - -static void -sp_flowtext_class_init(SPFlowtextClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - SPObjectClass *sp_object_class = (SPObjectClass *) klass; - SPItemClass *item_class = (SPItemClass *) klass; - - object_class->dispose = sp_flowtext_dispose; - - sp_object_class->child_added = sp_flowtext_child_added; - sp_object_class->remove_child = sp_flowtext_remove_child; - sp_object_class->update = sp_flowtext_update; - sp_object_class->modified = sp_flowtext_modified; - sp_object_class->write = sp_flowtext_write; - sp_object_class->build = sp_flowtext_build; - sp_object_class->set = sp_flowtext_set; - - item_class->bbox = sp_flowtext_bbox; - item_class->print = sp_flowtext_print; - item_class->description = sp_flowtext_description; - item_class->snappoints = sp_flowtext_snappoints; - item_class->show = sp_flowtext_show; - item_class->hide = sp_flowtext_hide; - item_class->set_transform = sp_flowtext_set_transform; + bool flowtextRegistered = SPFactory::instance().registerObject("svg:flowRoot", createFlowtext); } -static void -sp_flowtext_init(SPFlowtext *group) -{ - group->par_indent = 0; - new (&group->layout) Inkscape::Text::Layout(); - - group->_optimizeScaledText = false; +SPFlowtext::SPFlowtext() : SPItem() { + this->par_indent = 0; + //new (&this->layout) Inkscape::Text::Layout(); } -static void -sp_flowtext_dispose(GObject *object) -{ - SPFlowtext *group = (SPFlowtext*)object; - - group->layout.~Layout(); +SPFlowtext::~SPFlowtext() { + //this->layout.~Layout(); } -static void -sp_flowtext_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref) -{ - if (((SPObjectClass *) (sp_flowtext_parent_class))->child_added) - (* ((SPObjectClass *) (sp_flowtext_parent_class))->child_added)(object, child, ref); +void SPFlowtext::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref) { + SPItem::child_added(child, ref); - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + this->requestModified(SP_OBJECT_MODIFIED_FLAG); } + /* fixme: hide (Lauris) */ -static void -sp_flowtext_remove_child(SPObject *object, Inkscape::XML::Node *child) -{ - if (((SPObjectClass *) (sp_flowtext_parent_class))->remove_child) - (* ((SPObjectClass *) (sp_flowtext_parent_class))->remove_child)(object, child); +void SPFlowtext::remove_child(Inkscape::XML::Node* child) { + SPItem::remove_child(child); - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + this->requestModified(SP_OBJECT_MODIFIED_FLAG); } -static void sp_flowtext_update(SPObject *object, SPCtx *ctx, unsigned flags) -{ - SPFlowtext *group = SP_FLOWTEXT(object); +void SPFlowtext::update(SPCtx* ctx, unsigned int flags) { SPItemCtx *ictx = (SPItemCtx *) ctx; SPItemCtx cctx = *ictx; - if (((SPObjectClass *) (sp_flowtext_parent_class))->update) { - ((SPObjectClass *) (sp_flowtext_parent_class))->update(object, ctx, flags); - } + SPItem::update(ctx, flags); if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; flags &= SP_OBJECT_MODIFIED_CASCADE; GSList *l = NULL; - for (SPObject *child = object->firstChild() ; child ; child = child->getNext() ) { - g_object_ref(G_OBJECT(child)); + + for (SPObject *child = this->firstChild() ; child ; child = child->getNext() ) { + sp_object_ref(child); l = g_slist_prepend(l, child); } + l = g_slist_reverse(l); + while (l) { SPObject *child = SP_OBJECT(l->data); l = g_slist_remove(l, child); + if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { if (SP_IS_ITEM(child)) { SPItem const &chi = *SP_ITEM(child); @@ -150,42 +100,46 @@ static void sp_flowtext_update(SPObject *object, SPCtx *ctx, unsigned flags) child->updateDisplay(ctx, flags); } } - g_object_unref(G_OBJECT(child)); + + sp_object_unref(child); } - group->rebuildLayout(); + this->rebuildLayout(); + + Geom::OptRect pbox = this->geometricBounds(); - Geom::OptRect pbox = group->geometricBounds(); - for (SPItemView *v = group->display; v != NULL; v = v->next) { + for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); - group->_clearFlow(g); - g->setStyle(object->style); + this->_clearFlow(g); + g->setStyle(this->style); // pass the bbox of the flowtext object as paintbox (used for paintserver fills) - group->layout.show(g, pbox); + this->layout.show(g, pbox); } } -static void sp_flowtext_modified(SPObject *object, guint flags) -{ - SPObject *ft = object; +void SPFlowtext::modified(unsigned int flags) { SPObject *region = NULL; - if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + if (flags & SP_OBJECT_MODIFIED_FLAG) { + flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + } + flags &= SP_OBJECT_MODIFIED_CASCADE; // FIXME: the below stanza is copied over from sp_text_modified, consider factoring it out if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG )) { - SPFlowtext *text = SP_FLOWTEXT(object); + SPFlowtext *text = SP_FLOWTEXT(this); Geom::OptRect pbox = text->geometricBounds(); + for (SPItemView* v = text->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); text->_clearFlow(g); - g->setStyle(object->style); + g->setStyle(this->style); text->layout.show(g, pbox); } } - for ( SPObject *o = ft->firstChild() ; o ; o = o->getNext() ) { + for ( SPObject *o = this->firstChild() ; o ; o = o->getNext() ) { if (SP_IS_FLOWREGION(o)) { region = o; break; @@ -199,39 +153,33 @@ static void sp_flowtext_modified(SPObject *object, guint flags) } } -static void -sp_flowtext_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) -{ - object->_requireSVGVersion(Inkscape::Version(1, 2)); +void SPFlowtext::build(SPDocument* doc, Inkscape::XML::Node* repr) { + this->_requireSVGVersion(Inkscape::Version(1, 2)); - if (((SPObjectClass *) (sp_flowtext_parent_class))->build) { - (* ((SPObjectClass *) (sp_flowtext_parent_class))->build)(object, document, repr); - } + SPItem::build(doc, repr); - object->readAttr( "inkscape:layoutOptions" ); // must happen after css has been read + this->readAttr( "inkscape:layoutOptions" ); // must happen after css has been read } -static void -sp_flowtext_set(SPObject *object, unsigned key, gchar const *value) -{ - SPFlowtext *group = (SPFlowtext *) object; - +void SPFlowtext::set(unsigned int key, const gchar* value) { switch (key) { case SP_ATTR_LAYOUT_OPTIONS: { // deprecated attribute, read for backward compatibility only //XML Tree being directly used while it shouldn't be. - SPCSSAttr *opts = sp_repr_css_attr(group->getRepr(), "inkscape:layoutOptions"); + SPCSSAttr *opts = sp_repr_css_attr(this->getRepr(), "inkscape:layoutOptions"); { gchar const *val = sp_repr_css_property(opts, "justification", NULL); - if (val != NULL && !object->style->text_align.set) { + + if (val != NULL && !this->style->text_align.set) { if ( strcmp(val, "0") == 0 || strcmp(val, "false") == 0 ) { - object->style->text_align.value = SP_CSS_TEXT_ALIGN_LEFT; + this->style->text_align.value = SP_CSS_TEXT_ALIGN_LEFT; } else { - object->style->text_align.value = SP_CSS_TEXT_ALIGN_JUSTIFY; + this->style->text_align.value = SP_CSS_TEXT_ALIGN_JUSTIFY; } - object->style->text_align.set = TRUE; - object->style->text_align.inherit = FALSE; - object->style->text_align.computed = object->style->text_align.value; + + this->style->text_align.set = TRUE; + this->style->text_align.inherit = FALSE; + this->style->text_align.computed = this->style->text_align.value; } } /* no equivalent css attribute for these two (yet) @@ -252,146 +200,139 @@ sp_flowtext_set(SPObject *object, unsigned key, gchar const *value) */ { // This would probably translate to padding-left, if SPStyle had it. gchar const *val = sp_repr_css_property(opts, "par-indent", NULL); + if ( val == NULL ) { - group->par_indent = 0.0; + this->par_indent = 0.0; } else { - sp_repr_get_double((Inkscape::XML::Node*)opts, "par-indent", &group->par_indent); + sp_repr_get_double((Inkscape::XML::Node*)opts, "par-indent", &this->par_indent); } } + sp_repr_css_attr_unref(opts); - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + this->requestModified(SP_OBJECT_MODIFIED_FLAG); break; } + default: - if (((SPObjectClass *) (sp_flowtext_parent_class))->set) { - (* ((SPObjectClass *) (sp_flowtext_parent_class))->set)(object, key, value); - } + SPItem::set(key, value); break; } } -static Inkscape::XML::Node *sp_flowtext_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) -{ +Inkscape::XML::Node* SPFlowtext::write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags) { if ( flags & SP_OBJECT_WRITE_BUILD ) { if ( repr == NULL ) { - repr = xml_doc->createElement("svg:flowRoot"); + repr = doc->createElement("svg:flowRoot"); } + GSList *l = NULL; - for (SPObject *child = object->firstChild() ; child ; child = child->getNext() ) { + + for (SPObject *child = this->firstChild() ; child ; child = child->getNext() ) { Inkscape::XML::Node *c_repr = NULL; + if ( SP_IS_FLOWDIV(child) || SP_IS_FLOWPARA(child) || SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child)) { - c_repr = child->updateRepr(xml_doc, NULL, flags); + c_repr = child->updateRepr(doc, NULL, flags); } + if ( c_repr ) { l = g_slist_prepend(l, c_repr); } } + while ( l ) { repr->addChild((Inkscape::XML::Node *) l->data, NULL); Inkscape::GC::release((Inkscape::XML::Node *) l->data); l = g_slist_remove(l, l->data); } } else { - for (SPObject *child = object->firstChild() ; child ; child = child->getNext() ) { + for (SPObject *child = this->firstChild() ; child ; child = child->getNext() ) { if ( SP_IS_FLOWDIV(child) || SP_IS_FLOWPARA(child) || SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child) ) { child->updateRepr(flags); } } } - if (((SPObjectClass *) (sp_flowtext_parent_class))->write) { - ((SPObjectClass *) (sp_flowtext_parent_class))->write(object, xml_doc, repr, flags); - } + SPItem::write(doc, repr, flags); return repr; } -static Geom::OptRect -sp_flowtext_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type) -{ - SPFlowtext *group = SP_FLOWTEXT(item); - Geom::OptRect bbox = group->layout.bounds(transform); +Geom::OptRect SPFlowtext::bbox(Geom::Affine const &transform, SPItem::BBoxType type) { + Geom::OptRect bbox = this->layout.bounds(transform); // Add stroke width // FIXME this code is incorrect - if (bbox && type == SPItem::VISUAL_BBOX && !item->style->stroke.isNone()) { + if (bbox && type == SPItem::VISUAL_BBOX && !this->style->stroke.isNone()) { double scale = transform.descrim(); - bbox->expandBy(0.5 * item->style->stroke_width.computed * scale); + bbox->expandBy(0.5 * this->style->stroke_width.computed * scale); } + return bbox; } -static void -sp_flowtext_print(SPItem *item, SPPrintContext *ctx) -{ - SPFlowtext *group = SP_FLOWTEXT(item); +void SPFlowtext::print(SPPrintContext *ctx) { Geom::OptRect pbox, bbox, dbox; + pbox = this->geometricBounds(); + bbox = this->desktopVisualBounds(); + dbox = Geom::Rect::from_xywh(Geom::Point(0,0), this->document->getDimensions()); - pbox = item->geometricBounds(); - bbox = item->desktopVisualBounds(); - dbox = Geom::Rect::from_xywh(Geom::Point(0,0), item->document->getDimensions()); - Geom::Affine const ctm (item->i2dt_affine()); + Geom::Affine const ctm (this->i2dt_affine()); - group->layout.print(ctx, pbox, dbox, bbox, ctm); + this->layout.print(ctx, pbox, dbox, bbox, ctm); } +const char* SPFlowtext::display_name() { + if (SP_FLOWTEXT(this)->has_internal_frame()) { + return _("Flowed Text"); + } else { + return _("Linked Flowed Text"); + } +} -static gchar *sp_flowtext_description(SPItem *item) -{ - Inkscape::Text::Layout const &layout = SP_FLOWTEXT(item)->layout; +gchar* SPFlowtext::description() { + Inkscape::Text::Layout const &layout = SP_FLOWTEXT(this)->layout; int const nChars = layout.iteratorToCharIndex(layout.end()); - char const *trunc = (layout.inputTruncated()) ? _(" [truncated]") : ""; - if (SP_FLOWTEXT(item)->has_internal_frame()) { - return g_strdup_printf(ngettext("<b>Flowed text</b> (%d character%s)", "<b>Flowed text</b> (%d characters%s)", nChars), nChars, trunc); - } else { - return g_strdup_printf(ngettext("<b>Linked flowed text</b> (%d character%s)", "<b>Linked flowed text</b> (%d characters%s)", nChars), nChars, trunc); - } + return g_strdup_printf(ngettext(_("(%d character%s)"), _("(%d characters%s)"), nChars), nChars, trunc); } -static void sp_flowtext_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) -{ +void SPFlowtext::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) { if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_TEXT_BASELINE)) { // Choose a point on the baseline for snapping from or to, with the horizontal position // of this point depending on the text alignment (left vs. right) - Inkscape::Text::Layout const *layout = te_get_layout((SPItem *) item); + Inkscape::Text::Layout const *layout = te_get_layout((SPItem *) this); + if (layout != NULL && layout->outputExists()) { boost::optional<Geom::Point> pt = layout->baselineAnchorPoint(); + if (pt) { - p.push_back(Inkscape::SnapCandidatePoint((*pt) * item->i2dt_affine(), Inkscape::SNAPSOURCE_TEXT_ANCHOR, Inkscape::SNAPTARGET_TEXT_ANCHOR)); + p.push_back(Inkscape::SnapCandidatePoint((*pt) * this->i2dt_affine(), Inkscape::SNAPSOURCE_TEXT_ANCHOR, Inkscape::SNAPTARGET_TEXT_ANCHOR)); } } } } -static Inkscape::DrawingItem * -sp_flowtext_show(SPItem *item, Inkscape::Drawing &drawing, unsigned/* key*/, unsigned /*flags*/) -{ - SPFlowtext *group = (SPFlowtext *) item; +Inkscape::DrawingItem* SPFlowtext::show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags) { Inkscape::DrawingGroup *flowed = new Inkscape::DrawingGroup(drawing); flowed->setPickChildren(false); - flowed->setStyle(group->style); + flowed->setStyle(this->style); // pass the bbox of the flowtext object as paintbox (used for paintserver fills) - Geom::OptRect bbox = group->geometricBounds(); - group->layout.show(flowed, bbox); + Geom::OptRect bbox = this->geometricBounds(); + this->layout.show(flowed, bbox); return flowed; } -static void -sp_flowtext_hide(SPItem *item, unsigned int key) -{ - if (((SPItemClass *) sp_flowtext_parent_class)->hide) - ((SPItemClass *) sp_flowtext_parent_class)->hide(item, key); +void SPFlowtext::hide(unsigned int key) { + SPItem::hide(key); } /* * */ - void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, std::list<Shape> *shapes, SPObject **pending_line_break_object) { Inkscape::Text::Layout::OptionalTextTagAttrs pi; @@ -464,13 +405,14 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, Shape* SPFlowtext::_buildExclusionShape() const { - Shape *shape = new Shape; - Shape *shape_temp = new Shape; + Shape *shape = new Shape(); + Shape *shape_temp = new Shape(); for (SPObject *child = children ; child ; child = child->getNext() ) { // RH: is it right that this shouldn't be recursive? if ( SP_IS_FLOWREGIONEXCLUDE(child) ) { SPFlowregionExclude *c_child = SP_FLOWREGIONEXCLUDE(child); + if ( c_child->computed && c_child->computed->hasEdges() ) { if (shape->hasEdges()) { shape_temp->Booleen(shape, c_child->computed, bool_op_union); @@ -481,7 +423,9 @@ Shape* SPFlowtext::_buildExclusionShape() const } } } + delete shape_temp; + return shape; } @@ -684,7 +628,7 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Geom::Coord const w = x1 - x0; Geom::Coord const h = y1 - y0; - sp_rect_position_set(rect, x0, y0, w, h); + rect->setPosition(x0, y0, w, h); rect->updateRepr(); Inkscape::XML::Node *para_repr = xml_doc->createElement("svg:flowPara"); @@ -705,18 +649,16 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, return ft_item; } -static Geom::Affine -sp_flowtext_set_transform (SPItem *item, Geom::Affine const &xform) +Geom::Affine SPFlowtext::set_transform (Geom::Affine const &xform) { - SPFlowtext *ft = SP_FLOWTEXT(item); - if ((ft->_optimizeScaledText && !xform.withoutTranslation().isNonzeroUniformScale()) - || (!ft->_optimizeScaledText && !xform.isNonzeroUniformScale())) { - ft->_optimizeScaledText = false; + if ((this->_optimizeScaledText && !xform.withoutTranslation().isNonzeroUniformScale()) + || (!this->_optimizeScaledText && !xform.isNonzeroUniformScale())) { + this->_optimizeScaledText = false; return xform; } - ft->_optimizeScaledText = false; + this->_optimizeScaledText = false; - SPText *text = reinterpret_cast<SPText *>(item); + SPText *text = reinterpret_cast<SPText *>(this); double const ex = xform.descrim(); if (ex == 0) { @@ -730,18 +672,18 @@ sp_flowtext_set_transform (SPItem *item, Geom::Affine const &xform) ret[3] /= ex; // Adjust font size - text->_adjustFontsizeRecursive (item, ex); + text->_adjustFontsizeRecursive (this, ex); // Adjust stroke width - item->adjust_stroke_width_recursive (ex); + this->adjust_stroke_width_recursive (ex); // Adjust pattern fill - item->adjust_pattern(xform * ret.inverse()); + this->adjust_pattern(xform * ret.inverse()); // Adjust gradient fill - item->adjust_gradient(xform * ret.inverse()); + this->adjust_gradient(xform * ret.inverse()); - item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG); return ret; } |
