static void pdf_dev_path(fz_context *ctx, pdf_device *pdev, const fz_path *path) { gstate *gs = CURRENT_GSTATE(pdev); fz_walk_path(ctx, path, &pdf_dev_path_proc, (void *)gs->buf); }
static void pdf_dev_alpha(fz_context *ctx, pdf_device *pdev, float alpha, int stroke) { int i; pdf_document *doc = pdev->doc; gstate *gs = CURRENT_GSTATE(pdev); /* If the alpha is unchanged, nothing to do */ if (gs->alpha[stroke] == alpha) return; /* Have we sent such an alpha before? */ for (i = 0; i < pdev->num_alphas; i++) if (pdev->alphas[i].alpha == alpha && pdev->alphas[i].stroke == stroke) break; if (i == pdev->num_alphas) { pdf_obj *o; pdf_obj *ref = NULL; fz_var(ref); /* No. Need to make a new one */ if (pdev->num_alphas == pdev->max_alphas) { int newmax = pdev->max_alphas * 2; if (newmax == 0) newmax = 4; pdev->alphas = fz_resize_array(ctx, pdev->alphas, newmax, sizeof(*pdev->alphas)); pdev->max_alphas = newmax; } pdev->alphas[i].alpha = alpha; pdev->alphas[i].stroke = stroke; o = pdf_new_dict(ctx, doc, 1); fz_try(ctx) { char text[32]; pdf_dict_put_drop(ctx, o, (stroke ? PDF_NAME_CA : PDF_NAME_ca), pdf_new_real(ctx, doc, alpha)); ref = pdf_add_object(ctx, doc, o); fz_snprintf(text, sizeof(text), "ExtGState/Alp%d", i); pdf_dict_putp(ctx, pdev->resources, text, ref); } fz_always(ctx) { pdf_drop_obj(ctx, o); pdf_drop_obj(ctx, ref); } fz_catch(ctx) { fz_rethrow(ctx); } pdev->num_alphas++; }
static void pdf_dev_ctm(fz_context *ctx, pdf_device *pdev, fz_matrix ctm) { fz_matrix inverse; gstate *gs = CURRENT_GSTATE(pdev); if (memcmp(&gs->ctm, &ctm, sizeof(ctm)) == 0) return; inverse = fz_invert_matrix(gs->ctm); inverse = fz_concat(ctm, inverse); gs->ctm = ctm; fz_append_printf(ctx, gs->buf, "%M cm\n", &inverse); }
static void pdf_dev_ctm(fz_context *ctx, pdf_device *pdev, const fz_matrix *ctm) { fz_matrix inverse; gstate *gs = CURRENT_GSTATE(pdev); if (memcmp(&gs->ctm, ctm, sizeof(*ctm)) == 0) return; fz_invert_matrix(&inverse, &gs->ctm); fz_concat(&inverse, ctm, &inverse); gs->ctm = *ctm; fz_buffer_printf(ctx, gs->buf, "%M cm\n", &inverse); }
/* Helper functions */ static void pdf_dev_stroke_state(fz_context *ctx, pdf_device *pdev, const fz_stroke_state *stroke_state) { gstate *gs = CURRENT_GSTATE(pdev); if (stroke_state == gs->stroke_state) return; if (gs->stroke_state && !memcmp(stroke_state, gs->stroke_state, sizeof(*stroke_state))) return; if (!gs->stroke_state || gs->stroke_state->linewidth != stroke_state->linewidth) { fz_append_printf(ctx, gs->buf, "%g w\n", stroke_state->linewidth); } if (!gs->stroke_state || gs->stroke_state->start_cap != stroke_state->start_cap) { int cap = stroke_state->start_cap; /* FIXME: Triangle caps aren't supported in pdf */ if (cap == FZ_LINECAP_TRIANGLE) cap = FZ_LINECAP_BUTT; fz_append_printf(ctx, gs->buf, "%d J\n", cap); } if (!gs->stroke_state || gs->stroke_state->linejoin != stroke_state->linejoin) { int join = stroke_state->linejoin; if (join == FZ_LINEJOIN_MITER_XPS) join = FZ_LINEJOIN_MITER; fz_append_printf(ctx, gs->buf, "%d j\n", join); } if (!gs->stroke_state || gs->stroke_state->miterlimit != stroke_state->miterlimit) { fz_append_printf(ctx, gs->buf, "%g M\n", stroke_state->miterlimit); } if (gs->stroke_state == NULL && stroke_state->dash_len == 0) {} else if (!gs->stroke_state || gs->stroke_state->dash_phase != stroke_state->dash_phase || gs->stroke_state->dash_len != stroke_state->dash_len || memcmp(gs->stroke_state->dash_list, stroke_state->dash_list, sizeof(float)*stroke_state->dash_len)) { int i; if (stroke_state->dash_len == 0) fz_append_byte(ctx, gs->buf, '['); for (i = 0; i < stroke_state->dash_len; i++) { if (i > 0) fz_append_byte(ctx, gs->buf, ' '); fz_append_printf(ctx, gs->buf, "%g", stroke_state->dash_list[i]); } fz_append_printf(ctx, gs->buf, "]%g d\n", stroke_state->dash_phase); } fz_drop_stroke_state(ctx, gs->stroke_state); gs->stroke_state = fz_keep_stroke_state(ctx, stroke_state); }
static void pdf_dev_color(fz_context *ctx, pdf_device *pdev, fz_colorspace *colorspace, const float *color, int stroke, const fz_color_params *color_params) { int diff = 0; int i; int cspace = 0; float rgb[FZ_MAX_COLORS]; gstate *gs = CURRENT_GSTATE(pdev); if (colorspace == fz_device_gray(ctx)) cspace = 1; else if (colorspace == fz_device_rgb(ctx)) cspace = 3; else if (colorspace == fz_device_cmyk(ctx)) cspace = 4; if (cspace == 0) { /* If it's an unknown colorspace, fallback to rgb */ fz_convert_color(ctx, color_params, NULL, fz_device_rgb(ctx), rgb, colorspace, color); color = rgb; colorspace = fz_device_rgb(ctx); cspace = 3; } if (gs->colorspace[stroke] != colorspace) { gs->colorspace[stroke] = colorspace; diff = 1; } for (i=0; i < cspace; i++) if (gs->color[stroke][i] != color[i]) { gs->color[stroke][i] = color[i]; diff = 1; } if (diff == 0) return; switch (cspace + stroke*8) { case 1: fz_append_printf(ctx, gs->buf, "%g g\n", color[0]); break; case 3: fz_append_printf(ctx, gs->buf, "%g %g %g rg\n", color[0], color[1], color[2]); break; case 4: fz_append_printf(ctx, gs->buf, "%g %g %g %g k\n", color[0], color[1], color[2], color[3]); break; case 1+8: fz_append_printf(ctx, gs->buf, "%g G\n", color[0]); break; case 3+8: fz_append_printf(ctx, gs->buf, "%g %g %g RG\n", color[0], color[1], color[2]); break; case 4+8: fz_append_printf(ctx, gs->buf, "%g %g %g %g K\n", color[0], color[1], color[2], color[3]); break; } }
static void pdf_dev_color(fz_context *ctx, pdf_device *pdev, fz_colorspace *colorspace, const float *color, int stroke) { int diff = 0; int i; int cspace = 0; float rgb[FZ_MAX_COLORS]; gstate *gs = CURRENT_GSTATE(pdev); if (colorspace == fz_device_gray(ctx)) cspace = 1; else if (colorspace == fz_device_rgb(ctx)) cspace = 3; else if (colorspace == fz_device_cmyk(ctx)) cspace = 4; if (cspace == 0) { /* If it's an unknown colorspace, fallback to rgb */ colorspace->to_rgb(ctx, colorspace, color, rgb); color = rgb; colorspace = fz_device_rgb(ctx); } if (gs->colorspace[stroke] != colorspace) { gs->colorspace[stroke] = colorspace; diff = 1; } for (i=0; i < colorspace->n; i++) if (gs->color[stroke][i] != color[i]) { gs->color[stroke][i] = color[i]; diff = 1; } if (diff == 0) return; switch (cspace + stroke*8) { case 1: fz_buffer_printf(ctx, gs->buf, "%f g\n", color[0]); break; case 3: fz_buffer_printf(ctx, gs->buf, "%f %f %f rg\n", color[0], color[1], color[2]); break; case 4: fz_buffer_printf(ctx, gs->buf, "%f %f %f %f k\n", color[0], color[1], color[2], color[3]); break; case 1+8: fz_buffer_printf(ctx, gs->buf, "%f G\n", color[0]); break; case 3+8: fz_buffer_printf(ctx, gs->buf, "%f %f %f RG\n", color[0], color[1], color[2]); break; case 4+8: fz_buffer_printf(ctx, gs->buf, "%f %f %f %f K\n", color[0], color[1], color[2], color[3]); break; } }