Beispiel #1
0
static void
xps_add_fixed_document(xps_context_t *ctx, char *name)
{
    xps_document_t *fixdoc;

    /* Check for duplicates first */
    for (fixdoc = ctx->first_fixdoc; fixdoc; fixdoc = fixdoc->next)
        if (!strcmp(fixdoc->name, name))
            return;

    if_debug1m('|', ctx->memory, "doc: adding fixdoc %s\n", name);

    fixdoc = xps_alloc(ctx, sizeof(xps_document_t));
    if (!fixdoc) {
        gs_throw(gs_error_VMerror, "out of memory: xps_add_fixed_document\n");
        return;
    }
    fixdoc->name = xps_strdup(ctx, name);
    fixdoc->next = NULL;

    if (!ctx->first_fixdoc)
    {
        ctx->first_fixdoc = fixdoc;
        ctx->last_fixdoc = fixdoc;
    }
    else
    {
        ctx->last_fixdoc->next = fixdoc;
        ctx->last_fixdoc = fixdoc;
    }
}
Beispiel #2
0
static void
xps_add_fixed_page(xps_context_t *ctx, char *name, int width, int height)
{
    xps_page_t *page;

    /* Check for duplicates first */
    for (page = ctx->first_page; page; page = page->next)
        if (!strcmp(page->name, name))
            return;

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

    page = xps_alloc(ctx, sizeof(xps_page_t));
    if (!page) {
        gs_throw(gs_error_VMerror, "out of memory: xps_add_fixed_page\n");
        return;
    }
    page->name = xps_strdup(ctx, name);
    page->width = width;
    page->height = height;
    page->next = NULL;

    if (!ctx->first_page)
    {
        ctx->first_page = page;
        ctx->last_page = page;
    }
    else
    {
        ctx->last_page->next = page;
        ctx->last_page = page;
    }
}
Beispiel #3
0
static void
on_text(void *zp, char *buf, int len)
{
    xps_parser_t *parser = zp;
    xps_context_t *ctx = parser->ctx;
    char *atts[3];
    int i;

    if (parser->error)
        return;

    for (i = 0; i < len; i++)
    {
        if (!is_xml_space(buf[i]))
        {
            char *tmp = xps_alloc(ctx, len + 1);
            if (!tmp)
            {
                parser->error = "out of memory";
                return;
            }

            atts[0] = "";
            atts[1] = tmp;
            atts[2] = NULL;

            memcpy(tmp, buf, len);
            tmp[len] = 0;
            on_open_tag(zp, "", atts);
            on_close_tag(zp, "");
            xps_free(ctx, tmp);
            return;
        }
    }
}
Beispiel #4
0
xps_font_t *
xps_new_font(xps_context_t *ctx, byte *buf, int buflen, int index)
{
    xps_font_t *font;
    int code;

    font = xps_alloc(ctx, sizeof(xps_font_t));
    if (!font)
    {
        gs_throw(gs_error_VMerror, "out of memory");
        return NULL;
    }

    font->data = buf;
    font->length = buflen;
    font->font = NULL;

    font->subfontid = index;
    font->cmaptable = 0;
    font->cmapsubcount = 0;
    font->cmapsubtable = 0;
    font->usepua = 0;

    font->cffdata = 0;
    font->cffend = 0;
    font->gsubrs = 0;
    font->subrs = 0;
    font->charstrings = 0;

    if (memcmp(font->data, "OTTO", 4) == 0)
        code = xps_init_postscript_font(ctx, font);
    else if (memcmp(font->data, "\0\1\0\0", 4) == 0)
        code = xps_init_truetype_font(ctx, font);
    else if (memcmp(font->data, "true", 4) == 0)
        code = xps_init_truetype_font(ctx, font);
    else if (memcmp(font->data, "ttcf", 4) == 0)
        code = xps_init_truetype_font(ctx, font);
    else
    {
        xps_free_font(ctx, font);
        gs_throw(-1, "not an opentype font");
        return NULL;
    }

    if (code < 0)
    {
        xps_free_font(ctx, font);
        gs_rethrow(-1, "cannot init font");
        return NULL;
    }

    xps_load_sfnt_cmap(font);

    return font;
}
Beispiel #5
0
static void
xps_decode_jpegxr_block(jxr_image_t image, int mx, int my, int *data)
{
    struct state *state = jxr_get_user_data(image);
    xps_context_t *ctx = state->ctx;
    xps_image_t *output = state->output;
    int depth;
    unsigned char *p;
    int x, y, k;

    if (!output->samples)
    {
        output->width = jxr_get_IMAGE_WIDTH(image);
        output->height = jxr_get_IMAGE_HEIGHT(image);
        output->comps = jxr_get_IMAGE_CHANNELS(image);
        output->hasalpha = jxr_get_ALPHACHANNEL_FLAG(image);
        output->bits = 8;
        output->stride = output->width * output->comps;
        output->samples = xps_alloc(ctx, output->stride * output->height);
        if (!output->samples) {
            gs_throw(gs_error_VMerror, "out of memory: output->samples.\n");
            return;
        }

        switch (output->comps)
        {
        default:
        case 1: output->colorspace = ctx->gray; break;
        case 3: output->colorspace = ctx->srgb; break;
        case 4: output->colorspace = ctx->cmyk; break;
        }
    }

    depth = jxr_get_OUTPUT_BITDEPTH(image);

    my = my * 16;
    mx = mx * 16;

    for (y = 0; y < 16; y++)
    {
        if (my + y >= output->height)
            return;
        p = output->samples + (my + y) * output->stride + mx * output->comps;
        for (x = 0; x < 16; x++)
        {
            if (mx + x >= output->width)
                data += output->comps;
            else
                for (k = 0; k < output->comps; k++)
                    *p++ = scale_bits(depth, *data++);
        }
    }
}
Beispiel #6
0
xps_part_t *
xps_new_part(xps_context_t *ctx, char *name, int size)
{
    xps_part_t *part;

    part = xps_alloc(ctx, sizeof(xps_part_t));
    if (!part) {
        gs_throw(gs_error_VMerror, "out of memory: xps_new_part\n");
        return NULL;
    }
    part->name = xps_strdup(ctx, name);
    part->size = size;
    part->data = xps_alloc(ctx, size);
    if (!part->data) {
        xps_free(ctx, part);
        gs_throw(gs_error_VMerror, "out of memory: xps_new_part\n");
        return NULL;
    }

    return part;
}
Beispiel #7
0
static void
xps_decode_jpegxr_alpha_block(jxr_image_t image, int mx, int my, int *data)
{
    struct state *state = jxr_get_user_data(image);
    xps_context_t *ctx = state->ctx;
    xps_image_t *output = state->output;
    int depth;
    unsigned char *p;
    int x, y, k;

    if (!output->alpha)
    {
        output->alpha = xps_alloc(ctx, output->width * output->height);
        if (!output->alpha) {
            gs_throw(gs_error_VMerror, "out of memory: output->alpha.\n");
            return;
        }
    }

    depth = jxr_get_OUTPUT_BITDEPTH(image);

    my = my * 16;
    mx = mx * 16;

    for (y = 0; y < 16; y++)
    {
        if (my + y >= output->height)
            return;
        p = output->alpha + (my + y) * output->width + mx;
        for (x = 0; x < 16; x++)
        {
            if (mx + x >= output->width)
                data ++;
            else
                *p++ = scale_bits(depth, *data++);
        }
    }
}
Beispiel #8
0
int
xps_decode_jpeg(xps_context_t *ctx, byte *rbuf, int rlen, xps_image_t *image)
{
    jpeg_decompress_data jddp;
    stream_DCT_state state;
    stream_cursor_read rp;
    stream_cursor_write wp;
    int code;
    int wlen;
    byte *wbuf;
    jpeg_saved_marker_ptr curr_marker;

    s_init_state((stream_state*)&state, &s_DCTD_template, ctx->memory);
    state.report_error = xps_report_error;

    s_DCTD_template.set_defaults((stream_state*)&state);

    state.jpeg_memory = ctx->memory;
    state.data.decompress = &jddp;

    jddp.templat = s_DCTD_template;
    jddp.memory = ctx->memory;
    jddp.scanline_buffer = NULL;

    if ((code = gs_jpeg_create_decompress(&state)) < 0)
        return gs_throw(-1, "cannot gs_jpeg_create_decompress");

    s_DCTD_template.init((stream_state*)&state);

    rp.ptr = rbuf - 1;
    rp.limit = rbuf + rlen - 1;

    /* read the header only by not having a write buffer */
    wp.ptr = 0;
    wp.limit = 0;

    /* Set up to save the ICC marker APP2.
     * According to the spec we should be getting APP1 APP2 and APP13.
     * Library gets APP0 and APP14. */
    jpeg_save_markers(&(jddp.dinfo), 0xe2, 0xFFFF);

    code = s_DCTD_template.process((stream_state*)&state, &rp, &wp, true);
    if (code != 1)
        return gs_throw(-1, "premature EOF or error in jpeg");

    /* Check if we had an ICC profile */
    curr_marker = jddp.dinfo.marker_list;
    while (curr_marker != NULL)
    {
        if (curr_marker->marker == 0xe2)
        {
            /* Found ICC profile. Create a buffer and copy over now.
             * Strip JPEG APP2 14 byte header */
            image->profilesize = curr_marker->data_length - 14;
            image->profile = xps_alloc(ctx, image->profilesize);
            if (image->profile)
            {
                /* If we can't create it, just ignore */
                memcpy(image->profile, &(curr_marker->data[14]), image->profilesize);
            }
            break;
        }
        curr_marker = curr_marker->next;
    }

    image->width = jddp.dinfo.output_width;
    image->height = jddp.dinfo.output_height;
    image->comps = jddp.dinfo.output_components;
    image->bits = 8;
    image->stride = image->width * image->comps;

    if (image->comps == 1)
        image->colorspace = ctx->gray;
    if (image->comps == 3)
        image->colorspace = ctx->srgb;
    if (image->comps == 4)
        image->colorspace = ctx->cmyk;

    if (jddp.dinfo.density_unit == 1)
    {
        image->xres = jddp.dinfo.X_density;
        image->yres = jddp.dinfo.Y_density;
    }
    else if (jddp.dinfo.density_unit == 2)
    {
        image->xres = (int)(jddp.dinfo.X_density * 2.54 + 0.5);
        image->yres = (int)(jddp.dinfo.Y_density * 2.54 + 0.5);
    }
    else
    {
        image->xres = 96;
        image->yres = 96;
    }

    wlen = image->stride * image->height;
    wbuf = xps_alloc(ctx, wlen);
    if (!wbuf)
        return gs_throw1(gs_error_VMerror, "out of memory allocating samples: %d", wlen);

    image->samples = wbuf;

    wp.ptr = wbuf - 1;
    wp.limit = wbuf + wlen - 1;

    code = s_DCTD_template.process((stream_state*)&state, &rp, &wp, true);
    if (code != EOFC)
        return gs_throw1(-1, "error in jpeg (code = %d)", code);

    gs_jpeg_destroy(&state);

    return gs_okay;
}
Beispiel #9
0
int
xps_decode_jpegxr(xps_context_t *ctx, byte *buf, int len, xps_image_t *output)
{
    FILE *file;
    char *name = xps_alloc(ctx, gp_file_name_sizeof);
    struct state state;
    jxr_container_t container;
    jxr_image_t image;
    int offset, alpha_offset;
    int rc;

    if (!name) {
        return gs_throw(gs_error_VMerror, "cannot allocate scratch file name buffer");
    }

    memset(output, 0, sizeof(*output));

    file = gp_open_scratch_file(ctx->memory, "jpegxr-scratch-", name, "wb+");
    if (!file) {
        xps_free(ctx, name);
        return gs_throw(gs_error_invalidfileaccess, "cannot open scratch file");
    }
    rc = fwrite(buf, 1, len, file);
    if (rc != len) {
        xps_free(ctx, name);
        return gs_throw(gs_error_invalidfileaccess, "cannot write to scratch file");
    }
    fseek(file, 0, SEEK_SET);

    container = jxr_create_container();
    rc = jxr_read_image_container(container, file);
    if (rc < 0) {
        xps_free(ctx, name);
        return gs_throw1(-1, "jxr_read_image_container: %s", jxr_error_string(rc));
    }

    offset = jxrc_image_offset(container, 0);
    alpha_offset = jxrc_alpha_offset(container, 0);

    output->xres = jxrc_width_resolution(container, 0);
    output->yres = jxrc_height_resolution(container, 0);

    image = jxr_create_input();
    jxr_set_PROFILE_IDC(image, 111);
    jxr_set_LEVEL_IDC(image, 255);
    jxr_set_pixel_format(image, jxrc_image_pixelformat(container, 0));
    jxr_set_container_parameters(image,
        jxrc_image_pixelformat(container, 0),
        jxrc_image_width(container, 0),
        jxrc_image_height(container, 0),
        jxrc_alpha_offset(container, 0),
        jxrc_image_band_presence(container, 0),
        jxrc_alpha_band_presence(container, 0), 0);

    jxr_set_block_output(image, xps_decode_jpegxr_block);
    state.ctx = ctx;
    state.output = output;
    jxr_set_user_data(image, &state);

    fseek(file, offset, SEEK_SET);
    rc = jxr_read_image_bitstream(image, file);
    if (rc < 0) {
        xps_free(ctx, name);
        return gs_throw1(-1, "jxr_read_image_bitstream: %s", jxr_error_string(rc));
    }

    jxr_destroy(image);

    if (alpha_offset > 0)
    {
        image = jxr_create_input();
        jxr_set_PROFILE_IDC(image, 111);
        jxr_set_LEVEL_IDC(image, 255);
        jxr_set_pixel_format(image, jxrc_image_pixelformat(container, 0));
        jxr_set_container_parameters(image,
            jxrc_image_pixelformat(container, 0),
            jxrc_image_width(container, 0),
            jxrc_image_height(container, 0),
            jxrc_alpha_offset(container, 0),
            jxrc_image_band_presence(container, 0),
            jxrc_alpha_band_presence(container, 0), 0);

        jxr_set_block_output(image, xps_decode_jpegxr_alpha_block);
        state.ctx = ctx;
        state.output = output;
        jxr_set_user_data(image, &state);

        fseek(file, alpha_offset, SEEK_SET);
        rc = jxr_read_image_bitstream(image, file);
        if (rc < 0) {
            xps_free(ctx, name);
            return gs_throw1(-1, "jxr_read_image_bitstream: %s", jxr_error_string(rc));
        }

        jxr_destroy(image);
    }

    jxr_destroy_container(container);

    fclose(file);
    unlink(name);
    xps_free(ctx, name);

    return gs_okay;
}
Beispiel #10
0
static void
on_open_tag(void *zp, const char *ns_name, const char **atts)
{
    xps_parser_t *parser = zp;
    xps_context_t *ctx = parser->ctx;
    xps_item_t *item;
    xps_item_t *tail;
    int namelen;
    int attslen;
    int textlen;
    const char *name;
    char *p;
    int i;

    if (parser->error)
        return;

    /* check namespace */

    name = NULL;

    p = strstr(ns_name, NS_XPS);
    if (p == ns_name)
    {
        name = strchr(ns_name, ' ') + 1;
    }

    p = strstr(ns_name, NS_MC);
    if (p == ns_name)
    {
        name = strchr(ns_name, ' ') + 1;
    }

    p = strstr(ns_name, NS_OXPS);
    if (p == ns_name)
    {
        name = strchr(ns_name, ' ') + 1;
    }

    if (!name)
    {
        dmprintf1(ctx->memory, "unknown namespace: %s\n", ns_name);
        name = ns_name;
    }

    /* count size to alloc */

    namelen = strlen(name) + 1; /* zero terminated */
    attslen = sizeof(char*); /* with space for sentinel */
    textlen = 0;
    for (i = 0; atts[i]; i++)
    {
        attslen += sizeof(char*);
        if ((i & 1) == 0)
            textlen += strlen(skip_namespace(atts[i])) + 1;
        else
            textlen += strlen(atts[i]) + 1;
    }

    item = xps_alloc(ctx, sizeof(xps_item_t) + attslen + namelen + textlen);
    if (!item) {
        parser->error = "out of memory";
        gs_throw(gs_error_VMerror, "out of memory.\n");
        return;
    }

    /* copy strings to new memory */

    item->atts = (char**) (((char*)item) + sizeof(xps_item_t));
    item->name = ((char*)item) + sizeof(xps_item_t) + attslen;
    p = ((char*)item) + sizeof(xps_item_t) + attslen + namelen;

    strcpy(item->name, name);
    for (i = 0; atts[i]; i++)
    {
        item->atts[i] = p;
        if ((i & 1) == 0)
            strcpy(item->atts[i], skip_namespace(atts[i]));
        else
            strcpy(item->atts[i], atts[i]);
        p += strlen(p) + 1;
    }

    item->atts[i] = 0;

    /* link item into tree */

    item->up = parser->head;
    item->down = NULL;
    item->next = NULL;

    if (!parser->head)
    {
        parser->root = item;
        parser->head = item;
        return;
    }

    if (!parser->head->down)
    {
        parser->head->down = item;
        parser->head->tail = item;
        parser->head = item;
        return;
    }

    tail = parser->head->tail;
    tail->next = item;
    parser->head->tail = item;
    parser->head = item;
}
Beispiel #11
0
int
xps_decode_png(xps_context_t *ctx, byte *rbuf, int rlen, xps_image_t *image)
{
    png_structp png;
    png_infop info;
    struct xps_png_io_s io;
    int npasses;
    int pass;
    int y;

    /*
     * Set up PNG structs and input source
     */

    io.ptr = rbuf;
    io.lim = rbuf + rlen;

    png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
            NULL, NULL, NULL,
            ctx->memory, xps_png_malloc, xps_png_free);
    if (!png)
        return gs_throw(-1, "png_create_read_struct");

    info = png_create_info_struct(png);
    if (!info)
        return gs_throw(-1, "png_create_info_struct");

    png_set_read_fn(png, &io, xps_png_read);
    png_set_crc_action(png, PNG_CRC_WARN_USE, PNG_CRC_WARN_USE);

    /*
     * Jump to here on errors.
     */

    if (setjmp(png_jmpbuf(png)))
    {
        png_destroy_read_struct(&png, &info, NULL);
        return gs_throw(-1, "png reading failed");
    }

    /*
     * Read PNG header
     */

    png_read_info(png, info);

    if (png_get_interlace_type(png, info) == PNG_INTERLACE_ADAM7)
    {
        npasses = png_set_interlace_handling(png);
    }
    else
    {
        npasses = 1;
    }

    if (png_get_color_type(png, info) == PNG_COLOR_TYPE_PALETTE)
    {
        png_set_palette_to_rgb(png);
    }

    if (png_get_valid(png, info, PNG_INFO_tRNS))
    {
        /* this will also expand the depth to 8-bits */
        png_set_tRNS_to_alpha(png);
    }

    png_read_update_info(png, info);

    image->width = png_get_image_width(png, info);
    image->height = png_get_image_height(png, info);
    image->comps = png_get_channels(png, info);
    image->bits = png_get_bit_depth(png, info);

    /* See if we have an icc profile */
    if (info->iccp_profile != NULL)
    {
        image->profilesize = info->iccp_proflen;
        image->profile = xps_alloc(ctx, info->iccp_proflen);
        if (image->profile)
        {
            /* If we can't create it, just ignore */
            memcpy(image->profile, info->iccp_profile, info->iccp_proflen);
        }
    }

    switch (png_get_color_type(png, info))
    {
    case PNG_COLOR_TYPE_GRAY:
        image->colorspace = ctx->gray;
        image->hasalpha = 0;
        break;

    case PNG_COLOR_TYPE_RGB:
        image->colorspace = ctx->srgb;
        image->hasalpha = 0;
        break;

    case PNG_COLOR_TYPE_GRAY_ALPHA:
        image->colorspace = ctx->gray;
        image->hasalpha = 1;
        break;

    case PNG_COLOR_TYPE_RGB_ALPHA:
        image->colorspace = ctx->srgb;
        image->hasalpha = 1;
        break;

    default:
        return gs_throw(-1, "cannot handle this png color type");
    }

    /*
     * Extract DPI, default to 96 dpi
     */

    image->xres = 96;
    image->yres = 96;

    if (info->valid & PNG_INFO_pHYs)
    {
        png_uint_32 xres, yres;
        int unit;
        png_get_pHYs(png, info, &xres, &yres, &unit);
        if (unit == PNG_RESOLUTION_METER)
        {
            image->xres = xres * 0.0254 + 0.5;
            image->yres = yres * 0.0254 + 0.5;
        }
    }

    /*
     * Read rows, filling transformed output into image buffer.
     */

    image->stride = (image->width * image->comps * image->bits + 7) / 8;

    image->samples = xps_alloc(ctx, image->stride * image->height);

    for (pass = 0; pass < npasses; pass++)
    {
        for (y = 0; y < image->height; y++)
        {
            png_read_row(png, image->samples + (y * image->stride), NULL);
        }
    }

    /*
     * Clean up memory.
     */

    png_destroy_read_struct(&png, &info, NULL);

    return gs_okay;
}