diff options
| author | Liam P. White <inkscapebrony@gmail.com> | 2014-10-18 21:44:39 +0000 |
|---|---|---|
| committer | Liam P. White <inkscapebrony@gmail.com> | 2014-10-18 21:44:39 +0000 |
| commit | 68136c8b24a6995976db963a790207858e9baba5 (patch) | |
| tree | 550e81af7c8d626ec80a2be5efec66dd10d84bc4 /src/extension | |
| parent | Update to experimental r13598 (diff) | |
| parent | Update to trunk r13621 (diff) | |
| download | inkscape-68136c8b24a6995976db963a790207858e9baba5.tar.gz inkscape-68136c8b24a6995976db963a790207858e9baba5.zip | |
Update to experimental r13619
(bzr r13341.5.18)
Diffstat (limited to 'src/extension')
| -rw-r--r-- | src/extension/implementation/script.cpp | 100 | ||||
| -rw-r--r-- | src/extension/internal/cairo-render-context.cpp | 116 | ||||
| -rw-r--r-- | src/extension/internal/cairo-render-context.h | 1 | ||||
| -rw-r--r-- | src/extension/internal/cairo-renderer.cpp | 16 | ||||
| -rw-r--r-- | src/extension/internal/cairo-renderer.h | 2 | ||||
| -rw-r--r-- | src/extension/internal/cdr-input.cpp | 36 | ||||
| -rw-r--r-- | src/extension/internal/pdfinput/pdf-input.cpp | 24 | ||||
| -rw-r--r-- | src/extension/internal/pdfinput/pdf-parser.cpp | 182 | ||||
| -rw-r--r-- | src/extension/internal/pdfinput/pdf-parser.h | 30 | ||||
| -rw-r--r-- | src/extension/internal/vsd-input.cpp | 37 | ||||
| -rw-r--r-- | src/extension/internal/wpg-input.cpp | 57 | ||||
| -rw-r--r-- | src/extension/param/color.cpp | 12 | ||||
| -rw-r--r-- | src/extension/param/enum.cpp | 55 |
13 files changed, 462 insertions, 206 deletions
diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 5ee226ccf..e6ac13cdc 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -726,12 +726,12 @@ void Script::effect(Inkscape::Extension::Effect *module, vd->emitReconstructionStart(); copy_doc(vd->rroot, mydoc->rroot); vd->emitReconstructionFinish(); - SPObject *layer = NULL; - + // Getting the named view from the document generated by the extension SPNamedView *nv = sp_document_namedview(mydoc, NULL); //Check if it has a default layer set up + SPObject *layer = NULL; if ( nv != NULL) { if( nv->default_layer_id != 0 ) { @@ -760,19 +760,21 @@ void Script::effect(Inkscape::Extension::Effect *module, /** - \brief A function to take all the svg elements from one document - and put them in another. - \param oldroot The root node of the document to be replaced - \param newroot The root node of the document to replace it with - - This function first deletes all of the data in the old document. It - does this by creating a list of what needs to be deleted, and then - goes through the list. This two pass approach removes issues with - the list being change while parsing through it. Lots of nasty bugs. - - Then, it goes through the new document, duplicating all of the - elements and putting them into the old document. The copy - is then complete. + \brief A function to replace all the elements in an old document + by those from a new document. + document and repinserts them into an emptied old document. + \param oldroot The root node of the old (destination) document. + \param newroot The root node of the new (source) document. + + This function first deletes all the elements in the old document by + making two pass, the first to create a list of the old elements and + the second to actually delete them. This two pass approach removes issues + with the list being change while parsing through it... lots of nasty bugs. + + Then, it copies all the element in the new document into the old document. + + Finally, it replaces the attributes in the root element of the old document + by the attributes in root of the new document. */ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newroot) { @@ -781,9 +783,21 @@ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newr g_warning("Error on copy_doc: NULL pointer input."); return; } + + // For copying attributes in root and in namedview + using Inkscape::Util::List; + using Inkscape::XML::AttributeRecord; + + // Question: Why is the "sodipodi:namedview" special? Treating it as a normal + // elmement results in crashes. + // Seems to be a bug: + // http://inkscape.13.x6.nabble.com/Effect-that-modifies-the-document-properties-tt2822126.html + std::vector<Inkscape::XML::Node *> delete_list; Inkscape::XML::Node * oldroot_namedview = NULL; + Inkscape::XML::Node * newroot_namedview = NULL; + // Make list for (Inkscape::XML::Node * child = oldroot->firstChild(); child != NULL; child = child->next()) { @@ -798,14 +812,18 @@ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newr delete_list.push_back(child); } } + + // Unparent (delete) for (unsigned int i = 0; i < delete_list.size(); i++) { sp_repr_unparent(delete_list[i]); } + // Copy for (Inkscape::XML::Node * child = newroot->firstChild(); child != NULL; child = child->next()) { if (!strcmp("sodipodi:namedview", child->name())) { + newroot_namedview = child; if (oldroot_namedview != NULL) { for (Inkscape::XML::Node * newroot_namedview_child = child->firstChild(); newroot_namedview_child != NULL; @@ -818,26 +836,44 @@ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newr } } - { - using Inkscape::Util::List; - using Inkscape::XML::AttributeRecord; - std::vector<gchar const *> attribs; + std::vector<gchar const *> attribs; - // Make a list of all attributes of the old root node. - for (List<AttributeRecord const> iter = oldroot->attributeList(); iter; ++iter) { - attribs.push_back(g_quark_to_string(iter->key)); - } + // Must explicitly copy root attributes. - // Delete the attributes of the old root nodes. - for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); ++it) { - oldroot->setAttribute(*it, NULL); - } + // Make a list of all attributes of the old root node. + for (List<AttributeRecord const> iter = oldroot->attributeList(); iter; ++iter) { + attribs.push_back(g_quark_to_string(iter->key)); + } - // Set the new attributes. - for (List<AttributeRecord const> iter = newroot->attributeList(); iter; ++iter) { - gchar const *name = g_quark_to_string(iter->key); - oldroot->setAttribute(name, newroot->attribute(name)); - } + // Delete the attributes of the old root node. + for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); ++it) { + oldroot->setAttribute(*it, NULL); + } + + // Set the new attributes. + for (List<AttributeRecord const> iter = newroot->attributeList(); iter; ++iter) { + gchar const *name = g_quark_to_string(iter->key); + oldroot->setAttribute(name, newroot->attribute(name)); + } + + attribs.clear(); + + // Must explicitly copy namedview attributes. + + // Make a list of all attributes of the old namedview node. + for (List<AttributeRecord const> iter = oldroot_namedview->attributeList(); iter; ++iter) { + attribs.push_back(g_quark_to_string(iter->key)); + } + + // Delete the attributes of the old namedview node. + for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); ++it) { + oldroot_namedview->setAttribute(*it, NULL); + } + + // Set the new attributes. + for (List<AttributeRecord const> iter = newroot_namedview->attributeList(); iter; ++iter) { + gchar const *name = g_quark_to_string(iter->key); + oldroot_namedview->setAttribute(name, newroot_namedview->attribute(name)); } /** \todo Restore correct layer */ diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index c09b8e9c8..7e61cdbbb 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -39,6 +39,7 @@ #include "sp-item.h" #include "sp-item-group.h" #include "style.h" +#include "sp-hatch.h" #include "sp-linear-gradient.h" #include "sp-radial-gradient.h" #include "sp-pattern.h" @@ -1130,6 +1131,82 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver } cairo_pattern_t* +CairoRenderContext::_createHatchPainter(SPPaintServer const *const paintserver, Geom::OptRect const &pbox) { + g_assert( SP_IS_HATCH(paintserver) ); + SPHatch *hatch = SP_HATCH(paintserver); + + g_assert(hatch->pitch() > 0); + + // create drawing and group + Inkscape::Drawing drawing; + unsigned dkey = SPItem::display_key_new(1); + + hatch->show(drawing, dkey, pbox); + + SPHatch::RenderInfo render_info = hatch->calculateRenderInfo(dkey); + Geom::Rect tile_rect = render_info.tile_rect; + + // Cairo requires an integer pattern surface width/height. + // Subtract 0.5 to prevent small rounding errors from increasing pattern size by one pixel. + // Multiply by SUBPIX_SCALE to allow for less than a pixel precision + const int subpix_scale = 10; + double surface_width = MAX(ceil(subpix_scale * tile_rect.width() - 0.5), 1); + double surface_height = MAX(ceil(subpix_scale * tile_rect.height() - 0.5), 1); + Geom::Affine drawing_scale = Geom::Scale(surface_width / tile_rect.width(), surface_height / tile_rect.height()); + Geom::Affine drawing_transform = Geom::Translate(-tile_rect.min()) * drawing_scale; + + Geom::Affine child_transform = render_info.child_transform; + child_transform *= drawing_transform; + + //The rendering of hatch overflow is implemented by repeated drawing + //of hatch paths over one strip. Within each iteration paths are moved by pitch value. + //The movement progresses from right to left. This gives the same result + //as drawing whole strips in left-to-right order. + gdouble overflow_right_strip = 0.0; + int overflow_steps = 1; + Geom::Affine overflow_transform; + if (hatch->style->overflow.computed == SP_CSS_OVERFLOW_VISIBLE) { + Geom::Interval bounds = hatch->bounds(); + overflow_right_strip = floor(bounds.max() / hatch->pitch()) * hatch->pitch(); + overflow_steps = ceil((overflow_right_strip - bounds.min()) / hatch->pitch()) + 1; + overflow_transform = Geom::Translate(hatch->pitch(), 0.0); + } + + CairoRenderContext *pattern_ctx = cloneMe(surface_width, surface_height); + pattern_ctx->setTransform(child_transform); + pattern_ctx->transform(Geom::Translate(-overflow_right_strip, 0.0)); + pattern_ctx->pushState(); + + std::vector<SPHatchPath *> children; + hatch->hatchPaths(children); + + for (int i = 0; i < overflow_steps; i++) { + for (std::vector<SPHatchPath *>::iterator iter = children.begin(); iter != children.end(); iter++) { + SPHatchPath *path = *iter; + _renderer->renderHatchPath(pattern_ctx, *path, dkey); + } + pattern_ctx->transform(overflow_transform); + } + + pattern_ctx->popState(); + + // setup a cairo_pattern_t + cairo_surface_t *pattern_surface = pattern_ctx->getSurface(); + TEST(pattern_ctx->saveAsPng("hatch.png")); + cairo_pattern_t *result = cairo_pattern_create_for_surface(pattern_surface); + cairo_pattern_set_extend(result, CAIRO_EXTEND_REPEAT); + + Geom::Affine pattern_transform; + pattern_transform = render_info.pattern_to_user_transform.inverse() * drawing_transform; + ink_cairo_pattern_set_matrix(result, pattern_transform); + + hatch->hide(dkey); + + delete pattern_ctx; + return result; +} + +cairo_pattern_t* CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const paintserver, Geom::OptRect const &pbox, float alpha) { @@ -1182,8 +1259,9 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain cairo_pattern_add_color_stop_rgba(pattern, rg->vector.stops[i].offset, rgb[0], rgb[1], rgb[2], rg->vector.stops[i].opacity * alpha); } } else if (SP_IS_PATTERN (paintserver)) { - pattern = _createPatternPainter(paintserver, pbox); + } else if (SP_IS_HATCH (paintserver)) { + pattern = _createHatchPainter(paintserver, pbox); } else { return NULL; } @@ -1249,26 +1327,29 @@ CairoRenderContext::_setFillStyle(SPStyle const *const style, Geom::OptRect cons TRACE(("merged op=%f\n", alpha)); } - if (style->fill.isColor()) { - float rgb[3]; - sp_color_get_rgb_floatv(&style->fill.value.color, rgb); + SPPaintServer const *paint_server = style->getFillPaintServer(); + if (paint_server && paint_server->isValid()) { - cairo_set_source_rgba(_cr, rgb[0], rgb[1], rgb[2], alpha); - - } else if (!style->fill.set) { // unset fill is black - cairo_set_source_rgba(_cr, 0, 0, 0, alpha); - - } else { - g_assert( style->fill.isPaintserver() - || SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) - || SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style)) ); - - cairo_pattern_t *pattern = _createPatternForPaintServer(SP_STYLE_FILL_SERVER(style), pbox, alpha); + g_assert(SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) + || SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style)) + || SP_IS_HATCH(SP_STYLE_FILL_SERVER(style))); + cairo_pattern_t *pattern = _createPatternForPaintServer(paint_server, pbox, alpha); if (pattern) { cairo_set_source(_cr, pattern); cairo_pattern_destroy(pattern); } + } else if (style->fill.colorSet) { + float rgb[3]; + sp_color_get_rgb_floatv(&style->fill.value.color, rgb); + + cairo_set_source_rgba(_cr, rgb[0], rgb[1], rgb[2], alpha); + + } else { // unset fill is black + g_assert(!style->fill.set + || (paint_server && !paint_server->isValid())); + + cairo_set_source_rgba(_cr, 0, 0, 0, alpha); } } @@ -1279,7 +1360,7 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, Geom::OptRect const &p if (_state->merge_opacity) alpha *= _state->opacity; - if (style->stroke.isColor()) { + if (style->stroke.isColor() || (style->stroke.isPaintserver() && !style->getStrokePaintServer()->isValid())) { float rgb[3]; sp_color_get_rgb_floatv(&style->stroke.value.color, rgb); @@ -1287,7 +1368,8 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, Geom::OptRect const &p } else { g_assert( style->stroke.isPaintserver() || SP_IS_GRADIENT(SP_STYLE_STROKE_SERVER(style)) - || SP_IS_PATTERN(SP_STYLE_STROKE_SERVER(style)) ); + || SP_IS_PATTERN(SP_STYLE_STROKE_SERVER(style)) + || SP_IS_HATCH(SP_STYLE_STROKE_SERVER(style))); cairo_pattern_t *pattern = _createPatternForPaintServer(SP_STYLE_STROKE_SERVER(style), pbox, alpha); diff --git a/src/extension/internal/cairo-render-context.h b/src/extension/internal/cairo-render-context.h index 8071cae36..57d155b60 100644 --- a/src/extension/internal/cairo-render-context.h +++ b/src/extension/internal/cairo-render-context.h @@ -204,6 +204,7 @@ protected: cairo_pattern_t *_createPatternForPaintServer(SPPaintServer const *const paintserver, Geom::OptRect const &pbox, float alpha); cairo_pattern_t *_createPatternPainter(SPPaintServer const *const paintserver, Geom::OptRect const &pbox); + cairo_pattern_t *_createHatchPainter(SPPaintServer const *const paintserver, Geom::OptRect const &pbox); unsigned int _showGlyphs(cairo_t *cr, PangoFont *font, std::vector<CairoGlyphInfo> const &glyphtext, bool is_stroke); diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 8196e34fb..a725685d4 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -50,6 +50,7 @@ #include "sp-use.h" #include "sp-text.h" #include "sp-flowtext.h" +#include "sp-hatch-path.h" #include "sp-image.h" #include "sp-symbol.h" #include "sp-pattern.h" @@ -598,6 +599,21 @@ void CairoRenderer::renderItem(CairoRenderContext *ctx, SPItem *item) ctx->popState(); } +void CairoRenderer::renderHatchPath(CairoRenderContext *ctx, SPHatchPath const &hatchPath, unsigned key) { + ctx->pushState(); + ctx->setStateForStyle(hatchPath.style); + ctx->transform(Geom::Translate(hatchPath.offset.computed, 0)); + + SPCurve *curve = hatchPath.calculateRenderCurve(key); + Geom::PathVector const & pathv =curve->get_pathvector(); + if (!pathv.empty()) { + ctx->renderPathVector(pathv, hatchPath.style, Geom::OptRect()); + } + + curve->unref(); + ctx->popState(); +} + bool CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool pageBoundingBox, float bleedmargin_px, SPItem *base) { diff --git a/src/extension/internal/cairo-renderer.h b/src/extension/internal/cairo-renderer.h index cfef6bdea..abc0447d8 100644 --- a/src/extension/internal/cairo-renderer.h +++ b/src/extension/internal/cairo-renderer.h @@ -29,6 +29,7 @@ class SPClipPath; class SPMask; +class SPHatchPath; namespace Inkscape { namespace Extension { @@ -57,6 +58,7 @@ public: /** Traverses the object tree and invokes the render methods. */ void renderItem(CairoRenderContext *ctx, SPItem *item); + void renderHatchPath(CairoRenderContext *ctx, SPHatchPath const &hatchPath, unsigned key); }; // FIXME: this should be a static method of CairoRenderer diff --git a/src/extension/internal/cdr-input.cpp b/src/extension/internal/cdr-input.cpp index 1de3f304b..fb58887c9 100644 --- a/src/extension/internal/cdr-input.cpp +++ b/src/extension/internal/cdr-input.cpp @@ -24,7 +24,21 @@ #include <cstring> #include <libcdr/libcdr.h> -#include <libwpd-stream/libwpd-stream.h> + +// TODO: Drop this check when librevenge is widespread. +#if WITH_LIBCDR01 + #include <librevenge-stream/librevenge-stream.h> + + using librevenge::RVNGString; + using librevenge::RVNGFileStream; + using librevenge::RVNGStringVector; +#else + #include <libwpd-stream/libwpd-stream.h> + + typedef WPXString RVNGString; + typedef WPXFileStream RVNGFileStream; + typedef libcdr::CDRStringVector RVNGStringVector; +#endif #include <gtkmm/alignment.h> #include <gtkmm/comboboxtext.h> @@ -60,7 +74,7 @@ namespace Internal { class CdrImportDialog : public Gtk::Dialog { public: - CdrImportDialog(const std::vector<WPXString> &vec); + CdrImportDialog(const std::vector<RVNGString> &vec); virtual ~CdrImportDialog(); bool showDialog(); @@ -86,12 +100,12 @@ private: class Gtk::VBox * vbox2; class Gtk::Widget * _previewArea; - const std::vector<WPXString> &_vec; // Document to be imported + const std::vector<RVNGString> &_vec; // Document to be imported unsigned _current_page; // Current selected page int _preview_width, _preview_height; // Size of the preview area }; -CdrImportDialog::CdrImportDialog(const std::vector<WPXString> &vec) +CdrImportDialog::CdrImportDialog(const std::vector<RVNGString> &vec) : _vec(vec), _current_page(1) { int num_pages = _vec.size(); @@ -216,14 +230,20 @@ void CdrImportDialog::_setPreviewPage(unsigned page) SPDocument *CdrInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri) { - WPXFileStream input(uri); + RVNGFileStream input(uri); if (!libcdr::CDRDocument::isSupported(&input)) { return NULL; } - libcdr::CDRStringVector output; + RVNGStringVector output; +#if WITH_LIBCDR01 + librevenge::RVNGSVGDrawingGenerator generator(output, "svg"); + + if (!libcdr::CDRDocument::parse(&input, &generator)) { +#else if (!libcdr::CDRDocument::generateSVG(&input, output)) { +#endif return NULL; } @@ -231,9 +251,9 @@ SPDocument *CdrInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * u return NULL; } - std::vector<WPXString> tmpSVGOutput; + std::vector<RVNGString> tmpSVGOutput; for (unsigned i=0; i<output.size(); ++i) { - WPXString tmpString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); + RVNGString tmpString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); tmpString.append(output[i]); tmpSVGOutput.push_back(tmpString); } diff --git a/src/extension/internal/pdfinput/pdf-input.cpp b/src/extension/internal/pdfinput/pdf-input.cpp index e18d898f5..defb15754 100644 --- a/src/extension/internal/pdfinput/pdf-input.cpp +++ b/src/extension/internal/pdfinput/pdf-input.cpp @@ -647,7 +647,31 @@ PdfInput::open(::Inkscape::Extension::Input * /*mod*/, const gchar * uri) { // Initialize the globalParams variable for poppler if (!globalParams) { +#ifdef ENABLE_OSX_APP_LOCATIONS + // + // data files for poppler are not relocatable (loaded from + // path defined at build time). This fails to work with relocatable + // application bundles for OS X. + // + // Workaround: + // 1. define $POPPLER_DATADIR env variable in app launcher script + // 2. pass custom $POPPLER_DATADIR via poppler's GlobalParams() + // + // relevant poppler commit: + // <http://cgit.freedesktop.org/poppler/poppler/commit/?id=869584a84eed507775ff1c3183fe484c14b6f77b> + // + // FIXES: Inkscape bug #956282, #1264793 + // TODO: report RFE upstream (full relocation support for OS X packaging) + // + gchar const *poppler_datadir = g_getenv("POPPLER_DATADIR"); + if (poppler_datadir != NULL) { + globalParams = new GlobalParams(poppler_datadir); + } else { + globalParams = new GlobalParams(); + } +#else globalParams = new GlobalParams(); +#endif // ENABLE_OSX_APP_LOCATIONS } // poppler does not use glib g_open. So on win32 we must use unicode call. code was copied from glib gstdio.c #ifndef WIN32 diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index c5f03e5aa..0b7dc7905 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -247,30 +247,74 @@ PdfOperator PdfParser::opTab[] = { #define numOps (sizeof(opTab) / sizeof(PdfOperator)) +namespace { + +GfxPatch blankPatch() +{ + GfxPatch patch; + memset(&patch, 0, sizeof(patch)); // quick-n-dirty + return patch; +} + +} // namespace + //------------------------------------------------------------------------ -// PdfParser +// ClipHistoryEntry //------------------------------------------------------------------------ -PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *builderA, - int /*pageNum*/, int rotate, Dict *resDict, - PDFRectangle *box, PDFRectangle *cropBox) -{ - xref = xrefA; - subPage = gFalse; - printCommands = false; +class ClipHistoryEntry { +public: + + ClipHistoryEntry(GfxPath *clipPath = NULL, GfxClipType clipType = clipNormal); + virtual ~ClipHistoryEntry(); + + // Manipulate clip path stack + ClipHistoryEntry *save(); + ClipHistoryEntry *restore(); + GBool hasSaves() { return saved != NULL; } + void setClip(GfxPath *newClipPath, GfxClipType newClipType = clipNormal); + GfxPath *getClipPath() { return clipPath; } + GfxClipType getClipType() { return clipType; } - // start the resource stack - res = new GfxResources(xref, resDict, NULL); +private: - // initialize - state = new GfxState(72.0, 72.0, box, rotate, gTrue); - clipHistory = new ClipHistoryEntry(); + ClipHistoryEntry *saved; // next clip path on stack + + GfxPath *clipPath; // used as the path to be filled for an 'sh' operator + GfxClipType clipType; + + ClipHistoryEntry(ClipHistoryEntry *other); +}; + +//------------------------------------------------------------------------ +// PdfParser +//------------------------------------------------------------------------ + +PdfParser::PdfParser(XRef *xrefA, + Inkscape::Extension::Internal::SvgBuilder *builderA, + int /*pageNum*/, + int rotate, + Dict *resDict, + PDFRectangle *box, + PDFRectangle *cropBox) : + xref(xrefA), + builder(builderA), + subPage(gFalse), + printCommands(false), + res(new GfxResources(xref, resDict, NULL)), // start the resource stack + state(new GfxState(72.0, 72.0, box, rotate, gTrue)), + fontChanged(gFalse), + clip(clipNone), + ignoreUndef(0), + baseMatrix(), + formDepth(0), + parser(NULL), + colorDeltas(), + maxDepths(), + clipHistory(new ClipHistoryEntry()), + operatorHistory(NULL) +{ setDefaultApproximationPrecision(); - fontChanged = gFalse; - clip = clipNone; - ignoreUndef = 0; - operatorHistory = NULL; - builder = builderA; builder->setDocumentSize(Inkscape::Util::Quantity::convert(state->getPageWidth(), "pt", "px"), Inkscape::Util::Quantity::convert(state->getPageHeight(), "pt", "px")); @@ -306,50 +350,62 @@ PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *bui pushOperator("startPage"); } -PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *builderA, - Dict *resDict, PDFRectangle *box) { - - int i; - parser = NULL; - - xref = xrefA; - subPage = gTrue; - printCommands = false; - - // start the resource stack - res = new GfxResources(xref, resDict, NULL); - - // initialize - operatorHistory = NULL; - builder = builderA; - state = new GfxState(72, 72, box, 0, gFalse); - clipHistory = new ClipHistoryEntry(); +PdfParser::PdfParser(XRef *xrefA, + Inkscape::Extension::Internal::SvgBuilder *builderA, + Dict *resDict, + PDFRectangle *box) : + xref(xrefA), + builder(builderA), + subPage(gTrue), + printCommands(false), + res(new GfxResources(xref, resDict, NULL)), // start the resource stack + state(new GfxState(72, 72, box, 0, gFalse)), + fontChanged(gFalse), + clip(clipNone), + ignoreUndef(0), + baseMatrix(), + formDepth(0), + parser(NULL), + colorDeltas(), + maxDepths(), + clipHistory(new ClipHistoryEntry()), + operatorHistory(NULL) +{ setDefaultApproximationPrecision(); - fontChanged = gFalse; - clip = clipNone; - ignoreUndef = 0; - for (i = 0; i < 6; ++i) { + for (int i = 0; i < 6; ++i) { baseMatrix[i] = state->getCTM()[i]; } formDepth = 0; } PdfParser::~PdfParser() { - while (state->hasSaves()) { + while(operatorHistory) { + OpHistoryEntry *tmp = operatorHistory->next; + delete operatorHistory; + operatorHistory = tmp; + } + + while (state && state->hasSaves()) { restoreState(); } + if (!subPage) { //out->endPage(); } + while (res) { popResources(); } + if (state) { delete state; + state = NULL; } + if (clipHistory) { delete clipHistory; + clipHistory = NULL; } } @@ -460,7 +516,8 @@ void PdfParser::go(GBool /*topLevel*/) } } -void PdfParser::pushOperator(const char *name) { +void PdfParser::pushOperator(const char *name) +{ OpHistoryEntry *newEntry = new OpHistoryEntry; newEntry->name = name; newEntry->state = NULL; @@ -2086,13 +2143,19 @@ void PdfParser::doPatchMeshShFill(GfxPatchMeshShading *shading) { } void PdfParser::fillPatch(GfxPatch *patch, int nComps, int depth) { - GfxPatch patch00, patch01, patch10, patch11; + GfxPatch patch00 = blankPatch(); + GfxPatch patch01 = blankPatch(); + GfxPatch patch10 = blankPatch(); + GfxPatch patch11 = blankPatch(); #ifdef POPPLER_NEW_GFXPATCH - GfxColor color; + GfxColor color = {{0}}; #endif - double xx[4][8], yy[4][8]; - double xxm, yym; - double patchColorDelta = colorDeltas[pdfPatchMeshShading-1]; + double xx[4][8]; + double yy[4][8]; + double xxm; + double yym; + double patchColorDelta = colorDeltas[pdfPatchMeshShading - 1]; + int i; for (i = 0; i < nComps; ++i) { @@ -3463,9 +3526,7 @@ void PdfParser::popResources() { } void PdfParser::setDefaultApproximationPrecision() { - int i; - - for (i = 1; i <= pdfNumShadingTypes; ++i) { + for (int i = 1; i <= pdfNumShadingTypes; ++i) { setApproximationPrecision(i, defaultShadingColorDelta, defaultShadingMaxDepth); } } @@ -3484,19 +3545,18 @@ void PdfParser::setApproximationPrecision(int shadingType, double colorDelta, // ClipHistoryEntry //------------------------------------------------------------------------ -ClipHistoryEntry::ClipHistoryEntry(GfxPath *clipPathA, GfxClipType clipTypeA) { - if (clipPathA) { - clipPath = clipPathA->copy(); - } else { - clipPath = NULL; - } - clipType = clipTypeA; - saved = NULL; +ClipHistoryEntry::ClipHistoryEntry(GfxPath *clipPathA, GfxClipType clipTypeA) : + saved(NULL), + clipPath((clipPathA) ? clipPathA->copy() : NULL), + clipType(clipTypeA) +{ } -ClipHistoryEntry::~ClipHistoryEntry() { +ClipHistoryEntry::~ClipHistoryEntry() +{ if (clipPath) { delete clipPath; + clipPath = NULL; } } @@ -3510,6 +3570,7 @@ void ClipHistoryEntry::setClip(GfxPath *clipPathA, GfxClipType clipTypeA) { clipType = clipTypeA; } else { clipPath = NULL; + clipType = clipNormal; } } @@ -3526,7 +3587,7 @@ ClipHistoryEntry *ClipHistoryEntry::restore() { if (saved) { oldEntry = saved; saved = NULL; - delete this; + delete this; // TODO really should avoid deleting from inside. } else { oldEntry = this; } @@ -3540,6 +3601,7 @@ ClipHistoryEntry::ClipHistoryEntry(ClipHistoryEntry *other) { this->clipType = other->clipType; } else { this->clipPath = NULL; + this->clipType = clipNormal; } saved = NULL; } diff --git a/src/extension/internal/pdfinput/pdf-parser.h b/src/extension/internal/pdfinput/pdf-parser.h index a63d669c7..e28fecc2e 100644 --- a/src/extension/internal/pdfinput/pdf-parser.h +++ b/src/extension/internal/pdfinput/pdf-parser.h @@ -58,6 +58,8 @@ class AnnotBorderStyle; class PdfParser; +class ClipHistoryEntry; + //------------------------------------------------------------------------ #ifndef GFX_H @@ -101,34 +103,6 @@ struct OpHistoryEntry { }; //------------------------------------------------------------------------ -// ClipHistoryEntry -//------------------------------------------------------------------------ - -class ClipHistoryEntry { -public: - - ClipHistoryEntry(GfxPath *clipPath=NULL, GfxClipType clipType=clipNormal); - virtual ~ClipHistoryEntry(); - - // Manipulate clip path stack - ClipHistoryEntry *save(); - ClipHistoryEntry *restore(); - GBool hasSaves() { return saved != NULL; } - void setClip(GfxPath *newClipPath, GfxClipType newClipType=clipNormal); - GfxPath *getClipPath() { return clipPath; } - GfxClipType getClipType() { return clipType; } - -private: - - ClipHistoryEntry *saved; // next clip path on stack - - GfxPath *clipPath; // used as the path to be filled for an 'sh' operator - GfxClipType clipType; - - ClipHistoryEntry(ClipHistoryEntry *other); -}; - -//------------------------------------------------------------------------ // PdfParser //------------------------------------------------------------------------ diff --git a/src/extension/internal/vsd-input.cpp b/src/extension/internal/vsd-input.cpp index 2623d1ca7..25815e64f 100644 --- a/src/extension/internal/vsd-input.cpp +++ b/src/extension/internal/vsd-input.cpp @@ -24,7 +24,22 @@ #include <cstring> #include <libvisio/libvisio.h> -#include <libwpd-stream/libwpd-stream.h> + +// TODO: Drop this check when librevenge is widespread. +#if WITH_LIBVISIO01 + #include <librevenge-stream/librevenge-stream.h> + + using librevenge::RVNGString; + using librevenge::RVNGFileStream; + using librevenge::RVNGStringVector; +#else + #include <libwpd-stream/libwpd-stream.h> + + typedef WPXString RVNGString; + typedef WPXFileStream RVNGFileStream; + typedef libvisio::VSDStringVector RVNGStringVector; +#endif + #include <gtkmm/alignment.h> #include <gtkmm/comboboxtext.h> @@ -59,7 +74,7 @@ namespace Internal { class VsdImportDialog : public Gtk::Dialog { public: - VsdImportDialog(const std::vector<WPXString> &vec); + VsdImportDialog(const std::vector<RVNGString> &vec); virtual ~VsdImportDialog(); bool showDialog(); @@ -85,12 +100,12 @@ private: class Gtk::VBox * vbox2; class Gtk::Widget * _previewArea; - const std::vector<WPXString> &_vec; // Document to be imported + const std::vector<RVNGString> &_vec; // Document to be imported unsigned _current_page; // Current selected page int _preview_width, _preview_height; // Size of the preview area }; -VsdImportDialog::VsdImportDialog(const std::vector<WPXString> &vec) +VsdImportDialog::VsdImportDialog(const std::vector<RVNGString> &vec) : _vec(vec), _current_page(1) { int num_pages = _vec.size(); @@ -215,14 +230,20 @@ void VsdImportDialog::_setPreviewPage(unsigned page) SPDocument *VsdInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri) { - WPXFileStream input(uri); + RVNGFileStream input(uri); if (!libvisio::VisioDocument::isSupported(&input)) { return NULL; } - libvisio::VSDStringVector output; + RVNGStringVector output; +#if WITH_LIBVISIO01 + librevenge::RVNGSVGDrawingGenerator generator(output, "svg"); + + if (!libvisio::VisioDocument::parse(&input, &generator)) { +#else if (!libvisio::VisioDocument::generateSVG(&input, output)) { +#endif return NULL; } @@ -230,9 +251,9 @@ SPDocument *VsdInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * u return NULL; } - std::vector<WPXString> tmpSVGOutput; + std::vector<RVNGString> tmpSVGOutput; for (unsigned i=0; i<output.size(); ++i) { - WPXString tmpString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); + RVNGString tmpString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); tmpString.append(output[i]); tmpSVGOutput.push_back(tmpString); } diff --git a/src/extension/internal/wpg-input.cpp b/src/extension/internal/wpg-input.cpp index 14ff3ec77..12d86a99a 100644 --- a/src/extension/internal/wpg-input.cpp +++ b/src/extension/internal/wpg-input.cpp @@ -52,16 +52,24 @@ #include "util/units.h" #include <cstring> -// Take a guess and fallback to 0.1.x if no configure has run -#if !defined(WITH_LIBWPG01) && !defined(WITH_LIBWPG02) -#define WITH_LIBWPG01 1 +// Take a guess and fallback to 0.2.x if no configure has run +#if !defined(WITH_LIBWPG03) && !defined(WITH_LIBWPG02) +#define WITH_LIBWPG02 1 #endif #include "libwpg/libwpg.h" -#if WITH_LIBWPG01 -#include "libwpg/WPGStreamImplementation.h" -#elif WITH_LIBWPG02 -#include "libwpd-stream/libwpd-stream.h" +#if WITH_LIBWPG03 + #include <librevenge-stream/librevenge-stream.h> + + using librevenge::RVNGString; + using librevenge::RVNGFileStream; + using librevenge::RVNGInputStream; +#else + #include "libwpd-stream/libwpd-stream.h" + + typedef WPXString RVNGString; + typedef WPXFileStream RVNGFileStream; + typedef WPXInputStream RVNGInputStream; #endif using namespace libwpg; @@ -73,17 +81,15 @@ namespace Internal { SPDocument *WpgInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri) { -#if WITH_LIBWPG01 - WPXInputStream* input = new libwpg::WPGFileStream(uri); -#elif WITH_LIBWPG02 - WPXInputStream* input = new WPXFileStream(uri); -#endif + RVNGInputStream* input = new RVNGFileStream(uri); +#if WITH_LIBWPG03 + if (input->isStructured()) { + RVNGInputStream* olestream = input->getSubStreamByName("PerfectOffice_MAIN"); +#else if (input->isOLEStream()) { -#if WITH_LIBWPG01 - WPXInputStream* olestream = input->getDocumentOLEStream(); -#elif WITH_LIBWPG02 - WPXInputStream* olestream = input->getDocumentOLEStream("PerfectOffice_MAIN"); + RVNGInputStream* olestream = input->getDocumentOLEStream("PerfectOffice_MAIN"); #endif + if (olestream) { delete input; input = olestream; @@ -98,15 +104,24 @@ SPDocument *WpgInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * u return NULL; } -#if WITH_LIBWPG01 - libwpg::WPGString output; -#elif WITH_LIBWPG02 - WPXString output; -#endif +#if WITH_LIBWPG03 + librevenge::RVNGStringVector vec; + librevenge::RVNGSVGDrawingGenerator generator(vec, ""); + + if (!libwpg::WPGraphics::parse(input, &generator) || vec.empty() || vec[0].empty()) { + delete input; + return NULL; + } + + RVNGString output("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); + output.append(vec[0]); +#else + RVNGString output; if (!libwpg::WPGraphics::generateSVG(input, output)) { delete input; return NULL; } +#endif //printf("I've got a doc: \n%s", painter.document.c_str()); diff --git a/src/extension/param/color.cpp b/src/extension/param/color.cpp index 0a2598c56..5bd70359f 100644 --- a/src/extension/param/color.cpp +++ b/src/extension/param/color.cpp @@ -59,9 +59,10 @@ guint32 ParamColor::set( guint32 in, SPDocument * /*doc*/, Inkscape::XML::Node * return _value; } -ParamColor::ParamColor (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : - Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), - _changeSignal(0) +ParamColor::ParamColor(const gchar *name, const gchar *guitext, const gchar *desc, const Parameter::_scope_t scope, + bool gui_hidden, const gchar *gui_tip, Inkscape::Extension::Extension *ext, + Inkscape::XML::Node *xml) + : Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _value(0), _changeSignal(0) { const char * defaulthex = NULL; if (xml->firstChild() != NULL) @@ -75,7 +76,8 @@ ParamColor::ParamColor (const gchar * name, const gchar * guitext, const gchar * if (!paramval.empty()) defaulthex = paramval.data(); - _value = atoi(defaulthex); + if (defaulthex) + _value = atoi(defaulthex); } void ParamColor::string(std::string &string) const @@ -87,7 +89,7 @@ void ParamColor::string(std::string &string) const Gtk::Widget *ParamColor::get_widget( SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * changeSignal ) { - if (_gui_hidden) return NULL; + if (_gui_hidden) return NULL; _changeSignal = new sigc::signal<void>(*changeSignal); Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); diff --git a/src/extension/param/enum.cpp b/src/extension/param/enum.cpp index bb50c06e1..74b2a75ad 100644 --- a/src/extension/param/enum.cpp +++ b/src/extension/param/enum.cpp @@ -41,8 +41,8 @@ namespace Extension { class enumentry { public: enumentry (Glib::ustring &val, Glib::ustring &text) : - value(val), - guitext(text) + value(val), + guitext(text) {} Glib::ustring value; @@ -50,16 +50,19 @@ public: }; -ParamComboBox::ParamComboBox (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : - Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _indent(0) +ParamComboBox::ParamComboBox(const gchar *name, const gchar *guitext, const gchar *desc, + const Parameter::_scope_t scope, bool gui_hidden, const gchar *gui_tip, + Inkscape::Extension::Extension *ext, Inkscape::XML::Node *xml) + : Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext) + , _value(NULL) + , _indent(0) + , choices(NULL) { - choices = NULL; - _value = NULL; + const char *xmlval = NULL; // the value stored in XML - // Read XML tree to add enumeration items: - // printf("Extension Constructor: "); if (xml != NULL) { - for (Inkscape::XML::Node *node = xml->firstChild(); node; node = node->next()) { + // Read XML tree to add enumeration items: + for (Inkscape::XML::Node *node = xml->firstChild(); node; node = node->next()) { char const * chname = node->name(); if (!strcmp(chname, INKSCAPE_EXTENSION_NS "item") || !strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) { Glib::ustring newguitext, newvalue; @@ -69,8 +72,8 @@ ParamComboBox::ParamComboBox (const gchar * name, const gchar * guitext, const g } if (contents != NULL) { // don't translate when 'item' but do translate when '_item' - // NOTE: internal extensions use build_from_mem and don't need _item but - // still need to include if are to be localized + // NOTE: internal extensions use build_from_mem and don't need _item but + // still need to include if are to be localized if (!strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) { if (node->attribute("msgctxt") != NULL) { newguitext = g_dpgettext2(NULL, node->attribute("msgctxt"), contents); @@ -95,30 +98,28 @@ ParamComboBox::ParamComboBox (const gchar * name, const gchar * guitext, const g } } } - } - - // Initialize _value with the default value from xml - // for simplicity : default to the contents of the first xml-child - const char * defaultval = NULL; - if (xml->firstChild() && xml->firstChild()->firstChild()) { - defaultval = xml->firstChild()->attribute("value"); - } + + // Initialize _value with the default value from xml + // for simplicity : default to the contents of the first xml-child + if (xml->firstChild() && xml->firstChild()->firstChild()) { + xmlval = xml->firstChild()->attribute("value"); + } - const char * indent = xml->attribute("indent"); - if (indent != NULL) { - _indent = atoi(indent) * 12; + const char *indent = xml->attribute("indent"); + if (indent != NULL) { + _indent = atoi(indent) * 12; + } } gchar * pref_name = this->pref_name(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring paramval = prefs->getString(extension_pref_root + pref_name); + Glib::ustring paramval = prefs ? prefs->getString(extension_pref_root + pref_name) : ""; g_free(pref_name); if (!paramval.empty()) { - defaultval = paramval.data(); - } - if (defaultval != NULL) { - _value = g_strdup(defaultval); + _value = g_strdup(paramval.data()); + } else if (xmlval) { + _value = g_strdup(xmlval); } } |
