871fccc39b870543073d7015a9d8c701252b68f9joncruz/*
871fccc39b870543073d7015a9d8c701252b68f9joncruz * Helpers for SPItem -> gdk_pixbuf related stuff
871fccc39b870543073d7015a9d8c701252b68f9joncruz *
871fccc39b870543073d7015a9d8c701252b68f9joncruz * Authors:
871fccc39b870543073d7015a9d8c701252b68f9joncruz * John Cliff <simarilius@yahoo.com>
9dc68827cbd515262ecb8d5ae8547d9e82c72e00Jon A. Cruz * Jon A. Cruz <jon@joncruz.org>
9dc68827cbd515262ecb8d5ae8547d9e82c72e00Jon A. Cruz * Abhishek Sharma
871fccc39b870543073d7015a9d8c701252b68f9joncruz *
871fccc39b870543073d7015a9d8c701252b68f9joncruz * Copyright (C) 2008 John Cliff
871fccc39b870543073d7015a9d8c701252b68f9joncruz *
871fccc39b870543073d7015a9d8c701252b68f9joncruz * Released under GNU GPL, read the file 'COPYING' for more information
871fccc39b870543073d7015a9d8c701252b68f9joncruz */
871fccc39b870543073d7015a9d8c701252b68f9joncruz
871fccc39b870543073d7015a9d8c701252b68f9joncruz#ifdef HAVE_CONFIG_H
871fccc39b870543073d7015a9d8c701252b68f9joncruz# include "config.h"
871fccc39b870543073d7015a9d8c701252b68f9joncruz#endif
871fccc39b870543073d7015a9d8c701252b68f9joncruz
871fccc39b870543073d7015a9d8c701252b68f9joncruz#include <png.h>
e4b626a9206e4fabf4fc7601dfa14b133c2a27f0Krzysztof Kosiński#include <boost/scoped_ptr.hpp>
ef494f75ca77f36881ad59e94263a07c146c3649Krzysztof Kosiński#include <2geom/transforms.h>
871fccc39b870543073d7015a9d8c701252b68f9joncruz
cee084c8a6394fa638af2629ca8670ca138ed706Liam P. White#include "ui/interface.h"
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński#include "helper/png-write.h"
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński#include "display/cairo-utils.h"
3a3365c39fe3932d005ae1aa4324ef48606f5e18Krzysztof Kosiński#include "display/drawing.h"
ed422cc32e064690397f1e4aeb526ebda5fbca77Krzysztof Kosiński#include "display/drawing-context.h"
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński#include "display/drawing-item.h"
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński#include "document.h"
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński#include "sp-item.h"
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński#include "sp-root.h"
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński#include "sp-use.h"
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński#include "sp-defs.h"
c751b68e56ace7b9d649ee20b7f25ed1f65922e3Matthew Petroff#include "util/units.h"
871fccc39b870543073d7015a9d8c701252b68f9joncruz
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński#include "helper/pixbuf-ops.h"
871fccc39b870543073d7015a9d8c701252b68f9joncruz
f4d474ff2d58b3d32dacd5feed0c164e8df4936cJon A. Cruz// TODO look for copy-n-paste duplication of this function:
871fccc39b870543073d7015a9d8c701252b68f9joncruz/**
871fccc39b870543073d7015a9d8c701252b68f9joncruz * Hide all items that are not listed in list, recursively, skipping groups and defs.
871fccc39b870543073d7015a9d8c701252b68f9joncruz */
9dc68827cbd515262ecb8d5ae8547d9e82c72e00Jon A. Cruzstatic void hide_other_items_recursively(SPObject *o, GSList *list, unsigned dkey)
871fccc39b870543073d7015a9d8c701252b68f9joncruz{
f4d474ff2d58b3d32dacd5feed0c164e8df4936cJon A. Cruz SPItem *item = dynamic_cast<SPItem *>(o);
f4d474ff2d58b3d32dacd5feed0c164e8df4936cJon A. Cruz if ( item
f4d474ff2d58b3d32dacd5feed0c164e8df4936cJon A. Cruz && !dynamic_cast<SPDefs *>(item)
f4d474ff2d58b3d32dacd5feed0c164e8df4936cJon A. Cruz && !dynamic_cast<SPRoot *>(item)
f4d474ff2d58b3d32dacd5feed0c164e8df4936cJon A. Cruz && !dynamic_cast<SPGroup *>(item)
f4d474ff2d58b3d32dacd5feed0c164e8df4936cJon A. Cruz && !dynamic_cast<SPUse *>(item)
871fccc39b870543073d7015a9d8c701252b68f9joncruz && !g_slist_find(list, o) )
871fccc39b870543073d7015a9d8c701252b68f9joncruz {
f4d474ff2d58b3d32dacd5feed0c164e8df4936cJon A. Cruz item->invoke_hide(dkey);
871fccc39b870543073d7015a9d8c701252b68f9joncruz }
871fccc39b870543073d7015a9d8c701252b68f9joncruz
871fccc39b870543073d7015a9d8c701252b68f9joncruz // recurse
871fccc39b870543073d7015a9d8c701252b68f9joncruz if (!g_slist_find(list, o)) {
9dc68827cbd515262ecb8d5ae8547d9e82c72e00Jon A. Cruz for ( SPObject *child = o->firstChild() ; child; child = child->getNext() ) {
871fccc39b870543073d7015a9d8c701252b68f9joncruz hide_other_items_recursively(child, list, dkey);
871fccc39b870543073d7015a9d8c701252b68f9joncruz }
871fccc39b870543073d7015a9d8c701252b68f9joncruz }
871fccc39b870543073d7015a9d8c701252b68f9joncruz}
871fccc39b870543073d7015a9d8c701252b68f9joncruz
871fccc39b870543073d7015a9d8c701252b68f9joncruz
871fccc39b870543073d7015a9d8c701252b68f9joncruz// The following is a mutation of the flood fill code, the marker preview, and random other samplings.
871fccc39b870543073d7015a9d8c701252b68f9joncruz// The dpi settings dont do anything yet, but I want them to, and was wanting to keep reasonably close
871fccc39b870543073d7015a9d8c701252b68f9joncruz// to the call for the interface to the png writing.
871fccc39b870543073d7015a9d8c701252b68f9joncruz
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruzbool sp_export_jpg_file(SPDocument *doc, gchar const *filename,
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruz double x0, double y0, double x1, double y1,
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruz unsigned width, unsigned height, double xdpi, double ydpi,
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruz unsigned long bgcolor, double quality,GSList *items)
871fccc39b870543073d7015a9d8c701252b68f9joncruz{
e4b626a9206e4fabf4fc7601dfa14b133c2a27f0Krzysztof Kosiński boost::scoped_ptr<Inkscape::Pixbuf> pixbuf(
e4b626a9206e4fabf4fc7601dfa14b133c2a27f0Krzysztof Kosiński sp_generate_internal_bitmap(doc, filename, x0, y0, x1, y1,
e4b626a9206e4fabf4fc7601dfa14b133c2a27f0Krzysztof Kosiński width, height, xdpi, ydpi, bgcolor, items));
871fccc39b870543073d7015a9d8c701252b68f9joncruz
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruz gchar c[32];
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruz g_snprintf(c, 32, "%f", quality);
e4b626a9206e4fabf4fc7601dfa14b133c2a27f0Krzysztof Kosiński gboolean saved = gdk_pixbuf_save(pixbuf->getPixbufRaw(), filename, "jpeg", NULL, "quality", c, NULL);
c9e359471045b3567f4abe4de1df638db67fa8aeKris
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruz return saved;
871fccc39b870543073d7015a9d8c701252b68f9joncruz}
871fccc39b870543073d7015a9d8c701252b68f9joncruz
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib/**
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib generates a bitmap from given items
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib the bitmap is stored in RAM and not written to file
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib @param x0
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib @param y0
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib @param x1
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib @param y1
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib @param width
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib @param height
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib @param xdpi
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib @param ydpi
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib @return the created GdkPixbuf structure or NULL if no memory is allocable
6c28c26c5dc911196633a0c332b56f712085fa3ftheAdib*/
e4b626a9206e4fabf4fc7601dfa14b133c2a27f0Krzysztof KosińskiInkscape::Pixbuf *sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/,
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruz double x0, double y0, double x1, double y1,
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruz unsigned width, unsigned height, double xdpi, double ydpi,
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruz unsigned long /*bgcolor*/,
e0391459c8e12f29d9cc62f9631da59223dc11faJon A. Cruz GSList *items_only)
871fccc39b870543073d7015a9d8c701252b68f9joncruz
871fccc39b870543073d7015a9d8c701252b68f9joncruz{
e375f7b0799058a61b78199acdbc9b82696f1ae2Krzysztof Kosiński if (width == 0 || height == 0) return NULL;
871fccc39b870543073d7015a9d8c701252b68f9joncruz
e4b626a9206e4fabf4fc7601dfa14b133c2a27f0Krzysztof Kosiński Inkscape::Pixbuf *inkpb = NULL;
3a3365c39fe3932d005ae1aa4324ef48606f5e18Krzysztof Kosiński /* Create new drawing for offscreen rendering*/
3a3365c39fe3932d005ae1aa4324ef48606f5e18Krzysztof Kosiński Inkscape::Drawing drawing;
3a3365c39fe3932d005ae1aa4324ef48606f5e18Krzysztof Kosiński drawing.setExact(true);
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński unsigned dkey = SPItem::display_key_new(1);
871fccc39b870543073d7015a9d8c701252b68f9joncruz
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński doc->ensureUpToDate();
871fccc39b870543073d7015a9d8c701252b68f9joncruz
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński Geom::Rect screen=Geom::Rect(Geom::Point(x0,y0), Geom::Point(x1, y1));
871fccc39b870543073d7015a9d8c701252b68f9joncruz
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński double padding = 1.0;
871fccc39b870543073d7015a9d8c701252b68f9joncruz
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński Geom::Point origin(screen.min()[Geom::X],
d16495c17bbc27ff37e18ea3eb61f6b07448152aMatthew Petroff doc->getHeight().value("px") - screen[Geom::Y].extent() - screen.min()[Geom::Y]);
871fccc39b870543073d7015a9d8c701252b68f9joncruz
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński origin[Geom::X] = origin[Geom::X] + (screen[Geom::X].extent() * ((1 - padding) / 2));
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński origin[Geom::Y] = origin[Geom::Y] + (screen[Geom::Y].extent() * ((1 - padding) / 2));
871fccc39b870543073d7015a9d8c701252b68f9joncruz
35636e0c762d50c37515a072b12bdc0197afd24cMatthew Petroff Geom::Scale scale(Inkscape::Util::Quantity::convert(xdpi, "px", "in"), Inkscape::Util::Quantity::convert(ydpi, "px", "in"));
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński Geom::Affine affine = scale * Geom::Translate(-origin * scale);
871fccc39b870543073d7015a9d8c701252b68f9joncruz
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński /* Create ArenaItems and set transform */
3a3365c39fe3932d005ae1aa4324ef48606f5e18Krzysztof Kosiński Inkscape::DrawingItem *root = doc->getRoot()->invoke_show( drawing, dkey, SP_ITEM_SHOW_DISPLAY);
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński root->setTransform(affine);
3a3365c39fe3932d005ae1aa4324ef48606f5e18Krzysztof Kosiński drawing.setRoot(root);
871fccc39b870543073d7015a9d8c701252b68f9joncruz
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński // We show all and then hide all items we don't want, instead of showing only requested items,
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński // because that would not work if the shown item references something in defs
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński if (items_only) {
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński hide_other_items_recursively(doc->getRoot(), items_only, dkey);
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński }
871fccc39b870543073d7015a9d8c701252b68f9joncruz
ed422cc32e064690397f1e4aeb526ebda5fbca77Krzysztof Kosiński Geom::IntRect final_bbox = Geom::IntRect::from_xywh(0, 0, width, height);
3a3365c39fe3932d005ae1aa4324ef48606f5e18Krzysztof Kosiński drawing.update(final_bbox);
871fccc39b870543073d7015a9d8c701252b68f9joncruz
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
871fccc39b870543073d7015a9d8c701252b68f9joncruz
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński if (cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS) {
58ba7163a5ee19414f3357a7c84d93989cb7498cmathog Inkscape::DrawingContext dc(surface, Geom::Point(0,0));
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński // render items
58ba7163a5ee19414f3357a7c84d93989cb7498cmathog drawing.render(dc, final_bbox, Inkscape::DrawingItem::RENDER_BYPASS_CACHE);
871fccc39b870543073d7015a9d8c701252b68f9joncruz
e4b626a9206e4fabf4fc7601dfa14b133c2a27f0Krzysztof Kosiński inkpb = new Inkscape::Pixbuf(surface);
00cd8cdd29c4bcef32835fb75ed803cefeec6d10theAdib }
00cd8cdd29c4bcef32835fb75ed803cefeec6d10theAdib else
00cd8cdd29c4bcef32835fb75ed803cefeec6d10theAdib {
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński long long size = (long long) height * (long long) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
c97348400fa86585534b463cc1a3f70ecd9f4c72scislac g_warning("sp_generate_internal_bitmap: not enough memory to create pixel buffer. Need %lld.", size);
ec3cef722801728184cc83bd46740d0fdcadf908Krzysztof Kosiński cairo_surface_destroy(surface);
00cd8cdd29c4bcef32835fb75ed803cefeec6d10theAdib }
3a3365c39fe3932d005ae1aa4324ef48606f5e18Krzysztof Kosiński doc->getRoot()->invoke_hide(dkey);
f71fc608082707d67d010ff860df1a7df67da884buliabyak
871fccc39b870543073d7015a9d8c701252b68f9joncruz// gdk_pixbuf_save (pixbuf, "C:\\temp\\internal.jpg", "jpeg", NULL, "quality","100", NULL);
871fccc39b870543073d7015a9d8c701252b68f9joncruz
e4b626a9206e4fabf4fc7601dfa14b133c2a27f0Krzysztof Kosiński return inkpb;
871fccc39b870543073d7015a9d8c701252b68f9joncruz}
871fccc39b870543073d7015a9d8c701252b68f9joncruz
871fccc39b870543073d7015a9d8c701252b68f9joncruz/*
871fccc39b870543073d7015a9d8c701252b68f9joncruz Local Variables:
871fccc39b870543073d7015a9d8c701252b68f9joncruz mode:c++
871fccc39b870543073d7015a9d8c701252b68f9joncruz c-file-style:"stroustrup"
871fccc39b870543073d7015a9d8c701252b68f9joncruz c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
871fccc39b870543073d7015a9d8c701252b68f9joncruz indent-tabs-mode:nil
871fccc39b870543073d7015a9d8c701252b68f9joncruz fill-column:99
871fccc39b870543073d7015a9d8c701252b68f9joncruz End:
871fccc39b870543073d7015a9d8c701252b68f9joncruz*/
a4030d5ca449e7e384bc699cd249ee704faaeab0Chris Morgan// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :