Ejemplo n.º 1
0
static void
fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm, float alpha)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	fz_pixmap *converted = nil;
	fz_pixmap *scaled = nil;
	int dx, dy;

	if (!model)
	{
		fz_warn("cannot render image directly to an alpha mask");
		return;
	}

	if (image->w == 0 || image->h == 0)
		return;

	if (image->colorspace != model)
	{
		converted = fz_newpixmap(model, image->x, image->y, image->w, image->h);
		fz_convertpixmap(image, converted);
		image = converted;
	}

#ifdef SMOOTHSCALE
	dx = sqrtf(ctm.a * ctm.a + ctm.c * ctm.c);
	dy = sqrtf(ctm.b * ctm.b + ctm.d * ctm.d);
	if (dx < image->w && dy < image->h)
	{
		scaled = fz_smoothtransformpixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy);
		if (scaled == NULL)
		{
			if (dx < 1)
				dx = 1;
			if (dy < 1)
				dy = 1;
			scaled = fz_smoothscalepixmap(image, image->x, image->y, dx, dy);
		}
		if (scaled != NULL)
			image = scaled;
	}
#else
	if (fz_calcimagescale(image, ctm, &dx, &dy))
	{
		scaled = fz_scalepixmap(image, dx, dy);
		image = scaled;
	}
#endif

	fz_paintimage(dev->dest, dev->scissor, image, ctm, alpha * 255);

	if (scaled)
		fz_droppixmap(scaled);
	if (converted)
		fz_droppixmap(converted);
}
Ejemplo n.º 2
0
void
fz_droprenderer(fz_renderer *gc)
{
	if (gc->dest) fz_droppixmap(gc->dest);
	if (gc->over) fz_droppixmap(gc->over);

	if (gc->model) fz_dropcolorspace(gc->model);
	if (gc->cache) fz_dropglyphcache(gc->cache);
	if (gc->gel) fz_dropgel(gc->gel);
	if (gc->ael) fz_dropael(gc->ael);
	fz_free(gc);
}
Ejemplo n.º 3
0
fz_error *
fz_rendertreeover(fz_renderer *gc, fz_pixmap *dest, fz_tree *tree, fz_matrix ctm)
{
	fz_error *error;

	assert(!gc->maskonly);
	assert(dest->n == 4);

	gc->clip.x0 = dest->x;
	gc->clip.y0 = dest->y;
	gc->clip.x1 = dest->x + dest->w;
	gc->clip.y1 = dest->y + dest->h;

	gc->over = dest;

	error = rendernode(gc, tree->root, ctm);
	if (error)
	{
		gc->over = nil;
		return error;
	}

	if (gc->dest)
	{
		blendover(gc, gc->dest, gc->over);
		fz_droppixmap(gc->dest);
		gc->dest = nil;
	}

	gc->over = nil;

	return fz_okay;
}
Ejemplo n.º 4
0
void pdfapp_close(pdfapp_t *app)
{
    if (app->cache)
        fz_freeglyphcache(app->cache);
    app->cache = nil;

    if (app->page)
        pdf_droppage(app->page);
    app->page = nil;

    if (app->image)
        fz_droppixmap(app->image);
    app->image = nil;

    if (app->text)
        fz_freetextspan(app->text);
    app->text = nil;

    if (app->outline)
        pdf_dropoutline(app->outline);
    app->outline = nil;

    if (app->xref->store)
        pdf_dropstore(app->xref->store);
    app->xref->store = nil;

    pdf_closexref(app->xref);
    app->xref = nil;
}
Ejemplo n.º 5
0
void pdfapp_close(pdfapp_t *app)
{
	if (app->pages)
		pdf_droppagetree(app->pages);
	app->pages = nil;

	if (app->page)
		pdf_droppage(app->page);
	app->page = nil;

	if (app->image)
		fz_droppixmap(app->image);
	app->image = nil;

	if (app->outline)
		pdf_dropoutline(app->outline);
	app->outline = nil;

	if (app->xref->store)
		pdf_dropstore(app->xref->store);
	app->xref->store = nil;

	pdf_closexref(app->xref);
	app->xref = nil;
}
Ejemplo n.º 6
0
static int pdfLoadPage(PDFContext* ctx) {
	if (fullPageBuffer != NULL) {
		fz_droppixmap(fullPageBuffer);
		fullPageBuffer = NULL;
	}
	strcpy(lastPageError, "No error");

	fz_error *error;
	fz_obj *obj;

	if (ctx->page)
		pdf_droppage(ctx->page);
	ctx->page = 0;

	// empty store to save memory
	if (ctx->xref->store)
		pdf_emptystore(ctx->xref->store);
	bk_pdf_resetbufferssize();
	/*
	pdf_item *item;
	fz_obj *key;
	list<fz_obj *key> keys;
	for (item = ctx->xref->store->root; item; item = item->next) {
		if (item->kind == PDF_KIMAGE)
			keys << key;
	}
	list<fz_obj *key>::iterator it(keys.begin);
	while (it != keys.end()) {

		++it;
	}
	*/

	obj = pdf_getpageobject(ctx->pages, ctx->pageno - 1, ctx->xref);

	error = pdf_loadpage(&ctx->page, ctx->xref, obj);
	if (error) {
		printf("errLP1: %s\n", error->msg);
		strcpy(lastPageError, error->msg);
		return -1;
	}

	//printf("\n\n debug tree ------------------------------------------------\n");
	//fz_debugtree(ctx->page->tree);

	//optimizeNode(ctx->page->tree->root);

	//printf("\n\n OPT debug tree OPT ------------------------------------------------\n");
	//fz_debugtree(ctx->page->tree);

	recalcScreenMediaBox(ctx);
	if (BKUser::options.pdfFastScroll) {
		pdfRenderFullPage(ctx);
	}
	return 0;
}
Ejemplo n.º 7
0
static void
fz_drawpopclip(void *user)
{
	fz_drawdevice *dev = user;
	fz_pixmap *mask, *dest;
	if (dev->top > 0)
	{
		dev->top--;
		dev->scissor = dev->stack[dev->top].scissor;
		mask = dev->stack[dev->top].mask;
		dest = dev->stack[dev->top].dest;
		if (mask && dest)
		{
			fz_pixmap *scratch = dev->dest;
			fz_paintpixmapmask(dest, scratch, mask);
			fz_droppixmap(mask);
			fz_droppixmap(scratch);
			dev->dest = dest;
		}
	}
}
Ejemplo n.º 8
0
static void
fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm,
	fz_colorspace *colorspace, float *color, float alpha)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	unsigned char colorbv[FZ_MAXCOLORS + 1];
	float colorfv[FZ_MAXCOLORS];
	fz_pixmap *scaled = nil;
	int dx, dy;
	int i;

	if (image->w == 0 || image->h == 0)
		return;

#ifdef SMOOTHSCALE
	dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b);
	dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d);
	if (dx < image->w && dy < image->h)
	{
		scaled = fz_smoothtransformpixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy);
		if (scaled == NULL)
		{
			if (dx < 1)
				dx = 1;
			if (dy < 1)
				dy = 1;
			scaled = fz_smoothscalepixmap(image, image->x, image->y, dx, dy);
		}
		if (scaled != NULL)
			image = scaled;
	}
#else
	if (fz_calcimagescale(image, ctm, &dx, &dy))
	{
		scaled = fz_scalepixmap(image, dx, dy);
		image = scaled;
	}
