summaryrefslogtreecommitdiff
path: root/xps/xpsgradient.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2007-02-27 16:28:42 +0000
committerTor Andersson <tor.andersson@artifex.com>2007-02-27 16:28:42 +0000
commitdb432b0b614ce521ab76db567c9fc27cbe94a7a3 (patch)
tree4197d7d0a5ab3b9b7da29eb1af360a10abfd7546 /xps/xpsgradient.c
parent26993883b5312d37142eb464cdc195a066582fee (diff)
downloadghostpdl-db432b0b614ce521ab76db567c9fc27cbe94a7a3.tar.gz
We have linear gradients.
git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@2776 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'xps/xpsgradient.c')
-rw-r--r--xps/xpsgradient.c215
1 files changed, 175 insertions, 40 deletions
diff --git a/xps/xpsgradient.c b/xps/xpsgradient.c
index c492cbdf4..58f2f9321 100644
--- a/xps/xpsgradient.c
+++ b/xps/xpsgradient.c
@@ -195,7 +195,7 @@ xps_draw_one_radial_gradient(xps_context_t *ctx,
rect.q.x = int2fixed(10000);
rect.q.y = int2fixed(10000);
- code = gs_shading_fill_path_adjusted(shading, NULL, &rect, dev, pis, false);
+ code = gs_shading_fill_path_adjusted(shading, NULL, &rect, dev, pis, 0);
if (code < 0)
{
gs_free_object(mem, shading, "gs_shading_R");
@@ -208,6 +208,63 @@ xps_draw_one_radial_gradient(xps_context_t *ctx,
}
/*
+ * Linear gradients map to Axial shadings.
+ */
+
+int
+xps_draw_one_linear_gradient(xps_context_t *ctx,
+ gs_function_t *func, int extend,
+ float *pt0, float *pt1)
+{
+ gs_memory_t *mem = ctx->memory;
+ gs_state *pgs = ctx->pgs;
+ gs_imager_state *pis = (gs_imager_state*)pgs;
+ gx_device *dev = gs_currentdevice(pgs);
+ gs_shading_t *shading;
+ gs_shading_A_params_t params;
+ gs_color_space colorspace;
+ gs_fixed_rect rect;
+ int code;
+
+ gs_shading_A_params_init(&params);
+ {
+ gs_cspace_init_DeviceRGB(mem, &colorspace);
+
+ params.ColorSpace = &colorspace;
+
+ params.Coords[0] = pt0[0];
+ params.Coords[1] = pt0[1];
+ params.Coords[2] = pt1[0];
+ params.Coords[3] = pt1[1];
+
+ params.Extend[0] = extend;
+ params.Extend[1] = extend;
+
+ params.Function = func;
+ }
+
+ code = gs_shading_A_init(&shading, &params, mem);
+ if (code < 0)
+ return gs_throw(-1, "gs_shading_A_init failed");
+
+ rect.p.x = int2fixed(-10000);
+ rect.p.y = int2fixed(-10000);
+ rect.q.x = int2fixed(10000);
+ rect.q.y = int2fixed(10000);
+
+ code = gs_shading_fill_path_adjusted(shading, NULL, &rect, dev, pis, 0);
+ if (code < 0)
+ {
+ gs_free_object(mem, shading, "gs_shading_A");
+ return gs_throw(-1, "gs_shading_fill_path_adjusted failed");
+ }
+
+ gs_free_object(mem, shading, "gs_shading_A");
+
+ return gs_okay;
+}
+
+/*
* We need to loop and create many shading objects to account
* for the Repeat and Reflect SpreadMethods.
*/
@@ -247,7 +304,7 @@ xps_draw_radial_gradient(xps_context_t *ctx,
if (spread == SPREAD_PAD)
{
- code = xps_draw_one_radial_gradient(ctx, func, true, pt0, rad0, pt1, rad1);
+ code = xps_draw_one_radial_gradient(ctx, func, 1, pt0, rad0, pt1, rad1);
if (code < 0)
{
xps_free(ctx, func); /* XXX: is this the right free function? */
@@ -260,9 +317,9 @@ xps_draw_radial_gradient(xps_context_t *ctx,
for (i = 0; i < 10; i++)
{
if (spread == SPREAD_REFLECT && (i & 1))
- code = xps_draw_one_radial_gradient(ctx, func, false, pt1, rad1, pt0, rad0);
+ code = xps_draw_one_radial_gradient(ctx, func, 0, pt1, rad1, pt0, rad0);
else
- code = xps_draw_one_radial_gradient(ctx, func, false, pt0, rad0, pt1, rad1);
+ code = xps_draw_one_radial_gradient(ctx, func, 0, pt0, rad0, pt1, rad1);
if (code < 0)
{
@@ -284,54 +341,63 @@ xps_draw_radial_gradient(xps_context_t *ctx,
return gs_okay;
}
-/*
- *
- */
int
-xps_parse_linear_gradient_brush(xps_context_t *ctx, xps_item_t *root)
+xps_draw_linear_gradient(xps_context_t *ctx,
+ float *pt0, float *pt1, int spread,
+ float *offsets, float *colors, int count)
{
- xps_item_t *node;
-
- float stop_offsets[MAX_STOPS];
- float stop_colors[MAX_STOPS * 4];
- int stop_count = 0;
-
- char *opacity;
- char *color_interpolation_mode;
- char *spread_method;
- char *mapping_mode;
- char *transform;
- char *start_point;
- char *end_point;
-
- xps_item_t *transform_node = NULL;
+ gs_function_t *func;
+ int code;
+ int i;
- dputs("drawing linear gradient brush\n");
+ float dx = pt1[0] - pt0[0];
+ float dy = pt1[1] - pt0[1];
- opacity = xps_att(root, "Opacity");
- color_interpolation_mode = xps_att(root, "ColorInterpolationMode");
- spread_method = xps_att(root, "SpreadMethod");
- mapping_mode = xps_att(root, "MappingMode");
- transform = xps_att(root, "Transform");
- start_point = xps_att(root, "StartPoint");
- end_point = xps_att(root, "EndPoint");
+ func = xps_create_gradient_stop_function(ctx, offsets, colors, count);
+ if (!func)
+ return gs_rethrow(-1, "could not create gradient function");
- for (node = xps_down(root); node; node = xps_next(node))
+ if (spread == SPREAD_PAD)
{
- if (!strcmp(xps_tag(node), "LinearGradientBrush.Transform"))
- transform_node = xps_down(node);
- if (!strcmp(xps_tag(node), "LinearGradientBrush.GradientStops"))
- stop_count = xps_parse_gradient_stops(ctx, xps_down(node),
- stop_offsets, stop_colors, MAX_STOPS);
+ code = xps_draw_one_linear_gradient(ctx, func, 1, pt0, pt1);
+ if (code < 0)
+ {
+ gs_free_object(ctx->memory, func, "gs_function");
+ return gs_rethrow(code, "could not draw axial gradient");
+ }
}
+ else
+ {
+ pt0[0] -= 10 * dx; pt0[1] -= 10 * dy;
+ pt1[0] -= 10 * dx; pt1[1] -= 10 * dy;
- if (stop_count == 0)
- return gs_throw(-1, "no gradient stops found");
+ for (i = 0; i < 20; i++)
+ {
+ if (spread == SPREAD_REFLECT && (i & 1))
+ code = xps_draw_one_linear_gradient(ctx, func, 0, pt1, pt0);
+ else
+ code = xps_draw_one_linear_gradient(ctx, func, 0, pt0, pt1);
+ if (code < 0)
+ {
+ gs_free_object(ctx->memory, func, "gs_function");
+ return gs_rethrow(code, "could not draw axial gradient");
+ }
- return 0;
+ pt0[0] += dx; pt0[1] += dy;
+ pt1[0] += dx; pt1[1] += dy;
+ }
+ }
+
+ gs_free_object(ctx->memory, func, "gs_function");
+ return gs_okay;
}
+
+/*
+ *
+ */
+
int
xps_parse_radial_gradient_brush(xps_context_t *ctx, xps_item_t *root)
{
@@ -424,3 +490,72 @@ xps_parse_radial_gradient_brush(xps_context_t *ctx, xps_item_t *root)
return 0;
}
+int
+xps_parse_linear_gradient_brush(xps_context_t *ctx, xps_item_t *root)
+{
+ xps_item_t *node;
+
+ float stop_offsets[MAX_STOPS];
+ float stop_colors[MAX_STOPS * 4];
+ int stop_count = 0;
+
+ char *opacity;
+ char *color_interpolation_mode;
+ char *spread_method;
+ char *mapping_mode;
+ char *transform;
+ char *start_point;
+ char *end_point;
+
+ xps_item_t *transform_node = NULL;
+
+ dputs("drawing linear gradient brush\n");
+
+ opacity = xps_att(root, "Opacity");
+ color_interpolation_mode = xps_att(root, "ColorInterpolationMode");
+ spread_method = xps_att(root, "SpreadMethod");
+ mapping_mode = xps_att(root, "MappingMode");
+ transform = xps_att(root, "Transform");
+ start_point = xps_att(root, "StartPoint");
+ end_point = xps_att(root, "EndPoint");
+
+ for (node = xps_down(root); node; node = xps_next(node))
+ {
+ if (!strcmp(xps_tag(node), "LinearGradientBrush.Transform"))
+ transform_node = xps_down(node);
+ if (!strcmp(xps_tag(node), "LinearGradientBrush.GradientStops"))
+ stop_count = xps_parse_gradient_stops(ctx, xps_down(node),
+ stop_offsets, stop_colors, MAX_STOPS);
+ }
+
+ if (stop_count == 0)
+ return gs_throw(-1, "no gradient stops found");
+
+ {
+ float gpt0[2];
+ float gpt1[2];
+ int gspread;
+ int code;
+
+ sscanf(start_point, "%g,%g", gpt0, gpt0 + 1);
+ sscanf(end_point, "%g,%g", gpt1, gpt1 + 1);
+
+ gspread = SPREAD_PAD;
+ if (spread_method && !strcmp(spread_method, "Pad"))
+ gspread = SPREAD_PAD;
+ if (spread_method && !strcmp(spread_method, "Reflect"))
+ gspread = SPREAD_REFLECT;
+ if (spread_method && !strcmp(spread_method, "Repeat"))
+ gspread = SPREAD_REPEAT;
+
+ code = xps_draw_linear_gradient(ctx,
+ gpt0, gpt1, gspread,
+ stop_offsets, stop_colors, stop_count);
+
+ if (code < 0)
+ return gs_rethrow(-1, "could not draw linear gradient");
+ }
+
+ return 0;
+}
+