static int cleanwhite(fz_node *node) { fz_node *current; fz_node *next; fz_node *shape; fz_node *color; for (current = node->first; current; current = next) { next = current->next; if (fz_islinknode(current)) return 1; else if (fz_isimagenode(current)) return 1; else if (fz_isshadenode(current)) return 1; else if (fz_issolidnode(current)) { if (!iswhitenode((fz_solidnode*)current)) return 1; } else if (fz_ismasknode(current)) { shape = current->first; color = shape->next; if (fz_issolidnode(color)) { if (iswhitenode((fz_solidnode*)color)) fz_removenode(current); else return 1; fz_dropnode(current); /* cf. http://bugs.ghostscript.com/show_bug.cgi?id=690679 */ } else { if (cleanwhite(current)) return 1; } } else { if (cleanwhite(current)) return 1; } } return 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; }