summaryrefslogtreecommitdiffstats
path: root/src/helper/pixbuf-ops.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:50:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:50:49 +0000
commitc853ffb5b2f75f5a889ed2e3ef89b818a736e87a (patch)
tree7d13a0883bb7936b84d6ecdd7bc332b41ed04bee /src/helper/pixbuf-ops.cpp
parentInitial commit. (diff)
downloadinkscape-c853ffb5b2f75f5a889ed2e3ef89b818a736e87a.tar.xz
inkscape-c853ffb5b2f75f5a889ed2e3ef89b818a736e87a.zip
Adding upstream version 1.3+ds.upstream/1.3+dsupstream
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.cpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp
new file mode 100644
index 0000000..82d85e9
--- /dev/null
+++ b/src/helper/pixbuf-ops.cpp
@@ -0,0 +1,131 @@
+// 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 <gdk/gdk.h>
+
+#include "helper/pixbuf-ops.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 "util/scope_exit.h"
+#include "inkscape.h"
+
+/**
+ Generates a bitmap from given items. The bitmap is stored in RAM and not written to file.
+ @param document Inkscape document.
+ @param area Export area in document units.
+ @param dpi Resolution.
+ @param items Vector of pointers to SPItems to export. Export all items if empty.
+ @param opaque Set items opacity to 1 (used by Cairo renderer for filtered objects rendered as bitmaps).
+ @return The created GdkPixbuf structure or nullptr if rendering failed.
+*/
+Inkscape::Pixbuf *sp_generate_internal_bitmap(SPDocument *document,
+ Geom::Rect const &area,
+ double dpi,
+ std::vector<SPItem *> items,
+ bool opaque,
+ uint32_t const *checkerboard_color,
+ double device_scale)
+{
+ // Geometry
+ if (area.hasZeroArea()) {
+ return nullptr;
+ }
+
+ Geom::Point origin = area.min();
+ double scale_factor = Inkscape::Util::Quantity::convert(dpi, "px", "in");
+ Geom::Affine affine = Geom::Translate(-origin) * Geom::Scale (scale_factor, scale_factor);
+
+ int width = std::ceil(scale_factor * area.width());
+ int height = std::ceil(scale_factor * area.height());
+
+ // Document
+ document->ensureUpToDate();
+ unsigned dkey = SPItem::display_key_new(1);
+
+ // Drawing
+ Inkscape::Drawing drawing; // New drawing for offscreen rendering.
+ drawing.setRoot(document->getRoot()->invoke_show(drawing, dkey, SP_ITEM_SHOW_DISPLAY));
+ auto invoke_hide_guard = scope_exit([&] { document->getRoot()->invoke_hide(dkey); });
+ drawing.root()->setTransform(affine);
+ drawing.setExact(); // Maximum quality for blurs.
+
+ // 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 (!items.empty()) {
+ document->getRoot()->invoke_hide_except(dkey, items);
+ }
+
+ auto final_area = Geom::IntRect::from_xywh(0, 0, width, height);
+ drawing.update(final_area);
+
+ if (opaque) {
+ // Required by sp_asbitmap_render().
+ for (auto item : items) {
+ if (item->get_arenaitem(dkey)) {
+ item->get_arenaitem(dkey)->setOpacity(1.0);
+ }
+ }
+ }
+
+ // Rendering
+ cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+
+ if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
+ 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);
+ return nullptr;
+ }
+
+ Inkscape::DrawingContext dc(surface, Geom::Point(0, 0));
+
+ if (checkerboard_color) {
+ auto pattern = ink_cairo_pattern_create_checkerboard(*checkerboard_color);
+ dc.save();
+ dc.transform(Geom::Scale(device_scale));
+ dc.setOperator(CAIRO_OPERATOR_SOURCE);
+ dc.setSource(pattern);
+ dc.paint();
+ dc.restore();
+ cairo_pattern_destroy(pattern);
+ }
+
+ // render items
+ drawing.render(dc, final_area, Inkscape::DrawingItem::RENDER_BYPASS_CACHE);
+
+ if (device_scale != 1.0) {
+ cairo_surface_set_device_scale(surface, device_scale, device_scale);
+ }
+
+ return new Inkscape::Pixbuf(surface);
+}
+
+/*
+ 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 :