📄 pdf_build.c
字号:
#include "fitz.h"#include "mupdf.h"voidpdf_initgstate(pdf_gstate *gs){ gs->linewidth = 1.0; gs->linecap = 0; gs->linejoin = 0; gs->miterlimit = 10; gs->dashphase = 0; gs->dashlen = 0; memset(gs->dashlist, 0, sizeof(gs->dashlist)); gs->stroke.kind = PDF_MCOLOR; gs->stroke.cs = fz_keepcolorspace(pdf_devicegray); gs->stroke.v[0] = 0; gs->stroke.indexed = nil; gs->stroke.pattern = nil; gs->stroke.shade = nil; gs->stroke.alpha = 1.0; gs->fill.kind = PDF_MCOLOR; gs->fill.cs = fz_keepcolorspace(pdf_devicegray); gs->fill.v[0] = 0; gs->fill.indexed = nil; gs->fill.pattern = nil; gs->fill.shade = nil; gs->fill.alpha = 1.0; gs->blendmode = FZ_BNORMAL; gs->charspace = 0; gs->wordspace = 0; gs->scale = 1; gs->leading = 0; gs->font = nil; gs->size = -1; gs->render = 0; gs->rise = 0; gs->head = nil;}fz_error *pdf_newovernode(fz_node **nodep, pdf_gstate *gs){ if (gs->blendmode == FZ_BNORMAL) return fz_newovernode(nodep); else return fz_newblendnode(nodep, gs->blendmode, 0, 0);}fz_error *pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs){ pdf_gstate *gs = csi->gstate + csi->gtop; fz_error *error; pdf_material *mat; error = pdf_flushtext(csi); if (error) return fz_rethrow(error, "cannot finish text node (state change)"); mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; fz_dropcolorspace(mat->cs); mat->kind = PDF_MCOLOR; mat->cs = fz_keepcolorspace(cs); mat->v[0] = 0; /* FIXME: default color */ mat->v[1] = 0; /* FIXME: default color */ mat->v[2] = 0; /* FIXME: default color */ mat->v[3] = 1; /* FIXME: default color */ if (!strcmp(cs->name, "Indexed")) { mat->kind = PDF_MINDEXED; mat->indexed = (pdf_indexed*)cs; mat->cs = mat->indexed->base; } if (!strcmp(cs->name, "Lab")) mat->kind = PDF_MLAB; return fz_okay;}fz_error *pdf_setcolor(pdf_csi *csi, int what, float *v){ pdf_gstate *gs = csi->gstate + csi->gtop; fz_error *error; pdf_indexed *ind; pdf_material *mat; int i, k; error = pdf_flushtext(csi); if (error) return fz_rethrow(error, "cannot finish text node (state change)"); mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; switch (mat->kind) { case PDF_MPATTERN: if (!strcmp(mat->cs->name, "Lab")) goto Llab; if (!strcmp(mat->cs->name, "Indexed")) goto Lindexed; /* fall through */ case PDF_MCOLOR: for (i = 0; i < mat->cs->n; i++) mat->v[i] = v[i]; break; case PDF_MLAB:Llab: mat->v[0] = v[0] / 100.0; mat->v[1] = (v[1] + 100) / 200.0; mat->v[2] = (v[2] + 100) / 200.0; break; case PDF_MINDEXED:Lindexed: ind = mat->indexed; i = CLAMP(v[0], 0, ind->high); for (k = 0; k < ind->base->n; k++) mat->v[k] = ind->lookup[ind->base->n * i + k] / 255.0; break; default: return fz_throw("color incompatible with material"); } return fz_okay;}fz_error *pdf_setpattern(pdf_csi *csi, int what, pdf_pattern *pat, float *v){ pdf_gstate *gs = csi->gstate + csi->gtop; fz_error *error; pdf_material *mat; error = pdf_flushtext(csi); if (error) return fz_rethrow(error, "cannot finish text node (state change)"); mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; if (mat->pattern) pdf_droppattern(mat->pattern); mat->kind = PDF_MPATTERN; if (pat) mat->pattern = pdf_keeppattern(pat); else mat->pattern = nil; if (v) { error = pdf_setcolor(csi, what, v); if (error) return fz_rethrow(error, "cannot set color"); } return fz_okay;}fz_error *pdf_setshade(pdf_csi *csi, int what, fz_shade *shade){ pdf_gstate *gs = csi->gstate + csi->gtop; fz_error *error; pdf_material *mat; error = pdf_flushtext(csi); if (error) return fz_rethrow(error, "cannot finish text node (state change)"); mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; if (mat->shade) fz_dropshade(mat->shade); mat->kind = PDF_MSHADE; mat->shade = fz_keepshade(shade); return fz_okay;}fz_error *pdf_buildstrokepath(pdf_gstate *gs, fz_pathnode *path){ fz_error *error; fz_stroke stroke; fz_dash *dash; stroke.linecap = gs->linecap; stroke.linejoin = gs->linejoin; stroke.linewidth = gs->linewidth; stroke.miterlimit = gs->miterlimit; if (gs->dashlen) { error = fz_newdash(&dash, gs->dashphase, gs->dashlen, gs->dashlist); if (error) return fz_rethrow(error, "cannot create dash pattern"); } else dash = nil; error = fz_endpath(path, FZ_STROKE, &stroke, dash); if (error) { fz_dropdash(dash); return fz_rethrow(error, "cannot finish path node"); } return fz_okay;}fz_error *pdf_buildfillpath(pdf_gstate *gs, fz_pathnode *path, int eofill){ fz_error *error; error = fz_endpath(path, eofill ? FZ_EOFILL : FZ_FILL, nil, nil); if (error) return fz_rethrow(error, "cannot finish path node"); return fz_okay;}static fz_error *addcolorshape(pdf_gstate *gs, fz_node *shape, float alpha, fz_colorspace *cs, float *v){ fz_error *error; fz_node *mask; fz_node *solid; error = fz_newmasknode(&mask); if (error) return fz_rethrow(error, "cannot create mask node"); error = fz_newsolidnode(&solid, alpha, cs, cs->n, v); if (error) { fz_dropnode(mask); return fz_rethrow(error, "cannot create color node"); } fz_insertnodelast(mask, shape); fz_insertnodelast(mask, solid); fz_insertnodelast(gs->head, mask); return fz_okay;}static fz_error *addinvisibleshape(pdf_gstate *gs, fz_node *shape){ fz_error *error; fz_node *mask; fz_pathnode *path; error = fz_newmasknode(&mask); if (error) return fz_rethrow(error, "cannot create mask node"); error = fz_newpathnode(&path); if (error) { fz_dropnode(mask); return fz_rethrow(error, "cannot create path node"); } error = fz_endpath(path, FZ_FILL, nil, nil); if (error) { fz_dropnode(mask); fz_dropnode((fz_node*)path); return fz_rethrow(error, "cannot finish path node"); } fz_insertnodelast(mask, (fz_node*)path); fz_insertnodelast(mask, shape); fz_insertnodelast(gs->head, mask); return fz_okay;}static fz_matrix getmatrix(fz_node *node){ if (node->parent) { fz_matrix ptm = getmatrix(node->parent); if (fz_istransformnode(node)) return fz_concat(((fz_transformnode*)node)->m, ptm); return ptm; } if (fz_istransformnode(node)) return ((fz_transformnode*)node)->m; return fz_identity();}static fz_error *addpatternshape(pdf_gstate *gs, fz_node *shape, pdf_pattern *pat, fz_colorspace *cs, float *v){ fz_error *error; fz_node *xform; fz_node *over; fz_node *mask; fz_node *link; fz_matrix ctm; fz_matrix inv; fz_matrix ptm; fz_rect bbox; int x, y, x0, y0, x1, y1; /* patterns are painted in user space */ ctm = getmatrix(gs->head); inv = fz_invertmatrix(ctm); error = fz_newmasknode(&mask); if (error) return fz_rethrow(error, "cannot create mask node"); ptm = fz_concat(pat->matrix, fz_invertmatrix(ctm)); error = fz_newtransformnode(&xform, ptm); if (error) { fz_dropnode(mask); return fz_rethrow(error, "cannot create transform node"); } error = pdf_newovernode(&over, gs); if (error) { fz_dropnode(xform); fz_dropnode(mask); return fz_rethrow(error, "cannot create over node"); } fz_insertnodelast(mask, shape); fz_insertnodelast(mask, xform); fz_insertnodelast(xform, over); xform = nil; /* over, xform, mask are now owned by the tree */ /* get bbox of shape in pattern space for stamping */ ptm = fz_concat(ctm, fz_invertmatrix(pat->matrix)); bbox = fz_boundnode(shape, ptm); /* expand bbox by pattern bbox */ bbox.x0 += pat->bbox.x0; bbox.y0 += pat->bbox.y0; bbox.x1 += pat->bbox.x1; bbox.y1 += pat->bbox.y1; x0 = fz_floor(bbox.x0 / pat->xstep); y0 = fz_floor(bbox.y0 / pat->ystep); x1 = fz_ceil(bbox.x1 / pat->xstep); y1 = fz_ceil(bbox.y1 / pat->ystep); for (y = y0; y <= y1; y++) { for (x = x0; x <= x1; x++) { ptm = fz_translate(x * pat->xstep, y * pat->ystep); error = fz_newtransformnode(&xform, ptm); if (error) return fz_rethrow(error, "cannot create transform node for stamp"); error = fz_newlinknode(&link, pat->tree); if (error) { fz_dropnode(xform); return fz_rethrow(error, "cannot create link node for stamp"); } fz_insertnodelast(xform, link); fz_insertnodelast(over, xform); } } if (pat->ismask) { error = addcolorshape(gs, mask, 1.0, cs, v); if (error) return fz_rethrow(error, "cannot add colored shape"); return fz_okay; } fz_insertnodelast(gs->head, mask); return fz_okay;}fz_error *pdf_addshade(pdf_gstate *gs, fz_shade *shade){ fz_error *error; fz_node *node; error = fz_newshadenode(&node, shade); if (error) return fz_rethrow(error, "cannot create shade node"); fz_insertnodelast(gs->head, node); return fz_okay;}static fz_error *addshadeshape(pdf_gstate *gs, fz_node *shape, fz_shade *shade){ fz_error *error; fz_node *mask; fz_node *color; fz_node *xform; fz_node *over; fz_node *bgnd; fz_matrix ctm; fz_matrix inv; ctm = getmatrix(gs->head); inv = fz_invertmatrix(ctm); error = fz_newtransformnode(&xform, inv); if (error) return fz_rethrow(error, "cannot create transform node"); error = fz_newmasknode(&mask); if (error) { fz_dropnode(xform); return fz_rethrow(error, "cannot create mask node"); } error = fz_newshadenode(&color, shade); if (error) { fz_dropnode(mask); fz_dropnode(xform); return fz_rethrow(error, "cannot create shade node"); } if (shade->usebackground) { error = pdf_newovernode(&over, gs); if (error) { fz_dropnode(color); fz_dropnode(mask); fz_dropnode(xform); return fz_rethrow(error, "cannot create over node for background color"); } error = fz_newsolidnode(&bgnd, 1.0f, shade->cs, shade->cs->n, shade->background); if (error) { fz_dropnode(over); fz_dropnode(color); fz_dropnode(mask); fz_dropnode(xform); return fz_rethrow(error, "cannot create solid node for background color");; } fz_insertnodelast(mask, shape); fz_insertnodelast(over, bgnd); fz_insertnodelast(over, color); fz_insertnodelast(xform, over); fz_insertnodelast(mask, xform); fz_insertnodelast(gs->head, mask); } else { fz_insertnodelast(mask, shape); fz_insertnodelast(xform, color); fz_insertnodelast(mask, xform); fz_insertnodelast(gs->head, mask); } return fz_okay;}fz_error *pdf_addfillshape(pdf_gstate *gs, fz_node *shape){ fz_error *error; switch (gs->fill.kind)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -