1 /* Copyright © 2006 Ian Osgood
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
17 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 * Except as contained in this notice, the names of the authors or their
21 * institutions shall not be used in advertising or otherwise to promote the
22 * sale, use or other dealings in this Software without prior written
23 * authorization from the authors.
29 #include "xcb_renderutil.h"
31 typedef struct _glyph_header_t {
37 /* implementation of the opaque stream */
38 struct xcb_render_util_composite_text_stream_t {
40 uint32_t glyph_size; /* 0 for unset, 1/2/4 for 8/16/32 */
41 xcb_render_glyphset_t initial_glyphset;
42 xcb_render_glyphset_t current_glyphset;
44 /* dynamically allocated stream */
45 /* contents are 32-bit aligned, network byte order */
51 #define CURRENT_LEN(s) (((char *)s->current - (char *)s->stream))
53 xcb_render_util_composite_text_stream_t *
54 xcb_render_util_composite_text_stream (
55 xcb_render_glyphset_t initial_glyphset,
56 uint32_t total_glyphs,
57 uint32_t total_glyphset_changes )
59 xcb_render_util_composite_text_stream_t *stream;
62 /* assume worst case: each glyph has its own dx,dy */
63 if (total_glyphs || total_glyphset_changes) {
64 size = total_glyphs * 3 * sizeof(uint32_t)
65 + total_glyphset_changes * 3 * sizeof(uint32_t);
68 stream = malloc(sizeof(xcb_render_util_composite_text_stream_t));
70 stream->glyph_size = 0;
71 stream->initial_glyphset = initial_glyphset;
72 stream->current_glyphset = initial_glyphset;
74 stream->stream_len = size;
75 stream->stream = malloc(size);
76 stream->current = stream->stream;
82 _grow_stream( xcb_render_util_composite_text_stream_t *stream, size_t increase )
84 size_t current_len = CURRENT_LEN(stream);
85 if (current_len + increase > stream->stream_len) {
86 uint32_t *s = realloc(stream->stream, 2 * stream->stream_len);
88 stream->stream_len *= 2;
90 stream->current = stream->stream + (current_len>>2);
96 xcb_render_util_glyphs_8 (
97 xcb_render_util_composite_text_stream_t *stream,
101 const uint8_t *glyphs )
103 _glyph_header_t header = { count, {0,0,0}, dx, dy };
105 if (count > 252) return; /* FIXME */
107 if (stream->glyph_size != sizeof(*glyphs)) {
108 if (stream->glyph_size != 0)
110 stream->glyph_size = sizeof(*glyphs);
112 _grow_stream(stream, sizeof(header) + count+3);
114 memcpy(stream->current, &header, sizeof(header));
115 stream->current += 2;
117 memcpy(stream->current, glyphs, header.count);
118 stream->current += ((int)header.count+3)>>2;
122 xcb_render_util_glyphs_16 (
123 xcb_render_util_composite_text_stream_t *stream,
127 const uint16_t *glyphs )
129 _glyph_header_t header = { count, {0,0,0}, dx, dy };
131 if (count > 254) return; /* FIXME */
133 if (stream->glyph_size != sizeof(*glyphs)) {
134 if (stream->glyph_size != 0)
136 stream->glyph_size = sizeof(*glyphs);
138 _grow_stream(stream, sizeof(header) + count*sizeof(*glyphs)+1);
140 memcpy(stream->current, &header, sizeof(header));
141 stream->current += 2;
143 memcpy(stream->current, glyphs, header.count*sizeof(*glyphs));
144 stream->current += ((int)header.count*sizeof(*glyphs)+3)>>2;
148 xcb_render_util_glyphs_32 (
149 xcb_render_util_composite_text_stream_t *stream,
153 const uint32_t *glyphs )
155 _glyph_header_t header = { count, {0,0,0}, dx, dy };
157 if (count > 254) return; /* FIXME */
159 if (stream->glyph_size != sizeof(*glyphs)) {
160 if (stream->glyph_size != 0)
162 stream->glyph_size = sizeof(*glyphs);
164 _grow_stream(stream, sizeof(header) + count*sizeof(*glyphs)+1);
166 memcpy(stream->current, &header, sizeof(header));
167 stream->current += 2;
169 memcpy(stream->current, glyphs, header.count*sizeof(*glyphs));
170 stream->current += header.count;
173 /* note: these glyph arrays must be swapped to network byte order */
176 xcb_render_util_change_glyphset (
177 xcb_render_util_composite_text_stream_t *stream,
178 xcb_render_glyphset_t glyphset )
180 static _glyph_header_t header = { 255, {0,0,0}, 0, 0 };
182 if (glyphset == stream->current_glyphset)
185 _grow_stream(stream, 3*sizeof(uint32_t));
187 memcpy(stream->current, &header, sizeof(header));
188 stream->current += 2;
190 *stream->current = glyphset;
193 stream->current_glyphset = glyphset;
196 typedef xcb_void_cookie_t
197 (*xcb_render_composite_glyphs_func) (xcb_connection_t *c,
199 xcb_render_picture_t src,
200 xcb_render_picture_t dst,
201 xcb_render_pictformat_t mask_format,
202 xcb_render_glyphset_t glyphset,
205 uint32_t glyphcmds_len,
206 const uint8_t *glyphcmds);
210 xcb_render_util_composite_text (
211 xcb_connection_t *xc,
213 xcb_render_picture_t src,
214 xcb_render_picture_t dst,
215 xcb_render_pictformat_t mask_format,
218 xcb_render_util_composite_text_stream_t *stream )
220 xcb_render_composite_glyphs_func f;
222 switch (stream->glyph_size)
225 f = xcb_render_composite_glyphs_8;
228 f = xcb_render_composite_glyphs_16;
231 f = xcb_render_composite_glyphs_32;
233 default: /* uninitialized */
234 return xcb_no_operation(xc);
237 xc, op, src, dst, mask_format,
238 stream->initial_glyphset,
241 (uint8_t *)stream->stream
246 xcb_render_util_composite_text_checked (
247 xcb_connection_t *xc,
249 xcb_render_picture_t src,
250 xcb_render_picture_t dst,
251 xcb_render_pictformat_t mask_format,
254 xcb_render_util_composite_text_stream_t *stream )
256 xcb_render_composite_glyphs_func f;
258 switch (stream->glyph_size)
261 f = xcb_render_composite_glyphs_8_checked;
264 f = xcb_render_composite_glyphs_16_checked;
267 f = xcb_render_composite_glyphs_32_checked;
269 default: /* uninitialized */
270 return xcb_no_operation_checked(xc);
273 xc, op, src, dst, mask_format,
274 stream->initial_glyphset,
277 (uint8_t *)stream->stream
282 xcb_render_util_composite_text_free (
283 xcb_render_util_composite_text_stream_t *stream )
285 free(stream->stream);