aboutsummaryrefslogtreecommitdiff
path: root/libstorycode/narrative_render_cairo.c
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.me.uk>2019-03-04 23:46:47 +0100
committerThomas White <taw@bitwiz.me.uk>2019-03-04 23:46:47 +0100
commit915fcacee4c49f017ab2599b4307198ca3f713d3 (patch)
treeed4c7a8f8aec7327934f86d9f3100f982ee1d624 /libstorycode/narrative_render_cairo.c
parent373d5183849c2855345ea45c964479086d67a7d2 (diff)
Thumbnail slide rendering in narrative
Diffstat (limited to 'libstorycode/narrative_render_cairo.c')
-rw-r--r--libstorycode/narrative_render_cairo.c65
1 files changed, 57 insertions, 8 deletions
diff --git a/libstorycode/narrative_render_cairo.c b/libstorycode/narrative_render_cairo.c
index cd2d872..6024ccc 100644
--- a/libstorycode/narrative_render_cairo.c
+++ b/libstorycode/narrative_render_cairo.c
@@ -36,6 +36,8 @@
#include "slide.h"
#include "narrative.h"
#include "stylesheet.h"
+#include "imagestore.h"
+#include "slide_render_cairo.h"
#include "narrative_priv.h"
@@ -107,13 +109,51 @@ static void 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);
item->h = pango_units_to_double(rect.height)+item->space_t+item->space_b;
}
-static void wrap_slide(struct narrative_item *item, Stylesheet *ss)
+/* Render a thumbnail of the slide */
+static cairo_surface_t *render_thumbnail(Slide *s, Stylesheet *ss, ImageStore *is,
+ int w, int h)
+{
+ cairo_surface_t *surf;
+ cairo_surface_t *full_surf;
+ cairo_t *cr;
+ double logical_w, logical_h;
+ PangoContext *pc;
+ const int rh = 1024; /* "reasonably big" height for slide */
+ int rw;
+
+ slide_get_logical_size(s, ss, &logical_w, &logical_h);
+ rw = rh*(logical_w/logical_h);
+
+ /* Render at a reasonably big size. Rendering to a small surface makes
+ * rounding of text positions (due to font hinting) cause significant
+ * differences between the thumbnail and "normal" rendering. */
+ full_surf = cairo_image_surface_create(CAIRO_FORMAT_RGB24, rw, rh);
+ cr = cairo_create(full_surf);
+ cairo_scale(cr, (double)rw/logical_w, (double)rh/logical_h);
+ pc = pango_cairo_create_context(cr);
+ slide_render_cairo(s, cr, is, ss, 0, pango_language_get_default(), pc);
+ g_object_unref(pc);
+ cairo_destroy(cr);
+
+ /* Scale down to the actual size of the thumbnail */
+ surf = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h);
+ cr = cairo_create(surf);
+ cairo_scale(cr, (double)w/rw, (double)h/rh);
+ cairo_set_source_surface(cr, full_surf, 0.0, 0.0);
+ cairo_paint(cr);
+ cairo_destroy(cr);
+
+ cairo_surface_destroy(full_surf);
+ return surf;
+}
+
+
+static void wrap_slide(struct narrative_item *item, Stylesheet *ss, ImageStore *is)
{
double w, h;
@@ -123,16 +163,21 @@ static void wrap_slide(struct narrative_item *item, Stylesheet *ss)
item->space_b = 10.0;
slide_get_logical_size(item->slide, ss, &w, &h);
- item->slide_h = 320.0;
- item->slide_w = item->slide_h*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;
+ 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);
}
int narrative_wrap(Narrative *n, Stylesheet *stylesheet, PangoLanguage *lang,
- PangoContext *pc, double w)
+ PangoContext *pc, double w, ImageStore *is)
{
int i;
struct length pad[4];
@@ -166,7 +211,7 @@ int narrative_wrap(Narrative *n, Stylesheet *stylesheet, PangoLanguage *lang,
break;
case NARRATIVE_ITEM_SLIDE :
- wrap_slide(&n->items[i], stylesheet);
+ wrap_slide(&n->items[i], stylesheet, is);
break;
default :
@@ -201,9 +246,13 @@ static void draw_slide(struct narrative_item *item, cairo_t *cr)
cairo_user_to_device(cr, &x, &y);
x = rint(x); y = rint(y);
cairo_device_to_user(cr, &x, &y);
- cairo_rectangle(cr, x+0.5, y+0.5, item->slide_w, item->slide_h);
- cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_rectangle(cr, x, y, item->slide_w, item->slide_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_set_source_rgb(cr, 0.0, 0.0, 0.0);
cairo_set_line_width(cr, 1.0);
cairo_stroke(cr);