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 }