renderer interface cleanup
[geeqie.git] / src / pixbuf-renderer.c
index ce60bff..341a25b 100644 (file)
@@ -930,8 +930,8 @@ static void pr_scroller_stop(PixbufRenderer *pr)
 
 static void pr_border_clear(PixbufRenderer *pr)
 {
-       pr->renderer->border_draw(pr->renderer, 0, 0, pr->viewport_width, pr->viewport_height);
-       if (pr->renderer2) pr->renderer2->border_draw(pr->renderer2, 0, 0, pr->viewport_width, pr->viewport_height);
+       pr->renderer->border_clear(pr->renderer);
+       if (pr->renderer2) pr->renderer2->border_clear(pr->renderer2);
 }
 
 void pixbuf_renderer_set_color(PixbufRenderer *pr, GdkColor *color)
@@ -969,10 +969,10 @@ void pixbuf_renderer_set_color(PixbufRenderer *pr, GdkColor *color)
 static void pr_redraw(PixbufRenderer *pr, gboolean new_data)
 {
        pr->renderer->queue_clear(pr->renderer);
-       pr->renderer->queue(pr->renderer, 0, 0, pr->width, pr->height, TRUE, TILE_RENDER_ALL, new_data, FALSE);
+       pr->renderer->redraw(pr->renderer, 0, 0, pr->width, pr->height, TRUE, TILE_RENDER_ALL, new_data, FALSE);
        if (pr->renderer2) {
                pr->renderer2->queue_clear(pr->renderer2);
-               pr->renderer2->queue(pr->renderer2, 0, 0, pr->width, pr->height, TRUE, TILE_RENDER_ALL, new_data, FALSE);
+               pr->renderer2->redraw(pr->renderer2, 0, 0, pr->width, pr->height, TRUE, TILE_RENDER_ALL, new_data, FALSE);
        }
 }
 
