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; }
static fz_error * rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm) { fz_error *error; DEBUG("transform [%g %g %g %g %g %g]\n", transform->m.a, transform->m.b, transform->m.c, transform->m.d, transform->m.e, transform->m.f); DEBUG("{\n"); ctm = fz_concat(transform->m, ctm); error = rendernode(gc, transform->super.first, ctm); DEBUG("}\n"); return error; }
static fz_error * rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm) { if (!node) return nil; gc->flag = FNONE; if (gc->over) gc->flag |= FOVER; switch (node->kind) { case FZ_NOVER: return renderover(gc, (fz_overnode*)node, ctm); case FZ_NMASK: return rendermask(gc, (fz_masknode*)node, ctm); case FZ_NTRANSFORM: return rendertransform(gc, (fz_transformnode*)node, ctm); case FZ_NCOLOR: return rendersolid(gc, (fz_solidnode*)node, ctm); case FZ_NPATH: return renderpath(gc, (fz_pathnode*)node, ctm); case FZ_NTEXT: return rendertext(gc, (fz_textnode*)node, ctm); case FZ_NIMAGE: return renderimage(gc, (fz_imagenode*)node, ctm); case FZ_NSHADE: return rendershade(gc, (fz_shadenode*)node, ctm); case FZ_NLINK: return rendernode(gc, ((fz_linknode*)node)->tree->root, ctm); case FZ_NMETA: return rendernode(gc, node->first, ctm); } return nil; }
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; }
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; }
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; }