summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2010-08-03 02:05:53 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2010-08-03 02:05:53 +0000
commit4b9f09e52f05a19f93546c075c7a3fb7be322ed7 (patch)
treef286d8509d4d47e58f37cb0f34ce62009085fe4b /src
parentSecond half of image filter, probably not 100% correct (diff)
downloadinkscape-4b9f09e52f05a19f93546c075c7a3fb7be322ed7.tar.gz
inkscape-4b9f09e52f05a19f93546c075c7a3fb7be322ed7.zip
Handle preserveAspectRatio for images
(bzr r9508.1.41)
Diffstat (limited to 'src')
-rw-r--r--src/display/cairo-utils.cpp17
-rw-r--r--src/display/cairo-utils.h3
-rw-r--r--src/display/nr-arena-image.cpp179
-rw-r--r--src/display/nr-arena-image.h18
-rw-r--r--src/sp-image.cpp189
-rw-r--r--src/sp-image.h8
6 files changed, 209 insertions, 205 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index a05d28170..25a1e7988 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -288,8 +288,17 @@ ink_cairo_set_source_color(cairo_t *ct, SPColor const &c, double opacity)
cairo_set_source_rgba(ct, c.v.c[0], c.v.c[1], c.v.c[2], opacity);
}
-static void
-ink_cairo_convert_matrix(cairo_matrix_t &cm, Geom::Matrix const &m)
+void ink_matrix_to_2geom(Geom::Matrix &m, cairo_matrix_t const &cm)
+{
+ m[0] = cm.xx;
+ m[2] = cm.xy;
+ m[4] = cm.x0;
+ m[1] = cm.yx;
+ m[3] = cm.yy;
+ m[5] = cm.y0;
+}
+
+void ink_matrix_to_cairo(cairo_matrix_t &cm, Geom::Matrix const &m)
{
cm.xx = m[0];
cm.xy = m[2];
@@ -303,7 +312,7 @@ void
ink_cairo_transform(cairo_t *ct, Geom::Matrix const &m)
{
cairo_matrix_t cm;
- ink_cairo_convert_matrix(cm, m);
+ ink_matrix_to_cairo(cm, m);
cairo_transform(ct, &cm);
}
@@ -311,7 +320,7 @@ void
ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Matrix const &m)
{
cairo_matrix_t cm;
- ink_cairo_convert_matrix(cm, m);
+ ink_matrix_to_cairo(cm, m);
cairo_pattern_set_matrix(cp, &cm);
}
diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h
index 12fcd8b3d..5ac546067 100644
--- a/src/display/cairo-utils.h
+++ b/src/display/cairo-utils.h
@@ -84,6 +84,9 @@ void ink_cairo_transform(cairo_t *ct, Geom::Matrix const &m);
void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Matrix const &m);
void ink_cairo_set_source_argb32_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y);
+void ink_matrix_to_2geom(Geom::Matrix &, cairo_matrix_t const &);
+void ink_matrix_to_cairo(cairo_matrix_t &, Geom::Matrix const &);
+
cairo_surface_t *ink_cairo_surface_copy(cairo_surface_t *s);
cairo_surface_t *ink_cairo_surface_create_identical(cairo_surface_t *s);
cairo_surface_t *ink_cairo_surface_create_same_size(cairo_surface_t *s, cairo_content_t c);
diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp
index 422b691b7..066133dde 100644
--- a/src/display/nr-arena-image.cpp
+++ b/src/display/nr-arena-image.cpp
@@ -39,6 +39,7 @@ static void nr_arena_image_finalize (NRObject *object);
static unsigned int nr_arena_image_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
static unsigned int nr_arena_image_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
static NRArenaItem *nr_arena_image_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
+static Geom::Rect nr_arena_image_rect (NRArenaImage *image);
static NRArenaItemClass *parent_class;
@@ -80,12 +81,10 @@ static void
nr_arena_image_init (NRArenaImage *image)
{
image->pixbuf = NULL;
- image->x = image->y = 0.0;
- image->width = 256.0;
- image->height = 256.0;
-
- image->grid2px.setIdentity();
- image->px2grid.setIdentity();
+ image->ctm.setIdentity();
+ image->clipbox = Geom::Rect();
+ image->ox = image->oy = 0.0;
+ image->sx = image->sy = 1.0;
image->style = 0;
image->render_opacity = TRUE;
@@ -106,54 +105,24 @@ nr_arena_image_finalize (NRObject *object)
static unsigned int
nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned int /*state*/, unsigned int /*reset*/ )
{
- Geom::Matrix grid2px;
-
// clear old bbox
nr_arena_item_request_render(item);
NRArenaImage *image = NR_ARENA_IMAGE (item);
/* Copy affine */
- grid2px = gc->transform.inverse();
- double hscale, vscale; // todo: replace with Geom::Scale
- if (image->pixbuf) {
- hscale = gdk_pixbuf_get_width(image->pixbuf) / image->width;
- vscale = gdk_pixbuf_get_height(image->pixbuf) / image->height;
- } else {
- hscale = 1.0;
- vscale = 1.0;
- }
-
- image->grid2px[0] = grid2px[0] * hscale;
- image->grid2px[2] = grid2px[2] * hscale;
- image->grid2px[4] = grid2px[4] * hscale;
- image->grid2px[1] = grid2px[1] * vscale;
- image->grid2px[3] = grid2px[3] * vscale;
- image->grid2px[5] = grid2px[5] * vscale;
-
- image->grid2px[4] -= image->x * hscale;
- image->grid2px[5] -= image->y * vscale;
+ image->ctm = gc->transform;
/* Calculate bbox */
if (image->pixbuf) {
NRRect bbox;
- bbox.x0 = image->x;
- bbox.y0 = image->y;
- bbox.x1 = image->x + image->width;
- bbox.y1 = image->y + image->height;
+ Geom::Rect r = nr_arena_image_rect(image) * gc->transform;
- image->c00 = (Geom::Point(bbox.x0, bbox.y0) * gc->transform);
- image->c01 = (Geom::Point(bbox.x0, bbox.y1) * gc->transform);
- image->c10 = (Geom::Point(bbox.x1, bbox.y0) * gc->transform);
- image->c11 = (Geom::Point(bbox.x1, bbox.y1) * gc->transform);
-
- nr_rect_d_matrix_transform (&bbox, &bbox, gc->transform);
-
- item->bbox.x0 = static_cast<NR::ICoord>(floor(bbox.x0)); // Floor gives the coordinate in which the point resides
- item->bbox.y0 = static_cast<NR::ICoord>(floor(bbox.y0));
- item->bbox.x1 = static_cast<NR::ICoord>(ceil (bbox.x1)); // Ceil gives the first coordinate beyond the point
- item->bbox.y1 = static_cast<NR::ICoord>(ceil (bbox.y1));
+ item->bbox.x0 = floor(r.left()); // Floor gives the coordinate in which the point resides
+ item->bbox.y0 = floor(r.top());
+ item->bbox.x1 = ceil(r.right()); // Ceil gives the first coordinate beyond the point
+ item->bbox.y1 = ceil(r.bottom());
} else {
item->bbox.x0 = (int) gc->transform[4];
item->bbox.y0 = (int) gc->transform[5];
@@ -164,19 +133,12 @@ nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned
return NR_ARENA_ITEM_STATE_ALL;
}
-#define FBITS 12
-#define b2i (image->grid2px)
-
static unsigned int
nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int /*flags*/ )
{
if (!ct)
return item->state;
-#if 0
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- nr_arena_image_x_sample = prefs->getInt("/options/bitmapoversample/value", 1);
- nr_arena_image_y_sample = nr_arena_image_x_sample;
-#endif
+
bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
NRArenaImage *image = NR_ARENA_IMAGE (item);
@@ -188,13 +150,25 @@ nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
// of the pixbuf. Fix this in Cairo and/or GDK.
cairo_save(ct);
cairo_translate(ct, -area->x0, -area->y0);
+ ink_cairo_transform(ct, image->ctm);
+
+ cairo_new_path(ct);
+ cairo_rectangle(ct, image->clipbox.left(), image->clipbox.top(),
+ image->clipbox.width(), image->clipbox.height());
+ cairo_clip(ct);
+
+ cairo_translate(ct, image->ox, image->oy);
+ cairo_scale(ct, image->sx, image->sy);
+
gdk_cairo_set_source_pixbuf(ct, image->pixbuf, 0, 0);
- cairo_pattern_t *p = cairo_get_source(ct);
- ink_cairo_pattern_set_matrix(p, image->grid2px);
+ cairo_matrix_t tt;
+ Geom::Matrix total;
+ cairo_get_matrix(ct, &tt);
+ ink_matrix_to_2geom(total, tt);
- Geom::Matrix total = item->ctm * image->grid2px.inverse();
if (total.expansionX() > 1.0 || total.expansionY() > 1.0) {
+ cairo_pattern_t *p = cairo_get_source(ct);
cairo_pattern_set_filter(p, CAIRO_FILTER_NEAREST);
}
@@ -202,6 +176,11 @@ nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
cairo_restore(ct);
} else { // outline; draw a rect instead
+
+ cairo_save(ct);
+ cairo_translate(ct, -area->x0, -area->y0);
+ ink_cairo_transform(ct, image->ctm);
+
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
guint32 rgba = prefs->getInt("/options/wireframecolors/images", 0xff0000ff);
ink_cairo_set_source_rgba32(ct, rgba);
@@ -209,11 +188,12 @@ nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
cairo_set_line_width(ct, 0.5);
cairo_new_path(ct);
- Geom::Point shift(area->x0, area->y0);
- Geom::Point c00 = image->c00 - shift;
- Geom::Point c01 = image->c01 - shift;
- Geom::Point c11 = image->c11 - shift;
- Geom::Point c10 = image->c10 - shift;
+ Geom::Rect r = nr_arena_image_rect (image);
+
+ Geom::Point c00 = r.corner(0);
+ Geom::Point c01 = r.corner(3);
+ Geom::Point c11 = r.corner(2);
+ Geom::Point c10 = r.corner(1);
cairo_move_to (ct, c00[Geom::X], c00[Geom::Y]);
@@ -263,16 +243,22 @@ nr_arena_image_pick( NRArenaItem *item, Geom::Point p, double delta, unsigned in
bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
if (outline) {
+ Geom::Rect r = nr_arena_image_rect (image);
+
+ Geom::Point c00 = r.corner(0);
+ Geom::Point c01 = r.corner(3);
+ Geom::Point c11 = r.corner(2);
+ Geom::Point c10 = r.corner(1);
// frame
- if (distance_to_segment (p, image->c00, image->c10) < delta) return item;
- if (distance_to_segment (p, image->c10, image->c11) < delta) return item;
- if (distance_to_segment (p, image->c11, image->c01) < delta) return item;
- if (distance_to_segment (p, image->c01, image->c00) < delta) return item;
+ if (distance_to_segment (p, c00, c10) < delta) return item;
+ if (distance_to_segment (p, c10, c11) < delta) return item;
+ if (distance_to_segment (p, c11, c01) < delta) return item;
+ if (distance_to_segment (p, c01, c00) < delta) return item;
// diagonals
- if (distance_to_segment (p, image->c00, image->c11) < delta) return item;
- if (distance_to_segment (p, image->c10, image->c01) < delta) return item;
+ if (distance_to_segment (p, c00, c11) < delta) return item;
+ if (distance_to_segment (p, c10, c01) < delta) return item;
return NULL;
@@ -282,9 +268,17 @@ nr_arena_image_pick( NRArenaItem *item, Geom::Point p, double delta, unsigned in
int const width = gdk_pixbuf_get_width(image->pixbuf);
int const height = gdk_pixbuf_get_height(image->pixbuf);
int const rowstride = gdk_pixbuf_get_rowstride(image->pixbuf);
- Geom::Point tp = p * image->grid2px;
- int const ix = (int)(tp[Geom::X]);
- int const iy = (int)(tp[Geom::Y]);
+
+ Geom::Point tp = p * image->ctm.inverse();
+ Geom::Rect r = nr_arena_image_rect(image);
+
+ if (!r.contains(tp))
+ return NULL;
+
+ double vw = width * image->sx;
+ double vh = height * image->sy;
+ int ix = floor((tp[Geom::X] - image->ox) / vw * width);
+ int iy = floor((tp[Geom::Y] - image->oy) / vh * height);
if ((ix < 0) || (iy < 0) || (ix >= width) || (iy >= height))
return NULL;
@@ -295,6 +289,26 @@ nr_arena_image_pick( NRArenaItem *item, Geom::Point p, double delta, unsigned in
}
}
+Geom::Rect
+nr_arena_image_rect (NRArenaImage *image)
+{
+ Geom::Rect r = image->clipbox;
+
+ if (image->pixbuf) {
+ double pw = gdk_pixbuf_get_width(image->pixbuf);
+ double ph = gdk_pixbuf_get_height(image->pixbuf);
+ double vw = pw * image->sx;
+ double vh = ph * image->sy;
+ Geom::Point p(image->ox, image->oy);
+ Geom::Point wh(vw, vh);
+ Geom::Rect view(p, p+wh);
+ Geom::OptRect res = Geom::intersect(r, view);
+ r = res ? *res : r;
+ }
+
+ return r;
+}
+
/* Utility */
void
@@ -316,15 +330,36 @@ nr_arena_image_set_pixbuf (NRArenaImage *image, GdkPixbuf *pb)
}
void
-nr_arena_image_set_geometry (NRArenaImage *image, double x, double y, double width, double height)
+nr_arena_image_set_clipbox (NRArenaImage *image, Geom::Rect const &clip)
+{
+ nr_return_if_fail (image != NULL);
+ nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
+
+ image->clipbox = clip;
+
+ nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
+}
+
+void
+nr_arena_image_set_origin (NRArenaImage *image, Geom::Point const &origin)
+{
+ nr_return_if_fail (image != NULL);
+ nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
+
+ image->ox = origin[Geom::X];
+ image->oy = origin[Geom::Y];
+
+ nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
+}
+
+void
+nr_arena_image_set_scale (NRArenaImage *image, double sx, double sy)
{
nr_return_if_fail (image != NULL);
nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
- image->x = x;
- image->y = y;
- image->width = width;
- image->height = height;
+ image->sx = sx;
+ image->sy = sy;
nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
}
diff --git a/src/display/nr-arena-image.h b/src/display/nr-arena-image.h
index c2a3b805c..76ff23c29 100644
--- a/src/display/nr-arena-image.h
+++ b/src/display/nr-arena-image.h
@@ -14,6 +14,7 @@
*/
#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <2geom/rect.h>
#include "nr-arena-item.h"
#include "style.h"
@@ -26,14 +27,10 @@ NRType nr_arena_image_get_type (void);
struct NRArenaImage : public NRArenaItem {
GdkPixbuf *pixbuf;
- double x, y;
- double width, height;
-
- Geom::Point c00, c01, c11, c10; // all 4 corners of the image, for outline mode rect
-
- /* From GRID to PIXELS */
- Geom::Matrix grid2px;
- Geom::Matrix px2grid;
+ Geom::Matrix ctm;
+ Geom::Rect clipbox;
+ double ox, oy;
+ double sx, sy;
SPStyle *style;
@@ -49,9 +46,10 @@ struct NRArenaImageClass {
};
void nr_arena_image_set_pixbuf (NRArenaImage *image, GdkPixbuf *pb);
-void nr_arena_image_set_geometry (NRArenaImage *image, double x, double y, double width, double height);
void nr_arena_image_set_style (NRArenaImage *image, SPStyle *style);
-
+void nr_arena_image_set_clipbox (NRArenaImage *image, Geom::Rect const &clip);
+void nr_arena_image_set_origin (NRArenaImage *image, Geom::Point const &origin);
+void nr_arena_image_set_scale (NRArenaImage *image, double sx, double sy);
#endif
diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index 32ba3f021..b383512f5 100644
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
@@ -19,6 +19,7 @@
#include <png.h>
#include <cstring>
+#include <algorithm>
#include <string>
#include <libnr/nr-matrix-fns.h>
#include <libnr/nr-matrix-ops.h>
@@ -94,6 +95,7 @@ static void sp_image_set_curve(SPImage *image);
static GdkPixbuf *sp_image_repr_read_image( time_t& modTime, gchar*& pixPath, const gchar *href, const gchar *absref, const gchar *base );
static GdkPixbuf *sp_image_pixbuf_force_rgba (GdkPixbuf * pixbuf);
+static void sp_image_update_arenaitem (SPImage *img, NRArenaImage *ai);
static void sp_image_update_canvas_image (SPImage *image);
static GdkPixbuf * sp_image_repr_read_dataURI (const gchar * uri_data);
static GdkPixbuf * sp_image_repr_read_b64 (const gchar * uri_data);
@@ -609,15 +611,9 @@ static void sp_image_init( SPImage *image )
image->width.unset();
image->height.unset();
image->aspect_align = SP_ASPECT_NONE;
-
- image->trimx = 0;
- image->trimy = 0;
- image->trimwidth = 0;
- image->trimheight = 0;
- image->viewx = 0;
- image->viewy = 0;
- image->viewwidth = 0;
- image->viewheight = 0;
+ image->clipbox = Geom::Rect();
+ image->sx = image->sy = 1.0;
+ image->ox = image->oy = 0.0;
image->curve = NULL;
@@ -924,13 +920,33 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
}
}
}
+
+ if (image->pixbuf) {
+ /* fixme: We are slightly violating spec here (Lauris) */
+ if (!image->width._set) {
+ image->width.computed = gdk_pixbuf_get_width(image->pixbuf);
+ }
+ if (!image->height._set) {
+ image->height.computed = gdk_pixbuf_get_height(image->pixbuf);
+ }
+ }
+
+ Geom::Point p(image->x.computed, image->y.computed);
+ Geom::Point wh(image->width.computed, image->height.computed);
+ image->clipbox = Geom::Rect(p, p + wh);
+
+ image->ox = image->x.computed;
+ image->oy = image->y.computed;
+
+ int pixwidth = gdk_pixbuf_get_width (image->pixbuf);
+ int pixheight = gdk_pixbuf_get_height (image->pixbuf);
+
+ image->sx = image->width.computed / pixwidth;
+ image->sy = image->height.computed / pixheight;
+
// preserveAspectRatio calculate bounds / clipping rectangle -- EAF
if (image->pixbuf && (image->aspect_align != SP_ASPECT_NONE)) {
- int imagewidth, imageheight;
- double x,y;
-
- imagewidth = gdk_pixbuf_get_width (image->pixbuf);
- imageheight = gdk_pixbuf_get_height (image->pixbuf);
+ double x, y;
switch (image->aspect_align) {
case SP_ASPECT_XMIN_YMIN:
@@ -976,43 +992,19 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags)
}
if (image->aspect_clip == SP_ASPECT_SLICE) {
- image->viewx = image->x.computed;
- image->viewy = image->y.computed;
- image->viewwidth = image->width.computed;
- image->viewheight = image->height.computed;
- if ((imagewidth*image->height.computed)>(image->width.computed*imageheight)) {
- // Pixels aspect is wider than bounding box
- image->trimheight = imageheight;
- image->trimwidth = static_cast<int>(static_cast<double>(imageheight) * image->width.computed / image->height.computed);
- image->trimy = 0;
- image->trimx = static_cast<int>(static_cast<double>(imagewidth - image->trimwidth) * x);
- } else {
- // Pixels aspect is taller than bounding box
- image->trimwidth = imagewidth;
- image->trimheight = static_cast<int>(static_cast<double>(imagewidth) * image->height.computed / image->width.computed);
- image->trimx = 0;
- image->trimy = static_cast<int>(static_cast<double>(imageheight - image->trimheight) * y);
- }
+ double scale = std::max(image->sx, image->sy);
+ image->sx = scale;
+ image->sy = scale;
} else {
- // Otherwise, assume SP_ASPECT_MEET
- image->trimx = 0;
- image->trimy = 0;
- image->trimwidth = imagewidth;
- image->trimheight = imageheight;
- if ((imagewidth*image->height.computed)>(image->width.computed*imageheight)) {
- // Pixels aspect is wider than bounding boz
- image->viewwidth = image->width.computed;
- image->viewheight = image->viewwidth * imageheight / imagewidth;
- image->viewx=image->x.computed;
- image->viewy=(image->height.computed - image->viewheight) * y + image->y.computed;
- } else {
- // Pixels aspect is taller than bounding box
- image->viewheight = image->height.computed;
- image->viewwidth = image->viewheight * imagewidth / imageheight;
- image->viewy=image->y.computed;
- image->viewx=(image->width.computed - image->viewwidth) * x + image->x.computed;
- }
+ double scale = std::min(image->sx, image->sy);
+ image->sx = scale;
+ image->sy = scale;
}
+
+ double vw = pixwidth * image->sx;
+ double vh = pixheight * image->sy;
+ image->ox += x * (image->width.computed - vw);
+ image->oy += y * (image->height.computed - vh);
}
sp_image_update_canvas_image ((SPImage *) object);
}
@@ -1100,26 +1092,35 @@ sp_image_print (SPItem *item, SPPrintContext *ctx)
int rs = gdk_pixbuf_get_rowstride(image->pixbuf);
int pixskip = gdk_pixbuf_get_n_channels(image->pixbuf) * gdk_pixbuf_get_bits_per_sample(image->pixbuf) / 8;
- Geom::Matrix t;
if (image->aspect_align == SP_ASPECT_NONE) {
- /* fixme: (Lauris) */
+ Geom::Matrix t;
Geom::Translate tp(image->x.computed, image->y.computed);
Geom::Scale s(image->width.computed, -image->height.computed);
Geom::Translate ti(0.0, -1.0);
t = s * tp;
t = ti * t;
+ sp_print_image_R8G8B8A8_N(ctx, px, w, h, rs, &t, SP_OBJECT_STYLE (item));
} else { // preserveAspectRatio
- Geom::Translate tp(image->viewx, image->viewy);
- Geom::Scale s(image->viewwidth, -image->viewheight);
+ double vw = image->width.computed / image->sx;
+ double vh = image->height.computed / image->sy;
+
+ int trimwidth = std::min<int>(w, ceil(image->width.computed / vw * w));
+ int trimheight = std::min<int>(h, ceil(image->height.computed / vh * h));
+ int trimx = std::max<int>(0, floor((image->x.computed - image->ox) / vw * w));
+ int trimy = std::max<int>(0, floor((image->y.computed - image->oy) / vh * h));
+
+ double vx = std::max<double>(image->ox, image->x.computed);
+ double vy = std::max<double>(image->oy, image->y.computed);
+ double vcw = std::min<double>(image->width.computed, vw);
+ double vch = std::min<double>(image->height.computed, vh);
+
+ Geom::Matrix t;
+ Geom::Translate tp(vx, vy);
+ Geom::Scale s(vcw, -vch);
Geom::Translate ti(0.0, -1.0);
t = s * tp;
t = ti * t;
- }
-
- if (image->aspect_align == SP_ASPECT_NONE) {
- sp_print_image_R8G8B8A8_N(ctx, px, w, h, rs, &t, SP_OBJECT_STYLE (item));
- } else { // preserveAspectRatio
- sp_print_image_R8G8B8A8_N(ctx, px + image->trimx*pixskip + image->trimy*rs, image->trimwidth, image->trimheight, rs, &t, SP_OBJECT_STYLE(item));
+ sp_print_image_R8G8B8A8_N(ctx, px + trimx*pixskip + trimy*rs, trimwidth, trimheight, rs, &t, SP_OBJECT_STYLE(item));
}
}
}
@@ -1154,36 +1155,7 @@ sp_image_show (SPItem *item, NRArena *arena, unsigned int /*key*/, unsigned int
SPImage * image = SP_IMAGE(item);
NRArenaItem *ai = NRArenaImage::create(arena);
- if (image->pixbuf) {
- nr_arena_image_set_pixbuf(NR_ARENA_IMAGE(ai), image->pixbuf);
-#if 0
- int pixskip = gdk_pixbuf_get_n_channels(image->pixbuf) * gdk_pixbuf_get_bits_per_sample(image->pixbuf) / 8;
- int rs = gdk_pixbuf_get_rowstride(image->pixbuf);
- nr_arena_image_set_style(NR_ARENA_IMAGE(ai), SP_OBJECT_STYLE(SP_OBJECT(item)));
- if (image->aspect_align == SP_ASPECT_NONE) {
- nr_arena_image_set_pixels(NR_ARENA_IMAGE(ai),
- gdk_pixbuf_get_pixels(image->pixbuf),
- gdk_pixbuf_get_width(image->pixbuf),
- gdk_pixbuf_get_height(image->pixbuf),
- rs);
- } else { // preserveAspectRatio
- nr_arena_image_set_pixels(NR_ARENA_IMAGE(ai),
- gdk_pixbuf_get_pixels(image->pixbuf) + image->trimx*pixskip + image->trimy*rs,
- image->trimwidth,
- image->trimheight,
- rs);
- }
-#endif
- } else {
- nr_arena_image_set_pixbuf(NR_ARENA_IMAGE(ai), NULL);
- }
-
- // TODO: reenable preserveAspectRatio
- //if (image->aspect_align == SP_ASPECT_NONE) {
- nr_arena_image_set_geometry(NR_ARENA_IMAGE(ai), image->x.computed, image->y.computed, image->width.computed, image->height.computed);
- //} else { // preserveAspectRatio
- // nr_arena_image_set_geometry(NR_ARENA_IMAGE(ai), image->viewx, image->viewy, image->viewwidth, image->viewheight);
- //}
+ sp_image_update_arenaitem(image, NR_ARENA_IMAGE(ai));
return ai;
}
@@ -1296,39 +1268,22 @@ sp_image_pixbuf_force_rgba (GdkPixbuf * pixbuf)
/* We assert that realpixbuf is either NULL or identical size to pixbuf */
static void
+sp_image_update_arenaitem (SPImage *image, NRArenaImage *ai)
+{
+ nr_arena_image_set_style(ai, SP_OBJECT_STYLE(SP_OBJECT(image)));
+ nr_arena_image_set_pixbuf(ai, image->pixbuf);
+ nr_arena_image_set_origin(ai, Geom::Point(image->ox, image->oy));
+ nr_arena_image_set_scale(ai, image->sx, image->sy);
+ nr_arena_image_set_clipbox(ai, image->clipbox);
+}
+
+static void
sp_image_update_canvas_image (SPImage *image)
{
SPItem *item = SP_ITEM(image);
- if (image->pixbuf) {
- /* fixme: We are slightly violating spec here (Lauris) */
- if (!image->width._set) {
- image->width.computed = gdk_pixbuf_get_width(image->pixbuf);
- }
- if (!image->height._set) {
- image->height.computed = gdk_pixbuf_get_height(image->pixbuf);
- }
- }
-
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- nr_arena_image_set_style(NR_ARENA_IMAGE(v->arenaitem), SP_OBJECT_STYLE(SP_OBJECT(image)));
- // TODO: reenable preserveAspectRatio
- //if (image->aspect_align == SP_ASPECT_NONE) {
- nr_arena_image_set_pixbuf(NR_ARENA_IMAGE(v->arenaitem),
- image->pixbuf);
- nr_arena_image_set_geometry(NR_ARENA_IMAGE(v->arenaitem),
- image->x.computed, image->y.computed,
- image->width.computed, image->height.computed);
- /*} else { // preserveAspectRatio
- nr_arena_image_set_pixels(NR_ARENA_IMAGE(v->arenaitem),
- gdk_pixbuf_get_pixels(image->pixbuf) + image->trimx*pixskip + image->trimy*rs,
- image->trimwidth,
- image->trimheight,
- rs);
- nr_arena_image_set_geometry(NR_ARENA_IMAGE(v->arenaitem),
- image->viewx, image->viewy,
- image->viewwidth, image->viewheight);
- }*/
+ sp_image_update_arenaitem(image, NR_ARENA_IMAGE(v->arenaitem));
}
}
diff --git a/src/sp-image.h b/src/sp-image.h
index 172cd7118..2d744fb12 100644
--- a/src/sp-image.h
+++ b/src/sp-image.h
@@ -39,12 +39,16 @@ struct SPImage : public SPItem {
SVGLength width;
SVGLength height;
+ Geom::Rect clipbox;
+ double sx, sy;
+ double ox, oy;
+
// Added by EAF
/* preserveAspectRatio */
unsigned int aspect_align : 4;
unsigned int aspect_clip : 1;
- int trimx, trimy, trimwidth, trimheight;
- double viewx, viewy, viewwidth, viewheight;
+ //int trimx, trimy, trimwidth, trimheight;
+ //double viewx, viewy, viewwidth, viewheight;
SPCurve *curve; // This curve is at the image's boundary for snapping