aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2012-12-04 23:56:09 +0100
committerThomas White <taw@bitwiz.org.uk>2012-12-04 23:56:09 +0100
commit5ed4ab710e8408f3cdad40b91eb8ca60de5f87bc (patch)
tree8737ff4ee2e2360f7657f2572797272a4871900b /src
parent1da61dcda8ac5d7e74ac06ba2659af38c55351a3 (diff)
Rendering WIP
Diffstat (limited to 'src')
-rw-r--r--src/frame.c27
-rw-r--r--src/frame.h17
-rw-r--r--src/mainwindow.c4
-rw-r--r--src/render.c208
-rw-r--r--src/render.h4
5 files changed, 188 insertions, 72 deletions
diff --git a/src/frame.c b/src/frame.c
index 81edf1d..21e26af 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -38,11 +38,11 @@ static int alloc_ro(struct frame *fr)
{
struct frame **new_ro;
- new_ro = realloc(fr->rendering_order,
- fr->max_ro*sizeof(struct frame *));
+ new_ro = realloc(fr->children,
+ fr->max_children*sizeof(struct frame *));
if ( new_ro == NULL ) return 1;
- fr->rendering_order = new_ro;
+ fr->children = new_ro;
return 0;
}
@@ -55,14 +55,15 @@ struct frame *frame_new()
n = calloc(1, sizeof(struct frame));
if ( n == NULL ) return NULL;
- n->rendering_order = NULL;
- n->max_ro = 32;
+ n->children = NULL;
+ n->max_children = 32;
alloc_ro(n);
- n->num_ro = 1;
- n->rendering_order[0] = n;
+ n->num_children = 1;
+ n->children[0] = n;
n->pl = NULL;
+ n->contents = NULL;
return n;
}
@@ -75,12 +76,12 @@ struct frame *add_subframe(struct frame *fr)
n = frame_new();
if ( n == NULL ) return NULL;
- if ( fr->num_ro == fr->max_ro ) {
- fr->max_ro += 32;
+ if ( fr->num_children == fr->max_children ) {
+ fr->max_children += 32;
if ( alloc_ro(fr) ) return NULL;
}
- fr->rendering_order[fr->num_ro++] = n;
+ fr->children[fr->num_children++] = n;
return n;
}
@@ -96,9 +97,9 @@ static void show_heirarchy(struct frame *fr, const char *t)
printf("%s%p %s\n", t, fr, fr->sc);
- for ( i=0; i<fr->num_ro; i++ ) {
- if ( fr->rendering_order[i] != fr ) {
- show_heirarchy(fr->rendering_order[i], tn);
+ for ( i=0; i<fr->num_children; i++ ) {
+ if ( fr->children[i] != fr ) {
+ show_heirarchy(fr->children[i], tn);
} else {
printf("%s<this frame>\n", tn);
}
diff --git a/src/frame.h b/src/frame.h
index 80072a2..25368d0 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -28,6 +28,7 @@
#endif
#include <pango/pango.h>
+#include <cairo.h>
typedef enum
@@ -58,25 +59,29 @@ struct layout_parameters
Direction grav;
+ int use_min_w;
double min_w;
+ int use_min_h;
double min_h;
};
struct frame
{
- struct frame **rendering_order;
- int num_ro;
- int max_ro;
+ struct frame **children;
+ int num_children;
+ int max_children;
char *sc; /* Storycode */
+ cairo_surface_t *contents;
+
struct layout_parameters lop;
struct style *style; /* Non-NULL if 'lop' came from SS */
- /* Location relative to parent, calculated from layout parameters */
- double offs_x;
- double offs_y;
+ /* The rectangle allocated to this frame, determined by the renderer */
+ double x;
+ double y;
double w;
double h;
diff --git a/src/mainwindow.c b/src/mainwindow.c
index a97dd29..3d6a4b1 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -711,8 +711,8 @@ static void draw_editing_box(cairo_t *cr, struct frame *fr)
const double dash[] = {2.0, 2.0};
double xmin, ymin, width, height;
- xmin = fr->offs_x;
- ymin = fr->offs_y;
+ xmin = fr->x;
+ ymin = fr->y;
width = fr->w;
height = fr->h;
diff --git a/src/render.c b/src/render.c
index f67f33b..11b1dc9 100644
--- a/src/render.c
+++ b/src/render.c
@@ -47,9 +47,27 @@ struct renderstuff
PangoFontMap *fontmap;
PangoFont *font;
struct frame *fr;
+ int width;
};
+static void calc_width(gpointer data, gpointer user_data)
+{
+ struct renderstuff *s = user_data;
+ PangoItem *item = data;
+ PangoGlyphString *glyphs;
+ GdkColor col;
+
+ glyphs = pango_glyph_string_new();
+
+ pango_shape(s->fr->sc+item->offset, item->length, &item->analysis,
+ glyphs);
+
+ s->width += pango_glyph_string_get_width(glyphs);
+ pango_glyph_string_free(glyphs);
+}
+
+
static void render_segment(gpointer data, gpointer user_data)
{
struct renderstuff *s = user_data;
@@ -67,17 +85,17 @@ static void render_segment(gpointer data, gpointer user_data)
gdk_cairo_set_source_color(s->cr, &col);
pango_cairo_show_glyph_string(s->cr, s->font, glyphs);
- pango_glyph_string_free(glyphs);
pango_item_free(item);
}
-/* Render Level 1 Storycode */
-int render_sc(struct frame *fr, cairo_t *cr, double w, double h)
+/* Render Level 1 Storycode (no subframes) */
+int render_sc(struct frame *fr, cairo_t *cr, double max_w, double max_h)
{
PangoFontDescription *fontdesc;
struct renderstuff s;
GList *list;
+ double w, h;
if ( fr->sc == NULL ) return 0;
@@ -85,6 +103,12 @@ int render_sc(struct frame *fr, cairo_t *cr, double w, double h)
s.fr = fr;
s.cr = cr;
+ /* If a minimum size is set, start there */
+ if ( fr->lop.use_min_w ) w = fr->lop.min_w;
+ if ( fr->lop.use_min_h ) h = fr->lop.min_h;
+
+ /* FIXME: Handle images as well */
+
/* Find and load font */
s.fontmap = pango_cairo_font_map_get_default();
fontdesc = pango_font_description_from_string("Serif 20");
@@ -96,80 +120,164 @@ int render_sc(struct frame *fr, cairo_t *cr, double w, double h)
/* Create glyph string */
list = pango_itemize(s.pc, fr->sc, 0, strlen(fr->sc), NULL, NULL);
- g_list_foreach(list, render_segment, &s);
- g_list_free(list);
+ s.width = 0;
+ g_list_foreach(list, calc_width, &s);
+
+ /* Determine width */
+ w = s.width;
+ if ( fr->lop.use_min_w && (s.width < fr->lop.min_w) ) {
+ w = fr->lop.min_w;
+ }
+ if ( w > max_w ) w = max_w;
+ h = 20.0;
+ if ( fr->lop.use_min_h && (h < fr->lop.min_h) ) {
+ h = fr->lop.min_h;
+ }
+ if ( h > max_h ) h = max_h;
+
+ if ( fr->contents != NULL ) cairo_surface_destroy(fr->contents);
+ fr->contents = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
+ cr = cairo_create(fr->contents);
+ cairo_rectangle(cr, 0.0, 0.0, w, h);
+ cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+ cairo_fill(cr);
+
+ g_list_free(list);
pango_font_description_free(fontdesc);
g_object_unref(s.pc);
+ fr->w = w;
+ fr->h = h;
+
return 0;
}
-int render_frame(struct frame *fr, cairo_t *cr)
+static void get_max_size(struct frame *fr, struct frame *parent,
+ int this_subframe, double fixed_x, double fixed_y,
+ double parent_max_width, double parent_max_height,
+ double *p_width, double *p_height)
{
+ double w, h;
int i;
- int d = 0;
- /* The rendering order is a list of children, but it also contains the
- * current frame. In this way, it contains information about which
- * layer the current frame is to be rendered as relative to its
- * children. */
- for ( i=0; i<fr->num_ro; i++ ) {
+ w = parent_max_width - parent->lop.pad_l - parent->lop.pad_r;
+ w -= fr->lop.margin_l + fr->lop.margin_r;
- if ( fr->rendering_order[i] == fr ) {
+ h = parent_max_height - parent->lop.pad_t - parent->lop.pad_b;
+ h -= fr->lop.margin_t + fr->lop.margin_b;
- double w, h;
+ for ( i=0; i<this_subframe; i++ ) {
- /* Draw the frame itself (rectangle) */
- cairo_rectangle(cr, 0.0, 0.0, fr->w, fr->h);
+ struct frame *ch;
- if ( (fr->style != NULL)
- && (strcmp(fr->style->name, "Default") == 0) )
- {
- cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);
- } else {
- cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
- }
- cairo_fill_preserve(cr);
- cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ ch = parent->children[i];
- /* if draw_border */
- //cairo_set_line_width(cr, 1.0);
- //cairo_stroke(cr);
+ /* FIXME: Shrink if this frame overlaps */
+ switch ( fr->lop.grav )
+ {
+ case DIR_UL:
+ /* Fix top left corner */
+ break;
- cairo_new_path(cr);
+ case DIR_U:
+ case DIR_UR:
+ case DIR_R:
+ case DIR_DR:
+ case DIR_D:
+ case DIR_DL:
+ case DIR_L:
+ fprintf(stderr, "Gravity not implemented.\n");
+ break;
- /* Set up padding, and then draw the contents */
- w = fr->w - (fr->lop.pad_l + fr->lop.pad_r);
- h = fr->h - (fr->lop.pad_t + fr->lop.pad_b);
+ case DIR_NONE:
+ break;
+ }
+ }
- cairo_move_to(cr, fr->lop.pad_l, fr->lop.pad_t+h);
- render_sc(fr, cr, w, h);
+ *p_width = w;
+ *p_height = h;
+}
- d = 1;
- continue;
- }
+static void position_frame(struct frame *fr, struct frame *parent)
+{
+ double x, y;
+
+ switch ( fr->lop.grav )
+ {
+ case DIR_UL:
+ /* Fix top left corner */
+ x = parent->x + parent->lop.pad_l + fr->lop.margin_l;
+ y = parent->y + parent->lop.pad_t + fr->lop.margin_t;
+ break;
+
+ case DIR_U:
+ case DIR_UR:
+ case DIR_R:
+ case DIR_DR:
+ case DIR_D:
+ case DIR_DL:
+ case DIR_L:
+ fprintf(stderr, "Gravity not implemented.\n");
+ break;
+
+ case DIR_NONE:
+ break;
+ }
- /* Sort out the transformation for the margins */
- cairo_translate(cr, fr->rendering_order[i]->offs_x,
- fr->rendering_order[i]->offs_y);
+ fr->x = x;
+ fr->y = y;
+}
- render_frame(fr->rendering_order[i], cr);
- }
+static int render_frame(struct frame *fr, cairo_t *cr,
+ double max_w, double max_h)
+{
+ int i;
+
+ /* Render all subframes */
+ for ( i=0; i<fr->num_children; i++ ) {
+
+ double x, y, child_max_w, child_max_h;
+
+ /* Determine the maximum possible size this subframe can be */
+ get_max_size(fr->children[i], fr, i, x, y,
+ max_w, max_h, &child_max_w, &child_max_h);
+
+ /* Render it and hence (recursives) find out how much space it
+ * actually needs.*/
+ render_frame(fr->children[i], cr, max_w, max_h);
+
+ /* Position the frame within the parent */
+ position_frame(fr->children[i], fr);
- if ( !d ) {
- fprintf(stderr, "WARNING: Frame didn't appear on its own "
- "rendering list?\n");
}
+ /* Render the actual contents of this frame in the remaining space */
+ render_sc(fr, cr, max_w, max_h);
+
return 0;
}
+static void composite_slide(struct slide *s)
+{
+ int level = 0;
+ int more = 0;
+
+ do {
+
+ int i;
+
+ composite_frames_at_level(s->top, level);
+
+ } while ( more );
+}
+
+
cairo_surface_t *render_slide(struct slide *s, int w, int h)
{
cairo_surface_t *surf;
@@ -195,8 +303,14 @@ cairo_surface_t *render_slide(struct slide *s, int w, int h)
cairo_font_options_set_antialias(fopts, CAIRO_ANTIALIAS_SUBPIXEL);
cairo_set_font_options(cr, fopts);
- printf("rendered to %p %ix%i\n", surf, w, h);
- render_frame(s->top, cr);
+ s->top->lop.min_w = w;
+ s->top->lop.min_h = h;
+ s->top->lop.use_min_w = 1;
+ s->top->lop.use_min_h = 1;
+ render_frame(s->top, cr, w, h);
+ printf("size: %f x %f\n", s->top->w, s->top->h);
+
+ composite_slide(s);
cairo_font_options_destroy(fopts);
cairo_destroy(cr);
diff --git a/src/render.h b/src/render.h
index d2f8388..a390f05 100644
--- a/src/render.h
+++ b/src/render.h
@@ -29,10 +29,6 @@
#include "presentation.h"
-extern int render_sc(struct frame *fr, cairo_t *cr, double w, double h);
-
-extern int render_frame(struct frame *fr, cairo_t *cr);
-
extern cairo_surface_t *render_slide(struct slide *s, int w, int h);
#endif /* RENDER_H */