int pdf_dev_setdash (int count, double *pattern, double offset) { m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = fmt_buf; int i; gs->linedash.num_dash = count; gs->linedash.offset = offset; pdf_doc_add_page_content(" [", 2); /* op: */ for (i = 0; i < count; i++) { buf[0] = ' '; len = pdf_sprint_length (buf + 1, pattern[i]); pdf_doc_add_page_content(buf, len + 1); /* op: */ gs->linedash.pattern[i] = pattern[i]; } pdf_doc_add_page_content("] ", 2); /* op: */ len = pdf_sprint_length (buf, offset); pdf_doc_add_page_content(buf, len); /* op: */ pdf_doc_add_page_content(" d", 2); /* op: d */ return 0; }
static void reset_text_state (void) { /* * We need to reset the line matrix to handle slanted fonts. */ pdf_doc_add_page_content(" BT", 3); /* op: BT */ /* * text_state.matrix is identity at top of page. * This sometimes write unnecessary "Tm"s when transition from * GRAPHICS_MODE to TEXT_MODE occurs. */ if (text_state.force_reset || text_state.matrix.slant != 0.0 || text_state.matrix.extend != 1.0 || ROTATE_TEXT(text_state.matrix.rotate)) { dev_set_text_matrix(0, 0, text_state.matrix.slant, text_state.matrix.extend, text_state.matrix.rotate); } text_state.ref_x = 0; text_state.ref_y = 0; text_state.offset = 0; text_state.force_reset = 0; }
void graphics_mode (void) { switch (motion_state) { case GRAPHICS_MODE: break; case STRING_MODE: pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ /* continue */ case TEXT_MODE: pdf_doc_add_page_content(" ET", 3); /* op: ET */ text_state.force_reset = 0; text_state.font_id = -1; break; } motion_state = GRAPHICS_MODE; }
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_gsave (void) { pdf_gstate *gs0, *gs1; gs0 = m_stack_top(&gs_stack); gs1 = NEW(1, pdf_gstate); init_a_gstate(gs1); copy_a_gstate(gs1, gs0); m_stack_push(&gs_stack, gs1); pdf_doc_add_page_content(" q", 2); /* op: q */ return 0; }
int pdf_dev_newpath (void) { m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *p = &gs->path; if (PA_LENGTH(p) > 0) { pdf_path__clearpath (p); } /* The following is required for "newpath" operator in mpost.c. */ pdf_doc_add_page_content(" n", 2); /* op: n */ return 0; }
int pdf_dev_setlinecap (int capstyle) { m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = fmt_buf; if (gs->linecap != capstyle) { len = sprintf(buf, " %d J", capstyle); pdf_doc_add_page_content(buf, len); /* op: J */ gs->linecap = capstyle; } return 0; }
int pdf_dev_setlinejoin (int joinstyle) { m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = fmt_buf; if (gs->linejoin != joinstyle) { len = sprintf(buf, " %d j", joinstyle); pdf_doc_add_page_content(buf, len); /* op: j */ gs->linejoin = joinstyle; } return 0; }
static void text_mode (void) { switch (motion_state) { case TEXT_MODE: break; case STRING_MODE: pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ break; case GRAPHICS_MODE: reset_text_state(); break; } motion_state = TEXT_MODE; text_state.offset = 0; }
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; }
int pdf_dev_setflat (int flatness) { m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = fmt_buf; if (flatness < 0 || flatness > 100) return -1; if (gs->flatness != flatness) { gs->flatness = flatness; len = sprintf(buf, " %d i", flatness); pdf_doc_add_page_content(buf, len); /* op: i */ } return 0; }
int pdf_dev_setlinewidth (double width) { m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = fmt_buf; if (gs->linewidth != width) { buf[len++] = ' '; len += pdf_sprint_length(buf + len, width); buf[len++] = ' '; buf[len++] = 'w'; pdf_doc_add_page_content(buf, len); /* op: w */ gs->linewidth = width; } return 0; }
/* * num w LW linewidth (g.t. 0) * int J LC linecap * int j LJ linejoin * num M ML miter limit (g.t. 0) * array num d D line dash * int ri RI renderint intnet * int i FL flatness tolerance (0-100) * name gs -- name: res. name of ExtGState dict. */ int pdf_dev_setmiterlimit (double mlimit) { m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = fmt_buf; if (gs->miterlimit != mlimit) { buf[len++] = ' '; len += pdf_sprint_length(buf + len, mlimit); buf[len++] = ' '; buf[len++] = 'M'; pdf_doc_add_page_content(buf, len); /* op: M */ gs->miterlimit = mlimit; } return 0; }
int pdf_dev_grestore (void) { pdf_gstate *gs; if (m_stack_depth(&gs_stack) <= 1) { /* Initial state at bottom */ WARN("Too many grestores."); return -1; } gs = m_stack_pop(&gs_stack); clear_a_gstate(gs); RELEASE(gs); pdf_doc_add_page_content(" Q", 2); /* op: Q */ pdf_dev_reset_fonts(); return 0; }
static void string_mode (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) { switch (motion_state) { case STRING_MODE: break; case GRAPHICS_MODE: reset_text_state(); /* continue */ case TEXT_MODE: if (text_state.force_reset) { dev_set_text_matrix(xpos, ypos, slant, extend, rotate); pdf_doc_add_page_content(text_state.is_mb ? "[<" : "[(", 2); /* op: */ text_state.force_reset = 0; } else { start_string(xpos, ypos, slant, extend, rotate); } break; } motion_state = STRING_MODE; }
void pdf_dev_grestore_to (int depth) { m_stack *gss = &gs_stack; pdf_gstate *gs; ASSERT(depth >= 0); if (m_stack_depth(gss) > depth + 1) { WARN("Closing pending transformations at end of page/XObject."); } while (m_stack_depth(gss) > depth + 1) { pdf_doc_add_page_content(" Q", 2); /* op: Q */ gs = m_stack_pop(gss); clear_a_gstate(gs); RELEASE(gs); } pdf_dev_reset_fonts(); return; }
/* * mask == 0 means stroking color, mask == 0x20 nonstroking color * * force == 1 means that operators will be generated even if * the color is the same as the current graphics state color */ void pdf_dev_set_color (const pdf_color *color, char mask, int force) { int len; pdf_gstate *gs = m_stack_top(&gs_stack); pdf_color *current = mask ? &gs->fillcolor : &gs->strokecolor; ASSERT(pdf_color_is_valid(color)); if (!(pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE) && (force || pdf_color_compare(color, current)))) /* If "color" is already the current color, then do nothing * unless a color operator is forced */ return; graphics_mode(); len = pdf_color_to_string(color, fmt_buf); fmt_buf[len++] = ' '; switch (pdf_color_type(color)) { case PDF_COLORSPACE_TYPE_RGB: fmt_buf[len++] = 'R' | mask; fmt_buf[len++] = 'G' | mask; break; case PDF_COLORSPACE_TYPE_CMYK: fmt_buf[len++] = 'K' | mask; break; case PDF_COLORSPACE_TYPE_GRAY: fmt_buf[len++] = 'G' | mask; break; default: /* already verified the given color */ break; } pdf_doc_add_page_content(fmt_buf, len); /* op: RG K G rg k g */ pdf_color_copycolor(current, color); }
int pdf_copy_clip (FILE *image_file, int pageNo, double x_user, double y_user) { pdf_obj *page_tree, *contents; int depth = 0, top = -1; const char *clip_path, *end_path; char *save_path, *temp; pdf_tmatrix M; double stack[6]; pdf_file *pf; pf = pdf_open(NULL, image_file); if (!pf) return -1; pdf_dev_currentmatrix(&M); pdf_invertmatrix(&M); M.e += x_user; M.f += y_user; page_tree = pdf_get_page_obj (pf, pageNo, NULL, NULL); if (!page_tree) { pdf_close(pf); return -1; } contents = pdf_get_page_content(page_tree); pdf_release_obj(page_tree); if (!contents) { pdf_close(pf); return -1; } pdf_doc_add_page_content(" ", 1); save_path = malloc(pdf_stream_length(contents) + 1); strncpy(save_path, (const char *) pdf_stream_dataptr(contents), pdf_stream_length(contents)); clip_path = save_path; end_path = clip_path + pdf_stream_length(contents); depth = 0; for (; clip_path < end_path; clip_path++) { int color_dimen = 0; /* silence uninitialized warning */ char *token; skip_white(&clip_path, end_path); if (clip_path == end_path) break; if (depth > 1) { if (*clip_path == 'q') depth++; if (*clip_path == 'Q') depth--; parse_ident(&clip_path, end_path); continue; } else if (*clip_path == '-' || *clip_path == '+' || *clip_path == '.' || isdigit((unsigned char)*clip_path)) { stack[++top] = strtod(clip_path, &temp); clip_path = temp; } else if (*clip_path == '[') { /* Ignore, but put a dummy value on the stack (in case of d operator) */ parse_pdf_array(&clip_path, end_path, pf); stack[++top] = 0; } else if (*clip_path == '/') { if (strncmp("/DeviceGray", clip_path, 11) == 0 || strncmp("/Indexed", clip_path, 8) == 0 || strncmp("/CalGray", clip_path, 8) == 0) { color_dimen = 1; continue; } else if (strncmp("/DeviceRGB", clip_path, 10) == 0 || strncmp("/CalRGB", clip_path, 7) == 0 || strncmp("/Lab", clip_path, 4) == 0) { color_dimen = 3; continue; } else if (strncmp("/DeviceCMYK", clip_path, 11) == 0) { color_dimen = 4; continue; } else { clip_path++; parse_ident(&clip_path, end_path); skip_white(&clip_path, end_path); token = parse_ident(&clip_path, end_path); if (strcmp(token, "gs") == 0) { continue; } return -1; } } else { int j; pdf_tmatrix T; pdf_coord p0, p1, p2, p3; token = parse_ident(&clip_path, end_path); for (j = 0; j < sizeof(pdf_operators) / sizeof(pdf_operators[0]); j++) if (strcmp(token, pdf_operators[j].token) == 0) break; if (j == sizeof(pdf_operators) / sizeof(pdf_operators[0])) { return -1; } switch (pdf_operators[j].opcode) { case 0: case -1: case -2: case -3: case -4: /* Just pop the stack and do nothing. */ top += pdf_operators[j].opcode; if (top < -1) return -1; break; case OP_SETCOLOR: top -= color_dimen; if (top < -1) return -1; break; case OP_CLOSEandCLIP: pdf_dev_closepath(); case OP_CLIP: #if 0 pdf_dev_clip(); #else pdf_dev_flushpath('W', PDF_FILL_RULE_NONZERO); #endif break; case OP_CONCATMATRIX: if (top < 5) return -1; T.f = stack[top--]; T.e = stack[top--]; T.d = stack[top--]; T.c = stack[top--]; T.b = stack[top--]; T.a = stack[top--]; pdf_concatmatrix(&M, &T); break; case OP_SETCOLORSPACE: /* Do nothing. */ break; case OP_RECTANGLE: if (top < 3) return -1; p1.y = stack[top--]; p1.x = stack[top--]; p0.y = stack[top--]; p0.x = stack[top--]; if (M.b == 0 && M.c == 0) { pdf_tmatrix M0; M0.a = M.a; M0.b = M.b; M0.c = M.c; M0.d = M.d; M0.e = 0; M0.f = 0; pdf_dev_transform(&p0, &M); pdf_dev_transform(&p1, &M0); pdf_dev_rectadd(p0.x, p0.y, p1.x, p1.y); } else { p2.x = p0.x + p1.x; p2.y = p0.y + p1.y; p3.x = p0.x; p3.y = p0.y + p1.y; p1.x += p0.x; p1.y = p0.y; pdf_dev_transform(&p0, &M); pdf_dev_transform(&p1, &M); pdf_dev_transform(&p2, &M); pdf_dev_transform(&p3, &M); pdf_dev_moveto(p0.x, p0.y); pdf_dev_lineto(p1.x, p1.y); pdf_dev_lineto(p2.x, p2.y); pdf_dev_lineto(p3.x, p3.y); pdf_dev_closepath(); } break; case OP_CURVETO: if (top < 5) return -1; p0.y = stack[top--]; p0.x = stack[top--]; pdf_dev_transform(&p0, &M); p1.y = stack[top--]; p1.x = stack[top--]; pdf_dev_transform(&p1, &M); p2.y = stack[top--]; p2.x = stack[top--]; pdf_dev_transform(&p2, &M); pdf_dev_curveto(p2.x, p2.y, p1.x, p1.y, p0.x, p0.y); break; case OP_CLOSEPATH: pdf_dev_closepath(); break; case OP_LINETO: if (top < 1) return -1; p0.y = stack[top--]; p0.x = stack[top--]; pdf_dev_transform(&p0, &M); pdf_dev_lineto(p0.x, p0.y); break; case OP_MOVETO: if (top < 1) return -1; p0.y = stack[top--]; p0.x = stack[top--]; pdf_dev_transform(&p0, &M); pdf_dev_moveto(p0.x, p0.y); break; case OP_NOOP: pdf_doc_add_page_content(" n", 2); break; case OP_GSAVE: depth++; break; case OP_GRESTORE: depth--; break; case OP_CURVETO1: if (top < 3) return -1; p0.y = stack[top--]; p0.x = stack[top--]; pdf_dev_transform(&p0, &M); p1.y = stack[top--]; p1.x = stack[top--]; pdf_dev_transform(&p1, &M); pdf_dev_vcurveto(p1.x, p1.y, p0.x, p0.y); break; case OP_CURVETO2: if (top < 3) return -1; p0.y = stack[top--]; p0.x = stack[top--]; pdf_dev_transform(&p0, &M); p1.y = stack[top--]; p1.x = stack[top--]; pdf_dev_transform(&p1, &M); pdf_dev_ycurveto(p1.x, p1.y, p0.x, p0.y); break; default: return -1; } } } free(save_path); pdf_release_obj(contents); pdf_close(pf); return 0; }
/* FIXME */ static int pdf_dev__flushpath (pdf_path *pa, char opchr, int rule, int ignore_rule) { pa_elem *pe, *pe1; char *b = fmt_buf; long b_len = FORMAT_BUFF_LEN; pdf_rect r; /* FIXME */ pdf_coord *pt; int n_pts, n_seg; int len = 0; int isclip = 0; int isrect, i, j; ASSERT(pa && PT_OP_VALID(opchr)); isclip = (opchr == 'W') ? 1 : 0; if (PA_LENGTH(pa) <= 0 && path_added == 0) return 0; path_added = 0; graphics_mode(); isrect = pdf_path__isarect(pa, ignore_rule); if (isrect) { pe = &(pa->path[0]); pe1 = &(pa->path[2]); r.llx = pe->p[0].x; r.lly = pe->p[0].y; r.urx = pe1->p[0].x - pe->p[0].x; /* width... */ r.ury = pe1->p[0].y - pe->p[0].y; /* height... */ b[len++] = ' '; len += pdf_sprint_rect(b + len, &r); b[len++] = ' '; b[len++] = 'r'; b[len++] = 'e'; pdf_doc_add_page_content(b, len); /* op: re */ len = 0; } else { n_seg = PA_LENGTH(pa); for (i = 0, len = 0, pe = &pa->path[0]; i < n_seg; pe++, i++) { n_pts = PE_N_PTS(pe); for (j = 0, pt = &pe->p[0]; j < n_pts; j++, pt++) { b[len++] = ' '; len += pdf_sprint_coord(b + len, pt); } b[len++] = ' '; b[len++] = PE_OPCHR(pe); if (len + 128 > b_len) { pdf_doc_add_page_content(b, len); /* op: m l c v y h */ len = 0; } } if (len > 0) { pdf_doc_add_page_content(b, len); /* op: m l c v y h */ len = 0; } } b[len++] = ' '; b[len++] = opchr; if (rule == PDF_FILL_RULE_EVENODD) b[len++] = '*'; if (isclip) { b[len++] = ' '; b[len++] = 'n'; } pdf_doc_add_page_content(b, len); /* op: f F s S b B W f* F* s* S* b* B* 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; }
static void start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) { spt_t delx, dely, error_delx, error_dely; spt_t desired_delx, desired_dely; int len = 0; delx = xpos - text_state.ref_x; dely = ypos - text_state.ref_y; /* * Precompensating for line transformation matrix. * * Line transformation matrix L for horizontal font in horizontal * mode and it's inverse I is * * | e 0| | 1/e 0| * L_hh = | | , I_hh = | | * | s 1| |-s/e 1| * * For vertical font in vertical mode, * * | 1 -s| | 1 s/e| * L_vv = | | , I_vv = | | * | 0 e| | 0 1/e| * * For vertical font in horizontal mode, * * | s 1| | 0 1| * L_vh = | | = L_vv x | | * |-e 0| |-1 0| * * | 0 -1| * I_vh = | | x I_vv * | 1 0| * * For horizontal font in vertical mode, * * | 0 -e| | 0 -1| * L_hv = | | = L_hh x | | * | 1 -s| | 1 0| * * | 0 1| * I_hv = | | x I_hh * |-1 0| * */ switch (rotate) { case TEXT_WMODE_VH: /* Vertical font in horizontal mode: rot = +90 * | 0 -1/e| * d_user = d x I_vh = d x | | * | 1 s/e| */ desired_delx = dely; desired_dely = (spt_t) (-(delx - dely*slant)/extend); /* error_del is in device space * * | 0 1| * e = e_user x | | = (-e_user_y, e_user_x) * |-1 0| * * We must care about rotation here but not extend/slant... * The extend and slant actually is font matrix. */ format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); error_delx = -error_delx; break; case TEXT_WMODE_HV: /* Horizontal font in vertical mode: rot = -90 * * |-s/e 1| * d_user = d x I_hv = d x | | * |-1/e 0| */ desired_delx = (spt_t)(-(dely + delx*slant)/extend); desired_dely = delx; /* * e = (e_user_y, -e_user_x) */ format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); error_dely = -error_dely; break; case TEXT_WMODE_HH: /* Horizontal font in horizontal mode: * | 1/e 0| * d_user = d x I_hh = d x | | * |-s/e 1| */ desired_delx = (spt_t)((delx - dely*slant)/extend); desired_dely = dely; format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); break; case TEXT_WMODE_VV: /* Vertical font in vertical mode: * | 1 s/e| * d_user = d x I_vv = d x | | * | 0 1/e| */ desired_delx = delx; desired_dely = (spt_t)((dely + delx*slant)/extend); format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); break; case TEXT_WMODE_HD: /* Horizontal font in down-to-up mode: rot = +90 * * | s/e -1| * d_user = d x -I_hv = d x | | * | 1/e 0| */ desired_delx = -(spt_t)(-(dely + delx*slant)/extend); desired_dely = -delx; format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); error_delx = -error_delx; error_dely = -error_dely; break; case TEXT_WMODE_VD: /* Vertical font in down-to-up mode: rot = 180 * |-1 -s/e| * d_user = d x -I_vv = d x | | * | 0 -1/e| */ desired_delx = -delx; desired_dely = -(spt_t)((dely + delx*slant)/extend); format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); format_buffer[len++] = ' '; len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); error_delx = -error_delx; error_dely = -error_dely; break; } pdf_doc_add_page_content(format_buffer, len); /* op: */ /* * dvipdfm wrongly using "TD" in place of "Td". * The TD operator set leading, but we are not using T* etc. */ pdf_doc_add_page_content(text_state.is_mb ? " Td[<" : " Td[(", 5); /* op: Td */ /* Error correction */ text_state.ref_x = xpos - error_delx; text_state.ref_y = ypos - error_dely; text_state.offset = 0; }
static int dev_set_font (int font_id) { struct dev_font *font; struct dev_font *real_font; int text_rotate; double font_scale; int len; int vert_dir, vert_font; /* text_mode() must come before text_state.is_mb is changed. */ text_mode(); font = GET_FONT(font_id); ASSERT(font); /* Caller should check font_id. */ if (font->real_font_index >= 0) real_font = GET_FONT(font->real_font_index); else real_font = font; text_state.is_mb = (font->format == PDF_FONTTYPE_COMPOSITE) ? 1 : 0; vert_font = font->wmode ? 1 : 0; if (dev_param.autorotate) { vert_dir = text_state.dir_mode; } else { vert_dir = vert_font; } text_rotate = (vert_font << 2)|vert_dir; if (font->slant != text_state.matrix.slant || font->extend != text_state.matrix.extend || ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { text_state.force_reset = 1; } text_state.matrix.slant = font->slant; text_state.matrix.extend = font->extend; text_state.matrix.rotate = text_rotate; if (!real_font->resource) { real_font->resource = pdf_get_font_reference(real_font->font_id); real_font->used_chars = pdf_get_font_usedchars(real_font->font_id); } if (!real_font->used_on_this_page) { pdf_doc_add_page_resource("Font", real_font->short_name, pdf_link_obj(real_font->resource)); real_font->used_on_this_page = 1; } font_scale = (double) font->sptsize * dev_unit.dvi2pts; len = sprintf(format_buffer, " /%s", real_font->short_name); /* space not necessary. */ format_buffer[len++] = ' '; len += p_dtoa(font_scale, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), format_buffer+len); format_buffer[len++] = ' '; format_buffer[len++] = 'T'; format_buffer[len++] = 'f'; pdf_doc_add_page_content(format_buffer, len); /* op: Tf */ if (font->bold > 0.0 || font->bold != text_state.bold_param) { if (font->bold <= 0.0) len = sprintf(format_buffer, " 0 Tr"); else len = sprintf(format_buffer, " 2 Tr %.6f w", font->bold); /* _FIXME_ */ pdf_doc_add_page_content(format_buffer, len); /* op: Tr w */ } text_state.bold_param = font->bold; text_state.font_id = font_id; return 0; }