Hello again, I posted this patch to sourceforge. And I've attached it here also. It implements preserveAspectRatio rendering functionality as per SVG 1.1 spec with overflow assumed to be hidden. It currently has no human interface outside of the built in XML editor. Anybody care to check this out? Also, the attached file is just the piped output from 'cvs diff', is this acceptable?
Edward Flick
Index: src/sp-image.cpp =================================================================== RCS file: /cvsroot/inkscape/inkscape/src/sp-image.cpp,v retrieving revision 1.42 diff -r1.42 sp-image.cpp 26a27,29
//Added for preserveAspectRatio support, EAF #include "enums.h"
27a31
467a472
image->aspect_align = SP_ASPECT_NONE;
480a486
sp_object_read_attr (object, "preserveAspectRatio");
552a559,616
case SP_ATTR_PRESERVEASPECTRATIO: /* Do setup before, so we can use break to escape */ image->aspect_align = SP_ASPECT_NONE; image->aspect_clip = SP_ASPECT_MEET; object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG); if (value) { int len; gchar c[256]; const gchar *p, *e; unsigned int align, clip; p = value; while (*p && *p == 32) p += 1; if (!*p) break; e = p; while (*e && *e != 32) e += 1; len = e - p; if (len > 8) break; memcpy (c, value, len); c[len] = 0; /* Now the actual part */ if (!strcmp (c, "none")) { align = SP_ASPECT_NONE; } else if (!strcmp (c, "xMinYMin")) { align = SP_ASPECT_XMIN_YMIN; } else if (!strcmp (c, "xMidYMin")) { align = SP_ASPECT_XMID_YMIN; } else if (!strcmp (c, "xMaxYMin")) { align = SP_ASPECT_XMAX_YMIN; } else if (!strcmp (c, "xMinYMid")) { align = SP_ASPECT_XMIN_YMID; } else if (!strcmp (c, "xMidYMid")) { align = SP_ASPECT_XMID_YMID; } else if (!strcmp (c, "xMaxYMid")) { align = SP_ASPECT_XMAX_YMID; } else if (!strcmp (c, "xMinYMax")) { align = SP_ASPECT_XMIN_YMAX; } else if (!strcmp (c, "xMidYMax")) { align = SP_ASPECT_XMID_YMAX; } else if (!strcmp (c, "xMaxYMax")) { align = SP_ASPECT_XMAX_YMAX; } else { break; } clip = SP_ASPECT_MEET; while (*e && *e == 32) e += 1; if (e) { if (!strcmp (e, "meet")) { clip = SP_ASPECT_MEET; } else if (!strcmp (e, "slice")) { clip = SP_ASPECT_SLICE; } else { break; } } image->aspect_align = align; image->aspect_clip = clip; } break;
583a648,697
// 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); switch (image->aspect_align) { case SP_ASPECT_XMIN_YMIN: x = 0.0; y = 0.0; break; case SP_ASPECT_XMID_YMIN: x = 0.5; y = 0.0; break; case SP_ASPECT_XMAX_YMIN: x = 1.0; y = 0.0; break; case SP_ASPECT_XMIN_YMID: x = 0.0; y = 0.5; break; case SP_ASPECT_XMID_YMID: x = 0.5; y = 0.5; break; case SP_ASPECT_XMAX_YMID: x = 1.0; y = 0.5; break; case SP_ASPECT_XMIN_YMAX: x = 0.0; y = 1.0; break; case SP_ASPECT_XMID_YMAX: x = 0.5; y = 1.0; break; case SP_ASPECT_XMAX_YMAX: x = 1.0; y = 1.0; break; default: x = 0.0; y = 0.0; break; }
584a699,738
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); } } 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; } }
}
604a759
sp_repr_set_attr (repr, "preserveAspectRatio", sp_repr_attr (object->repr, "preserveAspectRatio"));
636c791 < int w, h, rs; ---
int w, h, rs, pixskip;
642c797 < ---
647,651c802,813 < < /* fixme: (Lauris) */ < nr_matrix_set_translate (&tp, image->x.computed, image->y.computed); < nr_matrix_set_scale (&s, image->width.computed, -image->height.computed); < nr_matrix_set_translate (&ti, 0.0, -1.0); ---
pixskip = gdk_pixbuf_get_n_channels (image->pixbuf) * gdk_pixbuf_get_bits_per_sample (image->pixbuf) / 8;
if (image->aspect_align == SP_ASPECT_NONE) { /* fixme: (Lauris) */ nr_matrix_set_translate (&tp, image->x.computed, image->y.computed); nr_matrix_set_scale (&s, image->width.computed, -image->height.computed); nr_matrix_set_translate (&ti, 0.0, -1.0); } else { // preserveAspectRatio nr_matrix_set_translate (&tp, image->viewx, image->viewy); nr_matrix_set_scale (&s, image->viewwidth, -image->viewheight); nr_matrix_set_translate (&ti, 0.0, -1.0); }
656c818,821 < sp_print_image_R8G8B8A8_N (ctx, px, w, h, rs, &t, SP_OBJECT_STYLE (item)); ---
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));
678a844
int pixskip, rs;
687c853,856 < nr_arena_image_set_pixels (NR_ARENA_IMAGE (ai), ---
pixskip = gdk_pixbuf_get_n_channels (image->pixbuf) * gdk_pixbuf_get_bits_per_sample (image->pixbuf) / 8; rs = gdk_pixbuf_get_rowstride (image->pixbuf); if (image->aspect_align == SP_ASPECT_NONE) nr_arena_image_set_pixels (NR_ARENA_IMAGE (ai),
691c860,866 < gdk_pixbuf_get_rowstride (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);
695c870,873 < nr_arena_image_set_geometry (NR_ARENA_IMAGE (ai), image->x.computed, image->y.computed, image->width.computed, image->height.computed); ---
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);
777a956
int rs, pixskip;
794c973,976 < nr_arena_image_set_pixels (NR_ARENA_IMAGE (v->arenaitem), ---
pixskip = gdk_pixbuf_get_n_channels (image->pixbuf) * gdk_pixbuf_get_bits_per_sample (image->pixbuf) / 8; rs = gdk_pixbuf_get_rowstride (image->pixbuf); if (image->aspect_align == SP_ASPECT_NONE) { nr_arena_image_set_pixels (NR_ARENA_IMAGE (v->arenaitem),
798,799c980,981 < gdk_pixbuf_get_rowstride (image->pixbuf)); < nr_arena_image_set_geometry (NR_ARENA_IMAGE (v->arenaitem), ---
rs); nr_arena_image_set_geometry (NR_ARENA_IMAGE (v->arenaitem),
801a984,993
} 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); }
Index: src/sp-image.h =================================================================== RCS file: /cvsroot/inkscape/inkscape/src/sp-image.h,v retrieving revision 1.5 diff -r1.5 sp-image.h 29,30d28 < < 42a41,47
// Added by EAF /* preserveAspectRatio */ unsigned int aspect_align : 4; unsigned int aspect_clip : 1; int trimx, trimy, trimwidth, trimheight; double viewx, viewy, viewwidth, viewheight;