Mercurial > MadButterfly
comparison src/shape_text.c @ 27:19c603dd6ff9
Add text shape.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Mon, 04 Aug 2008 10:10:47 +0800 |
parents | |
children | e06a4a667ce2 |
comparison
equal
deleted
inserted
replaced
26:d50f33040de6 | 27:19c603dd6ff9 |
---|---|
1 #include <stdio.h> | |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 #include <cairo.h> | |
5 #include "mb_types.h" | |
6 #include "shapes.h" | |
7 | |
8 #define OK 0 | |
9 #define ERR -1 | |
10 | |
11 typedef struct _sh_text { | |
12 shape_t shape; | |
13 char *data; | |
14 co_aix x, y; | |
15 co_aix d_x, d_y; /* device x and y */ | |
16 co_aix font_size; | |
17 cairo_font_face_t *face; | |
18 cairo_scaled_font_t *scaled_font; | |
19 int flags; | |
20 } sh_text_t; | |
21 | |
22 #define TXF_SCALE_DIRTY 0x1 | |
23 | |
24 shape_t *sh_text_new(const char *txt, co_aix x, co_aix y, | |
25 co_aix font_size, cairo_font_face_t *face) { | |
26 sh_text_t *text; | |
27 | |
28 text = (sh_text_t *)malloc(sizeof(sh_text_t)); | |
29 if(text == NULL) | |
30 return NULL; | |
31 | |
32 memset(text, 0, sizeof(sh_text_t)); | |
33 text->shape.sh_type = SHT_TEXT; | |
34 text->data = strdup(txt); | |
35 if(text->data == NULL) { | |
36 free(text); | |
37 return NULL; | |
38 } | |
39 text->x = x; | |
40 text->y = y; | |
41 text->font_size = font_size; | |
42 cairo_font_face_reference(face); | |
43 text->face = face; | |
44 text->flags |= TXF_SCALE_DIRTY; | |
45 | |
46 return (shape_t *)text; | |
47 } | |
48 | |
49 void sh_text_free(shape_t *shape) { | |
50 sh_text_t *text = (sh_text_t *)shape; | |
51 | |
52 if(text->scaled_font) | |
53 cairo_scaled_font_destroy(text->scaled_font); | |
54 cairo_font_face_destroy(text->face); | |
55 } | |
56 | |
57 static int get_extents(sh_text_t *text, cairo_text_extents_t *extents) { | |
58 cairo_matrix_t fmatrix; | |
59 cairo_matrix_t ctm; | |
60 cairo_scaled_font_t *new_scaled; | |
61 cairo_font_options_t *fopt; | |
62 | |
63 if((text->flags & TXF_SCALE_DIRTY) || | |
64 text->scaled_font == NULL) { | |
65 fopt = cairo_font_options_create(); | |
66 if(fopt == NULL) | |
67 return ERR; | |
68 memset(&fmatrix, 0, sizeof(cairo_matrix_t)); | |
69 fmatrix.xx = text->font_size; | |
70 fmatrix.yy = text->font_size; | |
71 memset(&ctm, 0, sizeof(cairo_matrix_t)); | |
72 ctm.xx = 1; | |
73 ctm.yy = 1; | |
74 new_scaled = cairo_scaled_font_create(text->face, | |
75 &fmatrix, | |
76 &ctm, | |
77 fopt); | |
78 cairo_font_options_destroy(fopt); | |
79 if(new_scaled == NULL) | |
80 return ERR; | |
81 | |
82 if(text->scaled_font) | |
83 cairo_scaled_font_destroy(text->scaled_font); | |
84 text->scaled_font = new_scaled; | |
85 text->flags &= ~TXF_SCALE_DIRTY; | |
86 } | |
87 | |
88 cairo_scaled_font_text_extents(text->scaled_font, | |
89 text->data, extents); | |
90 return OK; | |
91 } | |
92 | |
93 void sh_text_transform(shape_t *shape) { | |
94 sh_text_t *text; | |
95 co_aix x, y; | |
96 co_aix shw; | |
97 cairo_text_extents_t extents; | |
98 co_aix poses[2][2]; | |
99 int r; | |
100 | |
101 text = (sh_text_t *)shape; | |
102 x = text->x; | |
103 y = text->y; | |
104 coord_trans_pos(shape->coord, &x, &y); | |
105 r = get_extents(text, &extents); | |
106 if(r != OK) | |
107 /* TODO: announce error. change return type? */ | |
108 return; | |
109 | |
110 text->d_x = x; | |
111 text->d_y = y; | |
112 shw = shape->stroke_width / 2; | |
113 /* FIXME: It is unreasonable that a font exceed it's bbox. | |
114 * We add 5 pixels in get right bbox. But, it is unreasonable. | |
115 */ | |
116 poses[0][0] = x + extents.x_bearing - 5 - shw; | |
117 poses[0][1] = y + extents.y_bearing - 5 - shw; | |
118 poses[1][0] = poses[0][0] + extents.width + 10 + shape->stroke_width; | |
119 poses[1][1] = poses[0][1] + extents.height + 10 + shape->stroke_width; | |
120 geo_from_positions(shape->geo, 2, poses); | |
121 } | |
122 | |
123 | |
124 static void draw_text(sh_text_t *text, cairo_t *cr) { | |
125 cairo_set_scaled_font(cr, text->scaled_font); | |
126 cairo_move_to(cr, text->d_x, text->d_y); | |
127 cairo_text_path(cr, text->data); | |
128 } | |
129 | |
130 | |
131 void sh_text_fill(shape_t *shape, cairo_t *cr) { | |
132 sh_text_t *text = (sh_text_t *)shape; | |
133 | |
134 draw_text(text, cr); | |
135 cairo_fill(cr); | |
136 } | |
137 | |
138 | |
139 void sh_text_stroke(shape_t *shape, cairo_t *cr) { | |
140 sh_text_t *text = (sh_text_t *)shape; | |
141 | |
142 draw_text(text, cr); | |
143 cairo_stroke(cr); | |
144 } |