summaryrefslogtreecommitdiff
path: root/fitz/dev_list.c
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2010-07-14 02:51:01 +0200
committerTor Andersson <tor@ghostscript.com>2010-07-14 02:51:01 +0200
commitb8fa3eabea0fc29a1937d661565cda0caf79ce50 (patch)
tree2a6d14905ea660155a8d0d5b5de294375f0f006f /fitz/dev_list.c
parent48f6f0e2cd05182613b78322c2b924635caf3f55 (diff)
downloadmupdf-b8fa3eabea0fc29a1937d661565cda0caf79ce50.tar.xz
Add transparency group/mask device calls and implement basic blend modes when drawing primitive objects.
Diffstat (limited to 'fitz/dev_list.c')
-rw-r--r--fitz/dev_list.c88
1 files changed, 86 insertions, 2 deletions
diff --git a/fitz/dev_list.c b/fitz/dev_list.c
index 3ca6fca6..f3e7c750 100644
--- a/fitz/dev_list.c
+++ b/fitz/dev_list.c
@@ -1,5 +1,8 @@
#include "fitz.h"
+#define ISOLATED 1
+#define KNOCKOUT 2
+
static fz_displaynode *
fz_newdisplaynode(fz_displaycommand cmd, fz_matrix ctm,
fz_colorspace *colorspace, float *color, float alpha)
@@ -10,6 +13,7 @@ fz_newdisplaynode(fz_displaycommand cmd, fz_matrix ctm,
node = fz_malloc(sizeof(fz_displaynode));
node->cmd = cmd;
node->next = nil;
+ node->rect = fz_emptyrect;
node->item.path = nil;
node->stroke = nil;
node->flag = 0;
@@ -17,8 +21,11 @@ fz_newdisplaynode(fz_displaycommand cmd, fz_matrix ctm,
if (colorspace)
{
node->colorspace = fz_keepcolorspace(colorspace);
- for (i = 0; i < node->colorspace->n; i++)
- node->color[i] = color[i];
+ if (color)
+ {
+ for (i = 0; i < node->colorspace->n; i++)
+ node->color[i] = color[i];
+ }
}
else
{
@@ -79,6 +86,10 @@ fz_freedisplaynode(fz_displaynode *node)
fz_droppixmap(node->item.image);
break;
case FZ_CMDPOPCLIP:
+ case FZ_CMDBEGINMASK:
+ case FZ_CMDENDMASK:
+ case FZ_CMDBEGINGROUP:
+ case FZ_CMDENDGROUP:
break;
}
if (node->stroke)
@@ -94,6 +105,7 @@ fz_listfillpath(void *user, fz_path *path, int evenodd, fz_matrix ctm,
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDFILLPATH, ctm, colorspace, color, alpha);
+ node->rect = fz_boundpath(path, nil, ctm);
node->item.path = fz_clonepath(path);
node->flag = evenodd;
fz_appenddisplaynode(user, node);
@@ -105,6 +117,7 @@ fz_liststrokepath(void *user, fz_path *path, fz_strokestate *stroke, fz_matrix c
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDSTROKEPATH, ctm, colorspace, color, alpha);
+ node->rect = fz_boundpath(path, stroke, ctm);
node->item.path = fz_clonepath(path);
node->stroke = fz_clonestrokestate(stroke);
fz_appenddisplaynode(user, node);
@@ -115,6 +128,7 @@ fz_listclippath(void *user, fz_path *path, int evenodd, fz_matrix ctm)
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDCLIPPATH, ctm, nil, nil, 0);
+ node->rect = fz_boundpath(path, nil, ctm);
node->item.path = fz_clonepath(path);
node->flag = evenodd;
fz_appenddisplaynode(user, node);
@@ -125,6 +139,7 @@ fz_listclipstrokepath(void *user, fz_path *path, fz_strokestate *stroke, fz_matr
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDCLIPSTROKEPATH, ctm, nil, nil, 0);
+ node->rect = fz_boundpath(path, stroke, ctm);
node->item.path = fz_clonepath(path);
node->stroke = fz_clonestrokestate(stroke);
fz_appenddisplaynode(user, node);
@@ -136,6 +151,7 @@ fz_listfilltext(void *user, fz_text *text, fz_matrix ctm,
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDFILLTEXT, ctm, colorspace, color, alpha);
+ node->rect = fz_boundtext(text, ctm);
node->item.text = fz_clonetext(text);
fz_appenddisplaynode(user, node);
}
@@ -146,6 +162,7 @@ fz_liststroketext(void *user, fz_text *text, fz_strokestate *stroke, fz_matrix c
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDSTROKETEXT, ctm, colorspace, color, alpha);
+ node->rect = fz_boundtext(text, ctm);
node->item.text = fz_clonetext(text);
node->stroke = fz_clonestrokestate(stroke);
fz_appenddisplaynode(user, node);
@@ -156,6 +173,7 @@ fz_listcliptext(void *user, fz_text *text, fz_matrix ctm, int accumulate)
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDCLIPTEXT, ctm, nil, nil, 0);
+ node->rect = fz_boundtext(text, ctm);
node->item.text = fz_clonetext(text);
node->flag = accumulate;
fz_appenddisplaynode(user, node);
@@ -166,6 +184,7 @@ fz_listclipstroketext(void *user, fz_text *text, fz_strokestate *stroke, fz_matr
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDCLIPSTROKETEXT, ctm, nil, nil, 0);
+ node->rect = fz_boundtext(text, ctm);
node->item.text = fz_clonetext(text);
node->stroke = fz_clonestrokestate(stroke);
fz_appenddisplaynode(user, node);
@@ -176,6 +195,7 @@ fz_listignoretext(void *user, fz_text *text, fz_matrix ctm)
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDIGNORETEXT, ctm, nil, nil, 0);
+ node->rect = fz_boundtext(text, ctm);
node->item.text = fz_clonetext(text);
fz_appenddisplaynode(user, node);
}
@@ -185,6 +205,7 @@ fz_listpopclip(void *user)
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDPOPCLIP, fz_identity, nil, nil, 0);
+ /* TODO: scan back for matching pushclip and calculate bbox of contents */
fz_appenddisplaynode(user, node);
}
@@ -193,6 +214,7 @@ fz_listfillshade(void *user, fz_shade *shade, fz_matrix ctm)
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDFILLSHADE, ctm, nil, nil, 0);
+ node->rect = fz_boundshade(shade, ctm);
node->item.shade = fz_keepshade(shade);
fz_appenddisplaynode(user, node);
}
@@ -202,6 +224,7 @@ fz_listfillimage(void *user, fz_pixmap *image, fz_matrix ctm)
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDFILLIMAGE, ctm, nil, nil, 0);
+ node->rect = fz_transformrect(ctm, fz_unitrect);
node->item.image = fz_keeppixmap(image);
fz_appenddisplaynode(user, node);
}
@@ -212,6 +235,7 @@ fz_listfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm,
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDFILLIMAGEMASK, ctm, colorspace, color, alpha);
+ node->rect = fz_transformrect(ctm, fz_unitrect);
node->item.image = fz_keeppixmap(image);
fz_appenddisplaynode(user, node);
}
@@ -221,10 +245,49 @@ fz_listclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm)
{
fz_displaynode *node;
node = fz_newdisplaynode(FZ_CMDCLIPIMAGEMASK, ctm, nil, nil, 0);
+ node->rect = fz_transformrect(ctm, fz_unitrect);
node->item.image = fz_keeppixmap(image);
fz_appenddisplaynode(user, node);
}
+static void
+fz_listbeginmask(void *user, fz_rect rect, int luminosity, fz_colorspace *colorspace, float *color)
+{
+ fz_displaynode *node;
+ node = fz_newdisplaynode(FZ_CMDBEGINMASK, fz_identity, colorspace, color, 0);
+ node->rect = rect;
+ node->flag = luminosity;
+ fz_appenddisplaynode(user, node);
+}
+
+static void
+fz_listendmask(void *user)
+{
+ fz_displaynode *node;
+ node = fz_newdisplaynode(FZ_CMDENDMASK, fz_identity, nil, nil, 0);
+ fz_appenddisplaynode(user, node);
+}
+
+static void
+fz_listbegingroup(void *user, fz_rect rect, fz_colorspace *colorspace, int isolated, int knockout, fz_blendmode blendmode)
+{
+ fz_displaynode *node;
+ node = fz_newdisplaynode(FZ_CMDBEGINGROUP, fz_identity, colorspace, nil, 0);
+ node->rect = rect;
+ node->item.blendmode = blendmode;
+ node->flag |= isolated ? ISOLATED : 0;
+ node->flag |= knockout ? KNOCKOUT : 0;
+ fz_appenddisplaynode(user, node);
+}
+
+static void
+fz_listendgroup(void *user)
+{
+ fz_displaynode *node;
+ node = fz_newdisplaynode(FZ_CMDENDGROUP, fz_identity, nil, nil, 0);
+ fz_appenddisplaynode(user, node);
+}
+
fz_device *
fz_newlistdevice(fz_displaylist *list)
{
@@ -248,6 +311,11 @@ fz_newlistdevice(fz_displaylist *list)
dev->popclip = fz_listpopclip;
+ dev->beginmask = fz_listbeginmask;
+ dev->endmask = fz_listendmask;
+ dev->begingroup = fz_listbegingroup;
+ dev->endgroup = fz_listendgroup;
+
return dev;
}
@@ -276,6 +344,7 @@ void
fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm)
{
fz_displaynode *node;
+ fz_rect bbox;
for (node = list->first; node; node = node->next)
{
fz_matrix ctm = fz_concat(node->ctm, topctm);
@@ -328,6 +397,21 @@ fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm)
case FZ_CMDPOPCLIP:
dev->popclip(dev->user);
break;
+ case FZ_CMDBEGINMASK:
+ bbox = fz_transformrect(topctm, node->rect);
+ dev->beginmask(dev->user, bbox, node->flag, node->colorspace, node->color);
+ break;
+ case FZ_CMDENDMASK:
+ dev->endmask(dev->user);
+ break;
+ case FZ_CMDBEGINGROUP:
+ bbox = fz_transformrect(topctm, node->rect);
+ dev->begingroup(dev->user, bbox, node->colorspace,
+ node->flag & ISOLATED, node->flag & KNOCKOUT, node->item.blendmode);
+ break;
+ case FZ_CMDENDGROUP:
+ dev->endgroup(dev->user);
+ break;
}
}
}