From acbec489df38e182a8e284095ccd7a0f1d84112e Mon Sep 17 00:00:00 2001 From: Thomas White Date: Sun, 3 Mar 2019 18:51:34 +0100 Subject: Styled narrative rendering --- data/demo.sc | 4 ++ libstorycode/gtk/gtknarrativeview.c | 1 + libstorycode/narrative.c | 22 ++++++- libstorycode/narrative.h | 5 +- libstorycode/narrative_priv.h | 11 +++- libstorycode/narrative_render_cairo.c | 121 ++++++++++++++++++++-------------- libstorycode/storycode.y | 9 ++- libstorycode/stylesheet.c | 17 +++++ libstorycode/stylesheet.h | 4 ++ 9 files changed, 136 insertions(+), 58 deletions(-) diff --git a/data/demo.sc b/data/demo.sc index 8890774..ea601c2 100644 --- a/data/demo.sc +++ b/data/demo.sc @@ -8,6 +8,10 @@ STYLES { PRESTITLE { FONT Cantarell Bold 20 } + BP { + FONT Cantarell Regular 14 + PARASPACE 20u,0u,10u,10u + } } SLIDE { SIZE 1024u x 768u diff --git a/libstorycode/gtk/gtknarrativeview.c b/libstorycode/gtk/gtknarrativeview.c index 55565d8..e6f4f38 100644 --- a/libstorycode/gtk/gtknarrativeview.c +++ b/libstorycode/gtk/gtknarrativeview.c @@ -131,6 +131,7 @@ static gboolean resize_sig(GtkWidget *widget, GdkEventConfigure *event, e->visible_height = event->height; e->visible_width = event->width; + e->w = e->visible_width; /* Wrap everything with the current width, to get the total height */ narrative_wrap(presentation_get_narrative(e->p), diff --git a/libstorycode/narrative.c b/libstorycode/narrative.c index 81c69b1..97d4353 100644 --- a/libstorycode/narrative.c +++ b/libstorycode/narrative.c @@ -58,13 +58,31 @@ static struct narrative_item *add_item(Narrative *n) } -void narrative_add_prestitle(Narrative *n, const char *text) +void narrative_add_prestitle(Narrative *n, char *text) { + struct narrative_item *item; + + item = add_item(n); + if ( item == NULL ) return; + + item->type = NARRATIVE_ITEM_PRESTITLE; + item->text = text; + item->align = ALIGN_LEFT; + item->layout = NULL; } -void narrative_add_bp(Narrative *n, const char *text) +void narrative_add_bp(Narrative *n, char *text) { + struct narrative_item *item; + + item = add_item(n); + if ( item == NULL ) return; + + item->type = NARRATIVE_ITEM_BP; + item->text = text; + item->align = ALIGN_LEFT; + item->layout = NULL; } diff --git a/libstorycode/narrative.h b/libstorycode/narrative.h index ef757c0..e42b4f3 100644 --- a/libstorycode/narrative.h +++ b/libstorycode/narrative.h @@ -34,11 +34,10 @@ typedef struct _narrative Narrative; extern Narrative *narrative_new(void); extern void narrative_free(Narrative *n); -extern void narrative_add_prestitle(Narrative *n, const char *text); -extern void narrative_add_bp(Narrative *n, const char *text); +extern void narrative_add_prestitle(Narrative *n, char *text); +extern void narrative_add_bp(Narrative *n, char *text); extern void narrative_add_text(Narrative *n, char *text); extern void narrative_add_slide(Narrative *n, Slide *slide); - #endif /* NARRATIVE_H */ diff --git a/libstorycode/narrative_priv.h b/libstorycode/narrative_priv.h index c1695e3..a661e97 100644 --- a/libstorycode/narrative_priv.h +++ b/libstorycode/narrative_priv.h @@ -33,6 +33,7 @@ enum narrative_item_type { NARRATIVE_ITEM_TEXT, + NARRATIVE_ITEM_PRESTITLE, NARRATIVE_ITEM_SLIDE, NARRATIVE_ITEM_BP, }; @@ -41,6 +42,11 @@ enum narrative_item_type struct narrative_item { enum narrative_item_type type; + double h; + double space_l; + double space_r; + double space_t; /* Already included in "h" */ + double space_b; /* Already included in "h" */ /* For TEXT, SLIDETITLE, PRESTITLE */ char *text; @@ -58,7 +64,10 @@ struct _narrative int n_items; struct narrative_item *items; double w; - double total_h; + double space_l; + double space_r; + double space_t; + double space_b; }; diff --git a/libstorycode/narrative_render_cairo.c b/libstorycode/narrative_render_cairo.c index afc8f16..b50944a 100644 --- a/libstorycode/narrative_render_cairo.c +++ b/libstorycode/narrative_render_cairo.c @@ -39,6 +39,8 @@ #include "narrative_priv.h" +const double dummy_h_val = 1024.0; + static double lcalc(struct length l, double pd) { @@ -61,12 +63,20 @@ static PangoAlignment to_pangoalignment(enum alignment align) } -static double wrap_text(struct narrative_item *item, PangoContext *pc, - Stylesheet *ss, enum style_element el, double wrap_w, - PangoFontDescription *fontdesc, enum alignment align) +static void wrap_text(struct narrative_item *item, PangoContext *pc, + Stylesheet *ss, enum style_element el, double w) { PangoAlignment palignment; PangoRectangle rect; + const char *font; + PangoFontDescription *fontdesc; + enum alignment align; + struct length paraspace[4]; + double wrap_w; + + font = stylesheet_get_font(ss, el, NULL, &align); + if ( font == NULL ) return; + fontdesc = pango_font_description_from_string(font); if ( item->align == ALIGN_INHERIT ) { /* Use value from stylesheet */ @@ -76,6 +86,15 @@ static double wrap_text(struct narrative_item *item, PangoContext *pc, palignment = to_pangoalignment(item->align); } + if ( stylesheet_get_paraspace(ss, el, 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; + if ( item->layout == NULL ) { item->layout = pango_layout_new(pc); } @@ -88,24 +107,9 @@ static double wrap_text(struct narrative_item *item, PangoContext *pc, //pango_layout_set_attributes(item->layout, attrs); //pango_attr_list_unref(attrs); - pango_layout_get_extents(item->layout, NULL, &rect); - return pango_units_to_double(rect.height); -} - - -static double draw_text(struct narrative_item *item, cairo_t *cr) -{ - PangoRectangle rect; - - //if ( (hpos + cur_h > min_y) && (hpos < max_y) ) { - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); - pango_cairo_update_layout(cr, item->layout); - pango_cairo_show_layout(cr, item->layout); - cairo_fill(cr); - //} /* else paragraph is not visible */ pango_layout_get_extents(item->layout, NULL, &rect); - return pango_units_to_double(rect.height); + item->h = pango_units_to_double(rect.height)+item->space_t+item->space_b; } @@ -114,40 +118,33 @@ int narrative_wrap(Narrative *n, Stylesheet *stylesheet, PangoLanguage *lang, { int i; struct length pad[4]; - double pad_l, pad_r, pad_t, pad_b; - const char *font; - PangoFontDescription *fontdesc; - double wrap_w; - enum alignment align; if ( stylesheet_get_padding(stylesheet, STYEL_NARRATIVE, pad) ) return 1; - pad_l = lcalc(pad[0], w); - pad_r = lcalc(pad[1], w); - pad_t = lcalc(pad[2], 1024.0); /* dummy value, h not allowed in narrative */ - pad_b = lcalc(pad[3], 1024.0); /* dummy value, h not allowed in narrative */ - wrap_w = w - pad_l - pad_r; + n->space_l = lcalc(pad[0], w); + n->space_r = lcalc(pad[1], w); + n->space_t = lcalc(pad[2], dummy_h_val); + n->space_b = lcalc(pad[3], dummy_h_val); n->w = w; - n->total_h = pad_t + pad_b; - - font = stylesheet_get_font(stylesheet, STYEL_NARRATIVE, NULL, &align); - if ( font == NULL ) return 1; - fontdesc = pango_font_description_from_string(font); + w -= n->space_l + n->space_r; for ( i=0; in_items; i++ ) { switch ( n->items[i].type ) { case NARRATIVE_ITEM_TEXT : - n->total_h += wrap_text(&n->items[i], pc, stylesheet, - STYEL_NARRATIVE, wrap_w, fontdesc, - align); + wrap_text(&n->items[i], pc, stylesheet, + STYEL_NARRATIVE, w); break; case NARRATIVE_ITEM_BP : - n->total_h += wrap_text(&n->items[i], pc, stylesheet, - STYEL_NARRATIVE, wrap_w, fontdesc, - align); + wrap_text(&n->items[i], pc, stylesheet, + STYEL_NARRATIVE_BP, w); + break; + + case NARRATIVE_ITEM_PRESTITLE : + wrap_text(&n->items[i], pc, stylesheet, + STYEL_NARRATIVE_PRESTITLE, w); break; case NARRATIVE_ITEM_SLIDE : @@ -165,10 +162,32 @@ int narrative_wrap(Narrative *n, Stylesheet *stylesheet, PangoLanguage *lang, double narrative_get_height(Narrative *n) { - return n->total_h; + int i; + double total = 0.0; + for ( i=0; in_items; i++ ) { + total += n->items[i].h; + } + return total + n->space_t + n->space_b; +} + + +static void draw_text(struct narrative_item *item, cairo_t *cr) +{ + cairo_save(cr); + cairo_translate(cr, item->space_l, item->space_t); + + //if ( (hpos + cur_h > min_y) && (hpos < max_y) ) { + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); + pango_cairo_update_layout(cr, item->layout); + pango_cairo_show_layout(cr, item->layout); + cairo_fill(cr); + //} /* else paragraph is not visible */ + + cairo_restore(cr); } +/* NB You must first call narrative_wrap() */ int narrative_render_cairo(Narrative *n, cairo_t *cr, Stylesheet *stylesheet) { int i, r; @@ -176,13 +195,12 @@ int narrative_render_cairo(Narrative *n, cairo_t *cr, Stylesheet *stylesheet) double bgcol[4]; double bgcol2[4]; cairo_pattern_t *patt = NULL; - double vpos = 0.0; r = stylesheet_get_background(stylesheet, STYEL_NARRATIVE, &bg, bgcol, bgcol2); if ( r ) return 1; /* Overall background */ - cairo_rectangle(cr, 0.0, 0.0, n->w, n->total_h); + cairo_rectangle(cr, 0.0, 0.0, n->w, narrative_get_height(n)); switch ( bg ) { case GRAD_NONE: @@ -190,7 +208,7 @@ int narrative_render_cairo(Narrative *n, cairo_t *cr, Stylesheet *stylesheet) break; case GRAD_VERT: - patt = cairo_pattern_create_linear(0.0, 0.0, 0.0, n->total_h); + patt = cairo_pattern_create_linear(0.0, 0.0, 0.0, narrative_get_height(n)); cairo_pattern_add_color_stop_rgb(patt, 0.0, bgcol[0], bgcol[1], bgcol[2]); cairo_pattern_add_color_stop_rgb(patt, 1.0, bgcol2[0], bgcol2[1], bgcol2[2]); cairo_set_source(cr, patt); @@ -206,19 +224,20 @@ int narrative_render_cairo(Narrative *n, cairo_t *cr, Stylesheet *stylesheet) } cairo_fill(cr); - for ( i=0; in_items; i++ ) { + cairo_save(cr); + cairo_translate(cr, n->space_l, n->space_t); - cairo_save(cr); - cairo_translate(cr, 0.0, vpos); + for ( i=0; in_items; i++ ) { switch ( n->items[i].type ) { case NARRATIVE_ITEM_TEXT : - vpos += draw_text(&n->items[i], cr); + case NARRATIVE_ITEM_PRESTITLE : + draw_text(&n->items[i], cr); break; case NARRATIVE_ITEM_BP : - vpos += draw_text(&n->items[i], cr); + draw_text(&n->items[i], cr); break; case NARRATIVE_ITEM_SLIDE : @@ -229,8 +248,10 @@ int narrative_render_cairo(Narrative *n, cairo_t *cr, Stylesheet *stylesheet) } - cairo_restore(cr); + cairo_translate(cr, 0.0, n->items[i].h); } + cairo_restore(cr); + return 0; } diff --git a/libstorycode/storycode.y b/libstorycode/storycode.y index 9be6723..f400bec 100644 --- a/libstorycode/storycode.y +++ b/libstorycode/storycode.y @@ -336,11 +336,16 @@ style_narrative: style_narrative_def: %empty | style_narrative_def style_narrative_prestitle -| style_narrative_def styledef +| style_narrative_def style_narrative_bp +| style_narrative_def styledef { set_style(ctx, STYEL_NARRATIVE); } ; style_narrative_prestitle: - PRESTITLE '{' styledefs '}' { } + PRESTITLE '{' styledefs '}' { set_style(ctx, STYEL_NARRATIVE_PRESTITLE); } +; + +style_narrative_bp: + BP '{' styledefs '}' { set_style(ctx, STYEL_NARRATIVE_BP); } ; style_slide: diff --git a/libstorycode/stylesheet.c b/libstorycode/stylesheet.c index 6dc1504..d287836 100644 --- a/libstorycode/stylesheet.c +++ b/libstorycode/stylesheet.c @@ -48,6 +48,8 @@ struct style struct _stylesheet { struct style narrative; + struct style narrative_bp; + struct style narrative_pt; double default_slide_w; double default_slide_h; @@ -117,6 +119,8 @@ Stylesheet *stylesheet_new() /* Ultimate defaults */ default_style(&s->narrative); + default_style(&s->narrative_bp); + default_style(&s->narrative_pt); default_style(&s->slide); default_style(&s->slide_text); default_style(&s->slide_prestitle); @@ -136,6 +140,8 @@ static struct style *get_style(Stylesheet *s, enum style_element el) if ( s == NULL ) return NULL; switch ( el ) { case STYEL_NARRATIVE : return &s->narrative; + case STYEL_NARRATIVE_BP : return &s->narrative_bp; + case STYEL_NARRATIVE_PRESTITLE : return &s->narrative_pt; case STYEL_SLIDE : return &s->slide; case STYEL_SLIDE_TEXT : return &s->slide_text; case STYEL_SLIDE_PRESTITLE : return &s->slide_prestitle; @@ -287,3 +293,14 @@ int stylesheet_get_padding(Stylesheet *s, enum style_element el, for ( i=0; i<4; i++ ) padding[i] = sty->padding[i]; return 0; } + + +int stylesheet_get_paraspace(Stylesheet *s, enum style_element el, + struct length paraspace[4]) +{ + int i; + struct style *sty = get_style(s, el); + if ( sty == NULL ) return 1; + for ( i=0; i<4; i++ ) paraspace[i] = sty->paraspace[i]; + return 0; +} diff --git a/libstorycode/stylesheet.h b/libstorycode/stylesheet.h index e905295..811b901 100644 --- a/libstorycode/stylesheet.h +++ b/libstorycode/stylesheet.h @@ -72,6 +72,8 @@ enum gradient enum style_element { STYEL_NARRATIVE, + STYEL_NARRATIVE_PRESTITLE, + STYEL_NARRATIVE_BP, STYEL_SLIDE, STYEL_SLIDE_TEXT, STYEL_SLIDE_PRESTITLE, @@ -100,6 +102,8 @@ extern int stylesheet_get_background(Stylesheet *s, enum style_element el, enum gradient *grad, double *bgcol, double *bgcol2); extern int stylesheet_get_padding(Stylesheet *s, enum style_element el, struct length padding[4]); +extern int stylesheet_get_paraspace(Stylesheet *s, enum style_element el, + struct length paraspace[4]); #endif /* STYLESHEET_H */ -- cgit v1.2.3