aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.me.uk>2019-03-03 18:51:34 +0100
committerThomas White <taw@bitwiz.me.uk>2019-03-03 18:52:22 +0100
commitacbec489df38e182a8e284095ccd7a0f1d84112e (patch)
tree1ad22572be6294ae761a2ecba7dea37c26f0b969
parentf2bfe89481217625f74224289947f7bcd839c55f (diff)
Styled narrative rendering
-rw-r--r--data/demo.sc4
-rw-r--r--libstorycode/gtk/gtknarrativeview.c1
-rw-r--r--libstorycode/narrative.c22
-rw-r--r--libstorycode/narrative.h5
-rw-r--r--libstorycode/narrative_priv.h11
-rw-r--r--libstorycode/narrative_render_cairo.c121
-rw-r--r--libstorycode/storycode.y9
-rw-r--r--libstorycode/stylesheet.c17
-rw-r--r--libstorycode/stylesheet.h4
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; i<n->n_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; i<n->n_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; i<n->n_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; i<n->n_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 */