@@ -1958,23 +1958,11 @@ static void pixbuf_renderer_paint(PixbufRenderer *pr, GdkRectangle *area)
 {
        gint x, y;
 
-
-       x = MAX(0, (gint)area->x - pr->x_offset + pr->x_scroll);
-       y = MAX(0, (gint)area->y - pr->y_offset + pr->y_scroll);
-
-       pr->renderer->border_draw(pr->renderer, area->x, area->y, area->width, area->height);
-       pr->renderer->queue(pr->renderer,
-                             x, y,
-                             MIN((gint)area->width, pr->width - x),
-                             MIN((gint)area->height, pr->height - y),
+       pr->renderer->redraw(pr->renderer, area->x, area->y, area->width, area->height,
                              FALSE, TILE_RENDER_ALL, FALSE, FALSE);
        if (pr->renderer2) 
                {
-               pr->renderer2->border_draw(pr->renderer2, area->x, area->y, area->width, area->height);
-               pr->renderer2->queue(pr->renderer2,
-                             x, y,
-                             MIN((gint)area->width, pr->width - x),
-                             MIN((gint)area->height, pr->height - y),
+               pr->renderer2->redraw(pr->renderer2, area->x, area->y, area->width, area->height,
                              FALSE, TILE_RENDER_ALL, FALSE, FALSE);
                }
 }
@@ -2272,7 +2260,7 @@ static void pr_signals_connect(PixbufRenderer *pr)
  */
 
 #define COLOR_BYTES 3   /* rgb */
-void pr_create_anaglyph(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
+static void pr_create_anaglyph_RC(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
 {
        gint srs, drs;
        guchar *s_pix, *d_pix;
@@ -2300,8 +2288,95 @@ void pr_create_anaglyph(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gin
                        }
                }
 }
+
+static void pr_create_anaglyph_gray(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
+{
+       gint srs, drs;
+       guchar *s_pix, *d_pix;
+       guchar *sp, *dp;
+       guchar *spi, *dpi;
+       gint i, j;
+       const double gc[3] = {0.299, 0.587, 0.114};
+
+       srs = gdk_pixbuf_get_rowstride(right);
+       s_pix = gdk_pixbuf_get_pixels(right);
+       spi = s_pix + (x * COLOR_BYTES);
+
+       drs = gdk_pixbuf_get_rowstride(pixbuf);
+       d_pix = gdk_pixbuf_get_pixels(pixbuf);
+       dpi =  d_pix + x * COLOR_BYTES;
+
+       for (i = y; i < y + h; i++)
+               {
+               sp = spi + (i * srs);
+               dp = dpi + (i * drs);
+               for (j = 0; j < w; j++)
+                       {
+                       guchar g1 = dp[0] * gc[0] + dp[1] * gc[1] + dp[2] * gc[2];
+                       guchar g2 = sp[0] * gc[0] + sp[1] * gc[1] + sp[2] * gc[2];
+                       dp[0] = g2; /* red channel from sp */
+                       dp[1] = g1; /* green and blue from dp */
+                       dp[2] = g1;
+                       sp += COLOR_BYTES;
+                       dp += COLOR_BYTES;
+                       }
+               }
+}
+
+const double pr_dubois_matrix[3][6] = {
+       { 0.456,  0.500,  0.176, -0.043, -0.088, -0.002},
+       {-0.040, -0.038, -0.016,  0.378,  0.734, -0.018},
+       {-0.015, -0.021, -0.005, -0.072, -0.113,  1.226}
+       }; 
+
+static void pr_create_anaglyph_dubois(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
+{
+       gint srs, drs;
+       guchar *s_pix, *d_pix;
+       guchar *sp, *dp;
+       guchar *spi, *dpi;
+       gint i, j, k;
+
+       srs = gdk_pixbuf_get_rowstride(right);
+       s_pix = gdk_pixbuf_get_pixels(right);
+       spi = s_pix + (x * COLOR_BYTES);
+
+       drs = gdk_pixbuf_get_rowstride(pixbuf);
+       d_pix = gdk_pixbuf_get_pixels(pixbuf);
+       dpi =  d_pix + x * COLOR_BYTES;
+
+       for (i = y; i < y + h; i++)
+               {
+               sp = spi + (i * srs);
+               dp = dpi + (i * drs);
+               for (j = 0; j < w; j++)
+                       {
+                       double res[3];
+                       for (k = 0; k < 3; k++) 
+                               {
+                               double *m = pr_dubois_matrix[k];
+                               res[k] = sp[0] * m[0] + sp[1] * m[1] + sp[2] * m[2] + dp[0] * m[3] + dp[1] * m[4] + dp[2] * m[5];
+                               if (res[k] < 0.0) res[k] = 0;
+                               if (res[k] > 255.0) res[k] = 255.0;
+                               }
+                       dp[0] = res[0];
+                       dp[1] = res[1];
+                       dp[2] = res[2];
+                       sp += COLOR_BYTES;
+                       dp += COLOR_BYTES;
+                       }
+               }
+}
  
+void pr_create_anaglyph(guint mode, GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
+{
+       if (mode & PR_STEREO_ANAGLYPH_RC)
+               pr_create_anaglyph_RC(pixbuf, right, x, y, w, h);
+       else if (mode & PR_STEREO_ANAGLYPH_GRAY)
+               pr_create_anaglyph_gray(pixbuf, right, x, y, w, h);
+       else if (mode & PR_STEREO_ANAGLYPH_DB)
+               pr_create_anaglyph_dubois(pixbuf, right, x, y, w, h);
+}
 
 /*
  *-------------------------------------------------------------------
@@ -2516,38 +2591,17 @@ void pixbuf_renderer_move(PixbufRenderer *pr, PixbufRenderer *source)
 //     pr_tile_free_all(source);
 }
 
-void pixbuf_renderer_area_changed(PixbufRenderer *pr, gint src_x, gint src_y, gint src_w, gint src_h)
+void pixbuf_renderer_area_changed(PixbufRenderer *pr, gint x, gint y, gint w, gint h)
 {
-       gint x, y, width, height,  x1, y1, x2, y2;
-
        g_return_if_fail(IS_PIXBUF_RENDERER(pr));
 
-       pr_coords_map_orientation_reverse(pr->orientation,
-                                    src_x, src_y,
-                                    pr->image_width, pr->image_height,
-                                    src_w, src_h,
-                                    &x, &y,
-                                    &width, &height);
-
        if (pr->source_tiles_enabled)
                {
-               pr_source_tile_changed(pr, x, y, width, height);
+               pr_source_tile_changed(pr, x, y, w, h);
                }
 
-       if (pr->scale != 1.0 && pr->zoom_quality != GDK_INTERP_NEAREST)
-               {
-               /* increase region when using a zoom quality that may access surrounding pixels */
-               y -= 1;
-               height += 2;
-               }
-
-       x1 = (gint)floor((gdouble)x * pr->scale);
-       y1 = (gint)floor((gdouble)y * pr->scale * pr->aspect_ratio);
-       x2 = (gint)ceil((gdouble)(x + width) * pr->scale);
-       y2 = (gint)ceil((gdouble)(y + height) * pr->scale * pr->aspect_ratio);
-
-       pr->renderer->queue(pr->renderer, x1, y1, x2 - x1, y2 - y1, FALSE, TILE_RENDER_AREA, TRUE, TRUE);
-       if (pr->renderer2) pr->renderer2->queue(pr->renderer2, x1, y1, x2 - x1, y2 - y1, FALSE, TILE_RENDER_AREA, TRUE, TRUE);
+       pr->renderer->area_changed(pr->renderer, x, y, w, h);
+       if (pr->renderer2) pr->renderer2->area_changed(pr->renderer2, x, y, w, h);
 }
 
 void pixbuf_renderer_zoom_adjust(PixbufRenderer *pr, gdouble increment)
@@ -2621,6 +2675,16 @@ static void pr_stereo_set(PixbufRenderer *pr)
                if (pr->renderer2) pr->renderer2->free(pr->renderer2);
                pr->renderer2 = NULL;
                }
+       if (pr->stereo_mode & PR_STEREO_HALF)
+               {
+               if (pr->stereo_mode & PR_STEREO_HORIZ) pr->aspect_ratio = 2.0;
+               else if (pr->stereo_mode & PR_STEREO_VERT) pr->aspect_ratio = 0.5;
+               else pr->aspect_ratio = 1.0;
+               }
+       else
+               {
+               pr->aspect_ratio = 1.0;
+               }
 }
 
 void pixbuf_renderer_stereo_set(PixbufRenderer *pr, gint stereo_mode)
@@ -2665,6 +2729,7 @@ static void pr_stereo_temp_disable(PixbufRenderer *pr, gboolean disable)
                pr->renderer->stereo_set(pr->renderer, PR_STEREO_NONE);
                if (pr->renderer2) pr->renderer2->free(pr->renderer2);
                pr->renderer2 = NULL;
+               pr->aspect_ratio = 1.0;
                }
        else
                {