Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
#include "fitz.h"
2
#include "muxps.h"
3
 
4
static inline int unhex(int a)
5
{
6
	if (a >= 'A' && a <= 'F') return a - 'A' + 0xA;
7
	if (a >= 'a' && a <= 'f') return a - 'a' + 0xA;
8
	if (a >= '0' && a <= '9') return a - '0';
9
	return 0;
10
}
11
 
12
void
13
xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node)
14
{
15
	/* SolidColorBrushes are handled in a special case and will never show up here */
16
	if (!strcmp(xml_tag(node), "ImageBrush"))
17
		xps_parse_image_brush(ctx, ctm, area, base_uri, dict, node);
18
	else if (!strcmp(xml_tag(node), "VisualBrush"))
19
		xps_parse_visual_brush(ctx, ctm, area, base_uri, dict, node);
20
	else if (!strcmp(xml_tag(node), "LinearGradientBrush"))
21
		xps_parse_linear_gradient_brush(ctx, ctm, area, base_uri, dict, node);
22
	else if (!strcmp(xml_tag(node), "RadialGradientBrush"))
23
		xps_parse_radial_gradient_brush(ctx, ctm, area, base_uri, dict, node);
24
	else
25
		fz_warn("unknown brush tag: %s", xml_tag(node));
26
}
27
 
28
void
29
xps_parse_element(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node)
30
{
31
	if (!strcmp(xml_tag(node), "Path"))
32
		xps_parse_path(ctx, ctm, base_uri, dict, node);
33
	if (!strcmp(xml_tag(node), "Glyphs"))
34
		xps_parse_glyphs(ctx, ctm, base_uri, dict, node);
35
	if (!strcmp(xml_tag(node), "Canvas"))
36
		xps_parse_canvas(ctx, ctm, area, base_uri, dict, node);
37
	/* skip unknown tags (like Foo.Resources and similar) */
38
}
39
 
40
void
41
xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area,
42
	char *base_uri, xps_resource *dict,
43
	char *opacity_att, xml_element *opacity_mask_tag)
44
{
45
	float opacity;
46
 
47
	if (!opacity_att && !opacity_mask_tag)
48
		return;
49
 
50
	opacity = 1;
51
	if (opacity_att)
52
		opacity = fz_atof(opacity_att);
53
 
54
	if (opacity_mask_tag && !strcmp(xml_tag(opacity_mask_tag), "SolidColorBrush"))
55
	{
56
		char *scb_opacity_att = xml_att(opacity_mask_tag, "Opacity");
57
		char *scb_color_att = xml_att(opacity_mask_tag, "Color");
58
		if (scb_opacity_att)
59
			opacity = opacity * fz_atof(scb_opacity_att);
60
		if (scb_color_att)
61
		{
62
			fz_colorspace *colorspace;
63
			float samples[32];
64
			xps_parse_color(ctx, base_uri, scb_color_att, &colorspace, samples);
65
			opacity = opacity * samples[0];
66
		}
67
		opacity_mask_tag = NULL;
68
	}
69
 
70
	if (ctx->opacity_top + 1 < nelem(ctx->opacity))
71
	{
72
		ctx->opacity[ctx->opacity_top + 1] = ctx->opacity[ctx->opacity_top] * opacity;
73
		ctx->opacity_top++;
74
	}
75
 
76
	if (opacity_mask_tag)
77
	{
78
		fz_begin_mask(ctx->dev, area, 0, NULL, NULL);
79
		xps_parse_brush(ctx, ctm, area, base_uri, dict, opacity_mask_tag);
80
		fz_end_mask(ctx->dev);
81
	}
82
}
83
 
84
void
85
xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict,
86
	char *opacity_att, xml_element *opacity_mask_tag)
87
{
88
	if (!opacity_att && !opacity_mask_tag)
89
		return;
90
 
91
	if (ctx->opacity_top > 0)
92
		ctx->opacity_top--;
93
 
94
	if (opacity_mask_tag)
95
	{
96
		if (strcmp(xml_tag(opacity_mask_tag), "SolidColorBrush"))
97
			fz_pop_clip(ctx->dev);
98
	}
99
}
100
 
101
void
102
xps_parse_render_transform(xps_context *ctx, char *transform, fz_matrix *matrix)
103
{
104
	float args[6];
105
	char *s = transform;
106
	int i;
107
 
108
	args[0] = 1; args[1] = 0;
109
	args[2] = 0; args[3] = 1;
110
	args[4] = 0; args[5] = 0;
111
 
112
	for (i = 0; i < 6 && *s; i++)
113
	{
114
		args[i] = fz_atof(s);
115
		while (*s && *s != ',')
116
			s++;
117
		if (*s == ',')
118
			s++;
119
	}
120
 
121
	matrix->a = args[0]; matrix->b = args[1];
122
	matrix->c = args[2]; matrix->d = args[3];
123
	matrix->e = args[4]; matrix->f = args[5];
124
}
125
 
