aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.me.uk>2019-05-10 00:08:38 +0200
committerThomas White <taw@bitwiz.me.uk>2019-05-10 00:20:30 +0200
commitc3426c404324c2a629fe1403da548699abf9592d (patch)
tree14593981a2fd719f832c9f993990db17cc2d49c5
parente9c36334f53bb6aea931d0ec00e8967ef822c92c (diff)
Clean up narrative item size arithmetic
-rw-r--r--libstorycode/gtk/gtknarrativeview.c62
-rw-r--r--libstorycode/narrative.c6
-rw-r--r--libstorycode/narrative_priv.h16
-rw-r--r--libstorycode/narrative_render_cairo.c81
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; i<pnum; i++ ) py += n->items[i].h;
- return py + n->items[pnum].space_t;
+ for ( i=0; i<pnum; i++ ) py += narrative_item_get_height(n, i);
+ return py;
}
static void draw_para_highlight(cairo_t *cr, Narrative *n, int cursor_para,
double w)
{
- double cx, cy, cw, ch;
+ double cx, cy;
struct narrative_item *item;
item = &n->items[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) && (i<n->n_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; i<n->n_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; i<n->n_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);