summaryrefslogtreecommitdiff
path: root/common/glyph_assemble.c
blob: cc7a7004f1b3b760459310364ac04467ebdcc3ae (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
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdlib.h>

#include "fb.h"
#include "mipict.h"

#include "glyph_assemble.h"
#include "glyph_cache.h"
#include "glyph_extents.h"

static size_t glyph_list_count(int nlist, GlyphListPtr list)
{
	size_t total = 0;

	while (nlist--) {
		total += list->len;
		list++;
	}

	return total;
}

int glyphs_assemble(ScreenPtr pScreen, struct glyph_render **gp,
	BoxPtr extents, int nlist, GlyphListPtr list, GlyphPtr *glyphs)
{
	struct glyph_render *gr, *grp;
	int x, y, total;

	/*
	 * Preload the cache with the glyphs which we intend to use.
	 * This means we can avoid having to reset the destination
	 * for the PictOpAdd below.  If this fails, fallback.
	 */
	if (!glyph_cache_preload(pScreen, nlist, list, glyphs))
		return -1;

	GlyphExtents(nlist, list, glyphs, extents);
	if (extents->x2 <= extents->x1 || extents->y2 <= extents->y1)
		return 0;

	total = glyph_list_count(nlist, list);
	gr = malloc(sizeof(struct glyph_render) * total);
	if (!gr)
		return -1;

	x = -extents->x1;
	y = -extents->y1;
	grp = gr;

	while (nlist--) {
		int n = list->len;

		x += list->xOff;
		y += list->yOff;

		while (n--) {
			GlyphPtr glyph = *glyphs++;

			if (glyph->info.width && glyph->info.height) {
				grp->dest_box.x1 = x - glyph->info.x;
				grp->dest_box.y1 = y - glyph->info.y;
				grp->dest_box.x2 = grp->dest_box.x1 +
						   glyph->info.width;
				grp->dest_box.y2 = grp->dest_box.y1 +
						   glyph->info.height;
				grp->picture = glyph_cache_only(pScreen, glyph,
					      &grp->glyph_pos);
				if (!grp->picture) {
					free(gr);
					return -1;
				}
				grp++;
			}
			x += glyph->info.xOff;
			y += glyph->info.yOff;
		}
		list++;
	}

	*gp = gr;

	return grp - gr;
}