view src/shape_text.c @ 528:d687d3395264 Android_Skia

Clear variables and draw root coord. Although root coord is never in zeroing list, now, it still need to be redrawed after redrawing other zeroed coords.
author Thinker K.F. Li <thinker@branda.to>
date Wed, 23 Dec 2009 10:33:51 +0800
parents ba64f928542b
children 586e50f82c1f
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "mb_graph_engine.h"
#include <pango/pangocairo.h>
#include "mb_types.h"
#include "mb_shapes.h"

#define ASSERT(x)
#define OK 0
#define ERR -1

typedef struct _sh_text {
    shape_t shape;
    char *data;
    co_aix x, y,w,h;
    co_aix d_x, d_y;		/* device x and y */
    co_aix font_size;
    co_aix d_font_size;
    mbe_font_face_t *face;
    mbe_scaled_font_t *scaled_font;
    int flags;
    PangoLayout *layout;
    int align;
    PangoAttrList *attrs;
} sh_text_t;

#define TXF_SCALE_DIRTY 0x1

static void sh_text_free(shape_t *shape) {
    sh_text_t *text = (sh_text_t *)shape;

    if(text->scaled_font)
	mbe_scaled_font_destroy(text->scaled_font);
    mbe_font_face_destroy(text->face);
}

static void sh_text_P_generate_layout(sh_text_t *text,mbe_t *cr);
shape_t *rdman_shape_text_new(redraw_man_t *rdman,
			      const char *txt, co_aix x, co_aix y,
			      co_aix font_size, mbe_font_face_t *face,PangoAttrList *attrs) {
    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));
    mb_obj_init(text, MBO_TEXT);
    text->data = strdup(txt);
    if(text->data == NULL) {
	free(text);
	return NULL;
    }
    text->x = x;
    text->y = y;
    text->font_size = font_size;
    mbe_font_face_reference(face);
    text->face = face;
    text->flags |= TXF_SCALE_DIRTY;

    text->shape.free = sh_text_free;
    text->layout = NULL;
    text->attrs = attrs;
    text->align = TEXTALIGN_START;
    text->w = text->h = 0;
    
    rdman_shape_man(rdman, (shape_t *)text);

    return (shape_t *)text;
}

void sh_text_set_pos(shape_t *shape, co_aix x, co_aix y)
{
    sh_text_t *text = (sh_text_t *)shape;
    text->x = x;
    text->y = y;
}


void sh_text_get_pos(shape_t *shape, co_aix *x, co_aix *y)
{
    sh_text_t *text = (sh_text_t *)shape;
    *x = text->x;
    *y = text->y;
}

void sh_text_get_text(shape_t *shape, char *text,int size)
{
    sh_text_t *t = (sh_text_t *)shape;
    strncpy(text,t->data, size);
}

void sh_text_set_text(shape_t *shape, const char *txt) {
    sh_text_t *text = (sh_text_t *)shape;
    char *buf;

    buf = strdup(txt);
    if(text->data) free(text->data);
    text->data = buf;
}

void sh_text_set_color(shape_t *shape, unsigned int color)
{
    PangoAttribute *attr = pango_attr_foreground_new(TEXTCOLOR_RED(color)<<8,TEXTCOLOR_GREEN(color)<<8,TEXTCOLOR_BLUE(color)<<8);
    sh_text_t *text = (sh_text_t *)shape;
    attr->start_index = 0;
    attr->end_index = -1;
    pango_attr_list_change(text->attrs, attr);
}
void sh_text_set_bold(shape_t *shape,int bold)
{
    PangoAttribute *attr = pango_attr_weight_new(bold? PANGO_WEIGHT_BOLD:PANGO_WEIGHT_NORMAL);
    sh_text_t *text = (sh_text_t *)shape;
    attr->start_index = 0;
    attr->end_index = -1;
    pango_attr_list_change(text->attrs, attr);
}
void sh_text_set_italic(shape_t *shape,int italic)
{
    PangoAttribute *attr = pango_attr_style_new(italic? PANGO_STYLE_ITALIC:PANGO_STYLE_NORMAL);
    sh_text_t *text = (sh_text_t *)shape;
    attr->start_index = 0;
    attr->end_index = -1;
    pango_attr_list_change(text->attrs, attr);
}
void sh_text_set_underline(shape_t *shape,int underline)
{
    PangoAttribute *attr = pango_attr_underline_new(underline? PANGO_UNDERLINE_SINGLE:PANGO_UNDERLINE_NONE);
    sh_text_t *text = (sh_text_t *)shape;
    attr->start_index = 0;
    attr->end_index = -1;
    pango_attr_list_change(text->attrs, attr);
}
void sh_text_set_font(shape_t *shape,char *family)
{
    PangoAttribute *attr = pango_attr_family_new(family);
    sh_text_t *text = (sh_text_t *)shape;
    attr->start_index = 0;
    attr->end_index = -1;
    pango_attr_list_change(text->attrs, attr);
}

