27
|
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 }
|