comparison src/shape_stext.c @ 393:27774b93521e

Add sh_stext_t to implement a simple version of text shape. - It is still under construction. - It is supposed to be a simple, less dependency implementation. - It is more less functional than sh_text_t.
author Thinker K.F. Li <thinker@branda.to>
date Mon, 08 Jun 2009 07:04:20 +0800
parents
children b3d5ce48670a
comparison
equal deleted inserted replaced
392:ebf83a50e1e1 393:27774b93521e
1 #include <stdio.h>
2 #include <cairo.h>
3 #include <fontconfig.h>
4 #include "mb_shapes.h"
5
6 #if 0
7
8 #ifndef ASSERT
9 #define ASSERT(x)
10 #endif
11 #define OK 0
12 #define ERR -1
13
14 /*! \brief Query and return a font face for a specified attribute vector.
15 *
16 * Programmers use mb_font_face_t to specify fonts used to show a
17 * block of text on the output device. They can get mb_font_face_t with
18 * this function. The objects return by mb_font_face_query() should be
19 * freed with mb_font_face_free() when they are not more used.
20 *
21 * \param family is the name of a font family (times).
22 * \param slant is one of \ref MB_FONT_SLANTS.
23 * \param weight decides if a font is thin or heavy.
24 */
25 mb_font_face_t *mb_font_face_query(redraw_man_t *rdman,
26 const char *family,
27 int slant,
28 int weight) {
29 cairo_font_face_t *cface;
30 FcPattern *ptn;
31 FcValue val;
32 static int slant_map[] = { /* from MB_FONT_SLANT_* to FC_SLANT_* */
33 FC_SLANT_ROMAN,
34 FC_SLANT_ROMAN,
35 FC_SLANT_ITALIC,
36 FC_SLANT_OBLIQUE};
37
38 ptn = FcPatternCreate();
39 val.type = FcTypeString;
40 val.s = family;
41 FcPatternAdd(ptn, "family", val, FcTrue);
42
43 if(family < 0 || family >= MB_FONT_SLANT_MAX) {
44 FcPatternDestroy(ptn);
45 return NULL;
46 }
47 val.type = FcTypeInteger;
48 val.i = slant_map[slant];
49 FcPatternAdd(ptn, "slant", val, FcTrue);
50
51 val.type = FcTypeInteger;
52 val.i = weight;
53 FcPatternAdd(ptn, "weight", val, FcTrue);
54
55 cface = cairo_ft_font_face_create_for_pattern(ptn);
56 FcPatternDestroy(ptn);
57
58 return (mb_font_face_t *)cface;
59 }
60
61 void mb_font_face_free(mb_font_face_t *face) {
62 cairo_font_face_t *cface = (cairo_font_face_t *)face;
63 ASSERT(face != NULL);
64 cairo_font_face_destroy(face);
65 }
66
67 /*! \brief A simple implementation of text shape.
68 *
69 */
70 typedef struct _sh_stext {
71 shape_t shape;
72 const char *txt; /*!< \brief Text to be showed */
73 const mb_style_blk_t *style_blks; /*!< \brief Style of text */
74 int nblks; /*!< \brief Number of style blocks */
75 int max_nblks;
76 co_aix x, y;
77 cairo_scaled_font_t **scaled_fonts;
78 } sh_stext_t;
79
80 shape_t *rdman_shape_stext_new(redraw_man_t *rdman, co_aix x, co_aix y,
81 const char *txt) {
82 sh_stext_t *txt_o;
83
84 ASSERT(txt != NULL);
85
86 txt_o = (sh_stext_t *)malloc(sizeof(sh_stext_t));
87 if(txt_o == NULL)
88 return NULL;
89
90 memset(&txt_o->shape, 0, sizeof(shape_t));
91 mb_obj_init(txt_o, MBO_STEXT);
92
93 txt_o->txt = strdup(txt);
94 txt_o->style_blks = NULL;
95 txt_o->nblks = 0;
96 txt_o->max_nblks = 0;
97 txt_o->x = x;
98 txt_o->y = y;
99 txt_o->exts = NULL;
100
101 if(txt_o->txt == NULL) {
102 free(txt_o);
103 txt_o = NULL;
104 }
105
106 return (shape_t *)txt_o;
107 }
108
109 static
110 int compute_utf8_chars_sz(const char *txt, int n_chars) {
111 int i;
112 const char *p = txt;
113
114 for(i = 0; i < n && *p; i++) {
115 if(*p++ & 0x80)
116 continue; /* single byte */
117 /* multi-bytes */
118 while(*p && ((*p & 0xc0) == 0x80))
119 p++;
120 }
121 if(i < n)
122 return ERR;
123
124 return p - txt;
125 }
126
127 static
128 void compute_text_extents(char *txt, int txt_len,
129 cairo_scaled_font_t *scaled_font,
130 cairo_text_extents_t *extents) {
131 char saved;
132
133 saved = txt[txt_len];
134 txt[txt_len] = 0;
135 cairo_scaled_font_text_extents(scaled_font, txt, extents);
136 txt[txt_len] = saved;
137 }
138
139 static
140 cairo_scaled_font_t *make_scaled_font_face(sh_stext_t *txt_o,
141 cairo_font_face_t *face,
142 co_aix shift_x, co_aix shift_y,
143 co_aix font_sz) {
144 cairo_matrix_t cmtx;
145 static cairo_matrix_t cid;
146 static cairo_font_options_t *fopt = NULL;
147 co_aix *matrix;
148 cairo_scaled_font_t *scaled;
149 int i;
150
151 if(fopt == NULL) {
152 cairo_matrix_init_identify(&cid);
153 fopt = cairo_font_options_create();
154 if(fopt == NULL)
155 return NULL;
156 }
157
158 matrix = sh_get_aggr_matrix((shape_t *)txt_o);
159 i = 0;
160 cmtx.xx = matrix[i++];
161 cmtx.xy = matrix[i++];
162 cmtx.x0 = matrix[i++] + shift_x;
163 cmtx.yx = matrix[i++];
164 cmtx.yy = matrix[i++];
165 cmtx.y0 = matrix[i] + shift_y;
166
167 scaled = cairo_scaled_font_create(face, &cmtx, &cid, fopt);
168
169 return scaled;
170 }
171
172 static
173 void compute_extents(sh_stext_t *txt_o) {
174 co_aix adv_x, adv_y;
175 cairo_text_extents_t extents;
176 mb_style_blk_t *blk;
177 cairo_scaled_font_t *scaled_font;
178 char *txt;
179 co_aix shift_x, shift_y;
180 int blk_txt_len;
181 int i;
182
183 adv_x = adv_y = 0;
184 blk = txt_o->style_blks;
185 scaled_font = txt_o->scaled_fonts;
186 txt = (char *)txt_o->txt;
187 shift_x = txt_o->x;
188 shift_y = txt_o->y;
189 for(i = 0; i < txt_o->nblks; i++) {
190 *scaled_font = make_scaled_fonts(txt_o, blk->face,
191 shift_x, shift_y, font_sz);
192 ASSERT(*scaled_font != NULL);
193
194 blk_txt_len = compute_utf8_chars_sz(txt, blk->n_chars);
195 ASSERT(blk_txt_len != ERR);
196
197 compute_text_extents(txt, blk_txt_len, *scaled_font, &extents);
198 adv_x += extents.x_advance;
199 adv_y += extents.y_advance;
200
201 scaled_font++;
202 blk++;
203 txt += blk_txt_len;
204 }
205 }
206
207 /*
208 * What we have to do in sh_stext_transform() is
209 * - computing bounding box for the text,
210 * - computing offset x,y for the text of style blocks,
211 * - free old scaled fonts, and
212 * - making scaled fonts for style blocks.
213 */
214 void sh_stext_transform(shape_t *shape) {
215 sh_stext_t *txt_o = (sh_stext_t *)shape;
216
217 ASSERT(txt_o != NULL);
218 }
219
220 void sh_stext_draw(shape_t *shape, cairo_t *cr) {
221 sh_stext_t *txt_o = (sh_stext_t *)shape;
222
223 ASSERT(txt_o != NULL);
224 }
225
226 int sh_stext_set_text(shape_t *shape, const char *txt) {
227 sh_stext_t *txt_o = (sh_stext_t *)shape;
228 char *new_txt;
229 int sz;
230
231 ASSERT(txt_o != NULL);
232 ASSERT(txt != NULL);
233
234 sz = strlen(txt) + 1;
235 new_txt = realloc(txt_o->txt, sz);
236 if(new_txt == NULL)
237 return ERR;
238
239 memcpy(new_txt, txt, sz);
240 txt_o->txt = new_txt;
241
242 return OK;
243 }
244
245 int sh_stext_set_style(shape_t *shape,
246 const mb_style_blk_t *blks,
247 int nblks) {
248 sh_stext_t *txt_o = (sh_stext_t *)shape;
249 mb_style_blk_t *new_blks;
250 co_aix *new_exts;
251 int sz;
252
253 ASSERT(txt_o != NULL);
254 ASSERT(nblks >= 0);
255
256 if(nblks > txt_o->max_nblks) {
257 sz = nblks * (sizeof(mb_style_blk_t) + sizeof(int));
258 new_blks = (mb_style_blk_t *)realloc(txt_o->style_blks, sz);
259 if(new_blks == NULL)
260 return ERR;
261 new_exts = (int *)(new_blks + nblks);
262
263 txt_o->style_blks = new_blks;
264 txt_o->exts = new_exts;
265 txt_o->max_nblks = nblks;
266 }
267
268 memcpy(txt_o->blks, blks, nblks * sizeof(mb_style_blk_t));
269 txt_o->nblks = nblks;
270
271 return OK;
272 }
273
274 #endif /* 0 */