#endif

	fz_convertcolor(colorspace, color, model, colorfv);
	for (i = 0; i < model->n; i++)
		colorbv[i] = colorfv[i] * 255;
	colorbv[i] = alpha * 255;

	fz_paintimagecolor(dev->dest, dev->scissor, image, ctm, colorbv);

	if (scaled)
		fz_droppixmap(scaled);
}
Ejemplo n.º 9
0
fz_error
fz_rendert3glyph(fz_glyph *glyph, fz_font *font, int gid, fz_matrix trm)
{
	fz_error error;
	fz_renderer *gc;
	fz_tree *tree;
	fz_matrix ctm;
	fz_irect bbox;

	/* TODO: make it reentrant */
	static fz_pixmap *pixmap = nil;
	if (pixmap)
	{
		fz_droppixmap(pixmap);
		pixmap = nil;
	}

	if (gid < 0 || gid > 255)
		return fz_throw("assert: glyph out of range");

	tree = font->t3procs[gid];
	if (!tree)
	{
		glyph->w = 0;
		glyph->h = 0;
		return fz_okay;
	}

	ctm = fz_concat(font->t3matrix, trm);
	bbox = fz_roundrect(fz_boundtree(tree, ctm));

	error = fz_newrenderer(&gc, pdf_devicegray, 1, 4096);
	if (error)
		return fz_rethrow(error, "cannot create renderer");
	error = fz_rendertree(&pixmap, gc, tree, ctm, bbox, 0);
	fz_droprenderer(gc);
	if (error)
		return fz_rethrow(error, "cannot render glyph");

	assert(pixmap->n == 1);

	glyph->x = pixmap->x;
	glyph->y = pixmap->y;
	glyph->w = pixmap->w;
	glyph->h = pixmap->h;
	glyph->samples = pixmap->samples;

	return fz_okay;
}
Ejemplo n.º 10
0
void pdfapp_close(pdfapp_t *app)
{
#if 0
	if (app->page)
		pdf_droppage(app->page);
	app->page = nil;

	if (app->image)
		fz_droppixmap(app->image);
	app->image = nil;

/*	if (app->outline)
		pdf_dropoutline(app->outline);
	app->outline = nil;*/

	if (app->xref->store)
		pdf_dropstore(app->xref->store);
	app->xref->store = nil;

	pdf_closexref(app->xref);
	app->xref = nil;
#else
	if (app->cache)
		fz_free_glyph_cache(app->cache);
	app->cache = NULL;

	if (app->image)
		fz_drop_pixmap(app->image);
	app->image = NULL;

	if (app->outline)
		pdf_free_outline(app->outline);
	app->outline = NULL;

	if (app->xref)
	{
		if (app->xref->store)
			pdf_free_store(app->xref->store);
		app->xref->store = NULL;

		pdf_free_xref(app->xref);
		app->xref = NULL;
	}

	fz_flush_warnings();
#endif

}
Ejemplo n.º 11
0
NPError
NPP_Destroy(NPP inst, NPSavedData **saved)
{
    pdfmoz_t *moz = inst->pdata;
    int i;

    //MSG("NPP_Destroy");

    inst->pdata = NULL;

    DeleteObject(moz->graybrush);

    DestroyCursor(moz->arrow);
    DestroyCursor(moz->hand);
    DestroyCursor(moz->wait);

    fz_free(moz->dibinf);

    for (i = 0; i < moz->pagecount; i++)
    {
	if (moz->pages[i].obj)
	    fz_dropobj(moz->pages[i].obj);
	if (moz->pages[i].page)
	    pdf_droppage(moz->pages[i].page);
	if (moz->pages[i].image)
	    fz_droppixmap(moz->pages[i].image);
    }

    fz_free(moz->pages);

    if (moz->xref)
    {
	if (moz->xref->store)
	{
	    pdf_dropstore(moz->xref->store);
	    moz->xref->store = nil;
	}

	pdf_closexref(moz->xref);
    }

    fz_free(moz);

    return NPERR_NO_ERROR;
}
Ejemplo n.º 12
0
BKPDF::~BKPDF() {
	if (ctx != 0) {
		saveLastView();
		pdfClose(ctx);
		delete ctx;
	}
	ctx = 0;
	singleton = 0;

	if (fullPageBuffer != NULL) {
		fz_droppixmap(fullPageBuffer);
		fullPageBuffer = NULL;
	}

//#error reactivate the hash!
//#error idea - list allocs linear, list frees linear, do merge every N allocs
	bkfree_all();
}
Ejemplo n.º 13
0
static fz_error *
renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
{
	fz_error *error;
	fz_node *child;
	int cluster = 0;

	if (!gc->over)
	{
DEBUG("over cluster %d\n{\n", gc->maskonly ? 1 : 4);
		cluster = 1;
		if (gc->maskonly)
			error = fz_newpixmapwithrect(&gc->over, gc->clip, 1);
		else
			error = fz_newpixmapwithrect(&gc->over, gc->clip, 4);
		if (error)
			return error;
		fz_clearpixmap(gc->over);
	}
else DEBUG("over\n{\n");

	for (child = over->super.first; child; child = child->next)
	{
		error = rendernode(gc, child, ctm);
		if (error)
			return error;
		if (gc->dest)
		{
			blendover(gc, gc->dest, gc->over);
			fz_droppixmap(gc->dest);
			gc->dest = nil;
		}
	}

	if (cluster)
	{
		gc->dest = gc->over;
		gc->over = nil;
	}

DEBUG("}\n");

	return fz_okay;
}
Ejemplo n.º 14
0
fz_error *
fz_rendertree(fz_pixmap **outp,
	fz_renderer *gc, fz_tree *tree, fz_matrix ctm,
	fz_irect bbox, int white)
{
	fz_error *error;

	gc->clip = bbox;
	gc->over = nil;

	if (gc->maskonly)
		error = fz_newpixmapwithrect(&gc->over, bbox, 1);
	else
		error = fz_newpixmapwithrect(&gc->over, bbox, 4);
	if (error)
		return error;

	if (white)
		memset(gc->over->samples, 0xff, gc->over->w * gc->over->h * gc->over->n);
	else
		memset(gc->over->samples, 0x00, gc->over->w * gc->over->h * gc->over->n);

DEBUG("tree %d [%d %d %d %d]\n{\n",
gc->maskonly ? 1 : 4,
bbox.x0, bbox.y0, bbox.x1, bbox.y1);

	error = rendernode(gc, tree->root, ctm);
	if (error)
		return error;

DEBUG("}\n");

	if (gc->dest)
	{
		blendover(gc, gc->dest, gc->over);
		fz_droppixmap(gc->dest);
		gc->dest = nil;
	}

	*outp = gc->over;
	gc->over = nil;

	return fz_okay;
}
Ejemplo n.º 15
0
static void pdfRenderFullPage(PDFContext* ctx) {
	if (fullPageBuffer != NULL) {
		fz_droppixmap(fullPageBuffer);
		fullPageBuffer = NULL;
	}
	float h = ctx->page->mediabox.y1 - ctx->page->mediabox.y0;
	float w = ctx->page->mediabox.x1 - ctx->page->mediabox.x0;
	fullPageBuffer = pdfRenderTile(ctx,
		(int)ctx->page->mediabox.x0,
		(int)ctx->page->mediabox.y0,
		(int)w, (int)h, true);
	// precalc color shift
	unsigned int* s = (unsigned int*)fullPageBuffer->samples;
	unsigned int n = fullPageBuffer->w * fullPageBuffer->h;
	for (unsigned int i = 0; i < n; ++i) {
		*s >>= 8;
		++s;
	}
}
Ejemplo n.º 16
0
fz_pixmap *
fz_rendert3glyph(fz_font *font, int gid, fz_matrix trm)
{
	fz_error error;
	fz_matrix ctm;
	fz_buffer *contents;
	fz_bbox bbox;
	fz_device *dev;
	fz_glyphcache *cache;
	fz_pixmap *glyph;
	fz_pixmap *result;

	if (gid < 0 || gid > 255)
		return NULL;

	contents = font->t3procs[gid];
	if (!contents)
		return NULL;

	ctm = fz_concat(font->t3matrix, trm);
	dev = fz_newbboxdevice(&bbox);
	error = font->t3run(font->t3xref, font->t3resources, contents, dev, ctm);
	if (error)
		fz_catch(error, "cannot draw type3 glyph");
	fz_freedevice(dev);

	glyph = fz_newpixmap(fz_devicegray, bbox.x0-1, bbox.y0-1, bbox.x1 - bbox.x0 + 1, bbox.y1 - bbox.y0 + 1);
	fz_clearpixmap(glyph, 0);

	cache = fz_newglyphcache();
	dev = fz_newdrawdevice(cache, glyph);
	error = font->t3run(font->t3xref, font->t3resources, contents, dev, ctm);
	if (error)
		fz_catch(error, "cannot draw type3 glyph");
	fz_freedevice(dev);
	fz_freeglyphcache(cache);

	result = fz_alphafromgray(glyph, 0);
	fz_droppixmap(glyph);

	return result;
}
Ejemplo n.º 17
0
static void
fz_drawstroketext(void *user, fz_text *text, fz_strokestate *stroke, fz_matrix ctm,
	fz_colorspace *colorspace, float *color, float alpha)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	unsigned char colorbv[FZ_MAXCOLORS + 1];
	float colorfv[FZ_MAXCOLORS];
	fz_matrix tm, trm;
	fz_pixmap *glyph;
	int i, x, y, gid;

	fz_convertcolor(colorspace, color, model, colorfv);
	for (i = 0; i < model->n; i++)
		colorbv[i] = colorfv[i] * 255;
	colorbv[i] = alpha * 255;

	tm = text->trm;

	for (i = 0; i < text->len; i++)
	{
		gid = text->els[i].gid;
		if (gid < 0)
			continue;

		tm.e = text->els[i].x;
		tm.f = text->els[i].y;
		trm = fz_concat(tm, ctm);
		x = floorf(trm.e);
		y = floorf(trm.f);
		trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX);
		trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX);

		glyph = fz_renderstrokedglyph(dev->cache, text->font, gid, trm, ctm, stroke);
		if (glyph)
		{
			drawglyph(colorbv, dev->dest, glyph, x, y, dev->scissor);
			fz_droppixmap(glyph);
		}
	}
}
Ejemplo n.º 18
0
static void
fz_drawendmask(void *user)
{
	fz_drawdevice *dev = user;
	fz_pixmap *mask = dev->dest;
	fz_pixmap *temp, *dest;
	fz_bbox bbox;
	int luminosity;

	if (dev->top == STACKSIZE)
	{
		fz_warn("assert: too many buffers on stack");
		return;
	}

	if (dev->top > 0)
	{
		/* pop soft mask buffer */
		dev->top--;
		luminosity = dev->stack[dev->top].luminosity;
		dev->scissor = dev->stack[dev->top].scissor;
		dev->dest = dev->stack[dev->top].dest;

		/* convert to alpha mask */
		temp = fz_alphafromgray(mask, luminosity);
		fz_droppixmap(mask);

		/* create new dest scratch buffer */
		bbox = fz_boundpixmap(temp);
		dest = fz_newpixmapwithrect(dev->dest->colorspace, bbox);
		fz_clearpixmap(dest, 0);

		/* push soft mask as clip mask */
		dev->stack[dev->top].scissor = dev->scissor;
		dev->stack[dev->top].mask = temp;
		dev->stack[dev->top].dest = dev->dest;
		dev->scissor = bbox;
		dev->dest = dest;
		dev->top++;
	}
}
Ejemplo n.º 19
0
static void
fz_drawendgroup(void *user)
{
	fz_drawdevice *dev = user;
	fz_pixmap *group = dev->dest;
	fz_blendmode blendmode;
	float alpha;

	if (dev->top > 0)
	{
		dev->top--;
		alpha = dev->stack[dev->top].alpha;
		blendmode = dev->stack[dev->top].blendmode;
		dev->dest = dev->stack[dev->top].dest;
		dev->scissor = dev->stack[dev->top].scissor;

		if (blendmode == FZ_BNORMAL)
			fz_paintpixmap(dev->dest, group, alpha * 255);
		else
			fz_blendpixmap(dev->dest, group, alpha * 255, blendmode);

		fz_droppixmap(group);
	}
}
Ejemplo n.º 20
0
static void
fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	fz_bbox bbox;
	fz_pixmap *mask, *dest;
	fz_pixmap *scaled = nil;
	int dx, dy;

	if (dev->top == STACKSIZE)
	{
		fz_warn("assert: too many buffers on stack");
		return;
	}

	if (image->w == 0 || image->h == 0)
	{
		dev->stack[dev->top].scissor = dev->scissor;
		dev->stack[dev->top].mask = nil;
		dev->stack[dev->top].dest = nil;
		dev->scissor = fz_emptybbox;
		dev->top++;
		return;
	}

	bbox = fz_roundrect(fz_transformrect(ctm, fz_unitrect));
	bbox = fz_intersectbbox(bbox, dev->scissor);

	mask = fz_newpixmapwithrect(nil, bbox);
	dest = fz_newpixmapwithrect(model, bbox);

	fz_clearpixmap(mask, 0);
	fz_clearpixmap(dest, 0);

