aboutsummaryrefslogtreecommitdiff
path: root/src/tool_text.c
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2011-10-01 20:51:22 +0200
committerThomas White <taw@bitwiz.org.uk>2011-10-01 20:51:22 +0200
commit9a5060c094813d908d4c9ef7b8631916939bb53d (patch)
tree06dbcf835efc3be3e32ce9c72a604ace1a52a6be /src/tool_text.c
parente705f42069f505bb8111a1fd7d8534ab3cacd5b8 (diff)
Use function pointers for object rendering and overlays
Diffstat (limited to 'src/tool_text.c')
-rw-r--r--src/tool_text.c229
1 files changed, 202 insertions, 27 deletions
diff --git a/src/tool_text.c b/src/tool_text.c
index 9419a12..4881fec 100644
--- a/src/tool_text.c
+++ b/src/tool_text.c
@@ -34,33 +34,6 @@
#include "mainwindow.h"
-struct object *add_text_object(struct slide *s, double x, double y,
- struct style *sty)
-{
- struct object *new;
-
- new = new_object(TEXT, sty);
-
- new->x = x; new->y = y;
- new->bb_width = 10.0;
- new->bb_height = 40.0;
- new->text = malloc(1);
- new->text[0] = '\0';
- new->text_len = 1;
- new->insertion_point = 0;
- new->layout = NULL;
- new->fontdesc = NULL;
-
- if ( add_object_to_slide(s, new) ) {
- free_object(new);
- return NULL;
- }
- s->object_seq++;
-
- return new;
-}
-
-
void insert_text(struct object *o, char *t)
{
char *tmp;
@@ -201,3 +174,205 @@ void position_caret(struct object *o, double x, double y)
o->insertion_point = idx+trail;
}
+
+
+static void calculate_size_from_style(struct object *o,
+ double *peright, double *pebottom,
+ double *pmw, double *pmh)
+{
+ double max_width, max_height;
+ double ebottom, eright, mw, mh;
+
+ eright = o->parent->parent->slide_width - o->style->margin_right;
+ ebottom = o->parent->parent->slide_height - o->style->margin_bottom;
+ mw = o->parent->parent->slide_width;
+ mh = o->parent->parent->slide_height;
+
+ *peright = eright; *pebottom = ebottom;
+ *pmw = mw; *pmh = mh;
+
+ max_width = mw - o->style->margin_left - o->style->margin_right;
+
+ /* Use the provided maximum width if it exists and is smaller */
+ if ( o->style->use_max_width && (o->style->max_width < max_width) )
+ {
+ max_width = o->style->max_width;
+ }
+
+ max_height = mh - o->style->margin_top - o->style->margin_bottom;
+
+ pango_layout_set_width(o->layout, max_width*PANGO_SCALE);
+ pango_layout_set_height(o->layout, max_height*PANGO_SCALE);
+ pango_layout_set_wrap(o->layout, PANGO_WRAP_WORD_CHAR);
+ pango_layout_set_ellipsize(o->layout, PANGO_ELLIPSIZE_MIDDLE);
+
+ switch ( o->style->halign ) {
+ case J_LEFT :
+ pango_layout_set_alignment(o->layout, PANGO_ALIGN_LEFT);
+ break;
+ case J_RIGHT :
+ pango_layout_set_alignment(o->layout, PANGO_ALIGN_RIGHT);
+ break;
+ case J_CENTER :
+ pango_layout_set_alignment(o->layout, PANGO_ALIGN_CENTER);
+ break;
+ }
+}
+
+
+static void calculate_position_from_style(struct object *o,
+ double eright, double ebottom,
+ double mw, double mh,
+ double *pxo, double *pyo)
+{
+ double xo, yo;
+ PangoRectangle ink, logical;
+
+ pango_layout_get_extents(o->layout, &ink, &logical);
+ xo = ink.x/PANGO_SCALE; yo = logical.y/PANGO_SCALE;
+
+ switch ( o->style->halign ) {
+ case J_LEFT :
+ o->x = -xo + o->style->margin_left;
+ break;
+ case J_RIGHT :
+ o->x = -xo + eright - o->bb_width;
+ break;
+ case J_CENTER :
+ o->x = mw/2.0 - o->bb_width/2.0 - xo + o->style->offset_x;
+ break;
+ }
+
+ if ( o->style->halign == J_CENTER )
+ {
+ if ( o->x+xo < o->style->margin_left ) {
+ o->x = o->style->margin_left - xo;
+ }
+
+ if ( o->x+xo + o->bb_width > mw-o->style->margin_right ) {
+ o->x = mw-o->style->margin_right - xo - o->bb_width;
+ }
+ }
+
+ switch ( o->style->valign ) {
+ case V_TOP :
+ o->y = o->style->margin_top;
+ break;
+ case V_BOTTOM :
+ o->y = ebottom - o->bb_height;
+ break;
+ case V_CENTER :
+ o->y = mh/2.0 - o->bb_height/2.0 + yo - o->style->offset_y;
+ break;
+ }
+
+ if ( o->style->valign == V_CENTER ) {
+
+ if ( o->y < o->style->margin_top ) {
+ o->y = o->style->margin_top;
+ }
+
+ if ( o->y+yo + o->bb_height > mh - o->style->margin_bottom ) {
+ o->y = mh-o->style->margin_bottom - yo - o->bb_height;
+ }
+ }
+
+ *pxo = xo; *pyo = yo;
+}
+
+
+static void render_text_object(cairo_t *cr, struct object *o)
+{
+ PangoRectangle ink, logical;
+ double eright = 0.0;
+ double ebottom = 0.0;
+ double mw = 0.0;
+ double mh = 0.0;
+ double xo, yo;
+ int furniture = 0;
+ GdkColor col;
+
+ furniture = o->style != o->parent->parent->ss->styles[0];
+
+ o->layout = pango_cairo_create_layout(cr);
+ pango_layout_set_text(o->layout, o->text, -1);
+ o->fontdesc = pango_font_description_from_string(o->style->font);
+ pango_layout_set_font_description(o->layout, o->fontdesc);
+
+ if ( furniture ) {
+ calculate_size_from_style(o, &eright, &ebottom, &mw, &mh);
+ } else {
+ pango_layout_set_alignment(o->layout, PANGO_ALIGN_LEFT);
+ }
+
+ pango_cairo_update_layout(cr, o->layout);
+ pango_layout_get_extents(o->layout, &ink, &logical);
+ o->bb_width = ink.width / PANGO_SCALE;
+ o->bb_height = logical.height/PANGO_SCALE;
+
+ if ( furniture ) {
+ calculate_position_from_style(o, eright, ebottom,
+ mw, mh, &xo, &yo);
+ }
+
+ cairo_move_to(cr, o->x, o->y);
+ gdk_color_parse(o->style->colour, &col);
+ gdk_cairo_set_source_color(cr, &col); /* FIXME: Honour alpha as well */
+ pango_cairo_show_layout(cr, o->layout);
+
+ if ( furniture ) {
+ o->x += xo;
+ o->y += yo;
+ }
+}
+
+
+static void draw_caret(cairo_t *cr, struct object *o)
+{
+ int line, xpos;
+ double xposd;
+
+ assert(o->type == TEXT);
+
+ pango_layout_index_to_line_x(o->layout, o->insertion_point,
+ 0, &line, &xpos);
+
+ xposd = xpos/PANGO_SCALE;
+
+ cairo_move_to(cr, o->x+xposd, o->y);
+ cairo_line_to(cr, o->x+xposd, o->y+o->bb_height);
+ cairo_set_source_rgb(cr, 1.0, 0.5, 0.0);
+ cairo_set_line_width(cr, 2.0);
+ cairo_stroke(cr);
+}
+
+
+struct object *add_text_object(struct slide *s, double x, double y,
+ struct style *sty)
+{
+ struct object *new;
+
+ new = new_object(TEXT, sty);
+
+ new->x = x; new->y = y;
+ new->bb_width = 10.0;
+ new->bb_height = 40.0;
+ new->text = malloc(1);
+ new->text[0] = '\0';
+ new->text_len = 1;
+ new->insertion_point = 0;
+ new->layout = NULL;
+ new->fontdesc = NULL;
+
+ /* Methods for this object */
+ new->render_object = render_text_object;
+ new->draw_editing_overlay = draw_caret;
+
+ if ( add_object_to_slide(s, new) ) {
+ free_object(new);
+ return NULL;
+ }
+ s->object_seq++;
+
+ return new;
+}