Commit 5f0ab1d0 authored by Dom Lachowicz's avatar Dom Lachowicz

handle objbbox coordinate space for linear gradients, start of handling for radial

parent 49521f28
2003-01-29 Dom Lachowicz <cinamod@hotmail.com>
* rsvg-paint-server.[ch]: Handle objectBoundingBox units for linear gradients, radialGradients. Radial are untested and do not work properly.
* rsvg.c: Query the gradientUnits param, in order to pass to ^^^
* TODO: Update info so that the objectBoundingBox gets handled properly in case of percentage values.
* tests/obj_bbox.svg: Test for the above
2003-01-29 Dom Lachowicz <cinamod@hotmail.com>
* rsvg-gz.c: Fix build
......
TODO:
* Handle percentages correctly for gradients in objectBoundingBox space
* Clipping paths
* Masks
......@@ -15,7 +17,4 @@ TODO:
On the back burner:
* Consider storing the paths so that the file can be rerendered
multiple times without reparsing.
* Make error messages translatable (requires adding gettext).
......@@ -145,8 +145,21 @@ rsvg_paint_server_lin_grad_render (RsvgPaintServer *self, ArtRender *ar,
RsvgLinearGradient *rlg = z->gradient;
ArtGradientLinear *agl;
double x1, y1, x2, y2;
double g_x1, g_y1, g_x2, g_y2;
double dx, dy, scale;
g_x1 = rlg->x1;
g_x2 = rlg->x2;
g_y1 = rlg->y1;
g_y2 = rlg->y2;
if (rlg->obj_bbox == TRUE) {
g_x1 *= ar->x0;
g_x2 *= ar->x1;
g_y1 *= ar->y0;
g_y2 *= ar->y1;
}
agl = z->agl;
if (agl == NULL)
{
......@@ -161,11 +174,10 @@ rsvg_paint_server_lin_grad_render (RsvgPaintServer *self, ArtRender *ar,
}
/* compute [xy][12] in pixel space */
/* todo: this code implicitly implements gradientUnits = userSpace */
x1 = rlg->x1 * rlg->affine[0] + rlg->y1 * rlg->affine[2] + rlg->affine[4];
y1 = rlg->x1 * rlg->affine[1] + rlg->y1 * rlg->affine[3] + rlg->affine[5];
x2 = rlg->x2 * rlg->affine[0] + rlg->y2 * rlg->affine[2] + rlg->affine[4];
y2 = rlg->x2 * rlg->affine[1] + rlg->y2 * rlg->affine[3] + rlg->affine[5];
x1 = g_x1 * rlg->affine[0] + g_y1 * rlg->affine[2] + rlg->affine[4];
y1 = g_x1 * rlg->affine[1] + g_y1 * rlg->affine[3] + rlg->affine[5];
x2 = g_x2 * rlg->affine[0] + g_y2 * rlg->affine[2] + rlg->affine[4];
y2 = g_x2 * rlg->affine[1] + g_y2 * rlg->affine[3] + rlg->affine[5];
/* solve a, b, c so ax1 + by1 + c = 0 and ax2 + by2 + c = 1, maximum
gradient is in x1,y1 to x2,y2 dir */
......@@ -215,6 +227,27 @@ rsvg_paint_server_rad_grad_render (RsvgPaintServer *self, ArtRender *ar,
ArtGradientRadial *agr;
double aff1[6], aff2[6];
double r, cx, cy, fx, fy;
r = rrg->r;
cx = rrg->cx;
cy = rrg->cy;
fx = rrg->fx;
fy = rrg->fy;
if (rrg->obj_bbox) {
/* http://www.w3.org/TR/SVG11/pservers.html#RadialGradientUnitsAttribute
not quite sure of the math needed here in order to make this happen
relative to [ar->x0 ar->x1 ar->y0 ar->y1]
*/
/* todo: untested, known to be *quite* broken */
r *= (((ar->x1 - ar->x0) + (ar->y1 - ar->y0)) / 2.);
cx *= ((ar->x1 - ar->x0));
cy *= ((ar->y1 - ar->y0));
fx *= ((ar->x1 - ar->x0));
fy *= ((ar->y1 - ar->y0));
}
agr = z->agr;
if (agr == NULL)
{
......@@ -228,17 +261,16 @@ rsvg_paint_server_rad_grad_render (RsvgPaintServer *self, ArtRender *ar,
z->agr = agr;
}
/* todo: this code implicitly implements gradientUnits = userSpace */
art_affine_scale (aff1, rrg->r, rrg->r);
art_affine_translate (aff2, rrg->cx, rrg->cy);
art_affine_scale (aff1, r, r);
art_affine_translate (aff2, cx, cy);
art_affine_multiply (aff1, aff1, aff2);
art_affine_multiply (aff1, aff1, rrg->affine);
art_affine_invert (agr->affine, aff1);
/* TODO: libart doesn't support spreads on radial gradients */
/* todo: libart doesn't support spreads on radial gradients */
agr->fx = (rrg->fx - rrg->cx) / rrg->r;
agr->fy = (rrg->fy - rrg->cy) / rrg->r;
agr->fx = (fx - cx) / r;
agr->fy = (fy - cy) / r;
art_render_gradient_radial (ar, agr, ART_FILTER_NEAREST);
}
......@@ -363,6 +395,7 @@ rsvg_clone_radial_gradient (const RsvgRadialGradient *grad, gboolean * shallow_c
clone->super.type = RSVG_DEF_RADGRAD;
clone->super.free = rsvg_radial_gradient_free;
clone->obj_bbox = grad->obj_bbox;
for (i = 0; i < 6; i++)
clone->affine[i] = grad->affine[i];
......@@ -373,13 +406,11 @@ rsvg_clone_radial_gradient (const RsvgRadialGradient *grad, gboolean * shallow_c
for (i = 0; i < grad->stops->n_stop; i++)
clone->stops->stop[i] = grad->stops->stop[i];
} else {
clone->stops = NULL;
}
clone->spread = grad->spread;
/* EVIL EVIL - sodipodi can base LinearGradients on
/* EVIL EVIL - SVG can base LinearGradients on
RadialGradients, and vice-versa. it is legal, though:
http://www.w3.org/TR/SVG11/pservers.html#LinearGradients
*/
......@@ -408,6 +439,7 @@ rsvg_clone_linear_gradient (const RsvgLinearGradient *grad, gboolean * shallow_c
clone->super.type = RSVG_DEF_LINGRAD;
clone->super.free = rsvg_linear_gradient_free;
clone->obj_bbox = grad->obj_bbox;
for (i = 0; i < 6; i++)
clone->affine[i] = grad->affine[i];
......@@ -418,13 +450,11 @@ rsvg_clone_linear_gradient (const RsvgLinearGradient *grad, gboolean * shallow_c
for (i = 0; i < grad->stops->n_stop; i++)
clone->stops->stop[i] = grad->stops->stop[i];
} else {
clone->stops = NULL;
}
clone->spread = grad->spread;
/* EVIL EVIL - sodipodi can base LinearGradients on
/* EVIL EVIL - SVG can base LinearGradients on
RadialGradients, and vice-versa. it is legal, though:
http://www.w3.org/TR/SVG11/pservers.html#LinearGradients
*/
......
......@@ -42,48 +42,50 @@ typedef struct _RsvgPaintServer RsvgPaintServer;
typedef struct _RsvgPSCtx RsvgPSCtx;
struct _RsvgPSCtx {
int dummy;
/* todo: we need to take in some context information, including:
1. The global affine transformation.
2. User coordinates at time of reference (to implement
gradientUnits = "userSpaceOnUse").
3. Object bounding box (to implement gradientUnits =
"objectBoundingBox").
Maybe signal for lazy evaluation of object bbox.
*/
int dummy;
/* todo: we need to take in some context information, including:
1. The global affine transformation.
2. User coordinates at time of reference (to implement
gradientUnits = "userSpaceOnUse").
3. Object bounding box (to implement gradientUnits =
"objectBoundingBox").
Maybe signal for lazy evaluation of object bbox.
*/
};
struct _RsvgGradientStop {
double offset;
guint32 rgba;
double offset;
guint32 rgba;
};
struct _RsvgGradientStops {
int n_stop;
RsvgGradientStop *stop;
int n_stop;
RsvgGradientStop *stop;
};
struct _RsvgLinearGradient {
RsvgDefVal super;
double affine[6]; /* user space to actual at time of gradient def */
RsvgGradientStops *stops;
ArtGradientSpread spread;
double x1, y1;
double x2, y2;
RsvgDefVal super;
gboolean obj_bbox;
double affine[6]; /* user space to actual at time of gradient def */
RsvgGradientStops *stops;
ArtGradientSpread spread;
double x1, y1;
double x2, y2;
};
struct _RsvgRadialGradient {
RsvgDefVal super;
double affine[6]; /* user space to actual at time of gradient def */
RsvgGradientStops *stops;
ArtGradientSpread spread;
double cx, cy;
double r;
double fx, fy;
RsvgDefVal super;
gboolean obj_bbox;
double affine[6]; /* user space to actual at time of gradient def */
RsvgGradientStops *stops;
ArtGradientSpread spread;
double cx, cy;
double r;
double fx, fy;
};
/* Create a new paint server based on a specification string. */
......@@ -92,7 +94,7 @@ rsvg_paint_server_parse (const RsvgDefs *defs, const char *str);
void
rsvg_render_paint_server (ArtRender *ar, RsvgPaintServer *ps,
const RsvgPSCtx *ctx);
const RsvgPSCtx *ctx);
void
rsvg_paint_server_ref (RsvgPaintServer *ps);
......
......@@ -403,10 +403,11 @@ rsvg_start_linear_gradient (RsvgHandle *ctx, const xmlChar **atts)
double x1 = 0., y1 = 0., x2 = 0., y2 = 0.;
ArtGradientSpread spread = ART_GRADIENT_PAD;
const char * xlink_href = NULL;
gboolean got_x1, got_x2, got_y1, got_y2, got_spread, got_transform, cloned, shallow_cloned;
gboolean obj_bbox = TRUE;
gboolean got_x1, got_x2, got_y1, got_y2, got_spread, got_transform, got_bbox, cloned, shallow_cloned;
double affine[6];
got_x1 = got_x2 = got_y1 = got_y2 = got_spread = got_transform = cloned = shallow_cloned = FALSE;
got_x1 = got_x2 = got_y1 = got_y2 = got_spread = got_transform = got_bbox = cloned = shallow_cloned = FALSE;
/* 100% is the default */
x2 = rsvg_css_parse_normalized_length ("100%", ctx->dpi, (gdouble)ctx->width, state->font_size);
......@@ -451,8 +452,11 @@ rsvg_start_linear_gradient (RsvgHandle *ctx, const xmlChar **atts)
}
else if (!strcmp ((char *)atts[i], "xlink:href"))
xlink_href = (const char *)atts[i + 1];
else if (!strcmp ((char *)atts[i], "gradientTransform")) {
else if (!strcmp ((char *)atts[i], "gradientTransform"))
got_transform = rsvg_parse_transform (affine, (const char *)atts[i + 1]);
else if (!strcmp ((char *)atts[i], "gradientUnits")) {
obj_bbox = (strcmp ((char *)atts[i+1], "objectBoundingBox") == 0);
got_bbox = TRUE;
}
}
}
......@@ -485,6 +489,7 @@ rsvg_start_linear_gradient (RsvgHandle *ctx, const xmlChar **atts)
art_affine_multiply (grad->affine, affine, grad->affine);
/* state inherits parent/cloned information unless it's explicity gotten */
grad->obj_bbox = (cloned && !got_bbox) ? grad->obj_bbox : obj_bbox;
grad->x1 = (cloned && !got_x1) ? grad->x1 : x1;
grad->y1 = (cloned && !got_y1) ? grad->y1 : y1;
grad->x2 = (cloned && !got_x2) ? grad->x2 : x2;
......@@ -513,10 +518,11 @@ rsvg_start_radial_gradient (RsvgHandle *ctx, const xmlChar **atts, const char *
double cx = 0., cy = 0., r = 0., fx = 0., fy = 0.;
const char * xlink_href = NULL;
ArtGradientSpread spread = ART_GRADIENT_PAD;
gboolean got_cx, got_cy, got_r, got_fx, got_fy, got_spread, got_transform, cloned, shallow_cloned;
gboolean obj_bbox = TRUE;
gboolean got_cx, got_cy, got_r, got_fx, got_fy, got_spread, got_transform, got_bbox, cloned, shallow_cloned;
double affine[6];
got_cx = got_cy = got_r = got_fx = got_fy = got_spread = got_transform = cloned = shallow_cloned = FALSE;
got_cx = got_cy = got_r = got_fx = got_fy = got_spread = got_transform = got_bbox = cloned = shallow_cloned = FALSE;
/* setup defaults */
cx = rsvg_css_parse_normalized_length ("50%", ctx->dpi, (gdouble)ctx->width, state->font_size);
......@@ -572,6 +578,10 @@ rsvg_start_radial_gradient (RsvgHandle *ctx, const xmlChar **atts, const char *
got_spread = TRUE;
}
}
else if (!strcmp ((char *)atts[i], "gradientUnits")) {
obj_bbox = (strcmp ((char *)atts[i+1], "objectBoundingBox") == 0);
got_bbox = TRUE;
}
}
}
......@@ -613,6 +623,7 @@ rsvg_start_radial_gradient (RsvgHandle *ctx, const xmlChar **atts, const char *
art_affine_multiply (grad->affine, affine, grad->affine);
/* state inherits parent/cloned information unless it's explicity gotten */
grad->obj_bbox = (cloned && !got_bbox) ? grad->obj_bbox : obj_bbox;
grad->cx = (cloned && !got_cx) ? grad->cx : cx;
grad->cy = (cloned && !got_cy) ? grad->cy : cy;
grad->r = (cloned && !got_r) ? grad->r : r;
......
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"
[
<!ATTLIST svg
xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink">
]>
<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
<svg
xml:space="preserve"
width="282.773pt"
height="191.899pt"
viewBox="0 0 282.773 191.899"
id="svg170"
sodipodi:version="0.28"
sodipodi:docname="bbox.svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs
id="defs194">
<linearGradient
id="aigrd2"
gradientUnits="userSpaceOnUse"
x1="127.7222"
y1="99.6226"
x2="156.019"
y2="172.1655">
<stop
offset="0"
style="stop-color:#DEDFCE"
id="stop183" />
<stop
offset="1"
style="stop-color:#C2C4B5"
id="stop184" />
</linearGradient>
<linearGradient
id="linearGradient200">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0.000000"
id="stop201" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1.000000"
id="stop202" />
</linearGradient>
<linearGradient
id="linearGradient196">
<stop
style="stop-color:#000;stop-opacity:1;"
offset="0"
id="stop197" />
<stop
style="stop-color:#fff;stop-opacity:1;"
offset="1"
id="stop198" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient200"
id="radialGradient199"
cx="0.5"
cy="0.499997"
fx="0.5"
fy="0.499997"
r="0.5"
gradientUnits="objectBoundingBox"
gradientTransform="matrix(1,0,0,0.999999,-2.21187e-08,7.38927e-09)"
spreadMethod="pad" />
<linearGradient
id="aigrd1"
gradientUnits="userSpaceOnUse"
x1="174.9414"
y1="27.7495"
x2="138.2552"
y2="126.017">
<stop
offset="0"
style="stop-color:#989C80"
id="stop176" />
<stop
offset="1"
style="stop-color:#000000"
id="stop177" />
</linearGradient>
<linearGradient
id="aigrd3"
gradientUnits="userSpaceOnUse"
x1="92.187"
y1="73.4146"
x2="105.9913"
y2="122.4433">
<stop
offset="0"
style="stop-color:#DEDFCE"
id="stop187" />
<stop
offset="1"
style="stop-color:#FFFFFF"
id="stop188" />
</linearGradient>
<radialGradient
cx="0.5"
cy="0.5"
r="0.5"
fx="0.5"
fy="0.5"
xlink:href="#linearGradient196"
id="radialGradient34"
gradientUnits="objectBoundingBox"
gradientTransform="matrix(1,-2.45197e-08,-8.30791e-10,1,1.2663e-08,-3.59631e-08)"
spreadMethod="pad" />
<linearGradient
xlink:href="#linearGradient196"
id="linearGradient35"
x1="1.44999e-08"
y1="-7.76244e-09"
x2="1"
y2="-7.76244e-09"
gradientUnits="objectBoundingBox"
gradientTransform="matrix(1,-1.6501e-08,-3.69181e-10,1,3.47773e-09,-1.04109e-09)"
spreadMethod="pad" />
</defs>
<sodipodi:namedview
id="base" />
<rect
style="fill-rule:evenodd;stroke:none;fill:url(#radialGradient199);fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
id="rect195"
x="132.922286"
y="44.985791"
width="180.546021"
height="152.516037"
rx="0.000000"
ry="0.000000" />
<path
style="font-size:12;"
d="M190.663,5.936c-5.061,1.446-9.362,4.091-12.819,6.217c-3.429,2.109-6.391,3.93-8.675,3.93c-1.638-0.008-8.992-1.666-13.857-2.762C136.747,9.138,111.326,3.41,96.89,8.948c-6.075,2.331-12.5,9.554-19.573,21.903 c-2.881-0.516-6.252-1.12-6.252-1.12c-26.821-4.575-31.491-3.485-35.162-1.446c-4.056,2.253-6.548,6.506-7.408,12.641c-2.447,17.475,9.083,74.245,21.4,86.563c8.377,8.376,57.812,25.158,78.677,31.985c18.515,6.06,35.952,11.253,49.101,14.622 c22.379,5.734,28.731,5.469,33.181,2.88c3.813-2.22,27.168-19.573,43.785-72.776c2.662-8.524,9.468-33.644,9.468-47.996c0-3.091-0.322-5.685-1.082-7.509c-3.955-9.504-12.159-11.312-17.062-12.392c-1.08-0.238-2.589-0.58-3.278-0.888 c-0.104-0.673-0.185-1.879-0.218-2.406c-0.27-4.253-0.722-11.372-7.094-17.743C224.877,4.772,201.883,2.73,190.663,5.936z"
id="path172" />
<path
style="font-size:12;opacity:0.35;fill:none;"
d="M197.302,189.345c-19.362,3.052-140.636-33.053-150.459-43.86c-9.823-10.804,43.331-26.142,68.718-28.364c25.388-2.224,148.77,18.649,161.874,32.678c13.104,14.028-60.771,36.495-80.133,39.547z"
id="path173"
transform="translate(0,-1.64882)" />
<path
style="font-size:12;"
d="M190.372,11.021c-4.399,1.257-8.212,3.601-11.574,5.668c-4.076,2.506-7.597,4.67-11.294,4.67c-2.158,0-8.665-1.466-14.957-2.884c-17.939-4.042-42.507-9.578-55.531-4.582C82.821,19.339,65.881,62.867,62.63,71.537 c-6.489,17.302-13.376,39.529-9.338,47.158c0.962,1.817,3.891,7.35,44.509,21.131c24.85,8.431,52.596,15.986,74.221,20.212c35.505,6.937,44.89,3.31,48.861-0.021c12.253-10.279,22.358-40.088,27.291-56.941c0.511-1.744,12.46-42.828,8.568-52.18 c-2.955-7.102-9.063-8.447-13.521-9.43c-2.514-0.554-4.686-1.033-5.954-2.301c-1.077-1.077-1.255-2.38-1.456-5.56c-0.254-4.004-0.602-9.487-5.639-14.523c-8.767-8.767-29.858-10.9-39.8-8.06z"
id="path174" />
<rect
style="fill-rule:evenodd;stroke:none;fill:url(#linearGradient35);fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
id="rect205"
x="41.625938"
y="69.164471"
width="269.108531"
height="94.504338"
rx="0.000000"
ry="0.000000"
transform="matrix(0.978118,0.20805,-0.23694,0.971524,0,0)" />
<path
style="font-size:12;fill:url(#aigrd1);"
d="M95.807,18.563c-15.583,5.978-46.786,87.044-41.096,97.792c5.69,10.749,143.11,53.965,159.958,39.831c19.087-16.013,37.979-94.907,34.457-103.371c-3.42-8.219-13.021-4.742-18.395-10.116s-0.14-13.128-7.095-20.083 c-6.954-6.955-26.04-9.317-34.891-6.788c-8.852,2.529-15.391,10.531-24.242,10.531s-51.952-14.222-68.697-7.797z"
id="path178" />
<path
style="font-size:12;fill:#c1c2b4;"
d="M55.438,114.149c1.641-26.713,25.165-88.316,39.225-95.586c14.06-7.271,62.063,7.797,69.841,7.797s13.814-7.634,24.242-10.531c10.428-2.896,28.362,0.259,34.891,6.788c5.519,5.519,3.408,16.134,5.966,18.692 c2.559,2.559,15.222,6.177,17.887,8.842c0,0-14.935-4.061-18.801-7.927c-3.867-3.867-3.152-12.537-6.316-15.701c-3.163-3.164-28.523-8.669-35.267-5.74c-6.742,2.928-12.301,10.193-21.675,11.833s-53.662-14.06-67.253-6.092s-42.739,87.625-42.739,87.625z"
id="path179" />
<path
style="font-size:12;fill:#808078;"
d="M245.103,48.082c6.801,5.716-7.498,71.236-27.091,104.673c21.467-29.688,31.854-88.371,31.854-96.066c0-1.796-1.207-6.708-4.764-8.606z"
id="path180" />
<path
style="font-size:12;"
d="M36.666,32.934c-3.936,2.186-4.65,7.289-4.885,8.965c-2.438,17.411,9.695,72.044,19.984,82.333c8.191,8.191,69.708,28.483,76.696,30.77c18.416,6.027,35.742,11.188,48.787,14.53c22.597,5.791,26.926,4.856,29.424,3.402 c2.534-1.475,4.231-4.341,5.504-9.295c5.176-20.146,2.734-78.632-3.732-89.398c-1.593-2.652-5.365-6.112-30.122-13.66c-14.372-4.381-33.79-9.466-54.678-14.317c-20.166-4.684-39.729-8.706-55.084-11.325c-27.161-4.633-30.008-3.051-31.893-2.004z"
id="path181" />
<path
style="font-size:12;fill:url(#aigrd2);"
d="M202.157,167.613c8.948-5.207,6.525-80.933,0-91.798C195.631,64.95,45.984,31.366,37.094,36.305s6.493,73.678,16.207,83.392c9.714,9.713,139.908,53.123,148.856,47.916z"
id="path185" />
<path
style="font-size:12;fill:url(#aigrd3);"
d="M95.29,137.982c-27.779-61.166,67.208-16.267,47.188-82.525c0,0-100.067-24.468-105.383-19.152c-8.519,8.519,5.125,68.162,15.566,82.502c4.316,5.929,42.629,19.175,42.629,19.175z"
id="path189" />
<path
style="font-size:12;fill:#f1f2e1;"
d="M55.084,120.908c-8.353-13.077-22.936-68.863-12.097-75.533c16.17-9.951,140.406,21.704,140.406,21.704C171.717,63.116,51.427,29.409,37.094,36.305c-8.69,4.181,5.846,77.53,17.99,84.603z"
id="path190" />
<path
style="font-size:12;fill:#919187;"
d="M202.497,76.345c5.351,6.962,9.147,85.677-0.379,91.075S95.854,137.908,95.854,137.908s95.646,33.173,104.095,26.135s7.604-51.521,2.549-87.697z"
id="path191" />
<path
style="font-size:12;fill:none;"
d="M0,191.899h282.773V0H0v191.899z"
id="path192" />
</svg>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment