diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2010-06-14 06:37:27 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2010-06-14 09:31:58 +0800 |
commit | e6972011f01eab9f8d0a4584f32ee1e2a00f3231 (patch) | |
tree | 69e2a5e846965c3b369724b825f5b35c6d88056a /libart_lgpl/art_render_svp.c | |
parent | 7f3377c78a560aa762e04d596b79f847c4acd870 (diff) | |
download | gsoc2013-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.c | 421 |
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); +} |