From c3426c404324c2a629fe1403da548699abf9592d Mon Sep 17 00:00:00 2001 From: Thomas White Date: Fri, 10 May 2019 00:08:38 +0200 Subject: Clean up narrative item size arithmetic --- libstorycode/gtk/gtknarrativeview.c | 62 +++++++++++---------------- libstorycode/narrative.c | 6 +-- libstorycode/narrative_priv.h | 16 ++++--- libstorycode/narrative_render_cairo.c | 81 ++++++++++++++++++----------------- 4 files changed, 81 insertions(+), 84 deletions(-) diff --git a/libstorycode/gtk/gtknarrativeview.c b/libstorycode/gtk/gtknarrativeview.c index a174c9d..0876111 100644 --- a/libstorycode/gtk/gtknarrativeview.c +++ b/libstorycode/gtk/gtknarrativeview.c @@ -473,37 +473,23 @@ static double para_top(Narrative *n, int pnum) { int i; double py = 0.0; - for ( i=0; iitems[i].h; - return py + n->items[pnum].space_t; + for ( i=0; iitems[cursor_para]; - cx = n->space_l; - cy = n->space_t + para_top(n, cursor_para); - cw = w - n->space_l - n->space_r; - - if ( item->type == NARRATIVE_ITEM_SLIDE ) { - ch = item->slide_h; - } else { - if ( item->layout != NULL ) { - PangoRectangle rect; - pango_layout_get_extents(item->layout, NULL, &rect); - ch = pango_units_to_double(rect.height); - } else { - ch = 0.0; - fprintf(stderr, "No layout when drawing highlight box\n"); - } - } + cx = item->space_l; + cy = para_top(n, cursor_para) + item->space_t; cairo_new_path(cr); - cairo_rectangle(cr, cx, cy, cw, ch); + cairo_rectangle(cr, cx-5.0, cy-5.0, item->obj_w+10.0, item->obj_h+10.0); cairo_set_source_rgba(cr, 0.7, 0.7, 1.0, 0.5); cairo_set_line_width(cr, 5.0); cairo_stroke(cr); @@ -534,10 +520,10 @@ static void get_cursor_pos(Narrative *n, struct edit_pos cpos, struct narrative_item *item; item = &n->items[cpos.para]; - if ( item->type == NARRATIVE_ITEM_SLIDE ) { - *x = n->space_l + item->space_l; - *y = n->space_t + para_top(n, cpos.para); - *h = item->slide_h; + if ( !narrative_item_is_text(n, cpos.para) ) { + *x = item->space_l; + *y = para_top(n, cpos.para) + item->space_t; + *h = item->obj_h + item->space_t + item->space_b; return; } @@ -548,8 +534,8 @@ static void get_cursor_pos(Narrative *n, struct edit_pos cpos, offs = pos_trail_to_offset(item, cpos.pos, cpos.trail); pango_layout_get_cursor_pos(item->layout, offs, &rect, NULL); - *x = pango_units_to_double(rect.x) + n->space_l + item->space_l; - *y = pango_units_to_double(rect.y) + n->space_t + para_top(n, cpos.para); + *x = pango_units_to_double(rect.x) + item->space_l; + *y = pango_units_to_double(rect.y) + para_top(n, cpos.para) + item->space_t; *h = pango_units_to_double(rect.height); } @@ -591,11 +577,14 @@ static void draw_caret(cairo_t *cr, Narrative *n, struct edit_pos cpos, double w /* Block highlight cursor */ double cx, cy, cw, ch; + struct narrative_item *item; + + item = &n->items[cpos.para]; - cx = n->space_l - 5.5; - cy = n->space_t + para_top(n, cpos.para) - 5.5; - cw = n->items[cpos.para].slide_w + 11.0; - ch = n->items[cpos.para].slide_h + 11.0; + cx = item->space_l - 5.5; + cy = para_top(n, cpos.para) + item->space_t - 5.5; + cw = item->obj_w + 11.0; + ch = item->obj_h + 11.0; cairo_new_path(cr); cairo_rectangle(cr, cx, cy, cw, ch); @@ -639,6 +628,7 @@ static gboolean draw_sig(GtkWidget *da, cairo_t *cr, GtkNarrativeView *e) narrative_render_cairo(e->n, cr, narrative_get_stylesheet(e->n)); /* Editing overlay */ + cairo_translate(cr, e->n->space_l, e->n->space_t); draw_overlay(cr, e); return FALSE; @@ -667,7 +657,7 @@ static void check_cursor_visible(GtkNarrativeView *e) static size_t end_offset_of_para(Narrative *n, int pnum) { assert(pnum >= 0); - if ( n->items[pnum].type == NARRATIVE_ITEM_SLIDE ) return 0; + if ( !narrative_item_is_text(n, pnum) ) return 0; return strlen(n->items[pnum].text); } @@ -698,7 +688,7 @@ static void cursor_moveh(Narrative *n, struct edit_pos *cp, signed int dir) int np = cp->pos; int otrail = cp->trail; - if ( item->type == NARRATIVE_ITEM_SLIDE ) { + if ( !narrative_item_is_text(n, cp->para) ) { if ( dir > 0 ) { np = G_MAXINT; cp->trail = 0; @@ -834,7 +824,7 @@ static void split_paragraph_at_cursor(Narrative *n, struct edit_pos *pos) { size_t off; - if ( n->items[pos->para].type != NARRATIVE_ITEM_SLIDE ) { + if ( narrative_item_is_text(n, pos->para) ) { off = pos_trail_to_offset(&n->items[pos->para], pos->pos, pos->trail); } else { @@ -872,7 +862,7 @@ static void insert_text(char *t, GtkNarrativeView *e) return; } - if ( item->type != NARRATIVE_ITEM_SLIDE ) { + if ( narrative_item_is_text(e->n, e->cpos.para) ) { size_t off; @@ -907,12 +897,12 @@ static int find_cursor(Narrative *n, double x, double y, struct edit_pos *pos) cur_y = n->space_t; do { - cur_y += n->items[i++].h; + cur_y += narrative_item_get_height(n, i++); } while ( (cur_y < y) && (in_items) ); pos->para = i-1; item = &n->items[pos->para]; - if ( item->type == NARRATIVE_ITEM_SLIDE ) { + if ( !narrative_item_is_text(n, pos->para) ) { pos->pos = 0; return 0; } diff --git a/libstorycode/narrative.c b/libstorycode/narrative.c index cefbd0d..6ed719a 100644 --- a/libstorycode/narrative.c +++ b/libstorycode/narrative.c @@ -313,7 +313,7 @@ void narrative_delete_block(Narrative *n, int i1, size_t o1, int i2, size_t o2) int middle; /* This is where the "middle deletion" will begin */ /* Starting item */ - if ( n->items[i1].type == NARRATIVE_ITEM_SLIDE ) { + if ( !narrative_item_is_text(n, i1) ) { delete_item(n, i1); if ( i1 == i2 ) return; /* only one slide to delete */ middle = i1; /* ... which is now the item just after the slide */ @@ -341,7 +341,7 @@ void narrative_delete_block(Narrative *n, int i1, size_t o1, int i2, size_t o2) i2 -= n_del; /* Last item */ - if ( n->items[i2].type == NARRATIVE_ITEM_SLIDE ) { + if ( !narrative_item_is_text(n, i2) ) { delete_item(n, i2); return; } @@ -379,7 +379,7 @@ void narrative_split_item(Narrative *n, int i1, size_t o1) item1 = &n->items[i1]; item2 = insert_item(n, i1); - if ( item1->type != NARRATIVE_ITEM_SLIDE ) { + if ( !narrative_item_is_text(n, i1) ) { item2->text = strdup(&item1->text[o1]); item1->text[o1] = '\0'; } else { diff --git a/libstorycode/narrative_priv.h b/libstorycode/narrative_priv.h index 7ba7028..cea2a53 100644 --- a/libstorycode/narrative_priv.h +++ b/libstorycode/narrative_priv.h @@ -44,11 +44,19 @@ enum narrative_item_type struct narrative_item { enum narrative_item_type type; - double h; + + /* Space around the thing (PangoLayout, slide, marker etc) */ double space_l; double space_r; - double space_t; /* Already included in "h" */ - double space_b; /* Already included in "h" */ + double space_t; + double space_b; + + /* Size of the thing (PangoLayout, slide, marker etc) */ + double obj_w; + double obj_h; + + /* Total height is obj_h + space_t + space_b. + * obj_w + space_l + space_r might be less than width of rendering surface */ /* For TEXT, BP, PRESTITLE */ char *text; @@ -61,8 +69,6 @@ struct narrative_item /* For SLIDE */ Slide *slide; - double slide_w; - double slide_h; #ifdef HAVE_CAIRO cairo_surface_t *slide_thumbnail; #else diff --git a/libstorycode/narrative_render_cairo.c b/libstorycode/narrative_render_cairo.c index db1590f..160fc46 100644 --- a/libstorycode/narrative_render_cairo.c +++ b/libstorycode/narrative_render_cairo.c @@ -75,7 +75,6 @@ static void wrap_text(struct narrative_item *item, PangoContext *pc, const char *font; PangoFontDescription *fontdesc; enum alignment align; - struct length paraspace[4]; double wrap_w; PangoAttrList *attrs; PangoAttribute *attr; @@ -94,12 +93,6 @@ static void wrap_text(struct narrative_item *item, PangoContext *pc, palignment = to_pangoalignment(item->align); } - if ( stylesheet_get_paraspace(ss, stn, paraspace) ) return; - item->space_l = lcalc(paraspace[0], w); - item->space_r = lcalc(paraspace[1], w); - item->space_t = lcalc(paraspace[2], dummy_h_val); - item->space_b = lcalc(paraspace[3], dummy_h_val); - /* Calculate width of actual text */ wrap_w = w - item->space_l - item->space_r; @@ -134,7 +127,8 @@ static void wrap_text(struct narrative_item *item, PangoContext *pc, //pango_attr_list_unref(attrs); pango_layout_get_extents(item->layout, NULL, &rect); - item->h = pango_units_to_double(rect.height)+item->space_t+item->space_b; + item->obj_w = pango_units_to_double(rect.width); + item->obj_h = pango_units_to_double(rect.height); } @@ -185,34 +179,26 @@ static void wrap_slide(struct narrative_item *item, Stylesheet *ss, ImageStore * { double w, h; - item->space_l = 0.0; - item->space_r = 0.0; - item->space_t = 10.0; - item->space_b = 10.0; - slide_get_logical_size(item->slide, ss, &w, &h); - item->slide_h = 320.0; /* Actual height of thumbnail */ - item->slide_w = rint(item->slide_h*w/h); - - item->h = item->slide_h + item->space_t + item->space_b; + item->obj_h = 320.0; /* Actual height of thumbnail */ + item->obj_w = rint(item->obj_h*w/h); if ( item->slide_thumbnail != NULL ) { cairo_surface_destroy(item->slide_thumbnail); } item->slide_thumbnail = render_thumbnail(item->slide, ss, is, - item->slide_w, item->slide_h); + item->obj_w, item->obj_h); item->selected = sel_block; } -static size_t pos_trail_to_offset(struct narrative_item *item, int offs, int trail) +static size_t pos_trail_to_offset(Narrative *n, int i, int offs, int trail) { glong char_offs; char *ptr; + struct narrative_item *item = &n->items[i]; - if ( item->type == NARRATIVE_ITEM_SLIDE ) { - return offs; - } + if ( !narrative_item_is_text(n, i) ) return offs; char_offs = g_utf8_pointer_to_offset(item->text, item->text+offs); char_offs += trail; @@ -258,6 +244,8 @@ int narrative_wrap_range(Narrative *n, Stylesheet *stylesheet, PangoLanguage *la int i; struct length pad[4]; int sel_s, sel_e; + const char *stn; + struct length paraspace[4]; if ( stylesheet_get_padding(stylesheet, "NARRATIVE", pad) ) return 1; n->space_l = lcalc(pad[0], w); @@ -273,11 +261,8 @@ int narrative_wrap_range(Narrative *n, Stylesheet *stylesheet, PangoLanguage *la if ( max >= n->n_items ) max = n->n_items-1; if ( !positions_equal(sel_start, sel_end) ) { - struct narrative_item *item; - item = &n->items[sel_start.para]; - sel_s = pos_trail_to_offset(item, sel_start.pos, sel_start.trail); - item = &n->items[sel_end.para]; - sel_e = pos_trail_to_offset(item, sel_end.pos, sel_end.trail); + sel_s = pos_trail_to_offset(n, sel_start.para, sel_start.pos, sel_start.trail); + sel_e = pos_trail_to_offset(n, sel_end.para, sel_end.pos, sel_end.trail); } else { sel_s = 0; sel_e = 0; @@ -311,27 +296,43 @@ int narrative_wrap_range(Narrative *n, Stylesheet *stylesheet, PangoLanguage *la switch ( n->items[i].type ) { case NARRATIVE_ITEM_TEXT : - wrap_text(&n->items[i], pc, stylesheet, - "NARRATIVE", w, srt, end); + stn = "NARRATIVE.TEXT"; break; case NARRATIVE_ITEM_BP : - wrap_text(&n->items[i], pc, stylesheet, - "NARRATIVE.BP", w, srt, end); + stn = "NARRATIVE.BP"; + break; + + case NARRATIVE_ITEM_PRESTITLE : + stn = "NARRATIVE.PRESTITLE"; break; + case NARRATIVE_ITEM_SLIDE : + stn = "NARRATIVE.SLIDE"; + break; + } + + if ( stylesheet_get_paraspace(stylesheet, stn, paraspace) == 0 ) { + n->items[i].space_l = lcalc(paraspace[0], w); + n->items[i].space_r = lcalc(paraspace[1], w); + n->items[i].space_t = lcalc(paraspace[2], dummy_h_val); + n->items[i].space_b = lcalc(paraspace[3], dummy_h_val); + } + + switch ( n->items[i].type ) { + + case NARRATIVE_ITEM_TEXT : + case NARRATIVE_ITEM_BP : case NARRATIVE_ITEM_PRESTITLE : wrap_text(&n->items[i], pc, stylesheet, - "NARRATIVE.PRESTITLE", w, srt, end); + stn, w, srt, end); break; case NARRATIVE_ITEM_SLIDE : wrap_slide(&n->items[i], stylesheet, is, sel_block); break; - default : break; - } } @@ -341,7 +342,7 @@ int narrative_wrap_range(Narrative *n, Stylesheet *stylesheet, PangoLanguage *la double narrative_item_get_height(Narrative *n, int i) { - return n->items[i].h; + return n->items[i].obj_h + n->items[i].space_t + n->items[i].space_b; } @@ -350,7 +351,7 @@ double narrative_get_height(Narrative *n) int i; double total = 0.0; for ( i=0; in_items; i++ ) { - total += n->items[i].h; + total += narrative_item_get_height(n, i); } return total + n->space_t + n->space_b; } @@ -369,16 +370,16 @@ static void draw_slide(struct narrative_item *item, cairo_t *cr) cairo_device_to_user(cr, &x, &y); if ( item->selected ) { - cairo_rectangle(cr, x-5.0, y-5.0, item->slide_w+10.0, item->slide_h+10.0); + cairo_rectangle(cr, x-5.0, y-5.0, item->obj_w+10.0, item->obj_h+10.0); cairo_set_source_rgb(cr, 0.655, 0.899, 1.0); cairo_fill(cr); } - cairo_rectangle(cr, x, y, item->slide_w, item->slide_h); + cairo_rectangle(cr, x, y, item->obj_w, item->obj_h); cairo_set_source_surface(cr, item->slide_thumbnail, 0.0, 0.0); cairo_fill(cr); - cairo_rectangle(cr, x+0.5, y+0.5, item->slide_w, item->slide_h); + cairo_rectangle(cr, x+0.5, y+0.5, item->obj_w, item->obj_h); cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); cairo_set_line_width(cr, 1.0); cairo_stroke(cr); @@ -477,7 +478,7 @@ int narrative_render_cairo(Narrative *n, cairo_t *cr, Stylesheet *stylesheet) for ( i=0; in_items; i++ ) { narrative_render_item_cairo(n, cr, i); - cairo_translate(cr, 0.0, n->items[i].h); + cairo_translate(cr, 0.0, narrative_item_get_height(n, i)); } cairo_restore(cr); -- cgit v1.2.3