Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
#include "fitz.h"
2
 
3
fz_path *
4
fz_new_path(void)
5
{
6
	fz_path *path;
7
 
8
	path = fz_malloc(sizeof(fz_path));
9
	path->len = 0;
10
	path->cap = 0;
11
	path->items = NULL;
12
 
13
	return path;
14
}
15
 
16
fz_path *
17
fz_clone_path(fz_path *old)
18
{
19
	fz_path *path;
20
 
21
	path = fz_malloc(sizeof(fz_path));
22
	path->len = old->len;
23
	path->cap = old->len;
24
	path->items = fz_calloc(path->cap, sizeof(fz_path_item));
25
	memcpy(path->items, old->items, sizeof(fz_path_item) * path->len);
26
 
27
	return path;
28
}
29
 
30
void
31
fz_free_path(fz_path *path)
32
{
33
	fz_free(path->items);
34
	fz_free(path);
35
}
36
 
37
static void
38
grow_path(fz_path *path, int n)
39
{
40
	if (path->len + n < path->cap)
41
		return;
42
	while (path->len + n > path->cap)
43
		path->cap = path->cap + 36;
44
	path->items = fz_realloc(path->items, path->cap, sizeof(fz_path_item));
45
}
46
 
47
void
48
fz_moveto(fz_path *path, float x, float y)
49
{
50
	grow_path(path, 3);
51
	path->items[path->len++].k = FZ_MOVETO;
52
	path->items[path->len++].v = x;
53
	path->items[path->len++].v = y;
54
}
55
 
56
void
57
fz_lineto(fz_path *path, float x, float y)
58
{
59
	if (path->len == 0)
60
	{
61
		fz_warn("lineto with no current point");
62
		return;
63
	}
64
	grow_path(path, 3);
65
	path->items[path->len++].k = FZ_LINETO;
66
	path->items[path->len++].v = x;
67
	path->items[path->len++].v = y;
68
}
69
 
70
void
71
fz_curveto(fz_path *path,
72
	float x1, float y1,
73
	float x2, float y2,
74
	float x3, float y3)
75
{
76
	if (path->len == 0)
77
	{
78
		fz_warn("curveto with no current point");
79
		return;
80
	}
81
	grow_path(path, 7);
82
	path->items[path->len++].k = FZ_CURVETO;
83
	path->items[path->len++].v = x1;
84
	path->items[path->len++].v = y1;
85
	path->items[path->len++].v = x2;
86
	path->items[path->len++].v = y2;
87
	path->items[path->len++].v = x3;
88
	path->items[path->len++].v = y3;
89
}
90
 
91
void
92
fz_curvetov(fz_path *path, float x2, float y2, float x3, float y3)
93
{
94
	float x1, y1;
95
	if (path->len == 0)
96
	{
97
		fz_warn("curvetov with no current point");
98
		return;
99
	}
100
	x1 = path->items[path->len-2].v;
101
	y1 = path->items[path->len-1].v;
102
	fz_curveto(path, x1, y1, x2, y2, x3, y3);
103
}
104
 
105
void
106
fz_curvetoy(fz_path *path, float x1, float y1, float x3, float y3)
107
{
108
	fz_curveto(path, x1, y1, x3, y3, x3, y3);
109
}
110
 
111
void
112
fz_closepath(fz_path *path)
113
{
114
	if (path->len == 0)
115
	{
116
		fz_warn("closepath with no current point");
117
		return;
118
	}
119
	grow_path(path, 1);
120
	path->items[path->len++].k = FZ_CLOSE_PATH;
121
}
122
 
123
static inline fz_rect bound_expand(fz_rect r, fz_point p)
124
{
125
	if (p.x < r.x0) r.x0 = p.x;
126
	if (p.y < r.y0) r.y0 = p.y;
127
	if (p.x > r.x1) r.x1 = p.x;
128
	if (p.y > r.y1) r.y1 = p.y;
129
	return r;
130
}
131
 
