static void dev_set_text_matrix (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) { pdf_tmatrix tm; int len = 0; /* slant is negated for vertical font so that right-side * is always lower. */ switch (rotate) { case TEXT_WMODE_VH: /* Vertical font */ tm.a = slant ; tm.b = 1.0; tm.c = -extend; tm.d = 0.0 ; break; case TEXT_WMODE_HV: /* Horizontal font */ tm.a = 0.0; tm.b = -extend; tm.c = 1.0; tm.d = -slant ; break; case TEXT_WMODE_HH: /* Horizontal font */ tm.a = extend; tm.b = 0.0; tm.c = slant ; tm.d = 1.0; break; case TEXT_WMODE_VV: /* Vertical font */ tm.a = 1.0; tm.b = -slant; tm.c = 0.0; tm.d = extend; break; case TEXT_WMODE_HD: /* Horizontal font */ tm.a = 0.0; tm.b = extend; tm.c = -1.0; tm.d = slant ; break; case TEXT_WMODE_VD: /* Vertical font */ tm.a = -1.0; tm.b = slant; tm.c = 0.0; tm.d = -extend; break; } tm.e = xpos * dev_unit.dvi2pts; tm.f = ypos * dev_unit.dvi2pts; format_buffer[len++] = ' '; len += pdf_sprint_matrix(format_buffer+len, &tm); format_buffer[len++] = ' '; format_buffer[len++] = 'T'; format_buffer[len++] = 'm'; pdf_doc_add_page_content(format_buffer, len); /* op: Tm */ text_state.ref_x = xpos; text_state.ref_y = ypos; text_state.matrix.slant = slant; text_state.matrix.extend = extend; text_state.matrix.rotate = rotate; }
int pdf_dev_concat (const pdf_tmatrix *M) { m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; pdf_tmatrix *CTM = &gs->matrix; pdf_tmatrix W = {0, 0, 0, 0, 0, 0}; /* Init to avoid compiler warning */ char *buf = fmt_buf; int len = 0; ASSERT(M); /* Adobe Reader erases page content if there are * non invertible transformation. */ if (fabs(detP(M)) < 1.0e-8) { WARN("Transformation matrix not invertible."); WARN("--- M = [%g %g %g %g %g %g]", M->a, M->b, M->c, M->d, M->e, M->f); return -1; } if (fabs(M->a - 1.0) > 1.e-8 || fabs(M->b) > 1.e-8 || fabs(M->c) > 1.e-8 || fabs(M->d - 1.0) > 1.e-8 || fabs(M->e) > 1.e-8 || fabs(M->f) > 1.e-8) { buf[len++] = ' '; len += pdf_sprint_matrix(buf + len, M); buf[len++] = ' '; buf[len++] = 'c'; buf[len++] = 'm'; pdf_doc_add_page_content(buf, len); /* op: cm */ pdf_concatmatrix(CTM, M); } inversematrix(&W, M); pdf_path__transform (cpa, &W); pdf_coord__transform(cpt, &W); return 0; }
/* rectfill, rectstroke, rectclip, recteoclip * * Draw isolated rectangle without actually doing * gsave/grestore operation. * * TODO: * linestyle, fill-opacity, stroke-opacity,.... * As this routine draw a single graphics object * each time, there should be options for specifying * various drawing styles, which might inherite * current graphcs state parameter. */ static int pdf_dev__rectshape (const pdf_rect *r, const pdf_tmatrix *M, char opchr ) { char *buf = fmt_buf; int len = 0; int isclip = 0; pdf_coord p; double wd, ht; ASSERT(r && PT_OP_VALID(opchr)); isclip = (opchr == 'W' || opchr == ' ') ? 1 : 0; /* disallow matrix for clipping. * q ... clip Q does nothing and * n M cm ... clip n alter CTM. */ if (M && (isclip || !INVERTIBLE_MATRIX(M))) return -1; graphics_mode(); buf[len++] = ' '; if (!isclip) { buf[len++] = 'q'; if (M) { buf[len++] = ' '; len += pdf_sprint_matrix(buf + len, M); buf[len++] = ' '; buf[len++] = 'c'; buf[len++] = 'm'; } buf[len++] = ' '; } buf[len++] = 'n'; p.x = r->llx; p.y = r->lly; wd = r->urx - r->llx; ht = r->ury - r->lly; buf[len++] = ' '; len += pdf_sprint_coord (buf + len, &p); buf[len++] = ' '; len += pdf_sprint_length(buf + len, wd); buf[len++] = ' '; len += pdf_sprint_length(buf + len, ht); buf[len++] = ' '; buf[len++] = 'r'; buf[len++] = 'e'; if (opchr != ' ') { buf[len++] = ' '; buf[len++] = opchr; buf[len++] = ' '; buf[len++] = isclip ? 'n' : 'Q'; } pdf_doc_add_page_content(buf, len); /* op: q cm n re Q */ return 0; }