126
void
127
xps_parse_matrix_transform(xps_context *ctx, xml_element *root, fz_matrix *matrix)
128
{
129
	char *transform;
130
 
131
	*matrix = fz_identity;
132
 
133
	if (!strcmp(xml_tag(root), "MatrixTransform"))
134
	{
135
		transform = xml_att(root, "Matrix");
136
		if (transform)
137
			xps_parse_render_transform(ctx, transform, matrix);
138
	}
139
}
140
 
141
void
142
xps_parse_rectangle(xps_context *ctx, char *text, fz_rect *rect)
143
{
144
	float args[4];
145
	char *s = text;
146
	int i;
147
 
148
	args[0] = 0; args[1] = 0;
149
	args[2] = 1; args[3] = 1;
150
 
151
	for (i = 0; i < 4 && *s; i++)
152
	{
153
		args[i] = fz_atof(s);
154
		while (*s && *s != ',')
155
			s++;
156
		if (*s == ',')
157
			s++;
158
	}
159
 
160
	rect->x0 = args[0];
161
	rect->y0 = args[1];
162
	rect->x1 = args[0] + args[2];
163
	rect->y1 = args[1] + args[3];
164
}
165
 
166
static int count_commas(char *s)
167
{
168
	int n = 0;
169
	while (*s)
170
	{
171
		if (*s == ',')
172
			n ++;
173
		s ++;
174
	}
175
	return n;
176
}
177
 
178
void
179
xps_parse_color(xps_context *ctx, char *base_uri, char *string,
180
		fz_colorspace **csp, float *samples)
181
{
182
	char *p;
183
	int i, n;
184
	char buf[1024];
185
	char *profile;
186
 
187
	*csp = fz_device_rgb;
188
 
189
	samples[0] = 1;
190
	samples[1] = 0;
191
	samples[2] = 0;
192
	samples[3] = 0;
193
 
194
	if (string[0] == '#')
195
	{
196
		if (strlen(string) == 9)
197
		{
198
			samples[0] = unhex(string[1]) * 16 + unhex(string[2]);
199
			samples[1] = unhex(string[3]) * 16 + unhex(string[4]);
200
			samples[2] = unhex(string[5]) * 16 + unhex(string[6]);
201
			samples[3] = unhex(string[7]) * 16 + unhex(string[8]);
202
		}
203
		else
204
		{
205
			samples[0] = 255;
206
			samples[1] = unhex(string[1]) * 16 + unhex(string[2]);
207
			samples[2] = unhex(string[3]) * 16 + unhex(string[4]);
208
			samples[3] = unhex(string[5]) * 16 + unhex(string[6]);
209
		}
210
 
211
		samples[0] /= 255;
212
		samples[1] /= 255;
213
		samples[2] /= 255;
214
		samples[3] /= 255;
215
	}
216
 
217
	else if (string[0] == 's' && string[1] == 'c' && string[2] == '#')
218
	{
219
		if (count_commas(string) == 2)
220
			sscanf(string, "sc#%g,%g,%g", samples + 1, samples + 2, samples + 3);
221
		if (count_commas(string) == 3)
222
			sscanf(string, "sc#%g,%g,%g,%g", samples, samples + 1, samples + 2, samples + 3);
223
	}
224
 
225
	else if (strstr(string, "ContextColor ") == string)
226
	{
227
		/* Crack the string for profile name and sample values */
228
		fz_strlcpy(buf, string, sizeof buf);
229
 
230
		profile = strchr(buf, ' ');
231
		if (!profile)
232
		{
233
			fz_warn("cannot find icc profile uri in '%s'", string);
234
			return;
235
		}
236
 
237
		*profile++ = 0;
238
		p = strchr(profile, ' ');
239
		if (!p)
240
		{
241
			fz_warn("cannot find component values in '%s'", profile);
242
			return;
243
		}
244
 
245
		*p++ = 0;
246
		n = count_commas(p) + 1;
247
		i = 0;
248
		while (i < n)
249
		{
250
			samples[i++] = fz_atof(p);
251
			p = strchr(p, ',');
252
			if (!p)
253
				break;
254
			p ++;
255
			if (*p == ' ')
256
				p ++;
257
		}
258
		while (i < n)
259
		{
260
			samples[i++] = 0;
261
		}
262
 
263
		/* TODO: load ICC profile */
264
		switch (n)
265
		{
266
		case 2: *csp = fz_device_gray; break;
267
		case 4: *csp = fz_device_rgb; break;
268
		case 5: *csp = fz_device_cmyk; break;
269
		default: *csp = fz_device_gray; break;
270
		}
271
	}
272
}
273
 
274
void
275
xps_set_color(xps_context *ctx, fz_colorspace *colorspace, float *samples)
276
{
277
	int i;
278
	ctx->colorspace = colorspace;
279
	for (i = 0; i < colorspace->n; i++)
280
		ctx->color[i] = samples[i + 1];
281
	ctx->alpha = samples[0] * ctx->opacity[ctx->opacity_top];
282
}