Mercurial > MadButterfly
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 */ |