void sh_text_set_align(shape_t *shape,int align)
{
    sh_text_t *text = (sh_text_t *)shape;
    text->align = align;
}
void sh_text_set_width(shape_t *shape,int width)
{
    sh_text_t *text = (sh_text_t *)shape;
    text->w = width;
}
void sh_text_set_style(shape_t *shape,int begin,int end,mb_textstyle_t *format)
{
    PangoAttribute *attr;
    sh_text_t *text = (sh_text_t *)shape;

    if (end == -1) {
	end = strlen(text->data);
    } else
	end++;
    if (format->property & TEXTSTYLE_BOLD) {
	attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
	attr->start_index = begin;
	attr->end_index = end;
	pango_attr_list_change(text->attrs,attr);
    }
    if (format->property & TEXTSTYLE_ITALIC) {
	attr = pango_attr_style_new(PANGO_STYLE_ITALIC);
	attr->start_index = begin;
	attr->end_index = end;
	pango_attr_list_change(text->attrs,attr);
    }
    if (format->property & TEXTSTYLE_UNDERLINE) {
	attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
	attr->start_index = begin;
	attr->end_index = end;
	pango_attr_list_change(text->attrs,attr);
    }
    if (format->property & TEXTSTYLE_COLOR) {
	printf("color=%x\n", format->color);
	printf("red = %x\n",TEXTCOLOR_RED(format->color));
	printf("green = %x\n",TEXTCOLOR_GREEN(format->color));
	printf("blue = %x\n",TEXTCOLOR_BLUE(format->color));
	attr = pango_attr_foreground_new(TEXTCOLOR_RED(format->color)<<8,TEXTCOLOR_GREEN(format->color)<<8,TEXTCOLOR_BLUE(format->color)<<8);
	attr->start_index = begin;
	attr->end_index = end;
	pango_attr_list_change(text->attrs,attr);
    }
    if (format->property & TEXTSTYLE_FONT) {
	attr = pango_attr_family_new(format->font);
	attr->start_index = begin;
	attr->end_index = end;
	pango_attr_list_change(text->attrs,attr);
    }
    if (format->property & TEXTSTYLE_ALIGN) {
	// We can have one align style for the whole text only
	if (begin != 0 || (end != strlen(text->data)-1))
	    return;
	text->align = format->align;
    }
}

static int get_extents(sh_text_t *text, PangoRectangle *extents) {
    mbe_scaled_font_t *new_scaled;

    pango_layout_get_extents(text->layout, NULL, extents);
    pango_extents_to_pixels(extents,NULL);
    return OK;
}

void sh_text_transform(shape_t *shape) {
    sh_text_t *text;
    coord_t *coord;
    canvas_t *canvas;
    co_aix x, y;
    co_aix shw;
    PangoRectangle extents;
    co_aix poses[2][2];
    int r;

    text = (sh_text_t *)shape;
    
    text->d_font_size = coord_trans_size(shape->coord, text->font_size);
    
    coord = sh_get_coord(shape);
    canvas = _coord_get_canvas(coord);
    sh_text_P_generate_layout(text, (mbe_t *)canvas);

    x = text->x;
    y = text->y;
    coord_trans_pos(shape->coord, &x, &y);
    r = get_extents(text, &extents);

    //printf("x=%f y=%f text=%s ascent=%d,descent=%d,width=%d height=%d\n", x,y,text->data,PANGO_ASCENT(extents), PANGO_DESCENT(extents), extents.width, extents.height);
    ASSERT(r == OK);

    text->d_x = x-5;
    text->d_y = y-PANGO_DESCENT(extents)+5;
    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] = text->d_x + extents.x - shw;
    poses[0][1] = text->d_y + extents.y - shw;
    poses[1][0] = poses[0][0] + extents.width +  shape->stroke_width;
    poses[1][1] = poses[0][1] + extents.height +  shape->stroke_width;
    geo_from_positions(shape->geo, 2, poses);
    /*! \todo Support ratation for shape_text. */
}

static void sh_text_P_generate_layout(sh_text_t *text,mbe_t *cr)
{
    PangoAttribute *attr;
    PangoAttrList *attrlist;
    PangoFontDescription *desc;

    if (text->layout) {
        g_object_unref(text->layout);
    }
    text->layout = pango_cairo_create_layout(cr);
    desc = pango_font_description_from_string("Sans Bold");
    //mbe_set_source_rgb (cr, 0, 0, 0);
    pango_layout_set_font_description (text->layout, desc);
    if (text->w != 0)
        pango_layout_set_width(text->layout, text->w);
    pango_layout_set_text(text->layout,text->data,strlen(text->data));
    pango_layout_set_attributes(text->layout, text->attrs);
    if (text->align == TEXTALIGN_START)
	    pango_layout_set_alignment(text->layout, PANGO_ALIGN_LEFT);
    else if (text->align == TEXTALIGN_MIDDLE)
	    pango_layout_set_alignment(text->layout, PANGO_ALIGN_CENTER);
    else if (text->align == TEXTALIGN_END)
	    pango_layout_set_alignment(text->layout, PANGO_ALIGN_RIGHT);
    pango_cairo_update_layout(cr,text->layout);
    //printf("text=%s\n",text->data);
}
static void draw_text(sh_text_t *text, mbe_t *cr) {
    mbe_move_to(cr, text->d_x, text->d_y);
    pango_cairo_layout_path(cr,text->layout);
}


void sh_text_draw(shape_t *shape, mbe_t *cr) {
    draw_text((sh_text_t *)shape, cr);
}