summaryrefslogtreecommitdiff
path: root/xps/xpsanalyze.c
diff options
context:
space:
mode:
Diffstat (limited to 'xps/xpsanalyze.c')
-rw-r--r--xps/xpsanalyze.c321
1 files changed, 321 insertions, 0 deletions
diff --git a/xps/xpsanalyze.c b/xps/xpsanalyze.c
new file mode 100644
index 00000000..6e2f9d3e
--- /dev/null
+++ b/xps/xpsanalyze.c
@@ -0,0 +1,321 @@
+/* Copyright (C) 2006-2010 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* XPS interpreter - analyze page checking for transparency.
+ * This is a stripped down parser that looks for alpha values < 1.0 in
+ * any part of the page.
+ */
+
+#include "ghostxps.h"
+
+static int
+xps_remote_resource_dictionary_has_transparency(xps_context_t *ctx, char *base_uri, char *source_att)
+{
+ //dputs("page has transparency: uses a remote resource; not parsed; being conservative\n");
+ return 1;
+}
+
+int
+xps_resource_dictionary_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root)
+{
+ char *source;
+ xps_item_t *node;
+
+ source = xps_att(root, "Source");
+ if (source)
+ return xps_remote_resource_dictionary_has_transparency(ctx, base_uri, source);
+
+ for (node = xps_down(root); node; node = xps_next(node))
+ {
+ // TODO: ... all kinds of stuff can be here, brushes, elements, whatnot
+ }
+
+ return 1;
+}
+
+static int
+xps_gradient_stops_have_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root)
+{
+ xps_item_t *node;
+ gs_color_space *colorspace;
+ char *color_att;
+ float samples[32];
+
+ for (node = xps_down(root); node; node = xps_next(node))
+ {
+ if (!strcmp(xps_tag(node), "GradientStop"))
+ {
+ color_att = xps_att(node, "Color");
+ if (color_att)
+ {
+ xps_parse_color(ctx, base_uri, color_att, &colorspace, samples);
+ if (samples[0] < 1.0)
+ {
+ //dputs("page has transparency: GradientStop has alpha\n");
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+xps_gradient_brush_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root)
+{
+ xps_item_t *node;
+ char *opacity_att;
+
+ opacity_att = xps_att(root, "Opacity");
+ if (opacity_att)
+ {
+ if (atof(opacity_att) < 1.0)
+ {
+ //dputs("page has transparency: GradientBrush Opacity\n");
+ return 1;
+ }
+ }
+
+ for (node = xps_down(root); node; node = xps_next(node))
+ {
+ if (!strcmp(xps_tag(node), "RadialGradientBrush.GradientStops"))
+ {
+ if (xps_gradient_stops_have_transparency(ctx, base_uri, node))
+ return 1;
+ }
+ if (!strcmp(xps_tag(node), "LinearGradientBrush.GradientStops"))
+ {
+ if (xps_gradient_stops_have_transparency(ctx, base_uri, node))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+xps_brush_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root)
+{
+ char *opacity_att;
+ char *color_att;
+ xps_item_t *node;
+
+ gs_color_space *colorspace;
+ float samples[32];
+
+ if (!strcmp(xps_tag(root), "SolidColorBrush"))
+ {
+ opacity_att = xps_att(root, "Opacity");
+ if (opacity_att)
+ {
+ if (atof(opacity_att) < 1.0)
+ {
+ //dputs("page has transparency: SolidColorBrush Opacity\n");
+ return 1;
+ }
+ }
+
+ color_att = xps_att(root, "Color");
+ if (color_att)
+ {
+ xps_parse_color(ctx, base_uri, color_att, &colorspace, samples);
+ if (samples[0] < 1.0)
+ {
+ //dputs("page has transparency: SolidColorBrush Color has alpha\n");
+ return 1;
+ }
+ }
+ }
+
+ if (!strcmp(xps_tag(root), "VisualBrush"))
+ {
+ char *opacity_att = xps_att(root, "Opacity");
+ if (opacity_att)
+ {
+ if (atof(opacity_att) < 1.0)
+ {
+ //dputs("page has transparency: VisualBrush Opacity\n");
+ return 1;
+ }
+ }
+
+ for (node = xps_down(root); node; node = xps_next(node))
+ {
+ if (!strcmp(xps_tag(node), "VisualBrush.Visual"))
+ {
+ if (xps_element_has_transparency(ctx, base_uri, xps_down(node)))
+ return 1;
+ }
+ }
+ }
+
+ if (!strcmp(xps_tag(root), "ImageBrush"))
+ {
+ if (xps_image_brush_has_transparency(ctx, base_uri, root))
+ return 1;
+ }
+
+ if (!strcmp(xps_tag(root), "LinearGradientBrush"))
+ {
+ if (xps_gradient_brush_has_transparency(ctx, base_uri, root))
+ return 1;
+ }
+
+ if (!strcmp(xps_tag(root), "RadialGradientBrush"))
+ {
+ if (xps_gradient_brush_has_transparency(ctx, base_uri, root))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+xps_path_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root)
+{
+ xps_item_t *node;
+
+ for (node = xps_down(root); node; node = xps_next(node))
+ {
+ if (!strcmp(xps_tag(node), "Path.OpacityMask"))
+ {
+ //dputs("page has transparency: Path.OpacityMask\n");
+ return 1;
+ }
+
+ if (!strcmp(xps_tag(node), "Path.Stroke"))
+ {
+ if (xps_brush_has_transparency(ctx, base_uri, xps_down(node)))
+ return 1;
+ }
+
+ if (!strcmp(xps_tag(node), "Path.Fill"))
+ {
+ if (xps_brush_has_transparency(ctx, base_uri, xps_down(node)))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+xps_glyphs_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root)
+{
+ xps_item_t *node;
+
+ for (node = xps_down(root); node; node = xps_next(node))
+ {
+ if (!strcmp(xps_tag(node), "Glyphs.OpacityMask"))
+ {
+ //dputs("page has transparency: Glyphs.OpacityMask\n");
+ return 1;
+ }
+
+ if (!strcmp(xps_tag(node), "Glyphs.Fill"))
+ {
+ if (xps_brush_has_transparency(ctx, base_uri, xps_down(node)))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+xps_canvas_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root)
+{
+ xps_item_t *node;
+
+ for (node = xps_down(root); node; node = xps_next(node))
+ {
+ if (!strcmp(xps_tag(node), "Canvas.Resources"))
+ {
+ if (xps_resource_dictionary_has_transparency(ctx, base_uri, xps_down(node)))
+ return 1;
+ }
+
+ if (!strcmp(xps_tag(node), "Canvas.OpacityMask"))
+ {
+ //dputs("page has transparency: Canvas.OpacityMask\n");
+ return 1;
+ }
+
+ if (xps_element_has_transparency(ctx, base_uri, node))
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+xps_element_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *node)
+{
+ char *opacity_att;
+ char *stroke_att;
+ char *fill_att;
+
+ gs_color_space *colorspace;
+ float samples[32];
+
+ stroke_att = xps_att(node, "Stroke");
+ if (stroke_att)
+ {
+ xps_parse_color(ctx, base_uri, stroke_att, &colorspace, samples);
+ if (samples[0] < 1.0)
+ {
+ //dprintf1("page has transparency: Stroke alpha=%g\n", samples[0]);
+ return 1;
+ }
+ }
+
+ fill_att = xps_att(node, "Fill");
+ if (fill_att)
+ {
+ xps_parse_color(ctx, base_uri, fill_att, &colorspace, samples);
+ if (samples[0] < 1.0)
+ {
+ //dprintf1("page has transparency: Fill alpha=%g\n", samples[0]);
+ return 1;
+ }
+ }
+
+ opacity_att = xps_att(node, "Opacity");
+ if (opacity_att)
+ {
+ if (atof(opacity_att) < 1.0)
+ {
+ //dprintf1("page has transparency: Opacity=%g\n", atof(opacity_att));
+ return 1;
+ }
+ }
+
+ if (xps_att(node, "OpacityMask"))
+ {
+ //dputs("page has transparency: OpacityMask\n");
+ return 1;
+ }
+
+ if (!strcmp(xps_tag(node), "Path"))
+ if (xps_path_has_transparency(ctx, base_uri, node))
+ return 1;
+ if (!strcmp(xps_tag(node), "Glyphs"))
+ if (xps_glyphs_has_transparency(ctx, base_uri, node))
+ return 1;
+ if (!strcmp(xps_tag(node), "Canvas"))
+ if (xps_canvas_has_transparency(ctx, base_uri, node))
+ return 1;
+
+ return 0;
+}