diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:29:01 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:29:01 +0000 |
commit | 35a96bde514a8897f6f0fcc41c5833bf63df2e2a (patch) | |
tree | 657d15a03cc46bd099fc2c6546a7a4ad43815d9f /src/helper/pixbuf-ops.cpp | |
parent | Initial commit. (diff) | |
download | inkscape-35a96bde514a8897f6f0fcc41c5833bf63df2e2a.tar.xz inkscape-35a96bde514a8897f6f0fcc41c5833bf63df2e2a.zip |
Adding upstream version 1.0.2.upstream/1.0.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/helper/pixbuf-ops.cpp')
-rw-r--r-- | src/helper/pixbuf-ops.cpp | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp new file mode 100644 index 0000000..4c5b969 --- /dev/null +++ b/src/helper/pixbuf-ops.cpp @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Helpers for SPItem -> gdk_pixbuf related stuff + * + * Authors: + * John Cliff <simarilius@yahoo.com> + * Jon A. Cruz <jon@joncruz.org> + * Abhishek Sharma + * + * Copyright (C) 2008 John Cliff + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <2geom/transforms.h> + +#include "helper/png-write.h" +#include "display/cairo-utils.h" +#include "display/drawing.h" +#include "display/drawing-context.h" +#include "document.h" +#include "object/sp-root.h" +#include "object/sp-defs.h" +#include "object/sp-use.h" +#include "util/units.h" +#include "inkscape.h" + +#include "helper/pixbuf-ops.h" + +#include <gdk/gdk.h> + +// TODO look for copy-n-paste duplication of this function: +/** + * Hide all items except @item, recursively, skipping groups and defs. + */ +static void hide_other_items_recursively(SPObject *o, SPItem *i, unsigned dkey) +{ + SPItem *item = dynamic_cast<SPItem *>(o); + if ( item + && !dynamic_cast<SPDefs *>(item) + && !dynamic_cast<SPRoot *>(item) + && !dynamic_cast<SPGroup *>(item) + && !dynamic_cast<SPUse *>(item) + && (i != o) ) + { + item->invoke_hide(dkey); + } + + // recurse + if (i != o) { + for (auto& child: o->children) { + hide_other_items_recursively(&child, i, dkey); + } + } +} + + +// The following is a mutation of the flood fill code, the marker preview, and random other samplings. +// The dpi settings don't do anything yet, but I want them to, and was wanting to keep reasonably close +// to the call for the interface to the png writing. + +bool sp_export_jpg_file(SPDocument *doc, gchar const *filename, + double x0, double y0, double x1, double y1, + unsigned width, unsigned height, double xdpi, double ydpi, + unsigned long bgcolor, double quality, SPItem* item) +{ + std::unique_ptr<Inkscape::Pixbuf> pixbuf( + sp_generate_internal_bitmap(doc, filename, x0, y0, x1, y1, + width, height, xdpi, ydpi, bgcolor, item)); + + gchar c[32]; + g_snprintf(c, 32, "%f", quality); + gboolean saved = gdk_pixbuf_save(pixbuf->getPixbufRaw(), filename, "jpeg", nullptr, "quality", c, NULL); + + return saved; +} + + +/** + generates a bitmap from given items + the bitmap is stored in RAM and not written to file + @param x0 area left in document coordinates + @param y0 area top in document coordinates + @param x1 area right in document coordinates + @param y1 area bottom in document coordinates + @param width bitmap width in pixels + @param height bitmap height in pixels + @param xdpi + @param ydpi + @return the created GdkPixbuf structure or NULL if no memory is allocable +*/ +Inkscape::Pixbuf *sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/, + double x0, double y0, double x1, double y1, + unsigned width, unsigned height, double xdpi, double ydpi, + unsigned long /*bgcolor*/, + SPItem *item_only) + +{ + if (width == 0 || height == 0) return nullptr; + + Inkscape::Pixbuf *inkpb = nullptr; + /* Create new drawing for offscreen rendering*/ + Inkscape::Drawing drawing; + drawing.setExact(true); + unsigned dkey = SPItem::display_key_new(1); + + doc->ensureUpToDate(); + + Geom::Rect screen=Geom::Rect(Geom::Point(x0,y0), Geom::Point(x1, y1)); + + Geom::Point origin = screen.min(); + + Geom::Scale scale(Inkscape::Util::Quantity::convert(xdpi, "px", "in"), Inkscape::Util::Quantity::convert(ydpi, "px", "in")); + Geom::Affine affine = scale * Geom::Translate(-origin * scale); + + /* Create ArenaItems and set transform */ + Inkscape::DrawingItem *root = doc->getRoot()->invoke_show( drawing, dkey, SP_ITEM_SHOW_DISPLAY); + root->setTransform(affine); + drawing.setRoot(root); + + // We show all and then hide all items we don't want, instead of showing only requested items, + // because that would not work if the shown item references something in defs + if (item_only) { + hide_other_items_recursively(doc->getRoot(), item_only, dkey); + // TODO: The following line forces 100% opacity as required by sp_asbitmap_render() in cairo-renderer.cpp + // Make it conditional if 'item_only' is ever used by other callers which need to retain opacity + item_only->get_arenaitem(dkey)->setOpacity(1.0); + } + + Geom::IntRect final_bbox = Geom::IntRect::from_xywh(0, 0, width, height); + drawing.update(final_bbox); + + cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + + if (cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS) { + Inkscape::DrawingContext dc(surface, Geom::Point(0,0)); + + // render items + drawing.render(dc, final_bbox, Inkscape::DrawingItem::RENDER_BYPASS_CACHE); + + inkpb = new Inkscape::Pixbuf(surface); + } + else + { + long long size = (long long) height * (long long) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); + g_warning("sp_generate_internal_bitmap: not enough memory to create pixel buffer. Need %lld.", size); + cairo_surface_destroy(surface); + } + doc->getRoot()->invoke_hide(dkey); + +// gdk_pixbuf_save (pixbuf, "C:\\temp\\internal.jpg", "jpeg", NULL, "quality","100", NULL); + + return inkpb; +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |