Mercurial > MadButterfly
changeset 393:27774b93521e
Add sh_stext_t to implement a simple version of text shape.
- It is still under construction.
- It is supposed to be a simple, less dependency implementation.
- It is more less functional than sh_text_t.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Mon, 08 Jun 2009 07:04:20 +0800 |
parents | ebf83a50e1e1 |
children | b3d5ce48670a |
files | include/mb_shapes.h include/mb_types.h src/shape_stext.c src/shape_text.c |
diffstat | 4 files changed, 330 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/include/mb_shapes.h Wed Apr 15 08:34:27 2009 +0800 +++ b/include/mb_shapes.h Mon Jun 08 07:04:20 2009 +0800 @@ -18,6 +18,7 @@ * A shape implementation must include * - rdman_shape_*_new() * - clear memory for shape_t member. + * - mb_obj_init() to initialize shape_t::obj. * - assign *_free() to \ref shape_t::free. * - make new object been managed by a redraw manager. * - call rdman_shape_man() @@ -242,6 +243,58 @@ extern void sh_image_set_geometry(shape_t *shape, co_aix x, co_aix y, co_aix w, co_aix h); /* @} */ + +/*! \defgroup shape_stext A Simple Implementation of Shape of Image + * @{ + */ + +/*! \defgroup font_face Define font face used to describe style of text. + * @{ + */ +/*! \brief Font face of MadButterfly. + * + * It actully a cairo_font_face_t, now. But, it can be change for latter. + * So, programmer should not depend on cairo_font_face_t. + */ +typedef struct _mb_font_face mb_font_face_t; + +enum MB_FONT_SLANTS { + MB_FONT_SLANT_DUMMY, + MB_FONT_SLANT_ROMAN, + MB_FONT_SLANT_ITALIC, + MB_FONT_SLANT_OBLIQUE, + MB_FONT_SLANT_MAX +}; + +extern mb_font_face_t *mb_font_face_query(redraw_man_t *rdman, + const char *family, + int slant, + int weight); +extern void mb_font_face_free(mb_font_face_t *face); +/* @} */ + +/*! \brief Describe style of a block of text. + * + * \ref sh_stext_t describes style of a text by a list of + * \ref mb_style_blk_t. + */ +typedef struct { + int n_chars; + mb_font_face_t *face; + co_aix font_sz; +} mb_style_blk_t; + +extern shape_t *rdman_shape_stext_new(redraw_man_t *rdman, + co_aix x, co_aix y, + const char *txt); +extern void sh_stext_transform(shape_t *shape); +extern void sh_stext_draw(shape_t *shape, cairo_t *cr); +extern int sh_stext_set_text(shape_t *shape, const char *txt); +extern int sh_stext_set_style(shape_t *shape, + const mb_style_blk_t *blks, + int nblks); + +/* @} */ /* @} */ #endif /* __SHAPES_H_ */
--- a/include/mb_types.h Wed Apr 15 08:34:27 2009 +0800 +++ b/include/mb_types.h Mon Jun 08 07:04:20 2009 +0800 @@ -48,7 +48,8 @@ MBO_PATH, MBO_TEXT, MBO_RECT, - MBO_IMAGE + MBO_IMAGE, + MBO_STEXT }; #define MBO_CLASS_MASK 0xf000 #define MBO_CLASS(x) (((mb_obj_t *)(x))->obj_type & MBO_CLASS_MASK) @@ -374,6 +375,7 @@ #define sh_pos_is_in(sh, x, y) geo_pos_is_in(sh_get_geo(sh), x, y) #define sh_get_area(sh) geo_get_area(sh_get_geo(sh)) #define sh_get_coord(sh) ((sh)->coord) +#define sh_get_aggr_matrix(sh) (coord_get_aggr_matrix(sh_get_coord(sh))) #define sh_get_fill(sh) ((sh)->fill) #define sh_get_stroke(sh) ((sh)->stroke)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shape_stext.c Mon Jun 08 07:04:20 2009 +0800 @@ -0,0 +1,274 @@ +#include <stdio.h> +#include <cairo.h> +#include <fontconfig.h> +#include "mb_shapes.h" + +#if 0 + +#ifndef ASSERT +#define ASSERT(x) +#endif +#define OK 0 +#define ERR -1 + +/*! \brief Query and return a font face for a specified attribute vector. + * + * Programmers use mb_font_face_t to specify fonts used to show a + * block of text on the output device. They can get mb_font_face_t with + * this function. The objects return by mb_font_face_query() should be + * freed with mb_font_face_free() when they are not more used. + * + * \param family is the name of a font family (times). + * \param slant is one of \ref MB_FONT_SLANTS. + * \param weight decides if a font is thin or heavy. + */ +mb_font_face_t *mb_font_face_query(redraw_man_t *rdman, + const char *family, + int slant, + int weight) { + cairo_font_face_t *cface; + FcPattern *ptn; + FcValue val; + static int slant_map[] = { /* from MB_FONT_SLANT_* to FC_SLANT_* */ + FC_SLANT_ROMAN, + FC_SLANT_ROMAN, + FC_SLANT_ITALIC, + FC_SLANT_OBLIQUE}; + + ptn = FcPatternCreate(); + val.type = FcTypeString; + val.s = family; + FcPatternAdd(ptn, "family", val, FcTrue); + + if(family < 0 || family >= MB_FONT_SLANT_MAX) { + FcPatternDestroy(ptn); + return NULL; + } + val.type = FcTypeInteger; + val.i = slant_map[slant]; + FcPatternAdd(ptn, "slant", val, FcTrue); + + val.type = FcTypeInteger; + val.i = weight; + FcPatternAdd(ptn, "weight", val, FcTrue); + + cface = cairo_ft_font_face_create_for_pattern(ptn); + FcPatternDestroy(ptn); + + return (mb_font_face_t *)cface; +} + +void mb_font_face_free(mb_font_face_t *face) { + cairo_font_face_t *cface = (cairo_font_face_t *)face; + ASSERT(face != NULL); + cairo_font_face_destroy(face); +} + +/*! \brief A simple implementation of text shape. + * + */ +typedef struct _sh_stext { + shape_t shape; + const char *txt; /*!< \brief Text to be showed */ + const mb_style_blk_t *style_blks; /*!< \brief Style of text */ + int nblks; /*!< \brief Number of style blocks */ + int max_nblks; + co_aix x, y; + cairo_scaled_font_t **scaled_fonts; +} sh_stext_t; + +shape_t *rdman_shape_stext_new(redraw_man_t *rdman, co_aix x, co_aix y, + const char *txt) { + sh_stext_t *txt_o; + + ASSERT(txt != NULL); + + txt_o = (sh_stext_t *)malloc(sizeof(sh_stext_t)); + if(txt_o == NULL) + return NULL; + + memset(&txt_o->shape, 0, sizeof(shape_t)); + mb_obj_init(txt_o, MBO_STEXT); + + txt_o->txt = strdup(txt); + txt_o->style_blks = NULL; + txt_o->nblks = 0; + txt_o->max_nblks = 0; + txt_o->x = x; + txt_o->y = y; + txt_o->exts = NULL; + + if(txt_o->txt == NULL) { + free(txt_o); + txt_o = NULL; + } + + return (shape_t *)txt_o; +} + +static +int compute_utf8_chars_sz(const char *txt, int n_chars) { + int i; + const char *p = txt; + + for(i = 0; i < n && *p; i++) { + if(*p++ & 0x80) + continue; /* single byte */ + /* multi-bytes */ + while(*p && ((*p & 0xc0) == 0x80)) + p++; + } + if(i < n) + return ERR; + + return p - txt; +} + +static +void compute_text_extents(char *txt, int txt_len, + cairo_scaled_font_t *scaled_font, + cairo_text_extents_t *extents) { + char saved; + + saved = txt[txt_len]; + txt[txt_len] = 0; + cairo_scaled_font_text_extents(scaled_font, txt, extents); + txt[txt_len] = saved; +} + +static +cairo_scaled_font_t *make_scaled_font_face(sh_stext_t *txt_o, + cairo_font_face_t *face, + co_aix shift_x, co_aix shift_y, + co_aix font_sz) { + cairo_matrix_t cmtx; + static cairo_matrix_t cid; + static cairo_font_options_t *fopt = NULL; + co_aix *matrix; + cairo_scaled_font_t *scaled; + int i; + + if(fopt == NULL) { + cairo_matrix_init_identify(&cid); + fopt = cairo_font_options_create(); + if(fopt == NULL) + return NULL; + } + + matrix = sh_get_aggr_matrix((shape_t *)txt_o); + i = 0; + cmtx.xx = matrix[i++]; + cmtx.xy = matrix[i++]; + cmtx.x0 = matrix[i++] + shift_x; + cmtx.yx = matrix[i++]; + cmtx.yy = matrix[i++]; + cmtx.y0 = matrix[i] + shift_y; + + scaled = cairo_scaled_font_create(face, &cmtx, &cid, fopt); + + return scaled; +} + +static +void compute_extents(sh_stext_t *txt_o) { + co_aix adv_x, adv_y; + cairo_text_extents_t extents; + mb_style_blk_t *blk; + cairo_scaled_font_t *scaled_font; + char *txt; + co_aix shift_x, shift_y; + int blk_txt_len; + int i; + + adv_x = adv_y = 0; + blk = txt_o->style_blks; + scaled_font = txt_o->scaled_fonts; + txt = (char *)txt_o->txt; + shift_x = txt_o->x; + shift_y = txt_o->y; + for(i = 0; i < txt_o->nblks; i++) { + *scaled_font = make_scaled_fonts(txt_o, blk->face, + shift_x, shift_y, font_sz); + ASSERT(*scaled_font != NULL); + + blk_txt_len = compute_utf8_chars_sz(txt, blk->n_chars); + ASSERT(blk_txt_len != ERR); + + compute_text_extents(txt, blk_txt_len, *scaled_font, &extents); + adv_x += extents.x_advance; + adv_y += extents.y_advance; + + scaled_font++; + blk++; + txt += blk_txt_len; + } +} + +/* + * What we have to do in sh_stext_transform() is + * - computing bounding box for the text, + * - computing offset x,y for the text of style blocks, + * - free old scaled fonts, and + * - making scaled fonts for style blocks. + */ +void sh_stext_transform(shape_t *shape) { + sh_stext_t *txt_o = (sh_stext_t *)shape; + + ASSERT(txt_o != NULL); +} + +void sh_stext_draw(shape_t *shape, cairo_t *cr) { + sh_stext_t *txt_o = (sh_stext_t *)shape; + + ASSERT(txt_o != NULL); +} + +int sh_stext_set_text(shape_t *shape, const char *txt) { + sh_stext_t *txt_o = (sh_stext_t *)shape; + char *new_txt; + int sz; + + ASSERT(txt_o != NULL); + ASSERT(txt != NULL); + + sz = strlen(txt) + 1; + new_txt = realloc(txt_o->txt, sz); + if(new_txt == NULL) + return ERR; + + memcpy(new_txt, txt, sz); + txt_o->txt = new_txt; + + return OK; +} + +int sh_stext_set_style(shape_t *shape, + const mb_style_blk_t *blks, + int nblks) { + sh_stext_t *txt_o = (sh_stext_t *)shape; + mb_style_blk_t *new_blks; + co_aix *new_exts; + int sz; + + ASSERT(txt_o != NULL); + ASSERT(nblks >= 0); + + if(nblks > txt_o->max_nblks) { + sz = nblks * (sizeof(mb_style_blk_t) + sizeof(int)); + new_blks = (mb_style_blk_t *)realloc(txt_o->style_blks, sz); + if(new_blks == NULL) + return ERR; + new_exts = (int *)(new_blks + nblks); + + txt_o->style_blks = new_blks; + txt_o->exts = new_exts; + txt_o->max_nblks = nblks; + } + + memcpy(txt_o->blks, blks, nblks * sizeof(mb_style_blk_t)); + txt_o->nblks = nblks; + + return OK; +} + +#endif /* 0 */