summaryrefslogtreecommitdiff
path: root/source/fitz/text.c
blob: 0616d6a9fd3338e3637806cd1810cdb4ce3ac3b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "mupdf/fitz.h"

fz_text *
fz_new_text(fz_context *ctx, fz_font *font, const fz_matrix *trm, int wmode)
{
	fz_text *text;

	text = fz_malloc_struct(ctx, fz_text);
	text->refs = 1;
	text->font = fz_keep_font(ctx, font);
	text->trm = *trm;
	text->wmode = wmode;
	text->len = 0;
	text->cap = 0;
	text->items = NULL;

	return text;
}

fz_text *
fz_keep_text(fz_context *ctx, fz_text *text)
{
	return fz_keep_imp(ctx, text, &text->refs);
}

void
fz_drop_text(fz_context *ctx, fz_text *text)
{
	if (fz_drop_imp(ctx, text, &text->refs))
	{
		fz_drop_font(ctx, text->font);
		fz_free(ctx, text->items);
		fz_free(ctx, text);
	}
}

fz_rect *
fz_bound_text(fz_context *ctx, fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm, fz_rect *bbox)
{
	fz_matrix tm, trm;
	fz_rect gbox;
	int i;

	if (text->len == 0)
	{
		*bbox = fz_empty_rect;
		return bbox;
	}

	// TODO: stroke state

	tm = text->trm;

	tm.e = text->items[0].x;
	tm.f = text->items[0].y;
	fz_concat(&trm, &tm, ctm);
	fz_bound_glyph(ctx, text->font, text->items[0].gid, &trm, bbox);

	for (i = 1; i < text->len; i++)
	{
		if (text->items[i].gid >= 0)
		{
			tm.e = text->items[i].x;
			tm.f = text->items[i].y;
			fz_concat(&trm, &tm, ctm);
			fz_bound_glyph(ctx, text->font, text->items[i].gid, &trm, &gbox);

			bbox->x0 = fz_min(bbox->x0, gbox.x0);
			bbox->y0 = fz_min(bbox->y0, gbox.y0);
			bbox->x1 = fz_max(bbox->x1, gbox.x1);
			bbox->y1 = fz_max(bbox->y1, gbox.y1);
		}
	}

	if (stroke)
		fz_adjust_rect_for_stroke(ctx, bbox, stroke, ctm);

	/* Compensate for the glyph cache limited positioning precision */
	bbox->x0 -= 1;
	bbox->y0 -= 1;
	bbox->x1 += 1;
	bbox->y1 += 1;

	return bbox;
}

static void
fz_grow_text(fz_context *ctx, fz_text *text, int n)
{
	int new_cap = text->cap;
	if (text->len + n < new_cap)
		return;
	while (text->len + n > new_cap)
		new_cap = new_cap + 36;
	text->items = fz_resize_array(ctx, text->items, new_cap, sizeof(fz_text_item));
	text->cap = new_cap;
}

void
fz_add_text(fz_context *ctx, fz_text *text, int gid, int ucs, float x, float y)
{
	if (text->refs != 1)
		fz_throw(ctx, FZ_ERROR_GENERIC, "cannot modify shared text objects");

	fz_grow_text(ctx, text, 1);
	text->items[text->len].ucs = ucs;
	text->items[text->len].gid = gid;
	text->items[text->len].x = x;
	text->items[text->len].y = y;
	text->len++;
}