#ifdef SMOOTHSCALE
	dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b);
	dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d);
	if (dx < image->w && dy < image->h)
	{
		scaled = fz_smoothtransformpixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy);
		if (scaled == NULL)
		{
			if (dx < 1)
				dx = 1;
			if (dy < 1)
				dy = 1;
			scaled = fz_smoothscalepixmap(image, image->x, image->y, dx, dy);
		}
		if (scaled != NULL)
			image = scaled;
	}
#else
	if (fz_calcimagescale(image, ctm, &dx, &dy))
	{
		scaled = fz_scalepixmap(image, dx, dy);
		image = scaled;
	}
#endif

	fz_paintimage(mask, bbox, image, ctm, 255);

	if (scaled)
		fz_droppixmap(scaled);

	dev->stack[dev->top].scissor = dev->scissor;
	dev->stack[dev->top].mask = mask;
	dev->stack[dev->top].dest = dev->dest;
	dev->scissor = bbox;
	dev->dest = dest;
	dev->top++;
}
Ejemplo n.º 21
0
static fz_error
pdf_loadimageimp(fz_pixmap **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cstm, int forcemask)
{
	fz_stream *stm;
	fz_pixmap *tile;
	fz_obj *obj, *res;
	fz_error error;

	int w, h, bpc, n;
	int imagemask;
	int interpolate;
	int indexed;
	fz_colorspace *colorspace;
	fz_pixmap *mask; /* explicit mask/softmask image */
	int usecolorkey;
	int colorkey[FZ_MAXCOLORS * 2];
	float decode[FZ_MAXCOLORS * 2];

	int scale;
	int stride;
	unsigned char *samples;
	int i, len;

	/* special case for JPEG2000 images */
	if (pdf_isjpximage(dict))
	{
		tile = nil;
		error = pdf_loadjpximage(&tile, xref, dict);
		if (error)
			return fz_rethrow(error, "cannot load jpx image");
		if (forcemask)
		{
			if (tile->n != 2)
			{
				fz_droppixmap(tile);
				return fz_throw("softmask must be grayscale");
			}
			mask = fz_alphafromgray(tile, 1);
			fz_droppixmap(tile);
			*imgp = mask;
			return fz_okay;
		}
		*imgp = tile;
		return fz_okay;
	}

	w = fz_toint(fz_dictgetsa(dict, "Width", "W"));
	h = fz_toint(fz_dictgetsa(dict, "Height", "H"));
	bpc = fz_toint(fz_dictgetsa(dict, "BitsPerComponent", "BPC"));
	imagemask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM"));
	interpolate = fz_tobool(fz_dictgetsa(dict, "Interpolate", "I"));

	indexed = 0;
	usecolorkey = 0;
	colorspace = nil;
	mask = nil;

	if (imagemask)
		bpc = 1;

	if (w == 0)
		return fz_throw("image width is zero");
	if (h == 0)
		return fz_throw("image height is zero");
	if (bpc == 0)
		return fz_throw("image depth is zero");
	if (w > (1 << 16))
		return fz_throw("image is too wide");
	if (h > (1 << 16))
		return fz_throw("image is too high");

	obj = fz_dictgetsa(dict, "ColorSpace", "CS");
	if (obj && !imagemask && !forcemask)
	{
		/* colorspace resource lookup is only done for inline images */
		if (fz_isname(obj))
		{
			res = fz_dictget(fz_dictgets(rdb, "ColorSpace"), obj);
			if (res)
				obj = res;
		}

		error = pdf_loadcolorspace(&colorspace, xref, obj);
		if (error)
			return fz_rethrow(error, "cannot load image colorspace");

		if (!strcmp(colorspace->name, "Indexed"))
			indexed = 1;

		n = colorspace->n;
	}
	else
	{
		n = 1;
	}

	obj = fz_dictgetsa(dict, "Decode", "D");
	if (obj)
	{
		for (i = 0; i < n * 2; i++)
			decode[i] = fz_toreal(fz_arrayget(obj, i));
	}
	else
	{
		float maxval = indexed ? (1 << bpc) - 1 : 1;
		for (i = 0; i < n * 2; i++)
			decode[i] = i & 1 ? maxval : 0;
	}

	obj = fz_dictgetsa(dict, "SMask", "Mask");
	if (fz_isdict(obj))
	{
		/* Not allowed for inline images */
		if (!cstm)
		{
			error = pdf_loadimageimp(&mask, xref, rdb, obj, nil, 1);
			if (error)
			{
				if (colorspace)
					fz_dropcolorspace(colorspace);
				return fz_rethrow(error, "cannot load image mask/softmask");
			}
		}
	}
	else if (fz_isarray(obj))
	{
		usecolorkey = 1;
		for (i = 0; i < n * 2; i++)
			colorkey[i] = fz_toint(fz_arrayget(obj, i));
	}

	stride = (w * n * bpc + 7) / 8;
	samples = fz_calloc(h, stride);

	if (cstm)
	{
		stm = pdf_openinlinestream(cstm, xref, dict, stride * h);
	}
	else
	{
		error = pdf_openstream(&stm, xref, fz_tonum(dict), fz_togen(dict));
		if (error)
		{
			if (colorspace)
				fz_dropcolorspace(colorspace);
			if (mask)
				fz_droppixmap(mask);
			return fz_rethrow(error, "cannot open image data stream (%d 0 R)", fz_tonum(dict));
		}
	}

	len = fz_read(stm, samples, h * stride);
	if (len < 0)
	{
		fz_close(stm);
		if (colorspace)
			fz_dropcolorspace(colorspace);
		if (mask)
			fz_droppixmap(mask);
		return fz_rethrow(len, "cannot read image data");
	}

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

	fz_close(stm);

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

	/* Invert 1-bit image masks */
	if (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];
	}

	pdf_logimage("size %dx%d n=%d bpc=%d imagemask=%d indexed=%d\n", w, h, n, bpc, imagemask, indexed);

	/* Unpack samples into pixmap */

	tile = fz_newpixmap(colorspace, 0, 0, w, h);

	scale = 1;
	if (!indexed)
	{
		switch (bpc)
		{
		case 1: scale = 255; break;
		case 2: scale = 85; break;
		case 4: scale = 17; break;
		}
	}

	fz_unpacktile(tile, samples, n, bpc, stride, scale);

	if (usecolorkey)
		pdf_maskcolorkey(tile, n, colorkey);

	if (indexed)
	{
		fz_pixmap *conv;

		fz_decodeindexedtile(tile, decode, (1 << bpc) - 1);

		conv = pdf_expandindexedpixmap(tile);
		fz_droppixmap(tile);
		tile = conv;
	}
	else
	{
		fz_decodetile(tile, decode);
	}

	if (colorspace)
		fz_dropcolorspace(colorspace);

	tile->mask = mask;
	tile->interpolate = interpolate;

	fz_free(samples);

	*imgp = tile;
	return fz_okay;
}
Ejemplo n.º 22
0
static void
fz_drawfillshade(void *user, fz_shade *shade, fz_matrix ctm, float alpha)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	fz_pixmap *dest = dev->dest;
	fz_rect bounds;
	fz_bbox bbox;
	float colorfv[FZ_MAXCOLORS];
	unsigned char colorbv[FZ_MAXCOLORS + 1];

	bounds = fz_boundshade(shade, ctm);
	bbox = fz_intersectbbox(fz_roundrect(bounds), dev->scissor);

	// TODO: proper clip by shade->bbox
	if (!fz_isemptyrect(shade->bbox))
	{
		bounds = fz_transformrect(fz_concat(shade->matrix, ctm), shade->bbox);
		bbox = fz_intersectbbox(fz_roundrect(bounds), bbox);
	}

	if (fz_isemptyrect(bbox))
		return;

	if (!model)
	{
		fz_warn("cannot render shading directly to an alpha mask");
		return;
	}

	if (alpha < 1)
	{
		dest = fz_newpixmapwithrect(dev->dest->colorspace, bbox);
		fz_clearpixmap(dest, 0);
	}

	if (shade->usebackground)
	{
		unsigned char *s;
		int x, y, n, i;
		fz_convertcolor(shade->cs, shade->background, model, colorfv);
		for (i = 0; i < model->n; i++)
			colorbv[i] = colorfv[i] * 255;
		colorbv[i] = 255;

		n = dest->n;
		for (y = bbox.y0; y < bbox.y1; y++)
		{
			s = dest->samples + ((bbox.x0 - dest->x) + (y - dest->y) * dest->w) * dest->n;
			for (x = bbox.x0; x < bbox.x1; x++)
			{
				for (i = 0; i < n; i++)
					*s++ = colorbv[i];
			}
		}
	}

	fz_rendershade(shade, ctm, dest, bbox);

	if (alpha < 1)
	{
		fz_paintpixmap(dev->dest, dest, alpha * 255);
		fz_droppixmap(dest);
	}
}
Ejemplo n.º 23
0
static void
fz_drawclipstroketext(void *user, fz_text *text, fz_strokestate *stroke, fz_matrix ctm)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	fz_bbox bbox;
	fz_pixmap *mask, *dest;
	fz_matrix tm, trm;
	fz_pixmap *glyph;
	int i, x, y, gid;

	if (dev->top == STACKSIZE)
	{
		fz_warn("assert: too many buffers on stack");
		return;
	}

	/* make the mask the exact size needed */
	bbox = fz_roundrect(fz_boundtext(text, ctm));
	bbox = fz_intersectbbox(bbox, dev->scissor);

	mask = fz_newpixmapwithrect(nil, bbox);
	dest = fz_newpixmapwithrect(model, bbox);

	fz_clearpixmap(mask, 0);
	fz_clearpixmap(dest, 0);

	dev->stack[dev->top].scissor = dev->scissor;
	dev->stack[dev->top].mask = mask;
	dev->stack[dev->top].dest = dev->dest;
	dev->scissor = bbox;
	dev->dest = dest;
	dev->top++;

	if (!fz_isemptyrect(bbox))
	{
		tm = text->trm;

		for (i = 0; i < text->len; i++)
		{
			gid = text->els[i].gid;
			if (gid < 0)
				continue;

			tm.e = text->els[i].x;
			tm.f = text->els[i].y;
			trm = fz_concat(tm, ctm);
			x = floorf(trm.e);
			y = floorf(trm.f);
			trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX);
			trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX);

			glyph = fz_renderstrokedglyph(dev->cache, text->font, gid, trm, ctm, stroke);
			if (glyph)
			{
				drawglyph(nil, mask, glyph, x, y, bbox);
				fz_droppixmap(glyph);
			}
		}
	}
}
Ejemplo n.º 24
0
Archivo: pdfdraw.c Proyecto: Limsik/e17
static void drawpnm(int pagenum, struct benchmark *loadtimes, struct benchmark *drawtimes)
{
	fz_error error;
	fz_matrix ctm;
	fz_irect bbox;
	fz_pixmap *pix;
	char name[256];
	char pnmhdr[256];
	int i, x, y, w, h, b, bh;
	int fd = -1;
	long start;
	long end;
	long elapsed;
	fz_md5 digest;

	if (!drawpattern)
		fz_md5init(&digest);

	drawloadpage(pagenum, loadtimes);

	if (benchmark)
		gettime(&start);

	ctm = fz_identity();
	ctm = fz_concat(ctm, fz_translate(0, -drawpage->mediabox.y1));
	ctm = fz_concat(ctm, fz_scale(drawzoom, -drawzoom));
	ctm = fz_concat(ctm, fz_rotate(drawrotate + drawpage->rotate));

	bbox = fz_roundrect(fz_transformaabb(ctm, drawpage->mediabox));
	w = bbox.x1 - bbox.x0;
	h = bbox.y1 - bbox.y0;
	bh = h / drawbands;

	if (drawpattern)
	{
		sprintf(name, drawpattern, drawcount++);
		fd = open(name, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666);
		if (fd < 0)
			die(fz_throw("ioerror: could not open file '%s'", name));

		sprintf(pnmhdr, "P6\n%d %d\n255\n", w, h);
		write(fd, pnmhdr, strlen(pnmhdr));
	}

	error = fz_newpixmap(&pix, bbox.x0, bbox.y0, w, bh, 4);
	if (error)
		die(error);

	memset(pix->samples, 0xff, pix->h * pix->w * pix->n);

	for (b = 0; b < drawbands; b++)
	{
		if (drawbands > 1)
			fprintf(stderr, "drawing band %d / %d\n", b + 1, drawbands);

		error = fz_rendertreeover(drawgc, pix, drawpage->tree, ctm);
		if (error)
			die(error);

		if (drawpattern)
		{
			for (y = 0; y < pix->h; y++)
			{
				unsigned char *src = pix->samples + y * pix->w * 4;
				unsigned char *dst = src;

				for (x = 0; x < pix->w; x++)
				{
					dst[x * 3 + 0] = src[x * 4 + 1];
					dst[x * 3 + 1] = src[x * 4 + 2];
					dst[x * 3 + 2] = src[x * 4 + 3];
				}

				write(fd, dst, pix->w * 3);

				memset(src, 0xff, pix->w * 4);
			}
		}

		if (!drawpattern)
			fz_md5update(&digest, pix->samples, pix->h * pix->w * 4);

		pix->y += bh;
		if (pix->y + pix->h > bbox.y1)
			pix->h = bbox.y1 - pix->y;
	}

	fz_droppixmap(pix);

	if (!drawpattern) {
		unsigned char buf[16];
		fz_md5final(&digest, buf);
		for (i = 0; i < 16; i++)
			fprintf(stderr, "%02x", buf[i]);
	}

	if (drawpattern)
		close(fd);

	drawfreepage();

	if (benchmark)
	{
		gettime(&end);
		elapsed = end - start;

		if (elapsed < drawtimes->min)
		{
			drawtimes->min = elapsed;
			drawtimes->minpage = pagenum;
		}
		if (elapsed > drawtimes->max)
		{
			drawtimes->max = elapsed;
			drawtimes->maxpage = pagenum;
		}
		drawtimes->avg += elapsed;
		drawtimes->pages++;

		fprintf(stderr, " time %.3fs",
			elapsed / 1000000.0);
	}

	fprintf(stderr, "\n");
}
Ejemplo n.º 25
0
static fz_error
pdf_loadjpximage(fz_pixmap **imgp, pdf_xref *xref, fz_obj *dict)
{
	fz_error error;
	fz_buffer *buf;
	fz_pixmap *img;
	fz_obj *obj;

	pdf_logimage("jpeg2000\n");

	error = pdf_loadstream(&buf, xref, fz_tonum(dict), fz_togen(dict));
	if (error)
		return fz_rethrow(error, "cannot load jpx image data");

	error = fz_loadjpximage(&img, buf->data, buf->len);
	if (error)
	{
		fz_dropbuffer(buf);
		return fz_rethrow(error, "cannot load jpx image");
	}

	fz_dropbuffer(buf);

	obj = fz_dictgetsa(dict, "SMask", "Mask");
	if (fz_isdict(obj))
	{
		error = pdf_loadimageimp(&img->mask, xref, nil, obj, nil, 1);
		if (error)
		{
			fz_droppixmap(img);
			return fz_rethrow(error, "cannot load image mask/softmask");
		}
	}

	obj = fz_dictgets(dict, "ColorSpace");
	if (obj)
	{
		fz_colorspace *original = img->colorspace;
		img->colorspace = nil;

		error = pdf_loadcolorspace(&img->colorspace, xref, obj);
		if (error)
		{
			fz_dropcolorspace(original);
			return fz_rethrow(error, "cannot load image colorspace");
		}

		if (original->n != img->colorspace->n)
		{
			fz_warn("jpeg-2000 colorspace (%s) does not match promised colorspace (%s)", original->name, img->colorspace->name);
			fz_dropcolorspace(img->colorspace);
			img->colorspace = original;
		}
		else
			fz_dropcolorspace(original);

		if (!strcmp(img->colorspace->name, "Indexed"))
		{
			fz_pixmap *conv;
			conv = pdf_expandindexedpixmap(img);
			fz_droppixmap(img);
			img = conv;
		}
	}

	*imgp = img;
	return fz_okay;
}
static void saveimage(fz_obj *obj, int num, int gen)
{
    pdf_image *img = nil;
    fz_obj *ref;
    fz_error error;
    fz_pixmap *pix;
    char name[1024];
    FILE *f;
    int bpc;
    int w;
    int h;
    int n;
    int x;
    int y;

    error = fz_newindirect(&ref, num, gen, xref);
    if (error)
        die(error);

    error = pdf_newstore(&xref->store);
    if (error)
        die(error);

    error = pdf_loadimage(&img, xref, ref);
    if (error)
        die(error);

    n = img->super.n;
    w = img->super.w;
    h = img->super.h;
    bpc = img->bpc;

    error = fz_newpixmap(&pix, 0, 0, w, h, n + 1);
    if (error)
        die(error);

    error = img->super.loadtile(&img->super, pix);
    if (error)
        die(error);

    if (bpc == 1 && n == 0)
    {
        fz_pixmap *temp;

        error = fz_newpixmap(&temp, pix->x, pix->y, pix->w, pix->h, pdf_devicergb->n + 1);
        if (error)
            die(error);

        for (y = 0; y < pix->h; y++)
            for (x = 0; x < pix->w; x++)
            {
                int pixel = y * pix->w + x;
                temp->samples[pixel * temp->n + 0] = 255;
                temp->samples[pixel * temp->n + 1] = pix->samples[pixel];
                temp->samples[pixel * temp->n + 2] = pix->samples[pixel];
                temp->samples[pixel * temp->n + 3] = pix->samples[pixel];
            }

        fz_droppixmap(pix);
        pix = temp;
    }

    if (img->super.cs && strcmp(img->super.cs->name, "DeviceRGB"))
    {
        fz_pixmap *temp;

        error = fz_newpixmap(&temp, pix->x, pix->y, pix->w, pix->h, pdf_devicergb->n + 1);
        if (error)
            die(error);

        fz_convertpixmap(img->super.cs, pix, pdf_devicergb, temp);
        fz_droppixmap(pix);
        pix = temp;
    }

    sprintf(name, "img-%04d.pnm", num);

    f = fopen(name, "wb");
    if (f == NULL)
        die(fz_throw("Error creating image file"));

    fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);

    for (y = 0; y < pix->h; y++)
        for (x = 0; x < pix->w; x++)
        {
            fz_sample *sample = &pix->samples[(y * pix->w + x) * (pdf_devicergb->n + 1)];
            unsigned char r = sample[1];
            unsigned char g = sample[2];
            unsigned char b = sample[3];
            fprintf(f, "%c%c%c", r, g, b);
        }

    if (fclose(f) < 0)
        die(fz_throw("Error closing image file"));

    fz_droppixmap(pix);

    pdf_dropstore(xref->store);
    xref->store = nil;

    fz_dropimage(&img->super);

    fz_dropobj(ref);
}
Ejemplo n.º 27
0
LRESULT CALLBACK
MozWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    pdfmoz_t *moz = (pdfmoz_t*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
    char buf[256];

    int x = (signed short) LOWORD(lParam);
    int y = (signed short) HIWORD(lParam);
    int i, h;

    SCROLLINFO si;
    PAINTSTRUCT ps;
    HDC hdc;
    RECT rc;
    RECT pad;
    WORD sendmsg;
    float zoom;

    GetClientRect(hwnd, &rc);
    h = rc.bottom - rc.top;

    if (strlen(moz->error))
    {
	if (msg == WM_PAINT)
	{
	    hdc = BeginPaint(hwnd, &ps);
	    FillRect(hdc, &rc, GetStockBrush(WHITE_BRUSH));
	    rc.top += 10;
	    rc.bottom -= 10;
	    rc.left += 10;
	    rc.right -= 10;
	    DrawText(hdc, moz->error, strlen(moz->error), &rc, 0);
		// DT_SINGLELINE|DT_CENTER|DT_VCENTER);
	    EndPaint(hwnd, &ps);
	}
	if (msg == WM_MOUSEMOVE)
	{
	    SetCursor(moz->arrow);
	}
	return 0;
    }

    switch (msg)
    {

    case WM_PAINT:
	GetClientRect(moz->hwnd, &rc);

	si.cbSize = sizeof(si);
	si.fMask = SIF_ALL;
	GetScrollInfo(hwnd, SB_VERT, &si);

	decodescroll(moz, si.nPos);

	/* evict out-of-range images and pages */
	for (i = 0; i < moz->pagecount; i++)
	{
	    if (i < moz->scrollpage - 2 || i > moz->scrollpage + 6)
	    {
		if (moz->pages[i].page)
		{
		    pdf_droppage(moz->pages[i].page);
		    moz->pages[i].page = nil;
		}
	    }
	    if (i < moz->scrollpage - 1 || i > moz->scrollpage + 3)
	    {
		if (moz->pages[i].image)
		{
		    fz_droppixmap(moz->pages[i].image);
		    moz->pages[i].image = nil;
		}
	    }
	}

	i = moz->scrollpage;

	pdfmoz_loadpage(moz, i);
	if (moz->error[0]) return 0;

	pdfmoz_drawpage(moz, i);
	if (moz->error[0]) return 0;

	y = -moz->scrollyofs;
	while (y < h && i < moz->pagecount)
	{
	    pdfmoz_loadpage(moz, i);
	    if (moz->error[0]) return 0;
	    pdfmoz_drawpage(moz, i);
	    if (moz->error[0]) return 0;
	    y += moz->pages[i].image->h;
	    i ++;
	}

	hdc = BeginPaint(hwnd, &ps);

	pad.left = rc.left;
	pad.right = rc.right;

	i = moz->scrollpage;
	y = -moz->scrollyofs;
	while (y < h && i < moz->pagecount)
	{
	    drawimage(hdc, moz, moz->pages[i].image, y);
	    y += moz->pages[i].image->h;
	    i ++;

	    pad.top = y;
	    pad.bottom = y + PAD;
	    FillRect(hdc, &pad, moz->graybrush);
	    y += PAD;
	}

	if (y < h)
	{
	    pad.top = y;
	    pad.bottom = h;
	    FillRect(hdc, &pad, moz->graybrush);
	}

	EndPaint(hwnd, &ps);

	return 0;

    case WM_SIZE:
	ShowScrollBar(moz->hwnd, SB_VERT, TRUE);
	GetClientRect(moz->hwnd, &rc);

	si.cbSize = sizeof(si);
	si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE;
	si.nPos = 0;
	si.nMin = 0;
	si.nMax = 0;
	// si.nPage = MAX(30, rc.bottom - rc.top - 30);
	si.nPage = rc.bottom - rc.top;

	for (i = 0; i < moz->pagecount; i++)
	{
	    zoom = (rc.right - rc.left) / (float) moz->pages[i].w;
	    moz->pages[i].px = zoom * moz->pages[i].h + PAD;

	    if (moz->scrollpage == i)
	    {
		si.nPos = si.nMax;
		if (moz->pages[i].image)
		{
		    si.nPos +=
			moz->pages[i].px *
			moz->scrollyofs /
			moz->pages[i].image->h + 1;
		}
	    }

	    if (moz->pages[i].image)
	    {
		fz_droppixmap(moz->pages[i].image);
		moz->pages[i].image = nil;
	    }

	    si.nMax += moz->pages[i].px;
	}

	si.nMax --;

	SetScrollInfo(moz->hwnd, SB_VERT, &si, TRUE);

	break;

    case WM_MOUSEMOVE:
	pdfmoz_onmouse(moz, x, y, 0);
	break;

    case WM_LBUTTONDOWN:
	SetFocus(hwnd);
	pdfmoz_onmouse(moz, x, y, 1);
	break;

    case WM_VSCROLL:

	si.cbSize = sizeof(si);
	si.fMask = SIF_ALL;
	GetScrollInfo(hwnd, SB_VERT, &si);

	switch (LOWORD(wParam))
	{
	case SB_BOTTOM: si.nPos = si.nMax; break;
	case SB_TOP: si.nPos = 0; break;
	case SB_LINEUP: si.nPos -= 50; break;
	case SB_LINEDOWN: si.nPos += 50; break;
	case SB_PAGEUP: si.nPos -= si.nPage; break;
	case SB_PAGEDOWN: si.nPos += si.nPage; break;
	case SB_THUMBTRACK: si.nPos = si.nTrackPos; break;
	case SB_THUMBPOSITION: si.nPos = si.nTrackPos; break;
	}

	si.fMask = SIF_POS;
	si.nPos = MAX(0, MIN(si.nPos, si.nMax));
	SetScrollInfo(hwnd, SB_VERT, &si, TRUE);

	InvalidateRect(moz->hwnd, NULL, FALSE);

	decodescroll(moz, si.nPos);
	sprintf(buf, "Page %d of %d", moz->scrollpage + 1, moz->pagecount);
	NPN_Status(moz->inst, buf);

	return 0;

    case WM_MOUSEWHEEL:
	if ((signed short)HIWORD(wParam) > 0)
	    SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
	else
	    SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
	break;

    case WM_KEYDOWN:
	sendmsg = 0xFFFF;

	switch (wParam)
	{
	case VK_UP: sendmsg = SB_LINEUP; break;
	case VK_PRIOR: sendmsg = SB_PAGEUP; break;
	case ' ':
	case VK_NEXT: sendmsg = SB_PAGEDOWN; break;
	case '\r':
	case VK_DOWN: sendmsg = SB_LINEDOWN; break;
	case VK_HOME: sendmsg = SB_TOP; break;
	case VK_END: sendmsg = SB_BOTTOM; break;
	}

	if (sendmsg != 0xFFFF)
	    SendMessage(hwnd, WM_VSCROLL, MAKELONG(sendmsg, 0), 0);

	/* ick! someone eats events instead of bubbling... not my fault! */

	break;

    default:
	break;

    }

    return moz->winproc(hwnd, msg, wParam, lParam);
}
Ejemplo n.º 28
0
static fz_error *
renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm)
{
	fz_error *error;
	fz_image *image = node->image;
	fz_irect bbox;
	fz_irect clip;
	int dx, dy;
	fz_pixmap *tile;
	fz_pixmap *temp;
	fz_matrix imgmat;
	fz_matrix invmat;
	int fa, fb, fc, fd;
	int u0, v0;
	int x0, y0;
	int w, h;
	int tileheight;

DEBUG("image %dx%d %d+%d %s\n{\n", image->w, image->h, image->n, image->a, image->cs?image->cs->name:"(nil)");

	bbox = fz_roundrect(fz_boundnode((fz_node*)node, ctm));
	clip = fz_intersectirects(gc->clip, bbox);

	if (fz_isemptyrect(clip))
		return fz_okay;
        if (image->w == 0 || image->h == 0)
                return fz_okay;

	if (image->n + image->a == 0)
		return fz_okay;

	calcimagescale(ctm, image->w, image->h, &dx, &dy);

	/* try to fit tile into a typical L2 cachce */
	tileheight = 512 * 1024 / (image->w * (image->n + image->a));
	/* tileheight must be an even multiple of dy, except for last band */
	tileheight = (tileheight + dy - 1) / dy * dy;

	if ((dx != 1 || dy != 1) && image->h > tileheight) {
		int y = 0;

		DEBUG("  load image tile size = %dx%d\n", image->w, tileheight);
		error = fz_newpixmap(&tile, 0, 0, image->w,
				     tileheight, image->n + 1);
		if (error)
			return error;

		error = fz_newscaledpixmap(&temp, image->w, image->h, image->n + 1, dx, dy);
		if (error)
			goto cleanup;

		do {
			if (y + tileheight > image->h)
				tileheight = image->h - y;
			tile->y = y;
			tile->h = tileheight;
			DEBUG("  tile xywh=%d %d %d %d sxsy=1/%d 1/%d\n",
			      0, y, image->w, tileheight, dx, dy);
			error = image->loadtile(image, tile);
			if (error)
				goto cleanup1;

			error = fz_scalepixmaptile(temp, 0, y, tile, dx, dy);
			if (error)
				goto cleanup1;

			y += tileheight;
		} while (y < image->h);

		fz_droppixmap(tile);
		tile = temp;
	}
	else {


DEBUG("  load image\n");
		error = fz_newpixmap(&tile, 0, 0, image->w, image->h, image->n + 1);
		if (error)
			return error;

		error = image->loadtile(image, tile);
		if (error)
			goto cleanup;

		if (dx != 1 || dy != 1)
		{
DEBUG("  scale image 1/%d 1/%d\n", dx, dy);
			error = fz_scalepixmap(&temp, tile, dx, dy);
			if (error)
				goto cleanup;
			fz_droppixmap(tile);
			tile = temp;
		}
	}

	if (image->cs && image->cs != gc->model)
	{
DEBUG("  convert from %s to %s\n", image->cs->name, gc->model->name);
		error = fz_newpixmap(&temp, tile->x, tile->y, tile->w, tile->h, gc->model->n + 1);
		if (error)
			goto cleanup;
		fz_convertpixmap(image->cs, tile, gc->model, temp);
		fz_droppixmap(tile);
		tile = temp;
	}

	imgmat.a = 1.0 / tile->w;
	imgmat.b = 0.0;
	imgmat.c = 0.0;
	imgmat.d = -1.0 / tile->h;
	imgmat.e = 0.0;
	imgmat.f = 1.0;
	invmat = fz_invertmatrix(fz_concat(imgmat, ctm));

	w = clip.x1 - clip.x0;
	h = clip.y1 - clip.y0;
	x0 = clip.x0;
	y0 = clip.y0;
	u0 = (invmat.a * (x0+0.5) + invmat.c * (y0+0.5) + invmat.e) * 65536;
	v0 = (invmat.b * (x0+0.5) + invmat.d * (y0+0.5) + invmat.f) * 65536;
	fa = invmat.a * 65536;
	fb = invmat.b * 65536;
	fc = invmat.c * 65536;
	fd = invmat.d * 65536;

#define PSRC tile->samples, tile->w, tile->h
#define PDST(p) p->samples + ((y0-p->y) * p->w + (x0-p->x)) * p->n, p->w * p->n
#define PCTM u0, v0, fa, fb, fc, fd, w, h

	switch (gc->flag)
	{
	case FNONE:
		{
DEBUG("  fnone %d x %d\n", w, h);
			if (image->cs)
				error = fz_newpixmapwithrect(&gc->dest, clip, gc->model->n + 1);
			else
				error = fz_newpixmapwithrect(&gc->dest, clip, 1);
			if (error)
				goto cleanup;

			if (image->cs)
				fz_img_4c4(PSRC, PDST(gc->dest), PCTM);
			else
				fz_img_1c1(PSRC, PDST(gc->dest), PCTM);
		}
		break;

	case FOVER:
		{
DEBUG("  fover %d x %d\n", w, h);
			if (image->cs)
				fz_img_4o4(PSRC, PDST(gc->over), PCTM);
			else
				fz_img_1o1(PSRC, PDST(gc->over), PCTM);
		}
		break;

	case FOVER | FRGB:
DEBUG("  fover+rgb %d x %d\n", w, h);
		fz_img_w4i1o4(gc->argb, PSRC, PDST(gc->over), PCTM);
		break;

	default:
		assert(!"impossible flag in image span function");
	}

DEBUG("}\n");

	fz_droppixmap(tile);
	return fz_okay;

cleanup1:
	fz_droppixmap(temp);
cleanup:
	fz_droppixmap(tile);
	return error;
}
Ejemplo n.º 29
0
static void
fz_drawcliptext(void *user, fz_text *text, fz_matrix ctm, int accumulate)
{
	fz_drawdevice *dev = user;
	fz_colorspace *model = dev->dest->colorspace;
	fz_bbox bbox;
	fz_pixmap *mask, *dest;
	fz_matrix tm, trm;
	fz_pixmap *glyph;
	int i, x, y, gid;

	/* If accumulate == 0 then this text object is guaranteed complete */
	/* If accumulate == 1 then this text object is the first (or only) in a sequence */
	/* If accumulate == 2 then this text object is a continuation */

	if (dev->top == STACKSIZE)
	{
		fz_warn("assert: too many buffers on stack");
		return;
	}

	if (accumulate == 0)
	{
		/* make the mask the exact size needed */
		bbox = fz_roundrect(fz_boundtext(text, ctm));
		bbox = fz_intersectbbox(bbox, dev->scissor);
	}
	else
	{
		/* be conservative about the size of the mask needed */
		bbox = dev->scissor;
	}

	if (accumulate == 0 || accumulate == 1)
	{
		mask = fz_newpixmapwithrect(nil, bbox);
		dest = fz_newpixmapwithrect(model, bbox);

		fz_clearpixmap(mask, 0);
		fz_clearpixmap(dest, 0);

		dev->stack[dev->top].scissor = dev->scissor;
		dev->stack[dev->top].mask = mask;
		dev->stack[dev->top].dest = dev->dest;
		dev->scissor = bbox;
		dev->dest = dest;
		dev->top++;
	}
	else
	{
		mask = dev->stack[dev->top-1].mask;
	}

	if (!fz_isemptyrect(bbox))
	{
		tm = text->trm;

		for (i = 0; i < text->len; i++)
		{
			gid = text->els[i].gid;
			if (gid < 0)
				continue;

			tm.e = text->els[i].x;
			tm.f = text->els[i].y;
			trm = fz_concat(tm, ctm);
			x = floorf(trm.e);
			y = floorf(trm.f);
			trm.e = QUANT(trm.e - floorf(trm.e), HSUBPIX);
			trm.f = QUANT(trm.f - floorf(trm.f), VSUBPIX);

			glyph = fz_renderglyph(dev->cache, text->font, gid, trm);
			if (glyph)
			{
				drawglyph(nil, mask, glyph, x, y, bbox);
				fz_droppixmap(glyph);
			}
		}
	}
}
Ejemplo n.º 30
0
static fz_error *
rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm)
{
	fz_error *error;
	int oldmaskonly;
	fz_pixmap *oldover;
	fz_irect oldclip;
	fz_irect bbox;
	fz_irect clip;
	fz_pixmap *shapepix = nil;
	fz_pixmap *colorpix = nil;
	fz_node *shape;
	fz_node *color;
	float rgb[3];

	shape = mask->super.first;
	color = shape->next;

	/* special case black voodo */
	if (gc->flag & FOVER)
	{
		if (fz_issolidnode(color))
		{
			fz_solidnode *solid = (fz_solidnode*)color;

			fz_convertcolor(solid->cs, solid->samples, gc->model, rgb);
			gc->argb[0] = solid->a * 255;
			gc->argb[1] = rgb[0] * solid->a * 255;
			gc->argb[2] = rgb[1] * solid->a * 255;
			gc->argb[3] = rgb[2] * solid->a * 255;
			gc->argb[4] = rgb[0] * 255;
			gc->argb[5] = rgb[1] * 255;
			gc->argb[6] = rgb[2] * 255;
			gc->flag |= FRGB;

			/* we know these can handle the FRGB shortcut */
			if (fz_ispathnode(shape))
				return renderpath(gc, (fz_pathnode*)shape, ctm);
			if (fz_istextnode(shape))
				return rendertext(gc, (fz_textnode*)shape, ctm);
			if (fz_isimagenode(shape))
				return renderimage(gc, (fz_imagenode*)shape, ctm);
		}
	}

	oldclip = gc->clip;
	oldover = gc->over;

	bbox = fz_roundrect(fz_boundnode(shape, ctm));
	clip = fz_intersectirects(bbox, gc->clip);
	bbox = fz_roundrect(fz_boundnode(color, ctm));
	clip = fz_intersectirects(bbox, clip);

	if (fz_isemptyrect(clip))
		return fz_okay;

DEBUG("mask [%d %d %d %d]\n{\n", clip.x0, clip.y0, clip.x1, clip.y1);

{
fz_irect sbox = fz_roundrect(fz_boundnode(shape, ctm));
fz_irect cbox = fz_roundrect(fz_boundnode(color, ctm));
if (cbox.x0 >= sbox.x0 && cbox.x1 <= sbox.x1)
if (cbox.y0 >= sbox.y0 && cbox.y1 <= sbox.y1)
DEBUG("potentially useless mask\n");
}

	gc->clip = clip;
	gc->over = nil;

	oldmaskonly = gc->maskonly;
	gc->maskonly = 1;

	error = rendernode(gc, shape, ctm);
	if (error)
		goto cleanup;
	shapepix = gc->dest;
	gc->dest = nil;

	gc->maskonly = oldmaskonly;

	error = rendernode(gc, color, ctm);
	if (error)
		goto cleanup;
	colorpix = gc->dest;
	gc->dest = nil;

	gc->clip = oldclip;
	gc->over = oldover;

	if (shapepix && colorpix)
	{
		if (gc->over)
		{
			blendmask(gc, colorpix, shapepix, gc->over, 1);
		}
		else
		{
			clip.x0 = MAX(colorpix->x, shapepix->x);
			clip.y0 = MAX(colorpix->y, shapepix->y);
			clip.x1 = MIN(colorpix->x+colorpix->w, shapepix->x+shapepix->w);
			clip.y1 = MIN(colorpix->y+colorpix->h, shapepix->y+shapepix->h);
			error = fz_newpixmapwithrect(&gc->dest, clip, colorpix->n);
			if (error)
				goto cleanup;
			blendmask(gc, colorpix, shapepix, gc->dest, 0);
		}
	}

DEBUG("}\n");

	if (shapepix) fz_droppixmap(shapepix);
	if (colorpix) fz_droppixmap(colorpix);
	return fz_okay;

cleanup:
	if (shapepix) fz_droppixmap(shapepix);
	if (colorpix) fz_droppixmap(colorpix);
	return error;
}