static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float page_bot, fz_device *dev, const fz_matrix *ctm) { fz_html_flow *node; fz_text *text; fz_matrix trm; const char *s; float color[3]; float x, y; int c, g; for (node = box->flow_head; node; node = node->next) { if (node->type == FLOW_IMAGE) { if (node->y > page_bot || node->y + node->h < page_top) continue; } else { if (node->y > page_bot || node->y < page_top) continue; } if (node->type == FLOW_WORD) { fz_scale(&trm, node->em, -node->em); text = fz_new_text(ctx, node->style->font, &trm, 0); x = node->x; y = node->y; s = node->text; while (*s) { s += fz_chartorune(&c, s); g = fz_encode_character(ctx, node->style->font, c); fz_add_text(ctx, text, g, c, x, y); x += fz_advance_glyph(ctx, node->style->font, g) * node->em; } color[0] = node->style->color.r / 255.0f; color[1] = node->style->color.g / 255.0f; color[2] = node->style->color.b / 255.0f; fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1); fz_drop_text(ctx, text); } else if (node->type == FLOW_IMAGE) { fz_matrix local_ctm = *ctm; fz_pre_translate(&local_ctm, node->x, node->y); fz_pre_scale(&local_ctm, node->w, node->h); fz_fill_image(ctx, dev, node->image, &local_ctm, 1); } } }
static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float page_bot, fz_device *dev, const fz_matrix *ctm) { fz_font *font; fz_html_flow *node; fz_text *text; fz_matrix trm; const char *s; float color[3]; int c, g; for (node = box->flow_head; node; node = node->next) { if (node->type == FLOW_IMAGE) { if (node->y >= page_bot || node->y + node->h <= page_top) continue; } else { if (node->y > page_bot || node->y < page_top) continue; } if (node->type == FLOW_WORD) { fz_scale(&trm, node->em, -node->em); color[0] = node->style->color.r / 255.0f; color[1] = node->style->color.g / 255.0f; color[2] = node->style->color.b / 255.0f; /* TODO: reuse text object if color is unchanged */ text = fz_new_text(ctx); trm.e = node->x; trm.f = node->y; s = node->content.text; if (node->char_r2l) { float w = 0; const char *t = s; while (*t) { t += fz_chartorune(&c, t); if (node->mirror) c = ucdn_mirror(c); g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font); w += fz_advance_glyph(ctx, font, g) * node->em; } trm.e += w; while (*s) { s += fz_chartorune(&c, s); if (node->mirror) c = ucdn_mirror(c); g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font); trm.e -= fz_advance_glyph(ctx, font, g) * node->em; if (node->style->visibility == V_VISIBLE) fz_add_text(ctx, text, font, 0, &trm, g, c); } trm.e += w; } else { while (*s) { s += fz_chartorune(&c, s); g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font); if (node->style->visibility == V_VISIBLE) fz_add_text(ctx, text, font, 0, &trm, g, c); trm.e += fz_advance_glyph(ctx, font, g) * node->em; } } if (text) { fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1); fz_drop_text(ctx, text); } } else if (node->type == FLOW_IMAGE) { if (node->style->visibility == V_VISIBLE) { fz_matrix local_ctm = *ctm; fz_pre_translate(&local_ctm, node->x, node->y); fz_pre_scale(&local_ctm, node->w, node->h); fz_fill_image(ctx, dev, node->content.image, &local_ctm, 1); } } } }
static void draw_list_mark(fz_context *ctx, fz_html *box, float page_top, float page_bot, fz_device *dev, const fz_matrix *ctm, int n) { fz_font *font; fz_text *text; fz_matrix trm; fz_html_flow *line; float y, w; float color[3]; const char *s; char buf[40]; int c, g; fz_scale(&trm, box->em, -box->em); text = fz_new_text(ctx); line = find_list_mark_anchor(ctx, box); if (line) { y = line->y; } else { float h = fz_from_css_number_scale(box->style.line_height, box->em, box->em, box->em); float a = box->em * 0.8; float d = box->em * 0.2; if (a + d > h) h = a + d; y = box->y + a + (h - a - d) / 2; } if (y > page_bot || y < page_top) return; format_list_number(ctx, box->style.list_style_type, n, buf, sizeof buf); s = buf; w = 0; while (*s) { s += fz_chartorune(&c, s); g = fz_encode_character_with_fallback(ctx, box->style.font, c, UCDN_SCRIPT_LATIN, &font); w += fz_advance_glyph(ctx, font, g) * box->em; } s = buf; trm.e = box->x - w; trm.f = y; while (*s) { s += fz_chartorune(&c, s); g = fz_encode_character_with_fallback(ctx, box->style.font, c, UCDN_SCRIPT_LATIN, &font); fz_add_text(ctx, text, font, 0, &trm, g, c); trm.e += fz_advance_glyph(ctx, font, g) * box->em; } color[0] = box->style.color.r / 255.0f; color[1] = box->style.color.g / 255.0f; color[2] = box->style.color.b / 255.0f; fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1); fz_drop_text(ctx, text); }
/* * Parse unicode and indices strings and encode glyphs. * Calculate metrics for positioning. */ static fz_text * xps_parse_glyphs_imp(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, fz_font *font, float size, float originx, float originy, int is_sideways, int bidi_level, char *indices, char *unicode) { xps_glyph_metrics mtx; fz_text *text; fz_matrix tm; float e, f; float x = originx; float y = originy; char *us = unicode; char *is = indices; int un = 0; if (!unicode && !indices) fz_warn(ctx, "glyphs element with neither characters nor indices"); if (us) { if (us[0] == '{' && us[1] == '}') us = us + 2; un = strlen(us); } if (is_sideways) { fz_pre_scale(fz_rotate(&tm, 90), -size, size); } else fz_scale(&tm, size, -size); text = fz_new_text(ctx, font, &tm, is_sideways); while ((us && un > 0) || (is && *is)) { int char_code = '?'; int code_count = 1; int glyph_count = 1; if (is && *is) { is = xps_parse_cluster_mapping(is, &code_count, &glyph_count); } if (code_count < 1) code_count = 1; if (glyph_count < 1) glyph_count = 1; /* TODO: add code chars with cluster mappings for text extraction */ while (code_count--) { if (us && un > 0) { int t = fz_chartorune(&char_code, us); us += t; un -= t; } } while (glyph_count--) { int glyph_index = -1; float u_offset = 0; float v_offset = 0; float advance; if (is && *is) is = xps_parse_glyph_index(is, &glyph_index); if (glyph_index == -1) glyph_index = xps_encode_font_char(font, char_code); xps_measure_font_glyph(ctx, doc, font, glyph_index, &mtx); if (is_sideways) advance = mtx.vadv * 100; else if (bidi_level & 1) advance = -mtx.hadv * 100; else advance = mtx.hadv * 100; if (font->ft_bold) advance *= 1.02f; if (is && *is) { is = xps_parse_glyph_metrics(is, &advance, &u_offset, &v_offset); if (*is == ';') is ++; } if (bidi_level & 1) u_offset = -mtx.hadv * 100 - u_offset; u_offset = u_offset * 0.01f * size; v_offset = v_offset * 0.01f * size; if (is_sideways) { e = x + u_offset + (mtx.vorg * size); f = y - v_offset + (mtx.hadv * 0.5f * size); } else { e = x + u_offset; f = y - v_offset; } fz_add_text(ctx, text, glyph_index, char_code, e, f); x += advance * 0.01f * size; } } return text; }