Пример #1
0
static void scan_Coverage(fz_context *ctx, struct ft2vert_st *ret, const FT_Bytes top)
{
	int i;
	FT_Bytes s = top;
	struct Coverage_st *t;

	t = &ret->SubTable[ret->SubTableCount].Coverage;
	t->CoverageFormat = BYTE2(s);
	switch (t->CoverageFormat)
	{
	case 1: 
		t->GlyphCount = BYTE2(s);
		t->GlyphArray = fz_calloc(ctx, t->GlyphCount, sizeof(t->GlyphArray[0]));
		memset(t->GlyphArray, 0, t->GlyphCount * sizeof(t->GlyphArray[0]));
		for (i = 0; i < t->GlyphCount; i++)
			t->GlyphArray[i] = BYTE2(s);
		break;
	case 2:
		t->RangeCount = BYTE2(s);
		t->RangeRecord = fz_calloc(ctx, t->RangeCount, sizeof(t->RangeRecord[0]));
		memset(t->RangeRecord, 0, t->RangeCount * sizeof(t->RangeRecord[0]));
		for (i = 0; i < t->RangeCount; i++)
		{
			t->RangeRecord[i].Start = BYTE2(s);
			t->RangeRecord[i].End   = BYTE2(s);
			s += 2; /* drop StartCoverageIndex */
		}
		break;
	default:
		fz_warn(ctx, "scan_Coverage: unknown CoverageFormat (%d).", t->CoverageFormat);
		return;
	}
	ret->SubTableCount++;
}
Пример #2
0
/* Convert Unicode/PdfDocEncoding string into ucs-2 */
unsigned short *
pdf_to_ucs2(fz_obj *src)
{
	unsigned char *srcptr = (unsigned char *) fz_to_str_buf(src);
	unsigned short *dstptr, *dst;
	int srclen = fz_to_str_len(src);
	int i;

	if (srclen >= 2 && srcptr[0] == 254 && srcptr[1] == 255)
	{
		dstptr = dst = fz_calloc((srclen - 2) / 2 + 1, sizeof(short));
		for (i = 2; i + 1 < srclen; i += 2)
			*dstptr++ = srcptr[i] << 8 | srcptr[i+1];
	}
	else if (srclen >= 2 && srcptr[0] == 255 && srcptr[1] == 254)
	{
		dstptr = dst = fz_calloc((srclen - 2) / 2 + 1, sizeof(short));
		for (i = 2; i + 1 < srclen; i += 2)
			*dstptr++ = srcptr[i] | srcptr[i+1] << 8;
	}
	else
	{
		dstptr = dst = fz_calloc(srclen + 1, sizeof(short));
		for (i = 0; i < srclen; i++)
			*dstptr++ = pdf_doc_encoding[srcptr[i]];
	}

	*dstptr = '\0';
	return dst;
}
Пример #3
0
static void
pdf_makewidthtable(pdf_fontdesc *fontdesc)
{
	fz_font *font = fontdesc->font;
	int i, k, cid, gid;

	font->widthcount = 0;
	for (i = 0; i < fontdesc->nhmtx; i++)
	{
		for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++)
		{
			cid = pdf_lookupcmap(fontdesc->encoding, k);
			gid = pdf_fontcidtogid(fontdesc, cid);
			if (gid > font->widthcount)
				font->widthcount = gid;
		}
	}
	font->widthcount ++;

	font->widthtable = fz_calloc(font->widthcount, sizeof(int));
	memset(font->widthtable, 0, sizeof(int) * font->widthcount);

	for (i = 0; i < fontdesc->nhmtx; i++)
	{
		for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++)
		{
			cid = pdf_lookupcmap(fontdesc->encoding, k);
			gid = pdf_fontcidtogid(fontdesc, cid);
			if (gid >= 0 && gid < font->widthcount)
				font->widthtable[gid] = fontdesc->hmtx[i].w;
		}
	}
}
Пример #4
0
/* Used while reading the individual xref sections from a file */
pdf_xref_entry *pdf_get_populating_xref_entry(pdf_document *doc, int num)
{
	/* Return an entry within the xref currently being populated */
	pdf_xref *xref;
	int i;

	if (doc->num_xref_sections == 0)
	{
		doc->xref_sections = fz_calloc(doc->ctx, 1, sizeof(pdf_xref));
		doc->num_xref_sections = 1;
	}

	/* Ensure all xref sections map this entry */
	for (i = doc->num_xref_sections - 1; i >= 0; i--)
	{
		xref = &doc->xref_sections[i];

		if (num >= xref->len)
			pdf_resize_xref(doc->ctx, xref, num+1);
		else
			break; /* Remaining sections already of sufficient size */
	}

	/* Loop leaves xref pointing at the populating section */
	return &doc->xref_sections[doc->num_xref_sections-1].table[num];
}
Пример #5
0
static void scan_SubTable(fz_context *ctx, struct ft2vert_st *ret, const FT_Bytes top)
{
	int i;
	FT_Bytes s = top;
	FT_Offset Coverage;
	struct SingleSubst_st *t;

	t = &ret->SubTable[ret->SubTableCount].SingleSubst;
	t->SubstFormat = BYTE2(s);
	Coverage       = BYTE2(s);
	scan_Coverage(ctx, ret, top + Coverage);
	switch (t->SubstFormat)
	{
	case 1: /* SingleSubstFormat1 */
		t->DeltaGlyphID = BYTE2(s);
		break;
	case 2: /* SingleSubstFormat2 */
		t->GlyphCount   = BYTE2(s);
		t->Substitute = fz_calloc(ctx, t->GlyphCount, sizeof(t->Substitute[0]));
		memset(t->Substitute, 0, t->GlyphCount * sizeof(t->Substitute[0]));
		for (i = 0; i < t->GlyphCount; i++)
			t->Substitute[i] = BYTE2(s);
		break;
	default:
		fz_warn(ctx, "scan_SubTable: unknown SubstFormat (%d).", t->SubstFormat);
	}
}
Пример #6
0
static fz_error
pdf_read_ocg(pdf_xref *xref)
{
	fz_obj *obj, *ocg;
	int len, i;
	pdf_ocg_descriptor *desc;

	obj = fz_dict_gets(fz_dict_gets(xref->trailer, "Root"), "OCProperties");
	if (obj == NULL)
		return fz_okay;
	ocg = fz_dict_gets(obj, "OCGs");
	if (ocg == NULL || !fz_is_array(ocg))
		/* Not ever supposed to happen, but live with it. */
		return fz_okay;
	len = fz_array_len(ocg);
	desc = fz_malloc(sizeof(*desc));
	desc->len = len;
	desc->ocgs = fz_calloc(len, sizeof(*desc->ocgs));
	desc->intent = NULL;

	for (i=0; i < len; i++)
	{
		fz_obj *o = fz_array_get(ocg, i);
		desc->ocgs[i].num = fz_to_num(o);
		desc->ocgs[i].gen = fz_to_gen(o);
		desc->ocgs[i].state = 0;
	}
	xref->ocg = desc;

	return pdf_ocg_set_config(xref, 0);
}
Пример #7
0
fz_device *
fz_new_device_of_size(fz_context *ctx, int size)
{
	fz_device *dev = Memento_label(fz_calloc(ctx, 1, size), "fz_device");
	dev->refs = 1;
	return dev;
}
Пример #8
0
/*
		Ensure we have an incremental xref section where we can store
		updated versions of indirect objects
*/
static void ensure_incremental_xref(pdf_document *doc)
{
	fz_context *ctx = doc->ctx;

	if (!doc->xref_altered)
	{
		pdf_xref *xref = &doc->xref_sections[0];
		pdf_xref *pxref;
		pdf_xref_entry *new_table = fz_calloc(ctx, xref->len, sizeof(pdf_xref_entry));
		pdf_obj *trailer = NULL;

		fz_var(trailer);
		fz_try(ctx)
		{
			trailer = pdf_copy_dict(xref->trailer);
			doc->xref_sections = fz_resize_array(ctx, doc->xref_sections, doc->num_xref_sections + 1, sizeof(pdf_xref));
			xref = &doc->xref_sections[0];
			pxref = &doc->xref_sections[1];
			memmove(pxref, xref, doc->num_xref_sections * sizeof(pdf_xref));
			/* xref->len is already correct */
			xref->table = new_table;
			xref->trailer = trailer;
			doc->num_xref_sections++;
			doc->xref_altered = 1;
		}
		fz_catch(ctx)
		{
			fz_free(ctx, new_table);
			pdf_drop_obj(trailer);
			fz_rethrow(ctx);
		}
	}
Пример #9
0
static void
pdf_load_type5_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict,
	int funcs, pdf_function **func, fz_stream *stream)
{
	struct mesh_params p;
	struct vertex *buf, *ref;
	int first;
	int ncomp;
	int i, k;
	fz_context *ctx = xref->ctx;

	pdf_load_mesh_params(xref, dict, &p);

	if (funcs > 0)
	{
		ncomp = 1;
		pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]);
	}
	else
		ncomp = shade->colorspace->n;

	ref = fz_calloc(ctx, p.vprow, sizeof(struct vertex));
	buf = fz_calloc(ctx, p.vprow, sizeof(struct vertex));
	first = 1;

	while (!fz_is_eof_bits(stream))
	{
		for (i = 0; i < p.vprow; i++)
		{
			buf[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1);
			buf[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1);
			for (k = 0; k < ncomp; k++)
				buf[i].c[k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]);
		}

		if (!first)
			for (i = 0; i < p.vprow - 1; i++)
				pdf_add_quad(ctx, shade,
					&ref[i], &ref[i+1], &buf[i+1], &buf[i]);

		memcpy(ref, buf, p.vprow * sizeof(struct vertex));
		first = 0;
	}

	fz_free(ctx, ref);
	fz_free(ctx, buf);
}
Пример #10
0
fz_archive *
fz_new_archive_of_size(fz_context *ctx, fz_stream *file, int size)
{
	fz_archive *arch;
	arch = Memento_label(fz_calloc(ctx, 1, size), "fz_archive");
	arch->file = fz_keep_stream(ctx, file);
	return arch;
}
Пример #11
0
fz_ael *
fz_newael(void)
{
	fz_ael *ael;
	ael = fz_malloc(sizeof(fz_ael));
	ael->cap = 64;
	ael->len = 0;
	ael->edges = fz_calloc(ael->cap, sizeof(fz_edge*));
	return ael;
}
Пример #12
0
static void renumberobjs(void)
{
	pdf_xrefentry *oldxref;
	int newlen;
	int num;

	/* Apply renumber map to indirect references in all objects in xref */
	renumberobj(xref->trailer);
	for (num = 0; num < xref->len; num++)
	{
		fz_obj *obj = xref->table[num].obj;

		if (fz_isindirect(obj))
		{
			obj = fz_newindirect(renumbermap[fz_tonum(obj)], 0, xref);
			pdf_updateobject(xref, num, 0, obj);
			fz_dropobj(obj);
		}
		else
		{
			renumberobj(obj);
		}
	}

	/* Create new table for the reordered, compacted xref */
	oldxref = xref->table;
	xref->table = fz_calloc(xref->len, sizeof(pdf_xrefentry));
	xref->table[0] = oldxref[0];

	/* Move used objects into the new compacted xref */
	newlen = 0;
	for (num = 1; num < xref->len; num++)
	{
		if (uselist[num])
		{
			if (newlen < renumbermap[num])
				newlen = renumbermap[num];
			xref->table[renumbermap[num]] = oldxref[num];
		}
		else
		{
			if (oldxref[num].obj)
				fz_dropobj(oldxref[num].obj);
		}
	}

	fz_free(oldxref);

	/* Update the used objects count in compacted xref */
	xref->len = newlen + 1;

	/* Update list of used objects to fit with compacted xref */
	for (num = 1; num < xref->len; num++)
		uselist[num] = 1;
}
Пример #13
0
void *fz_new_rasterizer_of_size(fz_context *ctx, int size, const fz_rasterizer_fns *fns)
{
	fz_rasterizer *rast = fz_calloc(ctx, 1, size);

	rast->fns = *fns;
	rast->clip.x0 = rast->clip.y0 = BBOX_MIN;
	rast->clip.x1 = rast->clip.y1 = BBOX_MAX;

	rast->bbox.x0 = rast->bbox.y0 = BBOX_MAX;
	rast->bbox.x1 = rast->bbox.y1 = BBOX_MIN;

	return rast;
}
Пример #14
0
fz_path *
fz_clone_path(fz_path *old)
{
	fz_path *path;

	path = fz_malloc(sizeof(fz_path));
	path->len = old->len;
	path->cap = old->len;
	path->items = fz_calloc(path->cap, sizeof(fz_path_item));
	memcpy(path->items, old->items, sizeof(fz_path_item) * path->len);

	return path;
}
Пример #15
0
fz_path *
fz_clonepath(fz_path *old)
{
	fz_path *path;

	path = fz_malloc(sizeof(fz_path));
	path->len = old->len;
	path->cap = old->len;
	path->els = fz_calloc(path->cap, sizeof(fz_pathel));
	memcpy(path->els, old->els, sizeof(fz_pathel) * path->len);

	return path;
}
Пример #16
0
fz_gel *
fz_new_gel(fz_context *ctx)
{
	fz_gel *gel;

	gel = fz_malloc(ctx, sizeof(fz_gel));
	gel->ctx = ctx;
	gel->cap = 512;
	gel->len = 0;
	gel->edges = fz_calloc(ctx, gel->cap, sizeof(fz_edge));

	gel->clip.x0 = gel->clip.y0 = BBOX_MAX;
	gel->clip.x1 = gel->clip.y1 = BBOX_MIN;

	gel->bbox.x0 = gel->bbox.y0 = BBOX_MAX;
	gel->bbox.x1 = gel->bbox.y1 = BBOX_MIN;

	gel->acap = 64;
	gel->alen = 0;
	gel->active = fz_calloc(ctx, gel->acap, sizeof(fz_edge*));

	return gel;
}
Пример #17
0
fz_stream *
fz_open_concat(fz_context *ctx, int len, int pad)
{
	struct concat_filter *state;

	state = fz_calloc(ctx, 1, sizeof(struct concat_filter) + (len-1)*sizeof(fz_stream *));
	state->max = len;
	state->count = 0;
	state->current = 0;
	state->pad = pad;
	state->ws = 0; /* We never send padding byte at the start */

	return fz_new_stream(ctx, state, read_concat, close_concat);
}
Пример #18
0
fz_stream *
fz_open_concat(fz_context *ctx, int len, int pad)
{
	struct concat_filter *state;

	state = fz_calloc(ctx, 1, sizeof(struct concat_filter) + (len-1)*sizeof(fz_stream *));
	state->max = len;
	state->count = 0;
	state->current = 0;
	state->pad = pad;
	state->ws_buf = 32;

	return fz_new_stream(ctx, state, next_concat, close_concat, rebind_concat);
}
Пример #19
0
fz_text *
fz_clonetext(fz_text *old)
{
	fz_text *text;

	text = fz_malloc(sizeof(fz_text));
	text->font = fz_keepfont(old->font);
	text->trm = old->trm;
	text->wmode = old->wmode;
	text->len = old->len;
	text->cap = text->len;
	text->els = fz_calloc(text->len, sizeof(fz_textel));
	memcpy(text->els, old->els, text->len * sizeof(fz_textel));

	return text;
}
Пример #20
0
fz_gel *
fz_newgel(void)
{
	fz_gel *gel;

	gel = fz_malloc(sizeof(fz_gel));
	gel->cap = 512;
	gel->len = 0;
	gel->edges = fz_calloc(gel->cap, sizeof(fz_edge));

	gel->clip.x0 = gel->clip.y0 = BBOX_MAX;
	gel->clip.x1 = gel->clip.y1 = BBOX_MIN;

	gel->bbox.x0 = gel->bbox.y0 = BBOX_MAX;
	gel->bbox.x1 = gel->bbox.y1 = BBOX_MIN;

	return gel;
}
Пример #21
0
fz_obj *
fz_new_array(fz_context *ctx, int initialcap)
{
	fz_obj *obj;
	int i;

	obj = fz_malloc(ctx, sizeof(fz_obj));
	obj->refs = 1;
	obj->kind = FZ_ARRAY;

	obj->u.a.len = 0;
	obj->u.a.cap = initialcap > 1 ? initialcap : 6;

	obj->u.a.items = fz_calloc(ctx, obj->u.a.cap, sizeof(fz_obj*));
	for (i = 0; i < obj->u.a.cap; i++)
		obj->u.a.items[i] = NULL;

	return obj;
}
Пример #22
0
fz_obj *
fz_newarray(int initialcap)
{
    fz_obj *obj;
    int i;

    obj = fz_malloc(sizeof(fz_obj));
    obj->refs = 1;
    obj->kind = FZ_ARRAY;

    obj->u.a.len = 0;
    obj->u.a.cap = initialcap > 1 ? initialcap : 6;

    obj->u.a.items = fz_calloc(obj->u.a.cap, sizeof(fz_obj*));
    for (i = 0; i < obj->u.a.cap; i++)
        obj->u.a.items[i] = nil;

    return obj;
}
Пример #23
0
static fz_error
parseTTCs(char *path, pdf_xref *xref)
{
	FONT_COLLECTION fontcollection;
	ULONG i, numFonts, *offsettable = NULL;
	fz_error err;

	fz_stream *file = fz_open_file(xref->ctx, path);
	if (!file)
	{
		err = fz_error_make(xref->ctx, "fonterror : %s not found", path);
		goto cleanup;
	}

	err = safe_read(file, (char *)&fontcollection, sizeof(FONT_COLLECTION));
	if (err) goto cleanup;
	if (BEtoHl(fontcollection.Tag) != TTAG_ttcf)
	{
		err = fz_error_make(xref->ctx, "fonterror : wrong format");
		goto cleanup;
	}
	if (BEtoHl(fontcollection.Version) != TTC_VERSION1 &&
		BEtoHl(fontcollection.Version) != TTC_VERSION2)
	{
		err = fz_error_make(xref->ctx, "fonterror : invalid version");
		goto cleanup;
	}

	numFonts = BEtoHl(fontcollection.NumFonts);
	offsettable = fz_calloc(xref->ctx, numFonts, sizeof(ULONG));

	err = safe_read(file, (char *)offsettable, numFonts * sizeof(ULONG));
	for (i = 0; i < numFonts && !err; i++)
		err = parseTTF(file, BEtoHl(offsettable[i]), i, path, xref);

cleanup:
	fz_free(xref->ctx, offsettable);
	if (file)
		fz_close(file);

	return err;
}
Пример #24
0
pdf_graft_map *
pdf_new_graft_map(fz_context *ctx, pdf_document *src)
{
	pdf_graft_map *map = NULL;

	map = fz_malloc_struct(ctx, pdf_graft_map);

	fz_try(ctx)
	{
		map->len = pdf_xref_len(ctx, src);
		map->dst_from_src = fz_calloc(ctx, map->len, sizeof(int));
	}
	fz_catch(ctx)
	{
		fz_free(ctx, map);
		fz_rethrow(ctx);
	}
	map->refs = 1;
	return map;
}
Пример #25
0
/* source and dest can be same */
static fz_error
decodeunicodeBE(fz_context *ctx, char* source, int sourcelen, char* dest, int destlen)
{
	WCHAR *tmp;
	int converted, i;

	if (sourcelen % 2 != 0)
		return fz_error_make(ctx, "fonterror : invalid unicode string");

	tmp = fz_calloc(ctx, sourcelen / 2 + 1, sizeof(WCHAR));
	for (i = 0; i < sourcelen / 2; i++)
		tmp[i] = BEtoHs(((WCHAR *)source)[i]);
	tmp[sourcelen / 2] = '\0';

	converted = WideCharToMultiByte(CP_UTF8, 0, tmp, -1, dest, destlen, NULL, NULL);
	fz_free(ctx, tmp);
	if (!converted)
		return fz_error_make(ctx, "fonterror : invalid unicode string");

	return fz_okay;
}
Пример #26
0
static void scan_Lookup(fz_context *ctx, struct ft2vert_st *ret, const FT_Bytes top)
{
	int i;
	FT_Bytes s = top;
	FT_UShort LookupType;
	FT_UShort LookupFlag;
	FT_UShort SubTableCount;
	FT_UShort SubTable;

	LookupType    = BYTE2(s);
	LookupFlag    = BYTE2(s);
	SubTableCount = BYTE2(s);
	SubTable      = BYTE2(s);

	ret->SubTable = fz_calloc(ctx, SubTableCount, sizeof(ret->SubTable[0]));
	memset(ret->SubTable, 0, SubTableCount * sizeof(ret->SubTable[0]));
	for (i = 0; i < SubTableCount; i++)
		scan_SubTable(ctx, ret, top + SubTable);

	if (ret->SubTableCount != SubTableCount)
		fz_warn(ctx, "scan_Lookup: SubTableCount (=%d) is not expected (=%d).\n",
				ret->SubTableCount, SubTableCount);
}
Пример #27
0
int main(int argc, char **argv)
{
	fz_error error;
	char *infile;
	char *outfile = "out.pdf";
	char *password = "";
	int c, num;
	int subset;

	while ((c = fz_getopt(argc, argv, "adgp:")) != -1)
	{
		switch (c)
		{
		case 'p': password = fz_optarg; break;
		case 'g': dogarbage ++; break;
		case 'd': doexpand ++; break;
		case 'a': doascii ++; break;
		default: usage(); break;
		}
	}

	if (argc - fz_optind < 1)
		usage();

	infile = argv[fz_optind++];

	if (argc - fz_optind > 0 &&
		(strstr(argv[fz_optind], ".pdf") || strstr(argv[fz_optind], ".PDF")))
	{
		outfile = argv[fz_optind++];
	}

	subset = 0;
	if (argc - fz_optind > 0)
		subset = 1;

	error = pdf_openxref(&xref, infile, password);
	if (error)
		die(fz_rethrow(error, "cannot open input file '%s'", infile));

	out = fopen(outfile, "wb");
	if (!out)
		die(fz_throw("cannot open output file '%s'", outfile));

	fprintf(out, "%%PDF-%d.%d\n", xref->version / 10, xref->version % 10);
	fprintf(out, "%%\316\274\341\277\246\n\n");

	uselist = fz_calloc(xref->len + 1, sizeof(char));
	ofslist = fz_calloc(xref->len + 1, sizeof(int));
	genlist = fz_calloc(xref->len + 1, sizeof(int));
	renumbermap = fz_calloc(xref->len + 1, sizeof(int));

	for (num = 0; num < xref->len; num++)
	{
		uselist[num] = 0;
		ofslist[num] = 0;
		genlist[num] = 0;
		renumbermap[num] = num;
	}

	/* Make sure any objects hidden in compressed streams have been loaded */
	preloadobjstms();

	/* Only retain the specified subset of the pages */
	if (subset)
		retainpages(argc, argv);

	/* Sweep & mark objects from the trailer */
	if (dogarbage >= 1)
		sweepobj(xref->trailer);

	/* Coalesce and renumber duplicate objects */
	if (dogarbage >= 3)
		removeduplicateobjs();

	/* Compact xref by renumbering and removing unused objects */
	if (dogarbage >= 2)
		compactxref();

	/* Make renumbering affect all indirect references and update xref */
	if (dogarbage >= 2)
		renumberobjs();

	writepdf();

	if (fclose(out))
		die(fz_throw("cannot close output file '%s'", outfile));

	fz_free(uselist);
	fz_free(ofslist);
	fz_free(genlist);
	fz_free(renumbermap);

	pdf_freexref(xref);

	fz_flushwarnings();

	return 0;
}
Пример #28
0
void
fz_output_pcl_bitmap(fz_output *out, const fz_bitmap *bitmap, fz_pcl_options *pcl)
{
    unsigned char *data, *out_data;
    int y, ss, rmask, line_size;
    fz_context *ctx;
    int num_blank_lines;
    int compression = -1;
    unsigned char *prev_row = NULL;
    unsigned char *out_row_mode_2 = NULL;
    unsigned char *out_row_mode_3 = NULL;
    int out_count;
    int max_mode_2_size;
    int max_mode_3_size;

    if (!out || !bitmap)
        return;

    ctx = out->ctx;

    if (pcl->features & HACK__IS_A_OCE9050)
    {
        /* Enter HPGL/2 mode, begin plot, Initialise (start plot), Enter PCL mode */
        fz_puts(out, "\033%1BBPIN;\033%1A");
    }

    pcl_header(out, pcl, 1, bitmap->xres);

    fz_var(prev_row);
    fz_var(out_row_mode_2);
    fz_var(out_row_mode_3);

    fz_try(ctx)
    {
        num_blank_lines = 0;
        rmask = ~0 << (-bitmap->w & 7);
        line_size = (bitmap->w + 7)/8;
        max_mode_2_size = line_size + (line_size/127) + 1;
        max_mode_3_size = line_size + (line_size/8) + 1;
        prev_row = fz_calloc(ctx, line_size, sizeof(unsigned char));
        out_row_mode_2 = fz_calloc(ctx, max_mode_2_size, sizeof(unsigned char));
        out_row_mode_3 = fz_calloc(ctx, max_mode_3_size, sizeof(unsigned char));

        /* Transfer raster graphics. */
        data = bitmap->samples;
        ss = bitmap->stride;
        for (y = 0; y < bitmap->h; y++, data += ss)
        {
            unsigned char *end_data = data + line_size;

            if ((end_data[-1] & rmask) == 0)
            {
                end_data--;
                while (end_data > data && end_data[-1] == 0)
                    end_data--;
            }
            if (end_data == data)
            {
                /* Blank line */
                num_blank_lines++;
                continue;
            }
            wind();

            /* We've reached a non-blank line. */
            /* Put out a spacing command if necessary. */
            if (num_blank_lines == y) {
                /* We're at the top of a page. */
                if (pcl->features & PCL_ANY_SPACING)
                {
                    if (num_blank_lines > 0)
                        fz_printf(out, "\033*p+%dY", num_blank_lines * bitmap->yres);
                    /* Start raster graphics. */
                    fz_puts(out, "\033*r1A");
                }
                else if (pcl->features & PCL_MODE_3_COMPRESSION)
                {
                    /* Start raster graphics. */
                    fz_puts(out, "\033*r1A");
                    for (; num_blank_lines; num_blank_lines--)
                        fz_puts(out, "\033*b0W");
                }
                else
                {
                    /* Start raster graphics. */
                    fz_puts(out, "\033*r1A");
                    for (; num_blank_lines; num_blank_lines--)
                        fz_puts(out, "\033*bW");
                }
            }

            /* Skip blank lines if any */
            else if (num_blank_lines != 0)
            {
                /* Moving down from current position causes head
                 * motion on the DeskJet, so if the number of lines
                 * is small, we're better off printing blanks.
                 *
                 * For Canon LBP4i and some others, <ESC>*b<n>Y
                 * doesn't properly clear the seed row if we are in
                 * compression mode 3.
                 */
                if ((num_blank_lines < MIN_SKIP_LINES && compression != 3) ||
                        !(pcl->features & PCL_ANY_SPACING))
                {
                    int mode_3ns = ((pcl->features & PCL_MODE_3_COMPRESSION) && !(pcl->features & PCL_ANY_SPACING));
                    if (mode_3ns && compression != 2)
                    {
                        /* Switch to mode 2 */
                        fz_puts(out, from3to2);
                        compression = 2;
                    }
                    if (pcl->features & PCL_MODE_3_COMPRESSION)
                    {
                        /* Must clear the seed row. */
                        fz_puts(out, "\033*b1Y");
                        num_blank_lines--;
                    }
                    if (mode_3ns)
                    {
                        for (; num_blank_lines; num_blank_lines--)
                            fz_puts(out, "\033*b0W");
                    }
                    else
                    {
                        for (; num_blank_lines; num_blank_lines--)
                            fz_puts(out, "\033*bW");
                    }
                }
                else if (pcl->features & PCL3_SPACING)
                    fz_printf(out, "\033*p+%dY", num_blank_lines * bitmap->yres);
                else
                    fz_printf(out, "\033*b%dY", num_blank_lines);
                /* Clear the seed row (only matters for mode 3 compression). */
                memset(prev_row, 0, line_size);
            }
            num_blank_lines = 0;

            /* Choose the best compression mode for this particular line. */
            if (pcl->features & PCL_MODE_3_COMPRESSION)
            {
                /* Compression modes 2 and 3 are both available. Try
                 * both and see which produces the least output data.
                 */
                int count3 = mode3compress(out_row_mode_3, data, prev_row, line_size);
                int count2 = mode2compress(out_row_mode_2, data, line_size);
                int penalty3 = (compression == 3 ? 0 : penalty_from2to3);
                int penalty2 = (compression == 2 ? 0 : penalty_from3to2);

                if (count3 + penalty3 < count2 + penalty2)
                {
                    if (compression != 3)
                        fz_puts(out, from2to3);
                    compression = 3;
                    out_data = (unsigned char *)out_row_mode_3;
                    out_count = count3;
                }
                else
                {
                    if (compression != 2)
                        fz_puts(out, from3to2);
                    compression = 2;
                    out_data = (unsigned char *)out_row_mode_2;
                    out_count = count2;
                }
            }
            else if (pcl->features & PCL_MODE_2_COMPRESSION)
            {
                out_data = out_row_mode_2;
                out_count = mode2compress(out_row_mode_2, data, line_size);
            }
            else
            {
                out_data = data;
                out_count = line_size;
            }

            /* Transfer the data */
            fz_printf(out, "\033*b%dW", out_count);
            fz_write(out, out_data, out_count);
        }

        /* end raster graphics and eject page */
        fz_puts(out, "\033*rB\f");

        if (pcl->features & HACK__IS_A_OCE9050)
        {
            /* Pen up, pen select, advance full page, reset */
            fz_puts(out, "\033%1BPUSP0PG;\033E");
        }
    }
    fz_always(ctx)
    {
        fz_free(ctx, prev_row);
        fz_free(ctx, out_row_mode_2);
        fz_free(ctx, out_row_mode_3);
    }
    fz_catch(ctx)
    {
        fz_rethrow(ctx);
    }
}
Пример #29
0
void *
pdf_new_processor(fz_context *ctx, int size)
{
	return Memento_label(fz_calloc(ctx, 1, size), "pdf_processor");
}
Пример #30
0
fz_error
pdf_loadtounicode(pdf_fontdesc *font, pdf_xref *xref,
                  char **strings, char *collection, fz_obj *cmapstm)
{
    fz_error error = fz_okay;
    pdf_cmap *cmap;
    int cid;
    int ucsbuf[8];
    int ucslen;
    int i;

    if (pdf_isstream(xref, fz_tonum(cmapstm), fz_togen(cmapstm)))
    {
        pdf_logfont("tounicode embedded cmap\n");

        error = pdf_loadembeddedcmap(&cmap, xref, cmapstm);
        if (error)
            return fz_rethrow(error, "cannot load embedded cmap (%d %d R)", fz_tonum(cmapstm), fz_togen(cmapstm));

        font->tounicode = pdf_newcmap();

        for (i = 0; i < (strings ? 256 : 65536); i++)
        {
            cid = pdf_lookupcmap(font->encoding, i);
            if (cid >= 0)
            {
                ucslen = pdf_lookupcmapfull(cmap, i, ucsbuf);
                if (ucslen == 1)
                    pdf_maprangetorange(font->tounicode, cid, cid, ucsbuf[0]);
                if (ucslen > 1)
                    pdf_maponetomany(font->tounicode, cid, ucsbuf, ucslen);
            }
        }

        pdf_sortcmap(font->tounicode);

        pdf_dropcmap(cmap);
    }

    else if (collection)
    {
        pdf_logfont("tounicode cid collection (%s)\n", collection);

        error = fz_okay;

        if (!strcmp(collection, "Adobe-CNS1"))
            error = pdf_loadsystemcmap(&font->tounicode, "Adobe-CNS1-UCS2");
        else if (!strcmp(collection, "Adobe-GB1"))
            error = pdf_loadsystemcmap(&font->tounicode, "Adobe-GB1-UCS2");
        else if (!strcmp(collection, "Adobe-Japan1"))
            error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan1-UCS2");
        else if (!strcmp(collection, "Adobe-Japan2"))
            error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan2-UCS2"); /* where's this? */
        else if (!strcmp(collection, "Adobe-Korea1"))
            error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Korea1-UCS2");

        if (error)
            return fz_rethrow(error, "cannot load tounicode system cmap %s-UCS2", collection);
    }

    if (strings)
    {
        pdf_logfont("tounicode strings\n");

        /* TODO one-to-many mappings */

        font->ncidtoucs = 256;
        font->cidtoucs = fz_calloc(256, sizeof(unsigned short));

        for (i = 0; i < 256; i++)
        {
            if (strings[i])
                font->cidtoucs[i] = pdf_lookupagl(strings[i]);
            else
                font->cidtoucs[i] = '?';
        }
    }

    if (!font->tounicode && !font->cidtoucs)
    {
        pdf_logfont("tounicode could not be loaded\n");
        /* TODO: synthesize a ToUnicode if it's a freetype font with
        * cmap and/or post tables or if it has glyph names. */
    }

    return fz_okay;
}