Esempio n. 1
0
static void
res_table_free(fz_context *ctx, pdf_res_table *table)
{
	int i, n;
	pdf_obj *res;

	if (table == NULL)
		return;
	if (table->hash != NULL)
	{
		n = fz_hash_len(ctx, table->hash);
		for (i = 0; i < n; i++)
		{
			res = fz_hash_get_val(ctx, table->hash, i);
			if (res)
				pdf_drop_obj(ctx, res);
		}
		fz_drop_hash(ctx, table->hash);
	}
	fz_free(ctx, table);
}
Esempio n. 2
0
static void drawimage(HDC hdc, pdfmoz_t *moz, fz_pixmap *image, int yofs)
{
    int bmpstride = ((image->w * 3 + 3) / 4) * 4;
    unsigned char *bmpdata = fz_malloc(image->h * bmpstride);
    int x, y;

    if (!bmpdata)
	return;

    for (y = 0; y < image->h; y++)
    {
	unsigned char *p = bmpdata + y * bmpstride;
	unsigned char *s = image->samples + y * image->w * 4;
	for (x = 0; x < image->w; x++)
	{
	    p[x * 3 + 0] = s[x * 4 + 3];
	    p[x * 3 + 1] = s[x * 4 + 2];
	    p[x * 3 + 2] = s[x * 4 + 1];
	}
    }

    moz->dibinf->bmiHeader.biWidth = image->w;
    moz->dibinf->bmiHeader.biHeight = -image->h;
    moz->dibinf->bmiHeader.biSizeImage = image->h * bmpstride;
    SetDIBitsToDevice(hdc,
	    0, /* destx */
	    yofs, /* desty */
	    image->w, /* destw */
	    image->h, /* desth */
	    0, /* srcx */
	    0, /* srcy */
	    0, /* startscan */
	    image->h, /* numscans */
	    bmpdata, /* pBits */
	    moz->dibinf, /* pInfo */
	    DIB_RGB_COLORS /* color use flag */
		     );

    fz_free(bmpdata);
}
fz_error *
fz_newpredict(fz_filter **fp, fz_obj *params, int encode)
{
    fz_obj *obj;

    FZ_NEWFILTER(fz_predict, p, predict);

    p->encode = encode;

    p->predictor = 1;
    p->columns = 1;
    p->colors = 1;
    p->bpc = 8;

    obj = fz_dictgets(params, "Predictor");
    if (obj) p->predictor = fz_toint(obj);

    obj = fz_dictgets(params, "Columns");
    if (obj) p->columns = fz_toint(obj);

    obj = fz_dictgets(params, "Colors");
    if (obj) p->colors = fz_toint(obj);

    obj = fz_dictgets(params, "BitsPerComponent");
    if (obj) p->bpc = fz_toint(obj);

    p->stride = (p->bpc * p->colors * p->columns + 7) / 8;
    p->bpp = (p->bpc * p->colors + 7) / 8;

    if (p->predictor >= 10) {
        p->ref = fz_malloc(p->stride);
        if (!p->ref) { fz_free(p); return fz_throw("outofmem: predictor reference buffer"); }
        memset(p->ref, 0, p->stride);
    }
    else {
        p->ref = nil;
    }

    return fz_okay;
}
Esempio n. 4
0
fz_path *
fz_clone_path(fz_context *ctx, fz_path *old)
{
	fz_path *path;

	assert(old);
	path = fz_malloc_struct(ctx, fz_path);
	fz_try(ctx)
	{
		path->len = old->len;
		path->cap = old->len;
		path->items = fz_malloc_array(ctx, path->cap, sizeof(fz_path_item));
		memcpy(path->items, old->items, sizeof(fz_path_item) * path->len);
	}
	fz_catch(ctx)
	{
		fz_free(ctx, path);
		fz_rethrow(ctx);
	}

	return path;
}
Esempio n. 5
0
fz_stream *
fz_open_fd(fz_context *ctx, int fd)
{
	fz_stream *stm;
	int *state;

	state = fz_malloc_struct(ctx, int);
	*state = fd;

	fz_try(ctx)
	{
		stm = fz_new_stream(ctx, state, read_file, close_file);
	}
	fz_catch(ctx)
	{
		fz_free(ctx, state);
		fz_rethrow(ctx);
	}
	stm->seek = seek_file;

	return stm;
}
Esempio n. 6
0
fz_stream *
fz_open_file(fz_context *ctx, const char *name)
{
#ifdef _WIN32
	char *s = (char*)name;
	wchar_t *wname, *d;
	int c, fd;
	d = wname = fz_malloc(ctx, (strlen(name)+1) * sizeof(wchar_t));
	while (*s) {
		s += fz_chartorune(&c, s);
		*d++ = c;
	}
	*d = 0;
	fd = _wopen(wname, O_BINARY | O_RDONLY, 0);
	fz_free(ctx, wname);
#else
	int fd = open(name, O_BINARY | O_RDONLY, 0);
#endif
	if (fd == -1)
		fz_throw(ctx, "cannot open %s", name);
	return fz_open_fd(ctx, fd);
}
Esempio n. 7
0
fz_error *
pdf_newstore(pdf_store **storep)
{
	fz_error *error;
	pdf_store *store;

	store = fz_malloc(sizeof(pdf_store));
	if (!store)
		return fz_outofmem;

	error = fz_newhash(&store->hash, 4096, sizeof(struct refkey));
	if (error)
	{
		fz_free(store);
		return error;
	}

	store->root = nil;

	*storep = store;
	return nil;
}
fz_error fz_openrfilter(fz_stream **stmp, fz_filter *flt, fz_stream *src)
{
	fz_error error;
	fz_stream *stm;

	stm = newstm(FZ_SFILTER);
	if (!stm)
		return fz_rethrow(-1, "out of memory: stream struct");

	error = fz_newbuffer(&stm->buffer, FZ_BUFSIZE);
	if (error)
	{
		fz_free(stm);
		return fz_rethrow(error, "cannot create buffer");
	}

	stm->chain = fz_keepstream(src);
	stm->filter = fz_keepfilter(flt);

	*stmp = stm;
	return fz_okay;
}
Esempio n. 9
0
static void execute_action(fz_context *ctx, pdf_document *doc, pdf_obj *obj, pdf_obj *a)
{
    if (a)
    {
        pdf_obj *type = pdf_dict_get(ctx, a, PDF_NAME_S);

        if (pdf_name_eq(ctx, type, PDF_NAME_JavaScript))
        {
            pdf_obj *js = pdf_dict_get(ctx, a, PDF_NAME_JS);
            if (js)
            {
                char *code = pdf_to_utf8(ctx, doc, js);
                fz_try(ctx)
                {
                    pdf_js_execute(doc->js, code);
                }
                fz_always(ctx)
                {
                    fz_free(ctx, code);
                }
                fz_catch(ctx)
                {
                    fz_rethrow(ctx);
                }
            }
        }
        else if (pdf_name_eq(ctx, type, PDF_NAME_ResetForm))
        {
            reset_form(ctx, doc, pdf_dict_get(ctx, a, PDF_NAME_Fields), pdf_to_int(ctx, pdf_dict_get(ctx, a, PDF_NAME_Flags)) & 1);
        }
        else if (pdf_name_eq(ctx, type, PDF_NAME_Named))
        {
            pdf_obj *name = pdf_dict_get(ctx, a, PDF_NAME_N);

            if (pdf_name_eq(ctx, name, PDF_NAME_Print))
                pdf_event_issue_print(ctx, doc);
        }
    }
Esempio n. 10
0
static tiff_page *
tiff_load_page(fz_context *ctx, tiff_document *doc, int number)
{
	fz_pixmap *pixmap = NULL;
	fz_image *image = NULL;
	tiff_page *page = NULL;

	if (number < 0 || number >= doc->page_count)
		return NULL;

	fz_var(pixmap);
	fz_var(image);
	fz_var(page);

	fz_try(ctx)
	{
		pixmap = fz_load_tiff_subimage(ctx, doc->buffer->data, doc->buffer->len, number);
		image = fz_new_image_from_pixmap(ctx, pixmap, NULL);

		page = fz_new_page(ctx, sizeof *page);
		page->super.bound_page = (fz_page_bound_page_fn *)tiff_bound_page;
		page->super.run_page_contents = (fz_page_run_page_contents_fn *)tiff_run_page;
		page->super.drop_page_imp = (fz_page_drop_page_imp_fn *)tiff_drop_page_imp;
		page->image = fz_keep_image(ctx, image);
	}
	fz_always(ctx)
	{
		fz_drop_image(ctx, image);
		fz_drop_pixmap(ctx, pixmap);
	}
	fz_catch(ctx)
	{
		fz_free(ctx, page);
		fz_rethrow(ctx);
	}

	return page;
}
Esempio n. 11
0
void
fz_dropstream(fz_stream *stm)
{
	stm->refs --;
	if (stm->refs == 0)
	{
		if (stm->error)
		{
			fflush(stdout);
			fz_printerror(stm->error);
			fz_droperror(stm->error);
			fflush(stderr);
			fz_warn("dropped unhandled ioerror");
		}

		if (stm->mode == FZ_SWRITE)
		{
			stm->buffer->eof = 1;
			fz_flush(stm);
		}

		switch (stm->kind)
		{
		case FZ_SFILE:
			close(stm->file);
			break;
		case FZ_SFILTER:
			fz_dropfilter(stm->filter);
			fz_dropstream(stm->chain);
			break;
		case FZ_SBUFFER:
			break;
		}

		fz_dropbuffer(stm->buffer);
		fz_free(stm);
	}
}
Esempio n. 12
0
/* Convert UCS-2 string into PdfDocEncoding for authentication */
char *
pdf_from_ucs2(pdf_document *doc, unsigned short *src)
{
    fz_context *ctx = doc->ctx;
    int i, j, len;
    char *docstr;

    len = 0;
    while (src[len])
        len++;

    docstr = fz_malloc(ctx, len + 1);

    for (i = 0; i < len; i++)
    {
        /* shortcut: check if the character has the same code point in both encodings */
        if (0 < src[i] && src[i] < 256 && pdf_doc_encoding[src[i]] == src[i]) {
            docstr[i] = src[i];
            continue;
        }

        /* search through pdf_docencoding for the character's code point */
        for (j = 0; j < 256; j++)
            if (pdf_doc_encoding[j] == src[i])
                break;
        docstr[i] = j;

        /* fail, if a character can't be encoded */
        if (!docstr[i])
        {
            fz_free(ctx, docstr);
            return NULL;
        }
    }
    docstr[len] = '\0';

    return docstr;
}
Esempio n. 13
0
fz_error
fz_newfontfromfile(fz_font **fontp, char *path, int index)
{
	fz_error error;
	fz_font *font;
	int fterr;

	error = fz_initfreetype();
	if (error)
		return fz_rethrow(error, "cannot init freetype library");

	font = fz_newfont();

	fterr = FT_New_Face(fz_ftlib, path, index, (FT_Face*)&font->ftface);
	if (fterr)
	{
		fz_free(font);
		return fz_throw("freetype: cannot load font: %s", ft_errorstring(fterr));
	}

	*fontp = font;
	return fz_okay;
}
Esempio n. 14
0
static fz_error *
openfilter(fz_stream **stmp, fz_filter *flt, fz_stream *src, int mode)
{
	fz_error *error;
	fz_stream *stm;

	stm = newstm(FZ_SFILTER, mode);
	if (!stm)
		return fz_throw("outofmem: stream struct");

	error = fz_newbuffer(&stm->buffer, FZ_BUFSIZE);
	if (error)
	{
		fz_free(stm);
		return fz_rethrow(error, "cannot create buffer");
	}

	stm->chain = fz_keepstream(src);
	stm->filter = fz_keepfilter(flt);

	*stmp = stm;
	return fz_okay;
}
Esempio n. 15
0
fz_stream *
fz_open_file(fz_context *ctx, const char *name)
{
	FILE *f;
#if defined(_WIN32) || defined(_WIN64)
	char *s = (char*)name;
	wchar_t *wname, *d;
	int c;
	d = wname = fz_malloc(ctx, (strlen(name)+1) * sizeof(wchar_t));
	while (*s) {
		s += fz_chartorune(&c, s);
		*d++ = c;
	}
	*d = 0;
	f = _wfopen(wname, L"rb");
	fz_free(ctx, wname);
#else
	f = fz_fopen(name, "rb");
#endif
	if (f == NULL)
		fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open %s: %s", name, strerror(errno));
	return fz_open_file_ptr(ctx, f);
}
Esempio n. 16
0
void
pdf_free_page(pdf_document *doc, pdf_page *page)
{
	if (page == NULL)
		return;
	pdf_drop_obj(page->resources);
	pdf_drop_obj(page->contents);
	if (page->links)
		fz_drop_link(doc->ctx, page->links);
	if (page->annots)
		pdf_free_annot(doc->ctx, page->annots);
	if (page->deleted_annots)
		pdf_free_annot(doc->ctx, page->deleted_annots);
	if (page->tmp_annots)
		pdf_free_annot(doc->ctx, page->tmp_annots);
	/* doc->focus, when not NULL, refers to one of
	 * the annotations and must be NULLed when the
	 * annotations are destroyed. doc->focus_obj
	 * keeps track of the actual annotation object. */
	doc->focus = NULL;
	pdf_drop_obj(page->me);
	fz_free(doc->ctx, page);
}
Esempio n. 17
0
fz_error
fz_newfontfrombuffer(fz_font **fontp, unsigned char *data, int len, int index)
{
	fz_error error;
	fz_font *font;
	int fterr;

	error = fz_initfreetype();
	if (error)
		return fz_rethrow(error, "cannot init freetype library");

	font = fz_newfont();

	fterr = FT_New_Memory_Face(fz_ftlib, data, len, index, (FT_Face*)&font->ftface);
	if (fterr)
	{
		fz_free(font);
		return fz_throw("freetype: cannot load font: %s", ft_errorstring(fterr));
	}

	*fontp = font;
	return fz_okay;
}
Esempio n. 18
0
fz_error *
fz_newpixmap(fz_pixmap **pixp, int x, int y, int w, int h, int n)
{
	fz_pixmap *pix;

	pix = *pixp = fz_malloc(sizeof(fz_pixmap));
	if (!pix)
		return fz_outofmem;

	pix->x = x;
	pix->y = y;
	pix->w = w;
	pix->h = h;
	pix->n = n;

	pix->samples = fz_malloc(pix->w * pix->h * pix->n * sizeof(fz_sample));
	if (!pix->samples) {
		fz_free(pix);
		return fz_outofmem;
	}

	return nil;
}
Esempio n. 19
0
fz_buffer *
fz_new_buffer(fz_context *ctx, int size)
{
	fz_buffer *b;

	size = size > 1 ? size : 16;

	b = (fz_buffer*)fz_malloc_struct(ctx, fz_buffer);
	b->refs = 1;
	try
	{
		b->data = (unsigned char*)fz_malloc(ctx, size);
	}
	catch(...)
	{
		fz_free(ctx, b);
		throw(ctx);
	}
	b->cap = size;
	b->len = 0;

	return b;
}
Esempio n. 20
0
fz_text *
fz_clone_text(fz_context *ctx, fz_text *old)
{
    fz_text *text;

    text = fz_malloc_struct(ctx, fz_text);
    text->len = old->len;
    fz_try(ctx)
    {
        text->items = fz_malloc_array(ctx, text->len, sizeof(fz_text_item));
    }
    fz_catch(ctx)
    {
        fz_free(ctx, text);
        fz_rethrow(ctx);
    }
    memcpy(text->items, old->items, text->len * sizeof(fz_text_item));
    text->font = fz_keep_font(ctx, old->font);
    text->trm = old->trm;
    text->wmode = old->wmode;
    text->cap = text->len;

    return text;
}
Esempio n. 21
0
void
fz_drop_output_context(fz_context *ctx)
{
	if (!ctx)
		return;

	if (fz_drop_imp(ctx, ctx->output, &ctx->output->refs))
	{
		fz_try(ctx)
			fz_flush_output(ctx, ctx->output->out);
		fz_catch(ctx)
			fz_warn(ctx, "cannot flush stdout");
		fz_drop_output(ctx, ctx->output->out);

		fz_try(ctx)
			fz_flush_output(ctx, ctx->output->err);
		fz_catch(ctx)
			fz_warn(ctx, "cannot flush stderr");
		fz_drop_output(ctx, ctx->output->err);

		fz_free(ctx, ctx->output);
		ctx->output = NULL;
	}
}
Esempio n. 22
0
fz_document_writer *
fz_new_cbz_writer(fz_context *ctx, const char *path, const char *options)
{
	fz_cbz_writer *wri;

	wri = fz_malloc_struct(ctx, fz_cbz_writer);
	wri->super.begin_page = cbz_begin_page;
	wri->super.end_page = cbz_end_page;
	wri->super.close_writer = cbz_close_writer;
	wri->super.drop_writer = cbz_drop_writer;

	fz_try(ctx)
	{
		fz_parse_draw_options(ctx, &wri->options, options);
		wri->zip = fz_new_zip_writer(ctx, path ? path : "out.cbz");
	}
	fz_catch(ctx)
	{
		fz_free(ctx, wri);
		fz_rethrow(ctx);
	}

	return (fz_document_writer*)wri;
}
Esempio n. 23
0
struct element *
xml_parse_document(fz_context *ctx, unsigned char *s, int n)
{
	struct parser parser;
	struct element root;
	char *p, *error;

	/* s is already null-terminated (see xps_new_part) */

	memset(&root, 0, sizeof(root));
	parser.head = &root;
	parser.ctx = ctx;

	p = convert_to_utf8(ctx, s, n);

	error = xml_parse_document_imp(&parser, p);
	if (error)
		fz_throw(ctx, "%s", error);

	if (p != (char*)s)
		fz_free(ctx, p);

	return root.down;
}
fz_buffer *
fz_new_buffer(fz_context *ctx, int size)
{
	fz_buffer *b;

	size = size > 1 ? size : 16;

	b = fz_malloc_struct(ctx, fz_buffer);
	b->refs = 1;
	fz_try(ctx)
	{
		b->data = fz_malloc(ctx, size);
	}
	fz_catch(ctx)
	{
		fz_free(ctx, b);
		fz_rethrow(ctx);
	}
	b->cap = size;
	b->len = 0;
	b->unused_bits = 0;

	return b;
}
Esempio n. 25
0
static void
drop_glyph_cache_entry(fz_context *ctx, fz_glyph_cache_entry *entry)
{
	fz_glyph_cache *cache = ctx->glyph_cache;

	if (entry->lru_next)
		entry->lru_next->lru_prev = entry->lru_prev;
	else
		cache->lru_tail = entry->lru_prev;
	if (entry->lru_prev)
		entry->lru_prev->lru_next = entry->lru_next;
	else
		cache->lru_head = entry->lru_next;
	cache->total -= fz_glyph_size(ctx, entry->val);
	if (entry->bucket_next)
		entry->bucket_next->bucket_prev = entry->bucket_prev;
	if (entry->bucket_prev)
		entry->bucket_prev->bucket_next = entry->bucket_next;
	else
		cache->entry[entry->hash] = entry->bucket_next;
	fz_drop_font(ctx, entry->key.font);
	fz_drop_glyph(ctx, entry->val);
	fz_free(ctx, entry);
}
void winconvert(pdfapp_t *app, fz_pixmap *image)
{
    int y, x;

    if (bmpdata)
	fz_free(bmpdata);

    bmpstride = ((image->w * 3 + 3) / 4) * 4;
    bmpdata = fz_malloc(image->h * bmpstride);
    if (!bmpdata)
	return;

    for (y = 0; y < image->h; y++)
    {
	unsigned char *p = bmpdata + y * bmpstride;
	unsigned char *s = image->samples + y * image->w * 4;
	for (x = 0; x < image->w; x++)
	{
	    p[x * 3 + 0] = s[x * 4 + 3];
	    p[x * 3 + 1] = s[x * 4 + 2];
	    p[x * 3 + 2] = s[x * 4 + 1];
	}
    }
}
Esempio n. 27
0
void
pdf_dropfont(pdf_fontdesc *fontdesc)
{
	if (fontdesc && --fontdesc->refs == 0)
	{
		if (fontdesc->font)
			fz_dropfont(fontdesc->font);
		if (fontdesc->buffer)
			fz_free(fontdesc->buffer);
		if (fontdesc->encoding)
			pdf_dropcmap(fontdesc->encoding);
		if (fontdesc->tottfcmap)
			pdf_dropcmap(fontdesc->tottfcmap);
		if (fontdesc->tounicode)
			pdf_dropcmap(fontdesc->tounicode);
		fz_free(fontdesc->cidtogid);
		fz_free(fontdesc->cidtoucs);
		fz_free(fontdesc->hmtx);
		fz_free(fontdesc->vmtx);
		fz_free(fontdesc);
	}
}
Esempio n. 28
0
static void drawbmp(fz_context *ctx, fz_document *doc, fz_page *page, fz_display_list *list, int pagenum, fz_cookie *cookie)
{
	float zoom;
	fz_matrix ctm;
	fz_irect ibounds;
	fz_rect bounds, tbounds;

	int w, h;
	fz_device *dev;
	HDC dc, dc_main;
	RECT rc;
	HBRUSH bg_brush;
	HBITMAP hbmp;
	BITMAPINFO bmi = { 0 };
	int bmp_data_len;
	unsigned char *bmp_data;

	fz_bound_page(doc, page, &bounds);
	zoom = resolution / 72;
	fz_pre_scale(fz_rotate(&ctm, rotation), zoom, zoom);
	tbounds = bounds;
	fz_round_rect(&ibounds, fz_transform_rect(&tbounds, &ctm));

	w = width;
	h = height;
	if (res_specified)
	{
		fz_round_rect(&ibounds, &tbounds);
		if (w && ibounds.x1 - ibounds.x0 <= w)
			w = 0;
		if (h && ibounds.y1 - ibounds.y0 <= h)
			h = 0;
	}
	if (w || h)
	{
		float scalex = w / (tbounds.x1 - tbounds.x0);
		float scaley = h / (tbounds.y1 - tbounds.y0);
		fz_matrix scale_mat;
		if (w == 0)
			scalex = fit ? 1.0f : scaley;
		if (h == 0)
			scaley = fit ? 1.0f : scalex;
		if (!fit)
			scalex = scaley = min(scalex, scaley);
		fz_concat(&ctm, &ctm, fz_scale(&scale_mat, scalex, scaley));
		tbounds = bounds;
		fz_transform_rect(&tbounds, &ctm);
	}
	fz_round_rect(&ibounds, &tbounds);
	fz_rect_from_irect(&tbounds, &ibounds);

	w = ibounds.x1 - ibounds.x0;
	h = ibounds.y1 - ibounds.y0;

	dc_main = GetDC(NULL);
	dc = CreateCompatibleDC(dc_main);
	hbmp = CreateCompatibleBitmap(dc_main, w, h);
	DeleteObject(SelectObject(dc, hbmp));

	SetRect(&rc, 0, 0, w, h);
	bg_brush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF));
	FillRect(dc, &rc, bg_brush);
	DeleteObject(bg_brush);

	dev = fz_new_gdiplus_device(ctx, dc, &tbounds);
	if (list)
		fz_run_display_list(list, dev, &ctm, &tbounds, cookie);
	else
		fz_run_page(doc, page, dev, &ctm, cookie);
	fz_free_device(dev);

	bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
	bmi.bmiHeader.biWidth = w;
	bmi.bmiHeader.biHeight = output_format == OUT_TGA ? -h : h;
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = output_format == OUT_TGA ? 32 : 24;
	bmi.bmiHeader.biCompression = BI_RGB;

	bmp_data_len = output_format == OUT_TGA ? w * h * 4 : ((w * 3 + 3) / 4) * 4 * h;
	bmp_data = fz_malloc(ctx, bmp_data_len);
	if (!GetDIBits(dc, hbmp, 0, h, bmp_data, &bmi, DIB_RGB_COLORS))
		fz_throw(ctx, FZ_ERROR_GENERIC, "cannot draw page %d in PDF file '%s'", pagenum, filename);

	DeleteDC(dc);
	ReleaseDC(NULL, dc_main);
	DeleteObject(hbmp);

	if (output)
	{
		char buf[512];
		FILE *f;

		sprintf(buf, output, pagenum);
		f = fopen(buf, "wb");
		if (!f)
			fz_throw(ctx, FZ_ERROR_GENERIC, "could not create raster file '%s'", buf);

		if (output_format == OUT_TGA)
		{
			fz_pixmap *pix = fz_new_pixmap_with_data(ctx, fz_device_bgr(ctx), w, h, bmp_data);
			fz_write_tga(ctx, pix, buf, 0);
			fz_drop_pixmap(ctx, pix);
		}
		else
		{
			BITMAPFILEHEADER bmpfh = { 0 };
			static const int one = 1;
			if (!*(char *)&one)
				fz_throw(ctx, FZ_ERROR_GENERIC, "rendering to BMP is not supported on big-endian architectures");

			bmpfh.bfType = MAKEWORD('B', 'M');
			bmpfh.bfOffBits = sizeof(bmpfh) + sizeof(bmi);
			bmpfh.bfSize = bmpfh.bfOffBits + bmp_data_len;

			fwrite(&bmpfh, sizeof(bmpfh), 1, f);
			fwrite(&bmi, sizeof(bmi), 1, f);
			fwrite(bmp_data, 1, bmp_data_len, f);
		}

		fclose(f);
	}

	if (showmd5)
	{
		fz_pixmap *pix = fz_new_pixmap_with_data(ctx, fz_device_bgr(ctx), bmp_data_len / 4 / h, h, bmp_data);
		unsigned char digest[16];
		int i;

		fz_md5_pixmap(pix, digest);
		printf(" ");
		for (i = 0; i < 16; i++)
			printf("%02x", digest[i]);

		fz_drop_pixmap(ctx, pix);
	}

	fz_free(ctx, bmp_data);
}
Esempio n. 29
0
static pdf_font_desc *
pdf_load_simple_font(pdf_document *xref, pdf_obj *dict)
{
	pdf_obj *descriptor;
	pdf_obj *encoding;
	pdf_obj *widths;
	unsigned short *etable = NULL;
	pdf_font_desc *fontdesc = NULL;
	char *subtype;
	FT_Face face;
	FT_CharMap cmap;
	int symbolic;
	int kind;

	char *basefont;
	char *estrings[256];
	char ebuffer[256][32];
	int i, k, n;
	int fterr;
	fz_context *ctx = xref->ctx;

	fz_var(fontdesc);
	fz_var(etable);

	basefont = pdf_to_name(pdf_dict_gets(dict, "BaseFont"));

	/* Load font file */
	fz_try(ctx)
	{
		fontdesc = pdf_new_font_desc(ctx);

		descriptor = pdf_dict_gets(dict, "FontDescriptor");
		if (descriptor)
			pdf_load_font_descriptor(fontdesc, xref, descriptor, NULL, basefont);
		else
			pdf_load_builtin_font(ctx, fontdesc, basefont);

		/* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */
		if (descriptor && pdf_is_string(pdf_dict_gets(descriptor, "FontName")) &&
			!pdf_dict_gets(dict, "ToUnicode") &&
			!strcmp(pdf_to_name(pdf_dict_gets(dict, "Encoding")), "WinAnsiEncoding") &&
			pdf_to_int(pdf_dict_gets(descriptor, "Flags")) == 4)
		{
			char *cp936fonts[] = {
				"\xCB\xCE\xCC\xE5", "SimSun,Regular",
				"\xBA\xDA\xCC\xE5", "SimHei,Regular",
				"\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular",
				"\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular",
				"\xC1\xA5\xCA\xE9", "SimLi,Regular",
				NULL
			};
			for (i = 0; cp936fonts[i]; i += 2)
				if (!strcmp(basefont, cp936fonts[i]))
					break;
			if (cp936fonts[i])
			{
				fz_warn(ctx, "workaround for S22PDF lying about chinese font encodings");
				pdf_drop_font(ctx, fontdesc);
				fontdesc = pdf_new_font_desc(ctx);
				pdf_load_font_descriptor(fontdesc, xref, descriptor, "Adobe-GB1", cp936fonts[i+1]);
				fontdesc->encoding = pdf_load_system_cmap(ctx, "GBK-EUC-H");
				fontdesc->to_unicode = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2");
				fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2");

				face = fontdesc->font->ft_face;
				kind = ft_kind(face);
				goto skip_encoding;
			}
		}

		face = fontdesc->font->ft_face;
		kind = ft_kind(face);

		/* Encoding */

		symbolic = fontdesc->flags & 4;

		if (face->num_charmaps > 0)
			cmap = face->charmaps[0];
		else
			cmap = NULL;

		for (i = 0; i < face->num_charmaps; i++)
		{
			FT_CharMap test = face->charmaps[i];

			if (kind == TYPE1)
			{
				if (test->platform_id == 7)
					cmap = test;
			}

			if (kind == TRUETYPE)
			{
				if (test->platform_id == 1 && test->encoding_id == 0)
					cmap = test;
				if (test->platform_id == 3 && test->encoding_id == 1)
					cmap = test;
				if (symbolic && test->platform_id == 3 && test->encoding_id == 0)
					cmap = test;
			}
		}

		if (cmap)
		{
			fterr = FT_Set_Charmap(face, cmap);
			if (fterr)
				fz_warn(ctx, "freetype could not set cmap: %s", ft_error_string(fterr));
		}
		else
			fz_warn(ctx, "freetype could not find any cmaps");

		etable = fz_malloc_array(ctx, 256, sizeof(unsigned short));
		fontdesc->size += 256 * sizeof(unsigned short);
		for (i = 0; i < 256; i++)
		{
			estrings[i] = NULL;
			etable[i] = 0;
		}

		encoding = pdf_dict_gets(dict, "Encoding");
		if (encoding)
		{
			if (pdf_is_name(encoding))
				pdf_load_encoding(estrings, pdf_to_name(encoding));

			if (pdf_is_dict(encoding))
			{
				pdf_obj *base, *diff, *item;

				base = pdf_dict_gets(encoding, "BaseEncoding");
				if (pdf_is_name(base))
					pdf_load_encoding(estrings, pdf_to_name(base));
				else if (!fontdesc->is_embedded && !symbolic)
					pdf_load_encoding(estrings, "StandardEncoding");

				diff = pdf_dict_gets(encoding, "Differences");
				if (pdf_is_array(diff))
				{
					n = pdf_array_len(diff);
					k = 0;
					for (i = 0; i < n; i++)
					{
						item = pdf_array_get(diff, i);
						if (pdf_is_int(item))
							k = pdf_to_int(item);
						if (pdf_is_name(item) && k >= 0 && k < nelem(estrings))
							estrings[k++] = pdf_to_name(item);
					}
				}
			}
		}

		/* start with the builtin encoding */
		for (i = 0; i < 256; i++)
			etable[i] = ft_char_index(face, i);

		fz_lock(ctx, FZ_LOCK_FREETYPE);

		/* built-in and substitute fonts may be a different type than what the document expects */
		subtype = pdf_to_name(pdf_dict_gets(dict, "Subtype"));
		if (!strcmp(subtype, "Type1"))
			kind = TYPE1;
		else if (!strcmp(subtype, "MMType1"))
			kind = TYPE1;
		else if (!strcmp(subtype, "TrueType"))
			kind = TRUETYPE;
		else if (!strcmp(subtype, "CIDFontType0"))
			kind = TYPE1;
		else if (!strcmp(subtype, "CIDFontType2"))
			kind = TRUETYPE;

		/* encode by glyph name where we can */
		if (kind == TYPE1)
		{
			for (i = 0; i < 256; i++)
			{
				if (estrings[i])
				{
					etable[i] = FT_Get_Name_Index(face, estrings[i]);
					if (etable[i] == 0)
					{
						int aglcode = pdf_lookup_agl(estrings[i]);
						const char **dupnames = pdf_lookup_agl_duplicates(aglcode);
						while (*dupnames)
						{
							etable[i] = FT_Get_Name_Index(face, (char*)*dupnames);
							if (etable[i])
								break;
							dupnames++;
						}
					}
				}
			}
		}

		/* encode by glyph name where we can */
		if (kind == TRUETYPE)
		{
			/* Unicode cmap */
			if (!symbolic && face->charmap && face->charmap->platform_id == 3)
			{
				for (i = 0; i < 256; i++)
				{
					if (estrings[i])
					{
						int aglcode = pdf_lookup_agl(estrings[i]);
						if (!aglcode)
							etable[i] = FT_Get_Name_Index(face, estrings[i]);
						else
							etable[i] = ft_char_index(face, aglcode);
					}
				}
			}

			/* MacRoman cmap */
			else if (!symbolic && face->charmap && face->charmap->platform_id == 1)
			{
				for (i = 0; i < 256; i++)
				{
					if (estrings[i])
					{
						k = lookup_mre_code(estrings[i]);
						if (k <= 0)
							etable[i] = FT_Get_Name_Index(face, estrings[i]);
						else
							etable[i] = ft_char_index(face, k);
					}
				}
			}

			/* Symbolic cmap */
			else if (!face->charmap || face->charmap->encoding != FT_ENCODING_MS_SYMBOL)
			{
				for (i = 0; i < 256; i++)
				{
					if (estrings[i])
					{
						etable[i] = FT_Get_Name_Index(face, estrings[i]);
						if (etable[i] == 0)
							etable[i] = ft_char_index(face, i);
					}
				}
			}
		}

		/* try to reverse the glyph names from the builtin encoding */
		for (i = 0; i < 256; i++)
		{
			if (etable[i] && !estrings[i])
			{
				if (FT_HAS_GLYPH_NAMES(face))
				{
					fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32);
					if (fterr)
						fz_warn(ctx, "freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr));
					if (ebuffer[i][0])
						estrings[i] = ebuffer[i];
				}
				else
				{
					estrings[i] = (char*) pdf_win_ansi[i]; /* discard const */
				}
			}
		}

		/* symbolic Type 1 fonts with an implicit encoding and non-standard glyph names */
		if (kind == TYPE1 && symbolic)
		{
			for (i = 0; i < 256; i++)
				if (etable[i] && estrings[i] && !pdf_lookup_agl(estrings[i]))
					estrings[i] = (char*) pdf_standard[i];
		}

		fz_unlock(ctx, FZ_LOCK_FREETYPE);

		fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1);
		fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding);
		fontdesc->cid_to_gid_len = 256;
		fontdesc->cid_to_gid = etable;

		fz_try(ctx)
		{
			pdf_load_to_unicode(xref, fontdesc, estrings, NULL, pdf_dict_gets(dict, "ToUnicode"));
		}
		fz_catch(ctx)
		{
			fz_warn(ctx, "cannot load ToUnicode CMap");
		}

	skip_encoding:

		/* Widths */

		pdf_set_default_hmtx(ctx, fontdesc, fontdesc->missing_width);

		widths = pdf_dict_gets(dict, "Widths");
		if (widths)
		{
			int first, last;

			first = pdf_to_int(pdf_dict_gets(dict, "FirstChar"));
			last = pdf_to_int(pdf_dict_gets(dict, "LastChar"));

			if (first < 0 || last > 255 || first > last)
				first = last = 0;

			for (i = 0; i < last - first + 1; i++)
			{
				int wid = pdf_to_int(pdf_array_get(widths, i));
				pdf_add_hmtx(ctx, fontdesc, i + first, i + first, wid);
			}
		}
		else
		{
			fz_lock(ctx, FZ_LOCK_FREETYPE);
			fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72);
			if (fterr)
				fz_warn(ctx, "freetype set character size: %s", ft_error_string(fterr));
			for (i = 0; i < 256; i++)
			{
				pdf_add_hmtx(ctx, fontdesc, i, i, ft_width(ctx, fontdesc, i));
			}
			fz_unlock(ctx, FZ_LOCK_FREETYPE);
		}

		pdf_end_hmtx(ctx, fontdesc);
	}
	fz_catch(ctx)
	{
		if (fontdesc && etable != fontdesc->cid_to_gid)
			fz_free(ctx, etable);
		pdf_drop_font(ctx, fontdesc);
		fz_throw(ctx, "cannot load simple font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
	}
	return fontdesc;
}
Esempio n. 30
0
static fz_pixmap *
decomp_image_from_stream(fz_context *ctx, fz_stream *stm, pdf_image *image, int in_line, int indexed, int l2factor, int native_l2factor, int cache)
{
	fz_pixmap *tile = NULL;
	fz_pixmap *existing_tile;
	int stride, len, i;
	unsigned char *samples = NULL;
	int f = 1<<native_l2factor;
	int w = (image->base.w + f-1) >> native_l2factor;
	int h = (image->base.h + f-1) >> native_l2factor;
	pdf_image_key *key = NULL;

	fz_var(tile);
	fz_var(samples);
	fz_var(key);

	fz_try(ctx)
	{
		tile = fz_new_pixmap(ctx, image->base.colorspace, w, h);
		tile->interpolate = image->interpolate;

		stride = (w * image->n * image->base.bpc + 7) / 8;

		samples = fz_malloc_array(ctx, h, stride);

		len = fz_read(stm, samples, h * stride);
		if (len < 0)
		{
			fz_throw(ctx, "cannot read image data");
		}

		/* Make sure we read the EOF marker (for inline images only) */
		if (in_line)
		{
			unsigned char tbuf[512];
			fz_try(ctx)
			{
				int tlen = fz_read(stm, tbuf, sizeof tbuf);
				if (tlen > 0)
					fz_warn(ctx, "ignoring garbage at end of image");
			}
			fz_catch(ctx)
			{
				fz_warn(ctx, "ignoring error at end of image");
			}
		}

		/* Pad truncated images */
		if (len < stride * h)
		{
			fz_warn(ctx, "padding truncated image");
			memset(samples + len, 0, stride * h - len);
		}

		/* Invert 1-bit image masks */
		if (image->imagemask)
		{
			/* 0=opaque and 1=transparent so we need to invert */
			unsigned char *p = samples;
			len = h * stride;
			for (i = 0; i < len; i++)
				p[i] = ~p[i];
		}

		fz_unpack_tile(tile, samples, image->n, image->base.bpc, stride, indexed);

		fz_free(ctx, samples);
		samples = NULL;

		if (image->usecolorkey)
			pdf_mask_color_key(tile, image->n, image->colorkey);

		if (indexed)
		{
			fz_pixmap *conv;
			fz_decode_indexed_tile(tile, image->decode, (1 << image->base.bpc) - 1);
			conv = pdf_expand_indexed_pixmap(ctx, tile);
			fz_drop_pixmap(ctx, tile);
			tile = conv;
		}
		else
		{
			fz_decode_tile(tile, image->decode);
		}
	}
	fz_always(ctx)
	{
		fz_close(stm);
	}
	fz_catch(ctx)
	{
		if (tile)
			fz_drop_pixmap(ctx, tile);
		fz_free(ctx, samples);

		fz_rethrow(ctx);
	}

	/* Now apply any extra subsampling required */
	if (l2factor - native_l2factor > 0)
	{
		if (l2factor - native_l2factor > 8)
			l2factor = native_l2factor + 8;
		fz_subsample_pixmap(ctx, tile, l2factor - native_l2factor);
	}

	if (!cache)
		return tile;

	/* Now we try to cache the pixmap. Any failure here will just result
	 * in us not caching. */
	fz_try(ctx)
	{
		key = fz_malloc_struct(ctx, pdf_image_key);
		key->refs = 1;
		key->image = fz_keep_image(ctx, &image->base);
		key->l2factor = l2factor;
		existing_tile = fz_store_item(ctx, key, tile, fz_pixmap_size(ctx, tile), &pdf_image_store_type);
		if (existing_tile)
		{
			/* We already have a tile. This must have been produced by a
			 * racing thread. We'll throw away ours and use that one. */
			fz_drop_pixmap(ctx, tile);
			tile = existing_tile;
		}
	}
	fz_always(ctx)
	{
		pdf_drop_image_key(ctx, key);
	}
	fz_catch(ctx)
	{
		/* Do nothing */
	}

	return tile;
}