static void fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point *pen) { fz_font *font = text->font; FT_Face face = font->ft_face; fz_matrix tm = text->trm; fz_matrix trm; float size; float adv; fz_rect rect; fz_point dir, ndir; fz_point delta, ndelta; float dist, dot; float ascender = 1; float descender = 0; int multi; int i, err; if (text->len == 0) return; fz_lock(ctx, FZ_LOCK_FREETYPE); if (font->ft_face) { err = FT_Set_Char_Size(font->ft_face, 64, 64, 72, 72); if (err) fz_warn(ctx, "freetype set character size: %s", ft_error_string(err)); ascender = (float)face->ascender / face->units_per_EM; descender = (float)face->descender / face->units_per_EM; } rect = fz_empty_rect; if (text->wmode == 0) { dir.x = 1; dir.y = 0; } else { dir.x = 0; dir.y = 1; } tm.e = 0; tm.f = 0; trm = fz_concat(tm, ctm); dir = fz_transform_vector(trm, dir); dist = sqrtf(dir.x * dir.x + dir.y * dir.y); ndir.x = dir.x / dist; ndir.y = dir.y / dist; size = fz_matrix_expansion(trm); multi = 1; for (i = 0; i < text->len; i++) { if (text->items[i].gid < 0) { fz_add_text_char(ctx, last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); multi ++; fz_divide_text_chars(last, multi, fz_round_rect(rect)); continue; } multi = 1; /* Calculate new pen location and delta */ tm.e = text->items[i].x; tm.f = text->items[i].y; trm = fz_concat(tm, ctm); delta.x = pen->x - trm.e; delta.y = pen->y - trm.f; if (pen->x == -1 && pen->y == -1) delta.x = delta.y = 0; dist = sqrtf(delta.x * delta.x + delta.y * delta.y); /* Add space and newlines based on pen movement */ if (dist > 0) { ndelta.x = delta.x / dist; ndelta.y = delta.y / dist; dot = ndelta.x * ndir.x + ndelta.y * ndir.y; if (dist > size * LINE_DIST) { fz_add_text_newline(ctx, last, font, size, text->wmode); } else if (fabsf(dot) > 0.95f && dist > size * SPACE_DIST) { if ((*last)->len > 0 && (*last)->text[(*last)->len - 1].c != ' ') { fz_rect spacerect; spacerect.x0 = -0.2f; spacerect.y0 = 0; spacerect.x1 = 0; spacerect.y1 = 1; spacerect = fz_transform_rect(trm, spacerect); fz_add_text_char(ctx, last, font, size, text->wmode, ' ', fz_round_rect(spacerect)); } } } /* Calculate bounding box and new pen position based on font metrics */ if (font->ft_face) { FT_Fixed ftadv = 0; int mask = FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING | FT_LOAD_IGNORE_TRANSFORM; /* TODO: freetype returns broken vertical metrics */ /* if (text->wmode) mask |= FT_LOAD_VERTICAL_LAYOUT; */ FT_Get_Advance(font->ft_face, text->items[i].gid, mask, &ftadv); adv = ftadv / 65536.0f; rect.x0 = 0; rect.y0 = descender; rect.x1 = adv; rect.y1 = ascender; } else { adv = font->t3widths[text->items[i].gid]; rect.x0 = 0; rect.y0 = descender; rect.x1 = adv; rect.y1 = ascender; } rect = fz_transform_rect(trm, rect); pen->x = trm.e + dir.x * adv; pen->y = trm.f + dir.y * adv; fz_add_text_char(ctx, last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); } fz_unlock(ctx, FZ_LOCK_FREETYPE); }
static void fz_text_extract_span(fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point *pen) { // fz_font *font = text->font; // FT_Face face = font->ft_face; fz_matrix tm = text->trm; fz_matrix trm; float size; float adv = 0; fz_rect rect; fz_point dir, ndir; fz_point delta, ndelta; float dist, dot; float ascender = 1; float descender = 0; int multi; int i; if (text->len == 0) return; rect = fz_empty_rect; /* SumatraPDF: TODO: make this depend on the per-glyph displacement vector */ if (text->wmode == 0) { dir.x = 1; dir.y = 0; } else { dir.x = 0; dir.y = 1; } tm.e = 0; tm.f = 0; trm = fz_concat(tm, ctm); dir = fz_transform_vector(trm, dir); dist = sqrtf(dir.x * dir.x + dir.y * dir.y); ndir.x = dir.x / dist; ndir.y = dir.y / dist; size = fz_matrix_expansion(trm); multi = 1; for (i = 0; i < text->len; i++) { if (text->items[i].gid < 0) { fz_add_text_char(last, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); multi ++; fz_divide_text_chars(last, multi, fz_round_rect(rect)); continue; } multi = 1; /* Calculate new pen location and delta */ tm.e = text->items[i].x; tm.f = text->items[i].y; trm = fz_concat(tm, ctm); delta.x = pen->x - trm.e; delta.y = pen->y - trm.f; if (pen->x == -1 && pen->y == -1) delta.x = delta.y = 0; dist = sqrtf(delta.x * delta.x + delta.y * delta.y); /* Add space and newlines based on pen movement */ if (dist > 0) { ndelta.x = delta.x / dist; ndelta.y = delta.y / dist; dot = ndelta.x * ndir.x + ndelta.y * ndir.y; if (dist > size * LINE_DIST) { fz_add_text_newline(last, size, text->wmode); } else if (fabsf(dot) > 0.95f && dist > size * SPACE_DIST) { if ((*last)->len > 0 && (*last)->text[(*last)->len - 1].c != ' ') { fz_rect spacerect; spacerect.x0 = -0.2f; spacerect.y0 = 0; spacerect.x1 = 0; spacerect.y1 = 1; spacerect = fz_transform_rect(trm, spacerect); fz_add_text_char(last, size, text->wmode, ' ', fz_round_rect(spacerect)); } } } /* Calculate bounding box and new pen position based on font metrics */ //if (font->ft_face) //{ // FT_Fixed ftadv = 0; // int mask = FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING | FT_LOAD_IGNORE_TRANSFORM; // /* TODO: freetype returns broken vertical metrics */ // /* if (text->wmode) mask |= FT_LOAD_VERTICAL_LAYOUT; */ // FT_Get_Advance(font->ft_face, text->items[i].gid, mask, &ftadv); // adv = ftadv / 65536.0f; // rect.x0 = 0; // rect.y0 = descender; // rect.x1 = adv; // rect.y1 = ascender; //} //else { // adv = font->t3widths[text->items[i].gid]; rect.x0 = 0; rect.y0 = descender; rect.x1 = adv; rect.y1 = ascender; } rect = fz_transform_rect(trm, rect); pen->x = trm.e + dir.x * adv; pen->y = trm.f + dir.y * adv; fz_add_text_char(last, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); } }