aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.me.uk>2019-03-24 13:53:03 +0100
committerThomas White <taw@bitwiz.me.uk>2019-03-24 13:53:03 +0100
commita4a3ad0ee82b0731c540e90c3c137a240acb10f2 (patch)
treedffca362b77a9893da4971abe7c6045a8cac23e5
parentf5fd7623a14dd51a59657cbab4d5953b1b2e48ff (diff)
Implement text selection in slides
-rw-r--r--libstorycode/gtk/gtkslideview.c34
-rw-r--r--libstorycode/narrative_render_cairo.c6
-rw-r--r--libstorycode/slide_render_cairo.c112
-rw-r--r--libstorycode/slide_render_cairo.h5
-rw-r--r--src/pdfstorycode.c6
5 files changed, 131 insertions, 32 deletions
diff --git a/libstorycode/gtk/gtkslideview.c b/libstorycode/gtk/gtkslideview.c
index f80d1b5..e9abfb5 100644
--- a/libstorycode/gtk/gtkslideview.c
+++ b/libstorycode/gtk/gtkslideview.c
@@ -325,7 +325,8 @@ static gboolean draw_sig(GtkWidget *da, cairo_t *cr, GtkSlideView *e)
slide_render_cairo(e->slide, cr, presentation_get_imagestore(e->p),
presentation_get_stylesheet(e->p),
presentation_get_slide_number(e->p, e->slide),
- pango_language_get_default(), pc);
+ pango_language_get_default(), pc,
+ e->cursor_frame, e->sel_start, e->sel_end);
g_object_unref(pc);
/* Editing overlay */
@@ -564,15 +565,6 @@ static int find_cursor(SlideItem *item, Stylesheet *stylesheet,
static void unset_selection(GtkSlideView *e)
{
- int a, b;
-
- a = e->sel_start.para;
- b = e->sel_end.para;
- if ( a > b ) {
- a = e->sel_end.para;
- b = e->sel_start.para;
- }
-
e->sel_start.para = 0;
e->sel_start.pos = 0;
e->sel_start.trail = 0;
@@ -750,12 +742,17 @@ static gboolean motion_sig(GtkWidget *da, GdkEventMotion *event, GtkSlideView *e
{
gdouble x, y;
double frx, fry, frw, frh;
+ Stylesheet *stylesheet;
+ double slide_w, slide_h;
- x = event->x + e->h_scroll_pos;
- y = event->y + e->v_scroll_pos;
+ x = event->x - e->border_offs_x + e->h_scroll_pos;
+ y = event->y - e->border_offs_y + e->v_scroll_pos;
x /= e->view_scale;
y /= e->view_scale;
+ stylesheet = presentation_get_stylesheet(e->p);
+ slide_get_logical_size(e->slide, stylesheet, &slide_w, &slide_h);
+
if ( e->drag_status == DRAG_STATUS_COULD_DRAG ) {
/* We just got a motion signal, and the status was "could drag",
@@ -765,9 +762,6 @@ static gboolean motion_sig(GtkWidget *da, GdkEventMotion *event, GtkSlideView *e
}
if ( e->cursor_frame != NULL ) {
- double slide_w, slide_h;
- Stylesheet *stylesheet = presentation_get_stylesheet(e->p);
- slide_get_logical_size(e->slide, stylesheet, &slide_w, &slide_h);
slide_item_get_geom(e->cursor_frame, stylesheet,
&frx, &fry, &frw, &frh, slide_w, slide_h);
}
@@ -803,13 +797,9 @@ static gboolean motion_sig(GtkWidget *da, GdkEventMotion *event, GtkSlideView *e
break;
case DRAG_REASON_TEXTSEL :
- //unset_selection(e);
- //find_cursor(fr, x-fr->x, y-fr->y, &e->sel_end);
- //rewrap_paragraph_range(fr, e->sel_start.para, e->sel_end.para,
- // e->sel_start, e->sel_end, 1);
- //find_cursor(fr, x-fr->x, y-fr->y, &e->cpos);
- //e->sel_active = !positions_equal(e->sel_start, e->sel_end);
- //sc_editor_redraw(e);
+ find_cursor(e->cursor_frame, stylesheet, x-frx, y-fry, &e->sel_end, slide_w, slide_h);
+ e->cpos = e->sel_end;
+ redraw(e);
break;
}
diff --git a/libstorycode/narrative_render_cairo.c b/libstorycode/narrative_render_cairo.c
index b4f29cb..6da1db1 100644
--- a/libstorycode/narrative_render_cairo.c
+++ b/libstorycode/narrative_render_cairo.c
@@ -149,10 +149,13 @@ static cairo_surface_t *render_thumbnail(Slide *s, Stylesheet *ss, ImageStore *i
PangoContext *pc;
const int rh = 1024; /* "reasonably big" height for slide */
int rw;
+ struct slide_pos sel;
slide_get_logical_size(s, ss, &logical_w, &logical_h);
rw = rh*(logical_w/logical_h);
+ sel.para = 0; sel.pos = 0; sel.trail = 0;
+
/* 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. */
@@ -160,7 +163,8 @@ static cairo_surface_t *render_thumbnail(Slide *s, Stylesheet *ss, ImageStore *i
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);
+ slide_render_cairo(s, cr, is, ss, 0, pango_language_get_default(), pc,
+ NULL, sel, sel);
g_object_unref(pc);
cairo_destroy(cr);
diff --git a/libstorycode/slide_render_cairo.c b/libstorycode/slide_render_cairo.c
index 16be90f..c428fad 100644
--- a/libstorycode/slide_render_cairo.c
+++ b/libstorycode/slide_render_cairo.c
@@ -38,6 +38,7 @@
#include "narrative.h"
#include "stylesheet.h"
#include "imagestore.h"
+#include "slide_render_cairo.h"
#include "slide_priv.h"
@@ -63,9 +64,33 @@ static PangoAlignment to_pangoalignment(enum alignment align)
}
+static int slide_positions_equal(struct slide_pos a, struct slide_pos b)
+{
+ if ( a.para != b.para ) return 0;
+ if ( a.pos != b.pos ) return 0;
+ if ( a.trail != b.trail ) return 0;
+ return 1;
+}
+
+
+static size_t pos_trail_to_offset(SlideItem *item, int para,
+ size_t offs, int trail)
+{
+ glong char_offs;
+ char *ptr;
+
+ char_offs = g_utf8_pointer_to_offset(item->paras[para].text,
+ item->paras[para].text+offs);
+ char_offs += trail;
+ ptr = g_utf8_offset_to_pointer(item->paras[para].text, char_offs);
+ return ptr - item->paras[para].text;
+}
+
+
static void render_text(SlideItem *item, cairo_t *cr, PangoContext *pc,
Stylesheet *ss, enum style_element el,
- double parent_w, double parent_h)
+ double parent_w, double parent_h,
+ struct slide_pos sel_start, struct slide_pos sel_end)
{
int i;
double x, y, w;
@@ -77,6 +102,7 @@ static void render_text(SlideItem *item, cairo_t *cr, PangoContext *pc,
PangoRectangle rect;
PangoFontDescription *fontdesc;
PangoAlignment palignment;
+ size_t sel_s, sel_e;
x = lcalc(item->geom.x, parent_w);
y = lcalc(item->geom.y, parent_h);
@@ -100,6 +126,14 @@ static void render_text(SlideItem *item, cairo_t *cr, PangoContext *pc,
palignment = to_pangoalignment(item->align);
}
+ if ( !slide_positions_equal(sel_start, sel_end) ) {
+ sel_s = pos_trail_to_offset(item, sel_start.para, sel_start.pos, sel_start.trail);
+ sel_e = pos_trail_to_offset(item, sel_end.para, sel_end.pos, sel_end.trail);
+ } else {
+ sel_s = 0;
+ sel_e = 0;
+ }
+
/* FIXME: Apply background */
cairo_save(cr);
@@ -108,6 +142,28 @@ static void render_text(SlideItem *item, cairo_t *cr, PangoContext *pc,
for ( i=0; i<item->n_paras; i++ ) {
+ PangoAttrList *attrs;
+
+ size_t srt, end;
+ if ( i >= sel_start.para && i <= sel_end.para ) {
+ if ( i == sel_start.para ) {
+ srt = sel_s;
+ } else {
+ srt = 0;
+ }
+ if ( i == sel_end.para ) {
+ end = sel_e;
+ } else {
+ end = G_MAXUINT;
+ }
+ if ( i > sel_start.para && i < sel_end.para ) {
+ end = G_MAXUINT;
+ }
+ } else {
+ srt = 0;
+ end = 0;
+ }
+
if ( item->paras[i].layout == NULL ) {
item->paras[i].layout = pango_layout_new(pc);
}
@@ -119,9 +175,20 @@ static void render_text(SlideItem *item, cairo_t *cr, PangoContext *pc,
pango_layout_set_font_description(item->paras[i].layout, fontdesc);
+ attrs = pango_attr_list_new();
+
+ if ( srt > 0 || end > 0 ) {
+ PangoAttribute *attr;
+ attr = pango_attr_background_new(42919, 58853, 65535);
+ attr->start_index = srt;
+ attr->end_index = end;
+ pango_attr_list_insert(attrs, attr);
+ }
+
/* FIXME: Handle *bold*, _underline_, /italic/ etc. */
- //pango_layout_set_attributes(item->layouts[i], attrs);
- //pango_attr_list_unref(attrs);
+
+ pango_layout_set_attributes(item->paras[i].layout, attrs);
+ pango_attr_list_unref(attrs);
/* FIXME: Clip to w,h */
@@ -174,8 +241,29 @@ static void render_image(SlideItem *item, cairo_t *cr,
}
+static void sort_slide_positions(struct slide_pos *a, struct slide_pos *b)
+{
+ if ( a->para > b->para ) {
+ size_t tpos;
+ int tpara, ttrail;
+ tpara = b->para; tpos = b->pos; ttrail = b->trail;
+ b->para = a->para; b->pos = a->pos; b->trail = a->trail;
+ a->para = tpara; a->pos = tpos; a->trail = ttrail;
+ }
+
+ if ( (a->para == b->para) && (a->pos > b->pos) )
+ {
+ size_t tpos = b->pos;
+ int ttrail = b->trail;
+ b->pos = a->pos; b->trail = a->trail;
+ a->pos = tpos; a->trail = ttrail;
+ }
+}
+
+
int slide_render_cairo(Slide *s, cairo_t *cr, ImageStore *is, Stylesheet *stylesheet,
- int slide_number, PangoLanguage *lang, PangoContext *pc)
+ int slide_number, PangoLanguage *lang, PangoContext *pc,
+ SlideItem *sel_item, struct slide_pos sel_start, struct slide_pos sel_end)
{
int i, r;
enum gradient bg;
@@ -188,6 +276,7 @@ int slide_render_cairo(Slide *s, cairo_t *cr, ImageStore *is, Stylesheet *styles
if ( r ) return 1;
slide_get_logical_size(s, stylesheet, &w, &h);
+ sort_slide_positions(&sel_start, &sel_end);
/* Overall background */
cairo_rectangle(cr, 0.0, 0.0, w, h);
@@ -220,11 +309,20 @@ int slide_render_cairo(Slide *s, cairo_t *cr, ImageStore *is, Stylesheet *styles
for ( i=0; i<s->n_items; i++ ) {
+ struct slide_pos srt, end;
+
+ if ( &s->items[i] != sel_item ) {
+ srt.para = 0; srt.pos = 0; srt.trail = 0;
+ end.para = 0; end.pos = 0; end.trail = 0;
+ } else {
+ srt = sel_start; end = sel_end;
+ }
+
switch ( s->items[i].type ) {
case SLIDE_ITEM_TEXT :
render_text(&s->items[i], cr, pc, stylesheet, STYEL_SLIDE_TEXT,
- w, h);
+ w, h, srt, end);
break;
case SLIDE_ITEM_IMAGE :
@@ -234,12 +332,12 @@ int slide_render_cairo(Slide *s, cairo_t *cr, ImageStore *is, Stylesheet *styles
case SLIDE_ITEM_SLIDETITLE :
render_text(&s->items[i], cr, pc, stylesheet, STYEL_SLIDE_SLIDETITLE,
- w, h);
+ w, h, srt, end);
break;
case SLIDE_ITEM_PRESTITLE :
render_text(&s->items[i], cr, pc, stylesheet, STYEL_SLIDE_PRESTITLE,
- w, h);
+ w, h, srt, end);
break;
default :
diff --git a/libstorycode/slide_render_cairo.h b/libstorycode/slide_render_cairo.h
index 52bf43f..cd6e03b 100644
--- a/libstorycode/slide_render_cairo.h
+++ b/libstorycode/slide_render_cairo.h
@@ -38,6 +38,9 @@ struct slide_pos
};
extern int slide_render_cairo(Slide *s, cairo_t *cr, ImageStore *is, Stylesheet *stylesheet,
- int slide_number, PangoLanguage *lang, PangoContext *pc);
+ int slide_number, PangoLanguage *lang, PangoContext *pc,
+ SlideItem *sel_item, struct slide_pos sel_start,
+ struct slide_pos sel_end);
+
#endif /* RENDER_H */
diff --git a/src/pdfstorycode.c b/src/pdfstorycode.c
index 566f924..421839d 100644
--- a/src/pdfstorycode.c
+++ b/src/pdfstorycode.c
@@ -51,6 +51,7 @@ static int render_slides_to_pdf(Presentation *p, ImageStore *is, const char *fil
cairo_t *cr;
int i;
PangoContext *pc;
+ struct slide_pos sel;
surf = cairo_pdf_surface_create(filename, w, w);
if ( cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS ) {
@@ -61,6 +62,8 @@ static int render_slides_to_pdf(Presentation *p, ImageStore *is, const char *fil
cr = cairo_create(surf);
pc = pango_cairo_create_context(cr);
+ sel.para = 0; sel.pos = 0; sel.trail = 0;
+
for ( i=0; i<presentation_get_num_slides(p); i++ )
{
Slide *s;
@@ -75,7 +78,8 @@ static int render_slides_to_pdf(Presentation *p, ImageStore *is, const char *fil
cairo_save(cr);
cairo_scale(cr, w/log_w, w/log_w);
slide_render_cairo(s, cr, is, presentation_get_stylesheet(p),
- i, pango_language_get_default(), pc);
+ i, pango_language_get_default(), pc,
+ NULL, sel, sel);
cairo_show_page(cr);
cairo_restore(cr);
}