132
fz_rect
133
fz_bound_path(fz_path *path, fz_stroke_state *stroke, fz_matrix ctm)
134
{
135
	fz_point p;
136
	fz_rect r = fz_empty_rect;
137
	int i = 0;
138
 
139
	if (path->len)
140
	{
141
		p.x = path->items[1].v;
142
		p.y = path->items[2].v;
143
		p = fz_transform_point(ctm, p);
144
		r.x0 = r.x1 = p.x;
145
		r.y0 = r.y1 = p.y;
146
	}
147
 
148
	while (i < path->len)
149
	{
150
		switch (path->items[i++].k)
151
		{
152
		case FZ_CURVETO:
153
			p.x = path->items[i++].v;
154
			p.y = path->items[i++].v;
155
			r = bound_expand(r, fz_transform_point(ctm, p));
156
			p.x = path->items[i++].v;
157
			p.y = path->items[i++].v;
158
			r = bound_expand(r, fz_transform_point(ctm, p));
159
			p.x = path->items[i++].v;
160
			p.y = path->items[i++].v;
161
			r = bound_expand(r, fz_transform_point(ctm, p));
162
			break;
163
		case FZ_MOVETO:
164
		case FZ_LINETO:
165
			p.x = path->items[i++].v;
166
			p.y = path->items[i++].v;
167
			r = bound_expand(r, fz_transform_point(ctm, p));
168
			break;
169
		case FZ_CLOSE_PATH:
170
			break;
171
		}
172
	}
173
 
174
	if (stroke)
175
	{
176
		float miterlength = stroke->miterlimit;
177
		float linewidth = stroke->linewidth;
178
		float expand = MAX(miterlength, linewidth) * 0.5f;
179
		r.x0 -= expand;
180
		r.y0 -= expand;
181
		r.x1 += expand;
182
		r.y1 += expand;
183
	}
184
 
185
	return r;
186
}
187
 
188
void
189
fz_transform_path(fz_path *path, fz_matrix ctm)
190
{
191
	fz_point p;
192
	int k, i = 0;
193
 
194
	while (i < path->len)
195
	{
196
		switch (path->items[i++].k)
197
		{
198
		case FZ_CURVETO:
199
			for (k = 0; k < 3; k++)
200
			{
201
				p.x = path->items[i].v;
202
				p.y = path->items[i+1].v;
203
				p = fz_transform_point(ctm, p);
204
				path->items[i].v = p.x;
205
				path->items[i+1].v = p.y;
206
				i += 2;
207
			}
208
			break;
209
		case FZ_MOVETO:
210
		case FZ_LINETO:
211
			p.x = path->items[i].v;
212
			p.y = path->items[i+1].v;
213
			p = fz_transform_point(ctm, p);
214
			path->items[i].v = p.x;
215
			path->items[i+1].v = p.y;
216
			i += 2;
217
			break;
218
		case FZ_CLOSE_PATH:
219
			break;
220
		}
221
	}
222
}
223
 
224
void
225
fz_debug_path(fz_path *path, int indent)
226
{
227
	float x, y;
228
	int i = 0;
229
	int n;
230
	while (i < path->len)
231
	{
232
		for (n = 0; n < indent; n++)
233
			putchar(' ');
234
		switch (path->items[i++].k)
235
		{
236
		case FZ_MOVETO:
237
			x = path->items[i++].v;
238
			y = path->items[i++].v;
239
			printf("%g %g m\n", x, y);
240
			break;
241
		case FZ_LINETO:
242
			x = path->items[i++].v;
243
			y = path->items[i++].v;
244
			printf("%g %g l\n", x, y);
245
			break;
246
		case FZ_CURVETO:
247
			x = path->items[i++].v;
248
			y = path->items[i++].v;
249
			printf("%g %g ", x, y);
250
			x = path->items[i++].v;
251
			y = path->items[i++].v;
252
			printf("%g %g ", x, y);
253
			x = path->items[i++].v;
254
			y = path->items[i++].v;
255
			printf("%g %g c\n", x, y);
256
			break;
257
		case FZ_CLOSE_PATH:
258
			printf("h\n");
259
			break;
260
		}
261
	}
262
}