aboutsummaryrefslogtreecommitdiffstats
path: root/libart_lgpl/art_render_svp.c
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2010-06-14 06:37:27 +0800
committerMatthew Barnes <mbarnes@redhat.com>2010-06-14 09:31:58 +0800
commite6972011f01eab9f8d0a4584f32ee1e2a00f3231 (patch)
tree69e2a5e846965c3b369724b825f5b35c6d88056a /libart_lgpl/art_render_svp.c
parent7f3377c78a560aa762e04d596b79f847c4acd870 (diff)
downloadgsoc2013-evolution-e6972011f01eab9f8d0a4584f32ee1e2a00f3231.tar
gsoc2013-evolution-e6972011f01eab9f8d0a4584f32ee1e2a00f3231.tar.gz
gsoc2013-evolution-e6972011f01eab9f8d0a4584f32ee1e2a00f3231.tar.bz2
gsoc2013-evolution-e6972011f01eab9f8d0a4584f32ee1e2a00f3231.tar.lz
gsoc2013-evolution-e6972011f01eab9f8d0a4584f32ee1e2a00f3231.tar.xz
gsoc2013-evolution-e6972011f01eab9f8d0a4584f32ee1e2a00f3231.tar.zst
gsoc2013-evolution-e6972011f01eab9f8d0a4584f32ee1e2a00f3231.zip
Embed libart_lgpl and libgnomecanvas.
Both of these modules are deprecated and going away in GNOME 3 but we still rely heavily on them for GnomeCalendar and ETable. So, welcome to the island of unwanted libraries...
Diffstat (limited to 'libart_lgpl/art_render_svp.c')
-rw-r--r--libart_lgpl/art_render_svp.c421
1 files changed, 421 insertions, 0 deletions
diff --git a/libart_lgpl/art_render_svp.c b/libart_lgpl/art_render_svp.c
new file mode 100644
index 0000000000..af75b7718e
--- /dev/null
+++ b/libart_lgpl/art_render_svp.c
@@ -0,0 +1,421 @@
+/*
+ * art_render_gradient.c: SVP mask source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien <raph@acm.org>
+ */
+
+#include "art_render_svp.h"
+#include "art_svp_render_aa.h"
+
+typedef struct _ArtMaskSourceSVP ArtMaskSourceSVP;
+
+struct _ArtMaskSourceSVP {
+ ArtMaskSource super;
+ ArtRender *render;
+ const ArtSVP *svp;
+ art_u8 *dest_ptr;
+};
+
+static void
+art_render_svp_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static int
+art_render_svp_can_drive (ArtMaskSource *self, ArtRender *render)
+{
+ return 10;
+}
+
+/* The basic art_render_svp_callback function is repeated four times,
+ for all combinations of non-unit opacity and generating spans. In
+ general, I'd consider this bad style, but in this case I plead
+ a measurable performance improvement. */
+
+static void
+art_render_svp_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+ ArtRender *render = z->render;
+ int n_run = 0;
+ int i;
+ int running_sum = start;
+ int x0 = render->x0;
+ int x1 = render->x1;
+ int run_x0, run_x1;
+ ArtRenderMaskRun *run = render->run;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0 && running_sum > 0x80ff)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ n_run++;
+ }
+
+ for (i = 0; i < n_steps - 1; i++)
+ {
+ running_sum += steps[i].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[i + 1].x;
+ if (run_x1 > run_x0)
+ {
+ run[n_run].x = run_x0;
+ run[n_run].alpha = running_sum;
+ n_run++;
+ }
+ }
+ if (x1 > run_x1)
+ {
+ running_sum += steps[n_steps - 1].delta;
+ run[n_run].x = run_x1;
+ run[n_run].alpha = running_sum;
+ n_run++;
+ }
+ if (running_sum > 0x80ff)
+ {
+ run[n_run].x = x1;
+ run[n_run].alpha = 0x8000;
+ n_run++;
+ }
+ }
+ else if ((running_sum >> 16) > 0)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ run[1].x = x1;
+ run[1].alpha = running_sum;
+ n_run = 2;
+ }
+
+ render->n_run = n_run;
+
+ art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+ z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_callback_span (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+ ArtRender *render = z->render;
+ int n_run = 0;
+ int n_span = 0;
+ int i;
+ int running_sum = start;
+ int x0 = render->x0;
+ int x1 = render->x1;
+ int run_x0, run_x1;
+ ArtRenderMaskRun *run = render->run;
+ int *span_x = render->span_x;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0 && running_sum > 0x80ff)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ n_run++;
+ span_x[0] = x0;
+ n_span++;
+ }
+
+ for (i = 0; i < n_steps - 1; i++)
+ {
+ running_sum += steps[i].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[i + 1].x;
+ if (run_x1 > run_x0)
+ {
+ run[n_run].x = run_x0;
+ run[n_run].alpha = running_sum;
+ n_run++;
+ if ((n_span & 1) != (running_sum > 0x80ff))
+ span_x[n_span++] = run_x0;
+ }
+ }
+ if (x1 > run_x1)
+ {
+ running_sum += steps[n_steps - 1].delta;
+ run[n_run].x = run_x1;
+ run[n_run].alpha = running_sum;
+ n_run++;
+ if ((n_span & 1) != (running_sum > 0x80ff))
+ span_x[n_span++] = run_x1;
+ }
+ if (running_sum > 0x80ff)
+ {
+ run[n_run].x = x1;
+ run[n_run].alpha = 0x8000;
+ n_run++;
+ span_x[n_span++] = x1;
+ }
+ }
+ else if ((running_sum >> 16) > 0)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ run[1].x = x1;
+ run[1].alpha = running_sum;
+ n_run = 2;
+ span_x[0] = x0;
+ span_x[1] = x1;
+ n_span = 2;
+ }
+
+ render->n_run = n_run;
+ render->n_span = n_span;
+
+ art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+ z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_callback_opacity (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+ ArtRender *render = z->render;
+ int n_run = 0;
+ int i;
+ art_u32 running_sum;
+ int x0 = render->x0;
+ int x1 = render->x1;
+ int run_x0, run_x1;
+ ArtRenderMaskRun *run = render->run;
+ art_u32 opacity = render->opacity;
+ art_u32 alpha;
+
+ running_sum = start - 0x7f80;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
+ if (run_x1 > x0 && alpha > 0x80ff)
+ {
+ run[0].x = x0;
+ run[0].alpha = alpha;
+ n_run++;
+ }
+
+ for (i = 0; i < n_steps - 1; i++)
+ {
+ running_sum += steps[i].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[i + 1].x;
+ if (run_x1 > run_x0)
+ {
+ run[n_run].x = run_x0;
+ alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
+ run[n_run].alpha = alpha;
+ n_run++;
+ }
+ }
+ if (x1 > run_x1)
+ {
+ running_sum += steps[n_steps - 1].delta;
+ run[n_run].x = run_x1;
+ alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
+ run[n_run].alpha = alpha;
+ n_run++;
+ }
+ if (alpha > 0x80ff)
+ {
+ run[n_run].x = x1;
+ run[n_run].alpha = 0x8000;
+ n_run++;
+ }
+ }
+ else if ((running_sum >> 16) > 0)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ run[1].x = x1;
+ run[1].alpha = running_sum;
+ n_run = 2;
+ }
+
+ render->n_run = n_run;
+
+ art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+ z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_callback_opacity_span (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+ ArtRender *render = z->render;
+ int n_run = 0;
+ int n_span = 0;
+ int i;
+ art_u32 running_sum;
+ int x0 = render->x0;
+ int x1 = render->x1;
+ int run_x0, run_x1;
+ ArtRenderMaskRun *run = render->run;
+ int *span_x = render->span_x;
+ art_u32 opacity = render->opacity;
+ art_u32 alpha;
+
+ running_sum = start - 0x7f80;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
+ if (run_x1 > x0 && alpha > 0x80ff)
+ {
+ run[0].x = x0;
+ run[0].alpha = alpha;
+ n_run++;
+ span_x[0] = x0;
+ n_span++;
+ }
+
+ for (i = 0; i < n_steps - 1; i++)
+ {
+ running_sum += steps[i].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[i + 1].x;
+ if (run_x1 > run_x0)
+ {
+ run[n_run].x = run_x0;
+ alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
+ run[n_run].alpha = alpha;
+ n_run++;
+ if ((n_span & 1) != (alpha > 0x80ff))
+ span_x[n_span++] = run_x0;
+ }
+ }
+ if (x1 > run_x1)
+ {
+ running_sum += steps[n_steps - 1].delta;
+ run[n_run].x = run_x1;
+ alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
+ run[n_run].alpha = alpha;
+ n_run++;
+ if ((n_span & 1) != (alpha > 0x80ff))
+ span_x[n_span++] = run_x1;
+ }
+ if (alpha > 0x80ff)
+ {
+ run[n_run].x = x1;
+ run[n_run].alpha = 0x8000;
+ n_run++;
+ span_x[n_span++] = x1;
+ }
+ }
+ else if ((running_sum >> 16) > 0)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ run[1].x = x1;
+ run[1].alpha = running_sum;
+ n_run = 2;
+ span_x[0] = x0;
+ span_x[1] = x1;
+ n_span = 2;
+ }
+
+ render->n_run = n_run;
+ render->n_span = n_span;
+
+ art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+ z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_invoke_driver (ArtMaskSource *self, ArtRender *render)
+{
+ ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)self;
+ void (*callback) (void *callback_data,
+ int y,
+ int start,
+ ArtSVPRenderAAStep *steps, int n_steps);
+
+ z->dest_ptr = render->pixels;
+ if (render->opacity == 0x10000)
+ {
+ if (render->need_span)
+ callback = art_render_svp_callback_span;
+ else
+ callback = art_render_svp_callback;
+ }
+ else
+ {
+ if (render->need_span)
+ callback = art_render_svp_callback_opacity_span;
+ else
+ callback = art_render_svp_callback_opacity;
+ }
+
+ art_svp_render_aa (z->svp,
+ render->x0, render->y0,
+ render->x1, render->y1, callback,
+ self);
+ art_render_svp_done (&self->super, render);
+}
+
+G_GNUC_NORETURN static void
+art_render_svp_prepare (ArtMaskSource *self, ArtRender *render,
+ art_boolean first)
+{
+ /* todo */
+ art_die ("art_render_svp non-driver mode not yet implemented.\n");
+}
+
+/**
+ * art_render_svp: Use an SVP as a render mask source.
+ * @render: Render object.
+ * @svp: SVP.
+ *
+ * Adds @svp to the render object as a mask. Note: @svp must remain
+ * allocated until art_render_invoke() is called on @render.
+ **/
+void
+art_render_svp (ArtRender *render, const ArtSVP *svp)
+{
+ ArtMaskSourceSVP *mask_source;
+ mask_source = art_new (ArtMaskSourceSVP, 1);
+
+ mask_source->super.super.render = NULL;
+ mask_source->super.super.done = art_render_svp_done;
+ mask_source->super.can_drive = art_render_svp_can_drive;
+ mask_source->super.invoke_driver = art_render_svp_invoke_driver;
+ mask_source->super.prepare = art_render_svp_prepare;
+ mask_source->render = render;
+ mask_source->svp = svp;
+
+ art_render_add_mask_source (render, &mask_source->super);
+}