コード例 #1
0
ファイル: xpsanalyze.c プロジェクト: hackqiang/gs
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)
        {
            //dmputs(ctx->memory, "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;
}
コード例 #2
0
ファイル: xpsanalyze.c プロジェクト: hackqiang/gs
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_down(node) && xps_resource_dictionary_has_transparency(ctx, base_uri, xps_down(node)))
                return 1;
        }

        if (!strcmp(xps_tag(node), "Canvas.OpacityMask"))
        {
            //dmputs(ctx->memory, "page has transparency: Canvas.OpacityMask\n");
            return 1;
        }

        if (xps_element_has_transparency(ctx, base_uri, node))
            return 1;
    }

    return 0;
}
コード例 #3
0
ファイル: xpsanalyze.c プロジェクト: hackqiang/gs
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)
                {
                    //dmputs(ctx->memory, "page has transparency: GradientStop has alpha\n");
                    return 1;
                }
            }
        }
    }

    return 0;
}
コード例 #4
0
ファイル: xpsanalyze.c プロジェクト: hackqiang/gs
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"))
        {
            //dmputs(ctx->memory, "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;
}
コード例 #5
0
ファイル: xpsanalyze.c プロジェクト: hackqiang/gs
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))
    {
        if (!strcmp(xps_tag(node), "RadialGradientBrush") ||
                !strcmp(xps_tag(node), "LinearGradientBrush") ||
                !strcmp(xps_tag(node), "SolidColorBrush") ||
                !strcmp(xps_tag(node), "VisualBrush") ||
                !strcmp(xps_tag(node), "ImageBrush"))
            if (xps_brush_has_transparency(ctx, base_uri, node))
                return 1;
    }

    return 0;
}
コード例 #6
0
ファイル: xpstile.c プロジェクト: computersforpeace/ghostpdl
int
xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root,
    int (*func)(xps_context_t*, char*, xps_resource_t*, xps_item_t*, void*), void *user)
{
    xps_item_t *node;
    int code;

    char *opacity_att;
    char *transform_att;
    char *viewbox_att;
    char *viewport_att;
    char *tile_mode_att;
    /*char *viewbox_units_att;*/
    /*char *viewport_units_att;*/

    xps_item_t *transform_tag = NULL;

    gs_matrix transform;
    gs_rect viewbox;
    gs_rect viewport;
    float scalex, scaley;
    int tile_mode;

    opacity_att = xps_att(root, "Opacity");
    transform_att = xps_att(root, "Transform");
    viewbox_att = xps_att(root, "Viewbox");
    viewport_att = xps_att(root, "Viewport");
    tile_mode_att = xps_att(root, "TileMode");
    /*viewbox_units_att = xps_att(root, "ViewboxUnits");*/
    /*viewport_units_att = xps_att(root, "ViewportUnits");*/

    for (node = xps_down(root); node; node = xps_next(node))
    {
        if (!strcmp(xps_tag(node), "ImageBrush.Transform"))
            transform_tag = xps_down(node);
        if (!strcmp(xps_tag(node), "VisualBrush.Transform"))
            transform_tag = xps_down(node);
    }

    xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL);

    gs_make_identity(&transform);
    if (transform_att)
        xps_parse_render_transform(ctx, transform_att, &transform);
    if (transform_tag)
        xps_parse_matrix_transform(ctx, transform_tag, &transform);

    viewbox.p.x = 0.0; viewbox.p.y = 0.0;
    viewbox.q.x = 1.0; viewbox.q.y = 1.0;
    if (viewbox_att)
        xps_parse_rectangle(ctx, viewbox_att, &viewbox);

    viewport.p.x = 0.0; viewport.p.y = 0.0;
    viewport.q.x = 1.0; viewport.q.y = 1.0;
    if (viewport_att)
        xps_parse_rectangle(ctx, viewport_att, &viewport);

    /* some sanity checks on the viewport/viewbox size */
    if (fabs(viewport.q.x - viewport.p.x) < 0.01) { gs_warn("skipping tile with zero width view port"); return 0; }
    if (fabs(viewport.q.y - viewport.p.y) < 0.01) { gs_warn("skipping tile with zero height view port"); return 0; }
    if (fabs(viewbox.q.x - viewbox.p.x) < 0.01) { gs_warn("skipping tile with zero width view box"); return 0; }
    if (fabs(viewbox.q.y - viewbox.p.y) < 0.01) { gs_warn("skipping tile with zero height view box"); return 0; }

    scalex = (viewport.q.x - viewport.p.x) / (viewbox.q.x - viewbox.p.x);
    scaley = (viewport.q.y - viewport.p.y) / (viewbox.q.y - viewbox.p.y);

    tile_mode = TILE_NONE;
    if (tile_mode_att)
    {
        if (!strcmp(tile_mode_att, "None"))
            tile_mode = TILE_NONE;
        if (!strcmp(tile_mode_att, "Tile"))
            tile_mode = TILE_TILE;
        if (!strcmp(tile_mode_att, "FlipX"))
            tile_mode = TILE_FLIP_X;
        if (!strcmp(tile_mode_att, "FlipY"))
            tile_mode = TILE_FLIP_Y;
        if (!strcmp(tile_mode_att, "FlipXY"))
            tile_mode = TILE_FLIP_X_Y;
    }

    gs_gsave(ctx->pgs);

    code = xps_begin_opacity(ctx, base_uri, dict, opacity_att, NULL, false, false);
    if (code)
    {
        gs_grestore(ctx->pgs);
        return gs_rethrow(code, "cannot create transparency group");
    }

    /* TODO(tor): check viewport and tiling to see if we can set it to TILE_NONE */

    if (tile_mode != TILE_NONE)
    {
        struct tile_closure_s closure;

        gs_client_pattern gspat;
        gs_client_color gscolor;
        gs_color_space *cs;
        bool sa;

        closure.ctx = ctx;
        closure.base_uri = base_uri;
        closure.dict = dict;
        closure.tag = root;
        closure.tile_mode = tile_mode;
        closure.user = user;
        closure.func = func;

        closure.viewbox.p.x = viewbox.p.x;
        closure.viewbox.p.y = viewbox.p.y;
        closure.viewbox.q.x = viewbox.q.x;
        closure.viewbox.q.y = viewbox.q.y;

        gs_pattern1_init(&gspat);
        uid_set_UniqueID(&gspat.uid, gs_next_ids(ctx->memory, 1));
        gspat.PaintType = 1;
        gspat.TilingType = 2;
        gspat.PaintProc = xps_remap_pattern;
        gspat.client_data = &closure;

        /* We need to know if this tiling brush includes transparency.
           We could do a proper scan, but for now we'll be lazy and just look
           at the flag from scanning the page. */
        gspat.uses_transparency = ctx->has_transparency;

        gspat.XStep = viewbox.q.x - viewbox.p.x;
        gspat.YStep = viewbox.q.y - viewbox.p.y;
        gspat.BBox.p.x = viewbox.p.x;
        gspat.BBox.p.y = viewbox.p.y;
        gspat.BBox.q.x = viewbox.q.x;
        gspat.BBox.q.y = viewbox.q.y;

        if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y)
        {
            gspat.BBox.q.x += gspat.XStep;
            gspat.XStep *= 2;
        }

        if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y)
        {
            gspat.BBox.q.y += gspat.YStep;
            gspat.YStep *= 2;
        }

        gs_matrix_translate(&transform, viewport.p.x, viewport.p.y, &transform);
        gs_matrix_scale(&transform, scalex, scaley, &transform);
        gs_matrix_translate(&transform, -viewbox.p.x, -viewbox.p.y, &transform);

        cs = ctx->srgb;
        gs_setcolorspace(ctx->pgs, cs);
        gsicc_profile_reference(cs->cmm_icc_profile_data, 1);

        sa = gs_currentstrokeadjust(ctx->pgs);
        gs_setstrokeadjust(ctx->pgs, false);
        gs_makepattern(&gscolor, &gspat, &transform, ctx->pgs, NULL);
        gs_setpattern(ctx->pgs, &gscolor);
        xps_fill(ctx);
        gs_setstrokeadjust(ctx->pgs, sa);
        gsicc_profile_reference(cs->cmm_icc_profile_data, -1);

        /* gs_makepattern increments the pattern count stored in the color
         * structure. We will discard the color struct (its on the stack)
         * so we need to decrement the reference before we throw away
         * the structure.
         */
        gs_pattern_reference(&gscolor, -1);
    }
    else
    {
        xps_clip(ctx);

        gs_concat(ctx->pgs, &transform);

        gs_translate(ctx->pgs, viewport.p.x, viewport.p.y);
        gs_scale(ctx->pgs, scalex, scaley);
        gs_translate(ctx->pgs, -viewbox.p.x, -viewbox.p.y);

        gs_moveto(ctx->pgs, viewbox.p.x, viewbox.p.y);
        gs_lineto(ctx->pgs, viewbox.p.x, viewbox.q.y);
        gs_lineto(ctx->pgs, viewbox.q.x, viewbox.q.y);
        gs_lineto(ctx->pgs, viewbox.q.x, viewbox.p.y);
        gs_closepath(ctx->pgs);
        gs_clip(ctx->pgs);
        gs_newpath(ctx->pgs);

        code = func(ctx, base_uri, dict, root, user);
        if (code < 0)
        {
            xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL);
            gs_grestore(ctx->pgs);
            return gs_rethrow(code, "cannot draw tile");
        }
    }

    xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL);

    gs_grestore(ctx->pgs);

    return 0;
}
コード例 #7
0
ファイル: xpsanalyze.c プロジェクト: hackqiang/gs
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)
        {
            float opacity = atof(opacity_att);
            if (opacity < 1.0 && opacity != 0.0)
            {
                //dmputs(ctx->memory, "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 && samples[0] != 0.0)
            {
                //dmputs(ctx->memory, "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)
            {
                //dmputs(ctx->memory, "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;
}
コード例 #8
0
ファイル: xpspage.c プロジェクト: hackqiang/gs
int
xps_parse_canvas(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root)
{
    xps_resource_t *new_dict = NULL;
    xps_item_t *node;
    char *opacity_mask_uri;
    int code;

    char *transform_att;
    char *clip_att;
    char *opacity_att;
    char *opacity_mask_att;

    xps_item_t *transform_tag = NULL;
    xps_item_t *clip_tag = NULL;
    xps_item_t *opacity_mask_tag = NULL;

    gs_matrix transform;

    transform_att = xps_att(root, "RenderTransform");
    clip_att = xps_att(root, "Clip");
    opacity_att = xps_att(root, "Opacity");
    opacity_mask_att = xps_att(root, "OpacityMask");

    for (node = xps_down(root); node; node = xps_next(node))
    {
        if (!strcmp(xps_tag(node), "Canvas.Resources") && xps_down(node))
        {
            code = xps_parse_resource_dictionary(ctx, &new_dict, base_uri, xps_down(node));
            if (code)
                return gs_rethrow(code, "cannot load Canvas.Resources");
            if (new_dict && new_dict != dict)
            {
                new_dict->parent = dict;
                dict = new_dict;
            }
        }

        if (!strcmp(xps_tag(node), "Canvas.RenderTransform"))
            transform_tag = xps_down(node);
        if (!strcmp(xps_tag(node), "Canvas.Clip"))
            clip_tag = xps_down(node);
        if (!strcmp(xps_tag(node), "Canvas.OpacityMask"))
            opacity_mask_tag = xps_down(node);
    }

    opacity_mask_uri = base_uri;
    xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL);
    xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL);
    xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri);

    gs_gsave(ctx->pgs);

    gs_make_identity(&transform);
    if (transform_att)
        xps_parse_render_transform(ctx, transform_att, &transform);
    if (transform_tag)
        xps_parse_matrix_transform(ctx, transform_tag, &transform);
    gs_concat(ctx->pgs, &transform);

    if (clip_att || clip_tag)
    {
        if (clip_att)
            xps_parse_abbreviated_geometry(ctx, clip_att);
        if (clip_tag)
            xps_parse_path_geometry(ctx, dict, clip_tag, 0);
        xps_clip(ctx);
    }

    code = xps_begin_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag, false, false);
    if (code)
    {
        gs_grestore(ctx->pgs);
        return gs_rethrow(code, "cannot create transparency group");
    }

    for (node = xps_down(root); node; node = xps_next(node))
    {
        code = xps_parse_element(ctx, base_uri, dict, node);
        if (code)
        {
            xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);
            gs_grestore(ctx->pgs);
            return gs_rethrow(code, "cannot parse child of Canvas");
        }
    }

    xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);

    gs_grestore(ctx->pgs);

    if (new_dict)
        xps_free_resource_dictionary(ctx, new_dict);

    return 0;
}
コード例 #9
0
ファイル: xpspage.c プロジェクト: hackqiang/gs
int
xps_parse_fixed_page(xps_context_t *ctx, xps_part_t *part)
{
    xps_item_t *root, *node;
    xps_resource_t *dict;
    char *width_att;
    char *height_att;
    char base_uri[1024];
    char *s;
    int code;

    if_debug1m('|', ctx->memory, "doc: parsing page %s\n", part->name);

    xps_strlcpy(base_uri, part->name, sizeof base_uri);
    s = strrchr(base_uri, '/');
    if (s)
        s[1] = 0;

    root = xps_parse_xml(ctx, part->data, part->size);
    if (!root)
        return gs_rethrow(-1, "cannot parse xml");

    if (strcmp(xps_tag(root), "FixedPage"))
        return gs_throw1(-1, "expected FixedPage element (found %s)", xps_tag(root));

    width_att = xps_att(root, "Width");
    height_att = xps_att(root, "Height");

    if (!width_att)
        return gs_throw(-1, "FixedPage missing required attribute: Width");
    if (!height_att)
        return gs_throw(-1, "FixedPage missing required attribute: Height");

    dict = NULL;

    /* Setup new page */
    {
        gs_memory_t *mem = ctx->memory;
        gs_state *pgs = ctx->pgs;
        gx_device *dev = gs_currentdevice(pgs);
        gs_param_float_array fa;
        float fv[2];
        gs_c_param_list list;

        gs_c_param_list_write(&list, mem);

        fv[0] = atoi(width_att) / 96.0 * 72.0;
        fv[1] = atoi(height_att) / 96.0 * 72.0;
        fa.persistent = false;
        fa.data = fv;
        fa.size = 2;

        code = param_write_float_array((gs_param_list *)&list, ".MediaSize", &fa);
        if ( code >= 0 )
        {
            gs_c_param_list_read(&list);
            code = gs_putdeviceparams(dev, (gs_param_list *)&list);
        }
        gs_c_param_list_release(&list);

        /* nb this is for the demo it is wrong and should be removed */
        gs_initgraphics(pgs);

        /* 96 dpi default - and put the origin at the top of the page */

        gs_initmatrix(pgs);

        code = gs_scale(pgs, 72.0/96.0, -72.0/96.0);
        if (code < 0)
            return gs_rethrow(code, "cannot set page transform");

        code = gs_translate(pgs, 0.0, -atoi(height_att));
        if (code < 0)
            return gs_rethrow(code, "cannot set page transform");

        code = gs_erasepage(pgs);
        if (code < 0)
            return gs_rethrow(code, "cannot clear page");
    }

    /* Pre-parse looking for transparency */

    ctx->has_transparency = 0;

    for (node = xps_down(root); node; node = xps_next(node))
    {
        if (!strcmp(xps_tag(node), "FixedPage.Resources") && xps_down(node))
            if (xps_resource_dictionary_has_transparency(ctx, base_uri, xps_down(node)))
                ctx->has_transparency = 1;
        if (xps_element_has_transparency(ctx, base_uri, node))
            ctx->has_transparency = 1;
    }

    /* save the state with the original device before we push */
    gs_gsave(ctx->pgs);

    if (ctx->use_transparency && ctx->has_transparency)
    {
        code = gs_push_pdf14trans_device(ctx->pgs, false);
        if (code < 0)
        {
            gs_grestore(ctx->pgs);
            return gs_rethrow(code, "cannot install transparency device");
        }
    }

    /* Draw contents */

    for (node = xps_down(root); node; node = xps_next(node))
    {
        if (!strcmp(xps_tag(node), "FixedPage.Resources") && xps_down(node))
        {
            code = xps_parse_resource_dictionary(ctx, &dict, base_uri, xps_down(node));
            if (code)
            {
                gs_pop_pdf14trans_device(ctx->pgs, false);
                gs_grestore(ctx->pgs);
                return gs_rethrow(code, "cannot load FixedPage.Resources");
            }
        }
        code = xps_parse_element(ctx, base_uri, dict, node);
        if (code)
        {
            gs_pop_pdf14trans_device(ctx->pgs, false);
            gs_grestore(ctx->pgs);
            return gs_rethrow(code, "cannot parse child of FixedPage");
        }
    }

    if (ctx->use_transparency && ctx->has_transparency)
    {
        code = gs_pop_pdf14trans_device(ctx->pgs, false);
        if (code < 0)
        {
            gs_grestore(ctx->pgs);
            return gs_rethrow(code, "cannot uninstall transparency device");
        }
    }

    /* Flush page */
    {
        code = xps_show_page(ctx, 1, true); /* copies, flush */
        if (code < 0)
        {
            gs_grestore(ctx->pgs);
            return gs_rethrow(code, "cannot flush page");
        }
    }

    /* restore the original device, discarding the pdf14 compositor */
    gs_grestore(ctx->pgs);

    if (dict)
    {
        xps_free_resource_dictionary(ctx, dict);
    }

    xps_free_item(ctx, root);

    return 0;
}