aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.me.uk>2019-03-01 00:23:04 +0100
committerThomas White <taw@bitwiz.me.uk>2019-03-01 00:23:04 +0100
commit4104a6ff28d3a3be7069663c5677a5ee5076984a (patch)
treed7cfa39dc7d643140e03bffdaaade852e4f6af08
parentfcdd59665b27c3a7a558c5593178c5efe6286831 (diff)
Narrative rendering machinery
-rw-r--r--libstorycode/gtk/gtknarrativeview.c42
-rw-r--r--libstorycode/gtk/gtknarrativeview.h1
-rw-r--r--libstorycode/narrative.c8
-rw-r--r--libstorycode/narrative_priv.h70
-rw-r--r--libstorycode/narrative_render_cairo.c266
-rw-r--r--libstorycode/narrative_render_cairo.h43
-rw-r--r--libstorycode/presentation.c7
-rw-r--r--libstorycode/presentation.h1
-rw-r--r--libstorycode/stylesheet.c8
-rw-r--r--libstorycode/stylesheet.h2
-rw-r--r--meson.build1
11 files changed, 405 insertions, 44 deletions
diff --git a/libstorycode/gtk/gtknarrativeview.c b/libstorycode/gtk/gtknarrativeview.c
index 70d59f5..9040d55 100644
--- a/libstorycode/gtk/gtknarrativeview.c
+++ b/libstorycode/gtk/gtknarrativeview.c
@@ -34,6 +34,7 @@
#include <math.h>
#include <presentation.h>
+#include <narrative_render_cairo.h>
//#include "slide_window.h"
#include "gtknarrativeview.h"
@@ -121,24 +122,6 @@ static void set_vertical_params(GtkNarrativeView *e)
}
-static void update_size(GtkNarrativeView *e)
-{
-// double total = total_height(e->top);
-//
-// e->w = e->top->w;
-// e->h = total + e->top->pad_t + e->top->pad_b;
-//
-// e->top->h = e->h;
-//
-// if ( e->top->h < e->visible_height ) {
-// e->top->h = e->visible_height;
-// }
-//
-// set_vertical_params(e);
-// set_horizontal_params(e);
-}
-
-
static gboolean resize_sig(GtkWidget *widget, GdkEventConfigure *event,
GtkNarrativeView *e)
{
@@ -149,23 +132,13 @@ static gboolean resize_sig(GtkWidget *widget, GdkEventConfigure *event,
e->visible_height = event->height;
e->visible_width = event->width;
- /* Wrap everything with the current width, to get the total height */
- //e->top = interp_and_shape(e->scblocks, e->stylesheet, e->cbl,
- // e->is, e->slidenum, pc,
- // w, h, e->lang);
-// e->top->scblocks = e->scblocks;
-// recursive_wrap(e->top, pc);
-// }
-//
-// /* Wrap using current width */
-// e->top->w = event->width;
-// e->top->h = 0.0; /* To be updated in a moment */
-// e->top->x = 0.0;
-// e->top->y = 0.0;
-// /* Only the top level needs to be wrapped */
-// wrap_frame(e->top, pc);
+ e->w = e->visible_width;
+ e->h = narrative_get_height(presentation_get_narrative(e->p));
- update_size(e);
+ /* Wrap everything with the current width, to get the total height */
+ narrative_wrap(presentation_get_narrative(e->p),
+ presentation_get_stylesheet(e->p),
+ pango_language_get_default(), pc, e->w);
g_object_unref(pc);
@@ -1045,6 +1018,7 @@ GtkNarrativeView *gtk_narrative_view_new(Presentation *p, PangoLanguage *lang,
nview->h = 100;
nview->scroll_pos = 0;
nview->lang = lang;
+ nview->p = p;
nview->para_highlight = 0;
diff --git a/libstorycode/gtk/gtknarrativeview.h b/libstorycode/gtk/gtknarrativeview.h
index 1b0802f..717b0d0 100644
--- a/libstorycode/gtk/gtknarrativeview.h
+++ b/libstorycode/gtk/gtknarrativeview.h
@@ -91,6 +91,7 @@ struct _gtknarrativeview
GtkDrawingArea parent_instance;
/*< private >*/
+ Presentation *p;
GtkIMContext *im_context;
PangoContext *pc;
PangoLanguage *lang;
diff --git a/libstorycode/narrative.c b/libstorycode/narrative.c
index 23b8e34..85f5410 100644
--- a/libstorycode/narrative.c
+++ b/libstorycode/narrative.c
@@ -29,13 +29,7 @@
#include <string.h>
#include "narrative.h"
-
-struct _narrative
-{
- int n_items;
- struct narrative_item *items;
-};
-
+#include "narrative_priv.h"
Narrative *narrative_new()
{
diff --git a/libstorycode/narrative_priv.h b/libstorycode/narrative_priv.h
new file mode 100644
index 0000000..059b015
--- /dev/null
+++ b/libstorycode/narrative_priv.h
@@ -0,0 +1,70 @@
+/*
+ * narrative_priv.h
+ *
+ * Copyright © 2019 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef NARRATIVE_PRIV_H
+#define NARRATIVE_PRIV_H
+
+#ifdef HAVE_PANGO
+#include <pango/pangocairo.h>
+#endif
+
+#include "storycode.h"
+
+
+enum narrative_item_type
+{
+ NARRATIVE_ITEM_TEXT,
+ NARRATIVE_ITEM_SLIDE,
+ NARRATIVE_ITEM_BP,
+};
+
+
+struct narrative_item
+{
+ enum narrative_item_type type;
+
+ /* For TEXT, SLIDETITLE, PRESTITLE */
+ char **paragraphs;
+ int n_paras;
+ enum alignment align;
+#ifdef HAVE_PANGO
+ PangoLayout **layouts;
+#endif
+
+ /* For IMAGE */
+ char *filename;
+
+ /* For TEXT and IMAGE */
+ struct frame_geom geom;
+};
+
+
+struct _narrative
+{
+ int n_items;
+ struct narrative_item *items;
+ double w;
+ double total_h;
+};
+
+
+#endif /* NARRATIVE_PRIV_H */
diff --git a/libstorycode/narrative_render_cairo.c b/libstorycode/narrative_render_cairo.c
new file mode 100644
index 0000000..746ce62
--- /dev/null
+++ b/libstorycode/narrative_render_cairo.c
@@ -0,0 +1,266 @@
+/*
+ * narrative_render_cairo.c
+ *
+ * Copyright © 2013-2019 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cairo.h>
+#include <cairo-pdf.h>
+#include <pango/pangocairo.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "slide.h"
+#include "narrative.h"
+#include "stylesheet.h"
+
+#include "narrative_priv.h"
+
+
+static double lcalc(struct length l, double pd)
+{
+ if ( l.unit == LENGTH_UNIT ) {
+ return l.len;
+ } else {
+ return l.len * pd;
+ }
+}
+
+
+static PangoAlignment to_pangoalignment(enum alignment align)
+{
+ switch ( align ) {
+ case ALIGN_LEFT : return PANGO_ALIGN_LEFT;
+ case ALIGN_RIGHT : return PANGO_ALIGN_RIGHT;
+ case ALIGN_CENTER : return PANGO_ALIGN_CENTER;
+ default: return PANGO_ALIGN_LEFT;
+ }
+}
+
+
+static double wrap_text(struct narrative_item *item, PangoContext *pc,
+ Stylesheet *ss, enum style_element el, double wrap_w,
+ PangoFontDescription *fontdesc, enum alignment align)
+{
+ int i;
+ PangoAlignment palignment;
+ double total_h = 0.0;
+
+ if ( item->layouts == NULL ) {
+ item->layouts = malloc(item->n_paras*sizeof(PangoLayout *));
+ if ( item->layouts == NULL ) return 0.0;
+ for ( i=0; i<item->n_paras; i++ ) {
+ item->layouts[i] = NULL;
+ }
+ }
+
+ if ( item->align == ALIGN_INHERIT ) {
+ /* Use value from stylesheet */
+ palignment = to_pangoalignment(align);
+ } else {
+ /* Use item-specific value */
+ palignment = to_pangoalignment(item->align);
+ }
+
+ for ( i=0; i<item->n_paras; i++ ) {
+
+ PangoRectangle rect;
+
+ if ( item->layouts[i] == NULL ) {
+ item->layouts[i] = pango_layout_new(pc);
+ }
+ pango_layout_set_width(item->layouts[i], pango_units_from_double(wrap_w));
+ pango_layout_set_text(item->layouts[i], item->paragraphs[i], -1);
+ pango_layout_set_alignment(item->layouts[i], palignment);
+ pango_layout_set_font_description(item->layouts[i], fontdesc);
+
+ /* FIXME: Handle *bold*, _underline_, /italic/ etc. */
+ //pango_layout_set_attributes(item->layouts[i], attrs);
+ //pango_attr_list_unref(attrs);
+
+ pango_layout_get_extents(item->layouts[i], NULL, &rect);
+ total_h += pango_units_to_double(rect.height);
+
+ }
+
+ return total_h;
+}
+
+
+static void draw_text(struct narrative_item *item, cairo_t *cr)
+{
+ int i;
+ double hpos = 0.0;
+
+ cairo_save(cr);
+
+ for ( i=0; i<item->n_paras; i++ ) {
+
+ PangoRectangle rect;
+ double cur_h;
+
+ pango_layout_get_extents(item->layouts[i], NULL, &rect);
+ cur_h = rect.height;
+
+ cairo_save(cr);
+ cairo_translate(cr, 0.0, hpos);
+
+ //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->layouts[i]);
+ pango_cairo_show_layout(cr, item->layouts[i]);
+ cairo_fill(cr);
+ //} /* else paragraph is not visible */
+
+ hpos += cur_h;
+ cairo_restore(cr);
+
+ }
+
+ cairo_restore(cr);
+}
+
+
+int narrative_wrap(Narrative *n, Stylesheet *stylesheet, PangoLanguage *lang,
+ PangoContext *pc, double w)
+{
+ 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->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);
+
+ 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);
+ break;
+
+ case NARRATIVE_ITEM_BP :
+ n->total_h += wrap_text(&n->items[i], pc, stylesheet,
+ STYEL_NARRATIVE, wrap_w, fontdesc,
+ align);
+ break;
+
+ case NARRATIVE_ITEM_SLIDE :
+ break;
+
+ default :
+ break;
+
+ }
+ }
+
+ return 0;
+}
+
+
+double narrative_get_height(Narrative *n)
+{
+ return n->total_h;
+}
+
+
+int narrative_render_cairo(Narrative *n, cairo_t *cr, Stylesheet *stylesheet,
+ PangoLanguage *lang, PangoContext *pc, double w)
+{
+ int i, r;
+ enum gradient bg;
+ double bgcol[4];
+ double bgcol2[4];
+ cairo_pattern_t *patt = NULL;
+
+ r = stylesheet_get_background(stylesheet, STYEL_SLIDE, &bg, bgcol, bgcol2);
+ if ( r ) return 1;
+
+ /* Overall background */
+ cairo_rectangle(cr, 0.0, 0.0, n->w, n->total_h);
+ switch ( bg ) {
+
+ case GRAD_NONE:
+ cairo_set_source_rgb(cr, bgcol[0], bgcol[1], bgcol[2]);
+ break;
+
+ case GRAD_VERT:
+ patt = cairo_pattern_create_linear(0.0, 0.0, 0.0, n->total_h);
+ 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);
+ break;
+
+ case GRAD_HORIZ:
+ patt = cairo_pattern_create_linear(0.0, 0.0, n->w, 0.0);
+ 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);
+ break;
+
+ }
+ cairo_fill(cr);
+
+ for ( i=0; i<n->n_items; i++ ) {
+
+ switch ( n->items[i].type ) {
+
+ case NARRATIVE_ITEM_TEXT :
+ draw_text(&n->items[i], cr);
+ break;
+
+ case NARRATIVE_ITEM_BP :
+ draw_text(&n->items[i], cr);
+ break;
+
+ case NARRATIVE_ITEM_SLIDE :
+ break;
+
+ default :
+ break;
+
+ }
+ }
+
+ return 0;
+}
diff --git a/libstorycode/narrative_render_cairo.h b/libstorycode/narrative_render_cairo.h
new file mode 100644
index 0000000..1f16aae
--- /dev/null
+++ b/libstorycode/narrative_render_cairo.h
@@ -0,0 +1,43 @@
+/*
+ * narrative_render_cairo.h
+ *
+ * Copyright © 2013-2019 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef NARRATIVE_RENDER_CAIRO_H
+#define NARRATIVE_RENDER_CAIRO_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "presentation.h"
+#include "imagestore.h"
+
+
+extern int narrative_wrap(Narrative *n, Stylesheet *stylesheet,
+ PangoLanguage *lang, PangoContext *pc, double w);
+
+extern double narrative_get_height(Narrative *n);
+
+extern int narrative_render_cairo(Narrative *n, cairo_t *cr,
+ Stylesheet *stylesheet, PangoLanguage *lang,
+ PangoContext *pc);
+
+#endif /* NARRATIVE_RENDER_CAIRO_H */
diff --git a/libstorycode/presentation.c b/libstorycode/presentation.c
index 6eb7a50..f81dc84 100644
--- a/libstorycode/presentation.c
+++ b/libstorycode/presentation.c
@@ -148,3 +148,10 @@ Stylesheet *presentation_get_stylesheet(Presentation *p)
if ( p == NULL ) return NULL;
return p->stylesheet;
}
+
+
+Narrative *presentation_get_narrative(Presentation *p)
+{
+ if ( p == NULL ) return NULL;
+ return p->narrative;
+}
diff --git a/libstorycode/presentation.h b/libstorycode/presentation.h
index 250d7a6..d5269b9 100644
--- a/libstorycode/presentation.h
+++ b/libstorycode/presentation.h
@@ -46,5 +46,6 @@ extern void presentation_add_slide(Presentation *p, Slide *s);
extern int presentation_num_slides(Presentation *p);
extern Slide *presentation_slide(Presentation *p, int i);
extern Stylesheet *presentation_get_stylesheet(Presentation *p);
+extern Narrative *presentation_get_narrative(Presentation *p);
#endif /* PRESENTATION_H */
diff --git a/libstorycode/stylesheet.c b/libstorycode/stylesheet.c
index 88b60cd..6dc1504 100644
--- a/libstorycode/stylesheet.c
+++ b/libstorycode/stylesheet.c
@@ -246,14 +246,18 @@ int stylesheet_set_alignment(Stylesheet *s, enum style_element el, enum alignmen
const char *stylesheet_get_font(Stylesheet *s, enum style_element el,
- double fgcol[4], enum alignment *alignment)
+ double *fgcol, enum alignment *alignment)
{
int i;
struct style *sty = get_style(s, el);
if ( sty == NULL ) return NULL;
*alignment = sty->alignment;
- for ( i=0; i<4; i++ ) fgcol[i] = sty->fgcol[i];
+ if ( fgcol != NULL ) {
+ for ( i=0; i<4; i++ ) {
+ fgcol[i] = sty->fgcol[i];
+ }
+ }
return sty->font;
}
diff --git a/libstorycode/stylesheet.h b/libstorycode/stylesheet.h
index 5bd1695..e905295 100644
--- a/libstorycode/stylesheet.h
+++ b/libstorycode/stylesheet.h
@@ -95,7 +95,7 @@ extern int stylesheet_set_background(Stylesheet *s, enum style_element el, enum
double bgcol[4], double bgcol2[4]);
extern const char *stylesheet_get_font(Stylesheet *s, enum style_element el,
- double fgcol[4], enum alignment *alignment);
+ double *fgcol, enum alignment *alignment);
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,
diff --git a/meson.build b/meson.build
index 88d1051..c1daeea 100644
--- a/meson.build
+++ b/meson.build
@@ -69,6 +69,7 @@ libstorycode = library('storycode',
'libstorycode/stylesheet.c',
'libstorycode/storycode.c',
'libstorycode/slide_render_cairo.c',
+ 'libstorycode/narrative_render_cairo.c',
'libstorycode/imagestore.c',
storycode_lex_ch,
storycode_parse_ch,