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; } }
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; } }
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; } } }
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; }
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++); } } }
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; }
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++); } } }
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; }
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; }
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; }
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; }