Mercurial > MadButterfly
changeset 27:19c603dd6ff9
Add text shape.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Mon, 04 Aug 2008 10:10:47 +0800 |
parents | d50f33040de6 |
children | 604bc90d509d |
files | src/Makefile src/X_main.c src/redraw_man.c src/shape_text.c src/shapes.h |
diffstat | 5 files changed, 232 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/src/Makefile Sun Aug 03 13:04:55 2008 +0800 +++ b/src/Makefile Mon Aug 04 10:10:47 2008 +0800 @@ -1,4 +1,4 @@ -SRCS = coord.c geo.c shape_path.c redraw_man.c paint.c tools.c +SRCS = coord.c geo.c shape_path.c shape_text.c redraw_man.c paint.c tools.c OBJS = ${SRCS:C/(.*)\.c/\1.o/g} TESTCASE_OBJS = ${SRCS:C/(.*)\.c/testcase-\1.o/g} CFLAGS+= -Wall -I/usr/local/include `pkg-config --cflags cairo`
--- a/src/X_main.c Sun Aug 03 13:04:55 2008 +0800 +++ b/src/X_main.c Mon Aug 04 10:10:47 2008 +0800 @@ -17,22 +17,35 @@ cairo_surface_t *tmpsuf; redraw_man_t rdman; shape_t *path1, *path2, *path3; - coord_t *coord1, *coord2; + coord_t *coord1, *coord2, *coord3; paint_t *fill1, *fill2, *fill3; - paint_t *stroke; + paint_t *stroke, *text_stroke; + shape_t *text; grad_stop_t fill3_stops[3]; + cairo_font_face_t *face; int i; tmpsuf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); tmpcr = cairo_create(tmpsuf); + cairo_set_source_surface(cr, tmpsuf, 0, 0); redraw_man_init(&rdman, tmpcr, cr); coord1 = rdman_coord_new(&rdman, rdman.root_coord); coord2 = rdman_coord_new(&rdman, rdman.root_coord); + coord3 = rdman_coord_new(&rdman, rdman.root_coord); fill1 = paint_color_new(&rdman, 1, 1, 0, 0.5); fill2 = paint_color_new(&rdman, 0, 1, 1, 0.5); stroke = paint_color_new(&rdman, 0.4, 0.4, 0.4, 1); + text_stroke = paint_color_new(&rdman, 0.5, 0.5, 0.5, 1); + + face = cairo_get_font_face(tmpcr); + text = sh_text_new("hello \xe6\xbc\xa2\xe5\xad\x97", 10, h / 4, + 36.0, face); + rdman_paint_stroke(&rdman, text_stroke, text); + text->stroke_width = 0.5; + rdman_add_shape(&rdman, text, coord3); + path1 = sh_path_new("M 22,89.36218 C -34,-0.63782 39,-9.637817 82,12.36218 C 125,34.36218 142,136.36218 142,136.36218 C 100.66667,125.36218 74.26756,123.42795 22,89.36218 z "); rdman_paint_fill(&rdman, fill1, path1); rdman_paint_stroke(&rdman, stroke, path1); @@ -41,6 +54,7 @@ coord1->matrix[2] = 20; coord1->matrix[4] = 0.8; coord1->matrix[5] = 20; + path2 = sh_path_new("M 22,89.36218 C -34,-0.63782 39,-9.637817 82,12.36218 C 125,34.36218 142,136.36218 142,136.36218 C 100.66667,125.36218 74.26756,123.42795 22,89.36218 z "); rdman_paint_fill(&rdman, fill2, path2); rdman_paint_stroke(&rdman, stroke, path2); @@ -49,6 +63,7 @@ coord2->matrix[2] = 180; coord2->matrix[4] = 0.8; coord2->matrix[5] = 20; + rdman_coord_changed(&rdman, coord1); rdman_coord_changed(&rdman, coord2); rdman_add_shape(&rdman, (shape_t *)path1, coord1); @@ -115,11 +130,52 @@ XFlush(display); } + for(i = 0; i < 4; i++) { + usleep(500000); + text->stroke_width += 1; + rdman_shape_changed(&rdman, text); + coord3->matrix[2] += 5; + rdman_coord_changed(&rdman, coord3); + rdman_redraw_changed(&rdman); + XFlush(display); + } + for(i = 0; i < 4; i++) { + usleep(500000); + text->stroke_width -= 1; + rdman_shape_changed(&rdman, text); + coord3->matrix[2] -= 5; + rdman_coord_changed(&rdman, coord3); + rdman_redraw_changed(&rdman); + XFlush(display); + } + + for(i = 0; i < 4; i++) { + usleep(500000); + text->stroke_width += 1; + rdman_shape_changed(&rdman, text); + coord3->matrix[5] += 5; + rdman_coord_changed(&rdman, coord3); + rdman_redraw_changed(&rdman); + XFlush(display); + } + for(i = 0; i < 4; i++) { + usleep(500000); + text->stroke_width -= 1; + rdman_shape_changed(&rdman, text); + coord3->matrix[5] -= 5; + rdman_coord_changed(&rdman, coord3); + rdman_redraw_changed(&rdman); + XFlush(display); + } + fill1->free(fill1); fill2->free(fill2); + stroke->free(stroke); + text_stroke->free(text_stroke); redraw_man_destroy(&rdman); sh_path_free(path1); sh_path_free(path2); + sh_text_free(text); cairo_destroy(tmpcr); cairo_surface_destroy(tmpsuf); } @@ -130,14 +186,8 @@ cr = cairo_create(surface); cairo_set_source_rgb(cr, 0, 0, 0); cairo_paint(cr); - cairo_set_source_rgb(cr, 0.9, 0.1, 0.1); draw_path(cr, w, h); - cairo_set_source_rgb(cr, 0.5, 0.9, 0.8); - cairo_move_to(cr, 10, h / 2); - cairo_set_font_size(cr, 36.0); - cairo_text_path(cr, "hello \xe6\xbc\xa2\xe5\xad\x97"); - cairo_set_line_width(cr, 2); - cairo_stroke(cr); + cairo_destroy(cr); } int
--- a/src/redraw_man.c Sun Aug 03 13:04:55 2008 +0800 +++ b/src/redraw_man.c Mon Aug 04 10:10:47 2008 +0800 @@ -98,6 +98,9 @@ case SHT_PATH: sh_path_transform(shape); break; + case SHT_TEXT: + sh_text_transform(shape); + break; #ifdef UNITTEST default: sh_dummy_transform(shape); @@ -483,6 +486,9 @@ case SHT_PATH: sh_path_fill(shape, rdman->cr); break; + case SHT_TEXT: + sh_text_fill(shape, rdman->cr); + break; #ifdef UNITTEST default: sh_dummy_fill(shape, rdman->cr); @@ -498,6 +504,9 @@ case SHT_PATH: sh_path_stroke(shape, rdman->cr); break; + case SHT_TEXT: + sh_text_stroke(shape, rdman->cr); + break; #ifdef UNITTEST default: /* sh_dummy_fill(shape, rdman->cr); */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shape_text.c Mon Aug 04 10:10:47 2008 +0800 @@ -0,0 +1,144 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <cairo.h> +#include "mb_types.h" +#include "shapes.h" + +#define OK 0 +#define ERR -1 + +typedef struct _sh_text { + shape_t shape; + char *data; + co_aix x, y; + co_aix d_x, d_y; /* device x and y */ + co_aix font_size; + cairo_font_face_t *face; + cairo_scaled_font_t *scaled_font; + int flags; +} sh_text_t; + +#define TXF_SCALE_DIRTY 0x1 + +shape_t *sh_text_new(const char *txt, co_aix x, co_aix y, + co_aix font_size, cairo_font_face_t *face) { + sh_text_t *text; + + text = (sh_text_t *)malloc(sizeof(sh_text_t)); + if(text == NULL) + return NULL; + + memset(text, 0, sizeof(sh_text_t)); + text->shape.sh_type = SHT_TEXT; + text->data = strdup(txt); + if(text->data == NULL) { + free(text); + return NULL; + } + text->x = x; + text->y = y; + text->font_size = font_size; + cairo_font_face_reference(face); + text->face = face; + text->flags |= TXF_SCALE_DIRTY; + + return (shape_t *)text; +} + +void sh_text_free(shape_t *shape) { + sh_text_t *text = (sh_text_t *)shape; + + if(text->scaled_font) + cairo_scaled_font_destroy(text->scaled_font); + cairo_font_face_destroy(text->face); +} + +static int get_extents(sh_text_t *text, cairo_text_extents_t *extents) { + cairo_matrix_t fmatrix; + cairo_matrix_t ctm; + cairo_scaled_font_t *new_scaled; + cairo_font_options_t *fopt; + + if((text->flags & TXF_SCALE_DIRTY) || + text->scaled_font == NULL) { + fopt = cairo_font_options_create(); + if(fopt == NULL) + return ERR; + memset(&fmatrix, 0, sizeof(cairo_matrix_t)); + fmatrix.xx = text->font_size; + fmatrix.yy = text->font_size; + memset(&ctm, 0, sizeof(cairo_matrix_t)); + ctm.xx = 1; + ctm.yy = 1; + new_scaled = cairo_scaled_font_create(text->face, + &fmatrix, + &ctm, + fopt); + cairo_font_options_destroy(fopt); + if(new_scaled == NULL) + return ERR; + + if(text->scaled_font) + cairo_scaled_font_destroy(text->scaled_font); + text->scaled_font = new_scaled; + text->flags &= ~TXF_SCALE_DIRTY; + } + + cairo_scaled_font_text_extents(text->scaled_font, + text->data, extents); + return OK; +} + +void sh_text_transform(shape_t *shape) { + sh_text_t *text; + co_aix x, y; + co_aix shw; + cairo_text_extents_t extents; + co_aix poses[2][2]; + int r; + + text = (sh_text_t *)shape; + x = text->x; + y = text->y; + coord_trans_pos(shape->coord, &x, &y); + r = get_extents(text, &extents); + if(r != OK) + /* TODO: announce error. change return type? */ + return; + + text->d_x = x; + text->d_y = y; + shw = shape->stroke_width / 2; + /* FIXME: It is unreasonable that a font exceed it's bbox. + * We add 5 pixels in get right bbox. But, it is unreasonable. + */ + poses[0][0] = x + extents.x_bearing - 5 - shw; + poses[0][1] = y + extents.y_bearing - 5 - shw; + poses[1][0] = poses[0][0] + extents.width + 10 + shape->stroke_width; + poses[1][1] = poses[0][1] + extents.height + 10 + shape->stroke_width; + geo_from_positions(shape->geo, 2, poses); +} + + +static void draw_text(sh_text_t *text, cairo_t *cr) { + cairo_set_scaled_font(cr, text->scaled_font); + cairo_move_to(cr, text->d_x, text->d_y); + cairo_text_path(cr, text->data); +} + + +void sh_text_fill(shape_t *shape, cairo_t *cr) { + sh_text_t *text = (sh_text_t *)shape; + + draw_text(text, cr); + cairo_fill(cr); +} + + +void sh_text_stroke(shape_t *shape, cairo_t *cr) { + sh_text_t *text = (sh_text_t *)shape; + + draw_text(text, cr); + cairo_stroke(cr); +}
--- a/src/shapes.h Sun Aug 03 13:04:55 2008 +0800 +++ b/src/shapes.h Mon Aug 04 10:10:47 2008 +0800 @@ -4,10 +4,29 @@ #include <cairo.h> #include "mb_types.h" +/* Define a shape + * + * A shape must include + * - *_new() and *_free() + * - *_transform() + * - *_fill() + * - *_stroke() + * - struct of shape must include an shape_t as type of first member. + */ + extern void sh_path_free(shape_t *path); extern shape_t *sh_path_new(char *data); extern void sh_path_transform(shape_t *shape); extern void sh_path_fill(shape_t *shape, cairo_t *cr); extern void sh_path_stroke(shape_t *shape, cairo_t *cr); + +extern void sh_text_free(shape_t *text); +extern shape_t *sh_text_new(const char *txt, co_aix x, co_aix y, + co_aix font_size, cairo_font_face_t *face); +extern void sh_text_transform(shape_t *shape); +extern void sh_text_fill(shape_t *shape, cairo_t *cr); +extern void sh_text_stroke(shape_t *shape, cairo_t *cr); + + #endif /* __SHAPES_H_ */