summaryrefslogtreecommitdiff
path: root/fitz/dev_text.c
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2010-04-24 20:36:46 +0200
committerTor Andersson <tor@ghostscript.com>2010-04-24 20:36:46 +0200
commit7884b0e64811d129986e25da898debfa1e0aa2e8 (patch)
tree623a98d2443189792b94e52c626969175ecdf864 /fitz/dev_text.c
parent6c9882818e4afc1502c6200f082794811d394b1c (diff)
downloadmupdf-7884b0e64811d129986e25da898debfa1e0aa2e8.tar.xz
Add font and font size information to text spans.
Diffstat (limited to 'fitz/dev_text.c')
-rw-r--r--fitz/dev_text.c207
1 files changed, 141 insertions, 66 deletions
diff --git a/fitz/dev_text.c b/fitz/dev_text.c
index cfbf45b4..fbef5ef6 100644
--- a/fitz/dev_text.c
+++ b/fitz/dev_text.c
@@ -29,52 +29,90 @@ typedef struct fz_textdevice_s fz_textdevice;
struct fz_textdevice_s
{
fz_point point;
- fz_textspan *line;
+ fz_textspan *span;
};
fz_textspan *
fz_newtextspan(void)
{
- fz_textspan *line;
- line = fz_malloc(sizeof(fz_textspan));
- line->len = 0;
- line->cap = 0;
- line->text = nil;
- line->next = nil;
- return line;
+ fz_textspan *span;
+ span = fz_malloc(sizeof(fz_textspan));
+ span->font = nil;
+ span->size = 0.0;
+ span->len = 0;
+ span->cap = 0;
+ span->text = nil;
+ span->next = nil;
+ span->eol = 0;
+ return span;
}
void
-fz_freetextspan(fz_textspan *line)
+fz_freetextspan(fz_textspan *span)
{
- if (line->next)
- fz_freetextspan(line->next);
- fz_free(line->text);
- fz_free(line);
+ if (span->font)
+ fz_dropfont(span->font);
+ if (span->next)
+ fz_freetextspan(span->next);
+ fz_free(span->text);
+ fz_free(span);
}
static void
-fz_addtextchar(fz_textspan *line, int c, fz_bbox bbox)
+fz_addtextchar(fz_textspan **last, fz_font *font, float size, int c, fz_bbox bbox)
{
- if (line->len + 1 >= line->cap)
+ fz_textspan *span = *last;
+
+ if (!span->font)
{
- line->cap = line->cap ? (line->cap * 3) / 2 : 80;
- line->text = fz_realloc(line->text, sizeof(fz_textchar) * line->cap);
+ span->font = fz_keepfont(font);
+ span->size = size;
}
- line->text[line->len].c = c;
- line->text[line->len].bbox = bbox;
- line->len ++;
+
+ if (span->font != font || span->size != size)
+ {
+ span = fz_newtextspan();
+ span->font = fz_keepfont(font);
+ span->size = size;
+ (*last)->next = span;
+ *last = span;
+ }
+
+ if (span->len + 1 >= span->cap)
+ {
+ span->cap = span->cap ? (span->cap * 3) / 2 : 80;
+ span->text = fz_realloc(span->text, sizeof(fz_textchar) * span->cap);
+ }
+ span->text[span->len].c = c;
+ span->text[span->len].bbox = bbox;
+ span->len ++;
+}
+
+static void
+fz_addtextnewline(fz_textspan **last, fz_font *font, float size)
+{
+ fz_textspan *span;
+ span = fz_newtextspan();
+ span->font = fz_keepfont(font);
+ span->size = size;
+ (*last)->eol = 1;
+ (*last)->next = span;
+ *last = span;
}
void
-fz_debugtextspan(fz_textspan *line)
+fz_debugtextspanxml(fz_textspan *span)
{
char buf[10];
int c, n, k, i;
- for (i = 0; i < line->len; i++)
+ printf("<span font=\"%s\" size=\"%g\" eol=\"%d\">\n",
+ span->font ? span->font->name : "NULL", span->size, span->eol);
+
+ for (i = 0; i < span->len; i++)
{
- c = line->text[i].c;
+ printf("\t<char ucs=\"");
+ c = span->text[i].c;
if (c < 128)
putchar(c);
else
@@ -83,19 +121,52 @@ fz_debugtextspan(fz_textspan *line)
for (k = 0; k < n; k++)
putchar(buf[k]);
}
+ printf("\" bbox=\"[%d %d %d %d]\">\n",
+ span->text[i].bbox.x0,
+ span->text[i].bbox.y0,
+ span->text[i].bbox.x1,
+ span->text[i].bbox.y1);
}
- putchar('\n');
- if (line->next)
- fz_debugtextspan(line->next);
+ printf("</span>\n");
+
+ if (span->next)
+ fz_debugtextspanxml(span->next);
+}
+
+void
+fz_debugtextspan(fz_textspan *span)
+{
+ char buf[10];
+ int c, n, k, i;
+
+ for (i = 0; i < span->len; i++)
+ {
+ c = span->text[i].c;
+ if (c < 128)
+ putchar(c);
+ else
+ {
+ n = runetochar(buf, &c);
+ for (k = 0; k < n; k++)
+ putchar(buf[k]);
+ }
+ }
+
+ if (span->eol)
+ putchar('\n');
+
+ if (span->next)
+ fz_debugtextspan(span->next);
}
static void
-fz_textextractline(fz_textspan **line, fz_text *text, fz_matrix ctm, fz_point *oldpt)
+fz_textextractspan(fz_textspan **last, fz_text *text, fz_matrix ctm, fz_point *pen)
{
fz_font *font = text->font;
fz_matrix tm = text->trm;
fz_matrix inv = fz_invertmatrix(text->trm);
+ float size = fz_matrixexpansion(text->trm);
fz_matrix trm;
float dx, dy;
fz_rect rect;
@@ -103,6 +174,9 @@ fz_textextractline(fz_textspan **line, fz_text *text, fz_matrix ctm, fz_point *o
float adv;
int i, fterr;
+ if (text->len == 0)
+ return;
+
if (font->ftface)
{
FT_Set_Transform(font->ftface, NULL, NULL);
@@ -113,43 +187,17 @@ fz_textextractline(fz_textspan **line, fz_text *text, fz_matrix ctm, fz_point *o
for (i = 0; i < text->len; i++)
{
- /* Get bbox in device space */
- tm.e = text->els[i].x;
- tm.f = text->els[i].y;
- trm = fz_concat(tm, ctm);
-
- rect.x0 = 0.0;
- rect.y0 = 0.0;
- rect.x1 = adv;
- rect.y1 = 1.0;
- rect = fz_transformrect(trm, rect);
-
- /* Get point in user space to perform heuristic space and newline tests */
+ /* Get point in user space to perform heuristic space and newspan tests */
p.x = text->els[i].x;
p.y = text->els[i].y;
p = fz_transformpoint(inv, p);
- dx = oldpt->x - p.x;
- dy = oldpt->y - p.y;
- *oldpt = p;
-
- /* TODO: flip advance and test for vertical writing */
- if (fabs(dy) > 0.2)
- {
- fz_textspan *newline;
- newline = fz_newtextspan();
- (*line)->next = newline;
- *line = newline;
- }
- else if (fabs(dx) > 0.2)
- {
- /* TODO: improve the location of the invented space bbox */
- fz_bbox bbox = fz_roundrect(rect);
- bbox.x1 = bbox.x0;
- bbox.y1 = bbox.y0;
- fz_addtextchar(*line, ' ', bbox);
- }
+ dx = pen->x - p.x;
+ dy = pen->y - p.y;
+ if (pen->x == -1 && pen->y == -1)
+ dx = dy = 0;
+ *pen = p;
- /* Update oldpt for advance width */
+ /* Get advance width and update pen position */
if (font->ftface)
{
FT_Fixed ftadv;
@@ -159,15 +207,41 @@ fz_textextractline(fz_textspan **line, fz_text *text, fz_matrix ctm, fz_point *o
if (fterr)
fz_warn("freetype get advance (gid %d): %s", text->els[i].gid, ft_errorstring(fterr));
adv = ftadv / 65536.0;
- oldpt->x += adv;
+ pen->x += adv;
}
else
{
adv = font->t3widths[text->els[i].gid];
- oldpt->x += adv;
+ pen->x += adv;
}
- fz_addtextchar(*line, text->els[i].ucs, fz_roundrect(rect));
+ /* Get bbox in device space */
+ tm.e = text->els[i].x;
+ tm.f = text->els[i].y;
+ trm = fz_concat(tm, ctm);
+
+ rect.x0 = 0.0;
+ rect.y0 = 0.0;
+ rect.x1 = adv;
+ rect.y1 = 1.0;
+ rect = fz_transformrect(trm, rect);
+
+ /* Add to the text span */
+ if (fabs(dy) > 0.001)
+ {
+ fz_addtextnewline(last, font, size);
+ }
+ else if (fabs(dx) > 0.2)
+ {
+ fz_rect spacerect;
+ spacerect.x0 = -fabs(dx);
+ spacerect.y0 = 0.0;
+ spacerect.x1 = 0.0;
+ spacerect.y1 = 1.0;
+ spacerect = fz_transformrect(trm, spacerect);
+ fz_addtextchar(last, font, size, ' ', fz_roundrect(spacerect));
+ }
+ fz_addtextchar(last, font, size, text->els[i].ucs, fz_roundrect(rect));
}
}
@@ -176,20 +250,21 @@ fz_textfilltext(void *user, fz_text *text, fz_matrix ctm,
fz_colorspace *colorspace, float *color, float alpha)
{
fz_textdevice *tdev = user;
- fz_textextractline(&tdev->line, text, ctm, &tdev->point);
+ fz_textextractspan(&tdev->span, text, ctm, &tdev->point);
}
static void
fz_textignoretext(void *user, fz_text *text, fz_matrix ctm)
{
fz_textdevice *tdev = user;
- fz_textextractline(&tdev->line, text, ctm, &tdev->point);
+ fz_textextractspan(&tdev->span, text, ctm, &tdev->point);
}
static void
fz_textfreeuser(void *user)
{
fz_textdevice *tdev = user;
+ tdev->span->eol = 1;
fz_free(tdev);
}
@@ -197,7 +272,7 @@ fz_device *
fz_newtextdevice(fz_textspan *root)
{
fz_textdevice *tdev = fz_malloc(sizeof(fz_textdevice));
- tdev->line = root;
+ tdev->span = root;
tdev->point.x = -1;
tdev->point.y = -1;