00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <math.h>
00005 #include <cairo.h>
00006 #include "mb_types.h"
00007 #include "mb_shapes.h"
00008
00009 #define ASSERT(x)
00010 #define OK 0
00011 #define ERR -1
00012
00013 typedef struct _sh_text {
00014 shape_t shape;
00015 char *data;
00016 co_aix x, y;
00017 co_aix d_x, d_y;
00018 co_aix font_size;
00019 co_aix d_font_size;
00020 cairo_font_face_t *face;
00021 cairo_scaled_font_t *scaled_font;
00022 int flags;
00023 } sh_text_t;
00024
00025 #define TXF_SCALE_DIRTY 0x1
00026
00027 static void sh_text_free(shape_t *shape) {
00028 sh_text_t *text = (sh_text_t *)shape;
00029
00030 if(text->scaled_font)
00031 cairo_scaled_font_destroy(text->scaled_font);
00032 cairo_font_face_destroy(text->face);
00033 }
00034
00035 shape_t *rdman_shape_text_new(redraw_man_t *rdman,
00036 const char *txt, co_aix x, co_aix y,
00037 co_aix font_size, cairo_font_face_t *face) {
00038 sh_text_t *text;
00039
00040 text = (sh_text_t *)malloc(sizeof(sh_text_t));
00041 if(text == NULL)
00042 return NULL;
00043
00044 memset(text, 0, sizeof(sh_text_t));
00045 text->shape.sh_type = SHT_TEXT;
00046 text->data = strdup(txt);
00047 if(text->data == NULL) {
00048 free(text);
00049 return NULL;
00050 }
00051 text->x = x;
00052 text->y = y;
00053 text->font_size = font_size;
00054 cairo_font_face_reference(face);
00055 text->face = face;
00056 text->flags |= TXF_SCALE_DIRTY;
00057
00058 text->shape.free = sh_text_free;
00059
00060 rdman_shape_man(rdman, (shape_t *)text);
00061
00062 return (shape_t *)text;
00063 }
00064
00065 extern void sh_text_set_text(shape_t *shape, const char *txt) {
00066 sh_text_t *text = (sh_text_t *)shape;
00067 char *buf;
00068
00069 buf = strdup(txt);
00070 if(text->data) free(text->data);
00071 text->data = buf;
00072 }
00073
00074 static int get_extents(sh_text_t *text, cairo_text_extents_t *extents) {
00075 cairo_matrix_t fmatrix;
00076 cairo_matrix_t ctm;
00077 cairo_scaled_font_t *new_scaled;
00078 cairo_font_options_t *fopt;
00079
00080 if((text->flags & TXF_SCALE_DIRTY) ||
00081 text->scaled_font == NULL) {
00082 fopt = cairo_font_options_create();
00083 if(fopt == NULL)
00084 return ERR;
00085 memset(&fmatrix, 0, sizeof(cairo_matrix_t));
00086 fmatrix.xx = text->d_font_size;
00087 fmatrix.yy = text->d_font_size;
00088 memset(&ctm, 0, sizeof(cairo_matrix_t));
00089 ctm.xx = 1;
00090 ctm.yy = 1;
00091 new_scaled = cairo_scaled_font_create(text->face,
00092 &fmatrix,
00093 &ctm,
00094 fopt);
00095 cairo_font_options_destroy(fopt);
00096 if(new_scaled == NULL)
00097 return ERR;
00098
00099 if(text->scaled_font)
00100 cairo_scaled_font_destroy(text->scaled_font);
00101 text->scaled_font = new_scaled;
00102 text->flags &= ~TXF_SCALE_DIRTY;
00103 }
00104
00105 cairo_scaled_font_text_extents(text->scaled_font,
00106 text->data, extents);
00107 return OK;
00108 }
00109
00110 void sh_text_transform(shape_t *shape) {
00111 sh_text_t *text;
00112 co_aix x, y;
00113 co_aix shw;
00114 cairo_text_extents_t extents;
00115 co_aix poses[2][2];
00116 int r;
00117
00118 text = (sh_text_t *)shape;
00119
00120 text->d_font_size = coord_trans_size(shape->coord, text->font_size);
00121
00122 x = text->x;
00123 y = text->y;
00124 coord_trans_pos(shape->coord, &x, &y);
00125 r = get_extents(text, &extents);
00126 ASSERT(r == OK);
00127
00128 text->d_x = x;
00129 text->d_y = y;
00130 shw = shape->stroke_width / 2;
00131
00132
00133
00134 poses[0][0] = x + extents.x_bearing - 5 - shw;
00135 poses[0][1] = y + extents.y_bearing - 5 - shw;
00136 poses[1][0] = poses[0][0] + extents.width + 10 + shape->stroke_width;
00137 poses[1][1] = poses[0][1] + extents.height + 10 + shape->stroke_width;
00138 geo_from_positions(shape->geo, 2, poses);
00139
00140 }
00141
00142
00143 static void draw_text(sh_text_t *text, cairo_t *cr) {
00144 cairo_set_scaled_font(cr, text->scaled_font);
00145 cairo_move_to(cr, text->d_x, text->d_y);
00146 cairo_text_path(cr, text->data);
00147 }
00148
00149
00150 void sh_text_draw(shape_t *shape, cairo_t *cr) {
00151 draw_text((sh_text_t *)shape, cr);
00152 }
00153