diff options
Diffstat (limited to 'render/gradient.c')
| -rw-r--r-- | render/gradient.c | 836 |
1 files changed, 0 insertions, 836 deletions
diff --git a/render/gradient.c b/render/gradient.c deleted file mode 100644 index 60a0a555..00000000 --- a/render/gradient.c +++ /dev/null @@ -1,836 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - gradient.c for the Openbox window manager - Copyright (c) 2006 Mikael Magnusson - Copyright (c) 2003-2008 Dana Jansens - Copyright (c) 2003 Derek Foreman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - See the COPYING file for a copy of the GNU General Public License. -*/ - -#include "render.h" -#include "gradient.h" -#include "color.h" -#include <glib.h> -#include <string.h> - -static void highlight(RrSurface *s, RrPixel32 *x, RrPixel32 *y, - gboolean raised); -static void gradient_parentrelative(RrAppearance *a, gint w, gint h); -static void gradient_solid(RrAppearance *l, gint w, gint h); -static void gradient_splitvertical(RrAppearance *a, gint w, gint h); -static void gradient_vertical(RrSurface *sf, gint w, gint h); -static void gradient_horizontal(RrSurface *sf, gint w, gint h); -static void gradient_mirrorhorizontal(RrSurface *sf, gint w, gint h); -static void gradient_diagonal(RrSurface *sf, gint w, gint h); -static void gradient_crossdiagonal(RrSurface *sf, gint w, gint h); -static void gradient_pyramid(RrSurface *sf, gint inw, gint inh); - -void RrRender(RrAppearance *a, gint w, gint h) -{ - RrPixel32 *data = a->surface.pixel_data; - RrPixel32 current; - guint r,g,b; - register gint off, x; - - switch (a->surface.grad) { - case RR_SURFACE_PARENTREL: - gradient_parentrelative(a, w, h); - break; - case RR_SURFACE_SOLID: - gradient_solid(a, w, h); - break; - case RR_SURFACE_SPLIT_VERTICAL: - gradient_splitvertical(a, w, h); - break; - case RR_SURFACE_VERTICAL: - gradient_vertical(&a->surface, w, h); - break; - case RR_SURFACE_HORIZONTAL: - gradient_horizontal(&a->surface, w, h); - break; - case RR_SURFACE_MIRROR_HORIZONTAL: - gradient_mirrorhorizontal(&a->surface, w, h); - break; - case RR_SURFACE_DIAGONAL: - gradient_diagonal(&a->surface, w, h); - break; - case RR_SURFACE_CROSS_DIAGONAL: - gradient_crossdiagonal(&a->surface, w, h); - break; - case RR_SURFACE_PYRAMID: - gradient_pyramid(&a->surface, w, h); - break; - default: - g_assert_not_reached(); /* unhandled gradient */ - return; - } - - if (a->surface.interlaced) { - gint i; - RrPixel32 *p; - - r = a->surface.interlace_color->r; - g = a->surface.interlace_color->g; - b = a->surface.interlace_color->b; - current = (r << RrDefaultRedOffset) - + (g << RrDefaultGreenOffset) - + (b << RrDefaultBlueOffset); - p = data; - for (i = 0; i < h; i += 2, p += w) - for (x = 0; x < w; ++x, ++p) - *p = current; - } - - if (a->surface.relief == RR_RELIEF_FLAT && a->surface.border) { - r = a->surface.border_color->r; - g = a->surface.border_color->g; - b = a->surface.border_color->b; - current = (r << RrDefaultRedOffset) - + (g << RrDefaultGreenOffset) - + (b << RrDefaultBlueOffset); - for (off = 0, x = 0; x < w; ++x, off++) { - *(data + off) = current; - *(data + off + ((h-1) * w)) = current; - } - for (off = 0, x = 0; x < h; ++x, off++) { - *(data + (off * w)) = current; - *(data + (off * w) + w - 1) = current; - } - } - - if (a->surface.relief != RR_RELIEF_FLAT) { - if (a->surface.bevel == RR_BEVEL_1) { - for (off = 1, x = 1; x < w - 1; ++x, off++) - highlight(&a->surface, data + off, - data + off + (h-1) * w, - a->surface.relief==RR_RELIEF_RAISED); - for (off = 0, x = 0; x < h; ++x, off++) - highlight(&a->surface, data + off * w, - data + off * w + w - 1, - a->surface.relief==RR_RELIEF_RAISED); - } - - if (a->surface.bevel == RR_BEVEL_2) { - for (off = 2, x = 2; x < w - 2; ++x, off++) - highlight(&a->surface, data + off + w, - data + off + (h-2) * w, - a->surface.relief==RR_RELIEF_RAISED); - for (off = 1, x = 1; x < h-1; ++x, off++) - highlight(&a->surface, data + off * w + 1, - data + off * w + w - 2, - a->surface.relief==RR_RELIEF_RAISED); - } - } -} - -static void highlight(RrSurface *s, RrPixel32 *x, RrPixel32 *y, gboolean raised) -{ - register gint r, g, b; - - RrPixel32 *up, *down; - if (raised) { - up = x; - down = y; - } else { - up = y; - down = x; - } - - r = (*up >> RrDefaultRedOffset) & 0xFF; - r += (r * s->bevel_light_adjust) >> 8; - g = (*up >> RrDefaultGreenOffset) & 0xFF; - g += (g * s->bevel_light_adjust) >> 8; - b = (*up >> RrDefaultBlueOffset) & 0xFF; - b += (b * s->bevel_light_adjust) >> 8; - if (r > 0xFF) r = 0xFF; - if (g > 0xFF) g = 0xFF; - if (b > 0xFF) b = 0xFF; - *up = (r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) - + (b << RrDefaultBlueOffset); - - r = (*down >> RrDefaultRedOffset) & 0xFF; - r -= (r * s->bevel_dark_adjust) >> 8; - g = (*down >> RrDefaultGreenOffset) & 0xFF; - g -= (g * s->bevel_dark_adjust) >> 8; - b = (*down >> RrDefaultBlueOffset) & 0xFF; - b -= (b * s->bevel_dark_adjust) >> 8; - *down = (r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) - + (b << RrDefaultBlueOffset); -} - -static void create_bevel_colors(RrAppearance *l) -{ - register gint r, g, b; - - /* light color */ - r = l->surface.primary->r; - r += (r * l->surface.bevel_light_adjust) >> 8; - g = l->surface.primary->g; - g += (g * l->surface.bevel_light_adjust) >> 8; - b = l->surface.primary->b; - b += (b * l->surface.bevel_light_adjust) >> 8; - if (r > 0xFF) r = 0xFF; - if (g > 0xFF) g = 0xFF; - if (b > 0xFF) b = 0xFF; - g_assert(!l->surface.bevel_light); - l->surface.bevel_light = RrColorNew(l->inst, r, g, b); - - /* dark color */ - r = l->surface.primary->r; - r -= (r * l->surface.bevel_dark_adjust) >> 8; - g = l->surface.primary->g; - g -= (g * l->surface.bevel_dark_adjust) >> 8; - b = l->surface.primary->b; - b -= (b * l->surface.bevel_dark_adjust) >> 8; - g_assert(!l->surface.bevel_dark); - l->surface.bevel_dark = RrColorNew(l->inst, r, g, b); -} - -/*! Repeat the first pixel over the entire block of memory - @param start The block of memory. start[0] will be copied - to the rest of the block. - @param w The width of the block of memory (including the already-set first - element -*/ -static inline void repeat_pixel(RrPixel32 *start, gint w) -{ - register gint x; - RrPixel32 *dest; - - dest = start + 1; - - /* for really small things, just copy ourselves */ - if (w < 8) { - for (x = w-1; x > 0; --x) - *(dest++) = *start; - } - - /* for >= 8, then use O(log n) memcpy's... */ - else { - gchar *cdest; - gint lenbytes; - - /* copy the first 3 * 32 bits (3 words) ourselves - then we have - 3 + the original 1 = 4 words to make copies of at a time - - this is faster than doing memcpy for 1 or 2 words at a time - */ - for (x = 3; x > 0; --x) - *(dest++) = *start; - - /* cdest is a pointer to the pixel data that is typed char* so that - adding 1 to its position moves it only one byte - - lenbytes is the amount of bytes that we will be copying each - iteration. this doubles each time through the loop. - - x is the number of bytes left to copy into. lenbytes will alwaysa - be bounded by x - - this loop will run O(log n) times (n is the number of bytes we - need to copy into), since the size of the copy is doubled each - iteration. it seems that gcc does some nice optimizations to make - this memcpy very fast on hardware with support for vector operations - such as mmx or see. here is an idea of the kind of speed up we are - getting by doing this (splitvertical3 switches from doing - "*(data++) = color" n times to doing this memcpy thing log n times: - - % cumulative self self total - time seconds seconds calls ms/call ms/call name - 49.44 0.88 0.88 1063 0.83 0.83 splitvertical1 - 47.19 1.72 0.84 1063 0.79 0.79 splitvertical2 - 2.81 1.77 0.05 1063 0.05 0.05 splitvertical3 - */ - cdest = (gchar*)dest; - lenbytes = 4 * sizeof(RrPixel32); - for (x = (w - 4) * sizeof(RrPixel32); x > 0;) { - memcpy(cdest, start, lenbytes); - x -= lenbytes; - cdest += lenbytes; - lenbytes <<= 1; - if (lenbytes > x) - lenbytes = x; - } - } -} - -static void gradient_parentrelative(RrAppearance *a, gint w, gint h) -{ - RrPixel32 *source, *dest; - gint sw, sh, partial_w, partial_h; - register gint i; - - g_assert (a->surface.parent); - g_assert (a->surface.parent->w); - - sw = a->surface.parent->w; - sh = a->surface.parent->h; - - /* This is a little hack. When a texture is parentrelative, and the same - area as the parent, and has a bevel, it will draw its bevel on top - of the parent's, amplifying it. So instead, rerender the child with - the parent's settings, but the child's bevel and interlace */ - if (a->surface.relief != RR_RELIEF_FLAT && - (a->surface.parent->surface.relief != RR_RELIEF_FLAT || - a->surface.parent->surface.border) && - !a->surface.parentx && !a->surface.parenty && - sw == w && sh == h) - { - RrSurface old = a->surface; - a->surface = a->surface.parent->surface; - - /* turn these off for the parent */ - a->surface.relief = RR_RELIEF_FLAT; - a->surface.border = FALSE; - - a->surface.pixel_data = old.pixel_data; - - RrRender(a, w, h); - a->surface = old; - } else { - source = (a->surface.parent->surface.pixel_data + - a->surface.parentx + sw * a->surface.parenty); - dest = a->surface.pixel_data; - - if (a->surface.parentx + w > sw) { - partial_w = sw - a->surface.parentx; - } else partial_w = w; - - if (a->surface.parenty + h > sh) { - partial_h = sh - a->surface.parenty; - } else partial_h = h; - - for (i = 0; i < partial_h; i++, source += sw, dest += w) { - memcpy(dest, source, partial_w * sizeof(RrPixel32)); - } - } -} - -static void gradient_solid(RrAppearance *l, gint w, gint h) -{ - register gint i; - RrPixel32 pix; - RrPixel32 *data = l->surface.pixel_data; - RrSurface *sp = &l->surface; - gint left = 0, top = 0, right = w - 1, bottom = h - 1; - - pix = (sp->primary->r << RrDefaultRedOffset) - + (sp->primary->g << RrDefaultGreenOffset) - + (sp->primary->b << RrDefaultBlueOffset); - - for (i = 0; i < w * h; i++) - *data++ = pix; - - if (sp->interlaced) - return; - - XFillRectangle(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->primary), - 0, 0, w, h); - - switch (sp->relief) { - case RR_RELIEF_RAISED: - if (!sp->bevel_dark) - create_bevel_colors(l); - - switch (sp->bevel) { - case RR_BEVEL_1: - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left, bottom, right, bottom); - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - right, bottom, right, top); - - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left, top, right, top); - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left, bottom, left, top); - break; - case RR_BEVEL_2: - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left + 2, bottom - 1, right - 2, bottom - 1); - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - right - 1, bottom - 1, right - 1, top + 1); - - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left + 2, top + 1, right - 2, top + 1); - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left + 1, bottom - 1, left + 1, top + 1); - break; - default: - g_assert_not_reached(); /* unhandled BevelType */ - } - break; - case RR_RELIEF_SUNKEN: - if (!sp->bevel_dark) - create_bevel_colors(l); - - switch (sp->bevel) { - case RR_BEVEL_1: - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left, bottom, right, bottom); - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - right, bottom, right, top); - - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left, top, right, top); - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left, bottom, left, top); - break; - case RR_BEVEL_2: - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - left + 2, bottom - 1, right - 2, bottom - 1); - XDrawLine(RrDisplay(l->inst), l->pixmap,RrColorGC(sp->bevel_light), - right - 1, bottom - 1, right - 1, top + 1); - - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left + 2, top + 1, right - 2, top + 1); - XDrawLine(RrDisplay(l->inst), l->pixmap, RrColorGC(sp->bevel_dark), - left + 1, bottom - 1, left + 1, top + 1); - break; - default: - g_assert_not_reached(); /* unhandled BevelType */ - } - break; - case RR_RELIEF_FLAT: - if (sp->border) { - XDrawRectangle(RrDisplay(l->inst), l->pixmap, - RrColorGC(sp->border_color), - left, top, right, bottom); - } - break; - default: - g_assert_not_reached(); /* unhandled ReliefType */ - } -} - -/* * * * * * * * * * * * * * GRADIENT MAGIC WOOT * * * * * * * * * * * * * * */ - -#define VARS(x) \ - register gint len##x; \ - guint color##x[3]; \ - gint cdelta##x[3], error##x[3] = { 0, 0, 0 }, inc##x[3]; \ - gboolean bigslope##x[3] /* color slope > 1 */ - -#define SETUP(x, from, to, w) \ - len##x = w; \ - \ - color##x[0] = from->r; \ - color##x[1] = from->g; \ - color##x[2] = from->b; \ - \ - cdelta##x[0] = to->r - from->r; \ - cdelta##x[1] = to->g - from->g; \ - cdelta##x[2] = to->b - from->b; \ - \ - if (cdelta##x[0] < 0) { \ - cdelta##x[0] = -cdelta##x[0]; \ - inc##x[0] = -1; \ - } else \ - inc##x[0] = 1; \ - if (cdelta##x[1] < 0) { \ - cdelta##x[1] = -cdelta##x[1]; \ - inc##x[1] = -1; \ - } else \ - inc##x[1] = 1; \ - if (cdelta##x[2] < 0) { \ - cdelta##x[2] = -cdelta##x[2]; \ - inc##x[2] = -1; \ - } else \ - inc##x[2] = 1; \ - bigslope##x[0] = cdelta##x[0] > w;\ - bigslope##x[1] = cdelta##x[1] > w;\ - bigslope##x[2] = cdelta##x[2] > w - -#define COLOR_RR(x, c) \ - c->r = color##x[0]; \ - c->g = color##x[1]; \ - c->b = color##x[2] - -#define COLOR(x) \ - ((color##x[0] << RrDefaultRedOffset) + \ - (color##x[1] << RrDefaultGreenOffset) + \ - (color##x[2] << RrDefaultBlueOffset)) - -#define INCREMENT(x, i) \ - (inc##x[i]) - -#define NEXT(x) \ -{ \ - register gint i; \ - for (i = 2; i >= 0; --i) { \ - if (!cdelta##x[i]) continue; \ - \ - if (!bigslope##x[i]) { \ - /* Y (color) is dependant on X */ \ - error##x[i] += cdelta##x[i]; \ - if ((error##x[i] << 1) >= len##x) { \ - color##x[i] += INCREMENT(x, i); \ - error##x[i] -= len##x; \ - } \ - } else { \ - /* X is dependant on Y (color) */ \ - while (1) { \ - color##x[i] += INCREMENT(x, i); \ - error##x[i] += len##x; \ - if ((error##x[i] << 1) >= cdelta##x[i]) { \ - error##x[i] -= cdelta##x[i]; \ - break; \ - } \ - } \ - } \ - } \ -} - -static void gradient_splitvertical(RrAppearance *a, gint w, gint h) -{ - register gint y1, y2, y3; - RrSurface *sf = &a->surface; - RrPixel32 *data; - register gint y1sz, y2sz, y3sz; - - VARS(y1); - VARS(y2); - VARS(y3); - - /* if h <= 5, then a 0 or 1px middle gradient. - if h > 5, then always a 1px middle gradient. - */ - if (h <= 5) { - y1sz = MAX(h/2, 0); - y2sz = (h < 3) ? 0 : (h & 1); - y3sz = MAX(h/2, 1); - } - else { - y1sz = h/2 - (1 - (h & 1)); - y2sz = 1; - y3sz = h/2; - } - - SETUP(y1, sf->split_primary, sf->primary, y1sz); - if (y2sz) { - /* setup to get the colors _in between_ these other 2 */ - SETUP(y2, sf->primary, sf->secondary, y2sz + 2); - NEXT(y2); /* skip the first one, its the same as the last of y1 */ - } - SETUP(y3, sf->secondary, sf->split_secondary, y3sz); - - /* find the color for the first pixel of each row first */ - data = sf->pixel_data; - - for (y1 = y1sz-1; y1 > 0; --y1) { - *data = COLOR(y1); - data += w; - NEXT(y1); - } - *data = COLOR(y1); - data += w; - if (y2sz) { - for (y2 = y2sz-1; y2 > 0; --y2) { - *data = COLOR(y2); - data += w; - NEXT(y2); - } - *data = COLOR(y2); - data += w; - } - for (y3 = y3sz-1; y3 > 0; --y3) { - *data = COLOR(y3); - data += w; - NEXT(y3); - } - *data = COLOR(y3); - - /* copy the first pixels into the whole rows */ - data = sf->pixel_data; - for (y1 = h; y1 > 0; --y1) { - repeat_pixel(data, w); - data += w; - } -} - -static void gradient_horizontal(RrSurface *sf, gint w, gint h) -{ - register gint x, y, cpbytes; - RrPixel32 *data = sf->pixel_data, *datav; - gchar *datac; - - VARS(x); - SETUP(x, sf->primary, sf->secondary, w); - - /* set the color values for the first row */ - datav = data; - for (x = w - 1; x > 0; --x) { /* 0 -> w - 1 */ - *datav = COLOR(x); - ++datav; - NEXT(x); - } - *datav = COLOR(x); - ++datav; - - /* copy the first row to the rest in O(logn) copies */ - datac = (gchar*)datav; - cpbytes = 1 * w * sizeof(RrPixel32); - for (y = (h - 1) * w * sizeof(RrPixel32); y > 0;) { - memcpy(datac, data, cpbytes); - y -= cpbytes; - datac += cpbytes; - cpbytes <<= 1; - if (cpbytes > y) - cpbytes = y; - } -} - -static void gradient_mirrorhorizontal(RrSurface *sf, gint w, gint h) -{ - register gint x, y, half1, half2, cpbytes; - RrPixel32 *data = sf->pixel_data, *datav; - gchar *datac; - - VARS(x); - - half1 = (w + 1) / 2; - half2 = w / 2; - - /* set the color values for the first row */ - - SETUP(x, sf->primary, sf->secondary, half1); - datav = data; - for (x = half1 - 1; x > 0; --x) { /* 0 -> half1 - 1 */ - *datav = COLOR(x); - ++datav; - NEXT(x); - } - *datav = COLOR(x); - ++datav; - - if (half2 > 0) { - SETUP(x, sf->secondary, sf->primary, half2); - for (x = half2 - 1; x > 0; --x) { /* 0 -> half2 - 1 */ - *datav = COLOR(x); - ++datav; - NEXT(x); - } - *datav = COLOR(x); - ++datav; - } - - /* copy the first row to the rest in O(logn) copies */ - datac = (gchar*)datav; - cpbytes = 1 * w * sizeof(RrPixel32); - for (y = (h - 1) * w * sizeof(RrPixel32); y > 0;) { - memcpy(datac, data, cpbytes); - y -= cpbytes; - datac += cpbytes; - cpbytes <<= 1; - if (cpbytes > y) - cpbytes = y; - } -} - -static void gradient_vertical(RrSurface *sf, gint w, gint h) -{ - register gint y; - RrPixel32 *data; - - VARS(y); - SETUP(y, sf->primary, sf->secondary, h); - - /* find the color for the first pixel of each row first */ - data = sf->pixel_data; - - for (y = h - 1; y > 0; --y) { /* 0 -> h-1 */ - *data = COLOR(y); - data += w; - NEXT(y); - } - *data = COLOR(y); - - /* copy the first pixels into the whole rows */ - data = sf->pixel_data; - for (y = h; y > 0; --y) { - repeat_pixel(data, w); - data += w; - } -} - -static void gradient_diagonal(RrSurface *sf, gint w, gint h) -{ - register gint x, y; - RrPixel32 *data = sf->pixel_data; - RrColor left, right; - RrColor extracorner; - - VARS(lefty); - VARS(righty); - VARS(x); - - extracorner.r = (sf->primary->r + sf->secondary->r) / 2; - extracorner.g = (sf->primary->g + sf->secondary->g) / 2; - extracorner.b = (sf->primary->b + sf->secondary->b) / 2; - - SETUP(lefty, sf->primary, (&extracorner), h); - SETUP(righty, (&extracorner), sf->secondary, h); - - for (y = h - 1; y > 0; --y) { /* 0 -> h-1 */ - COLOR_RR(lefty, (&left)); - COLOR_RR(righty, (&right)); - - SETUP(x, (&left), (&right), w); - - for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ - *(data++) = COLOR(x); - - NEXT(x); - } - *(data++) = COLOR(x); - - NEXT(lefty); - NEXT(righty); - } - COLOR_RR(lefty, (&left)); - COLOR_RR(righty, (&right)); - - SETUP(x, (&left), (&right), w); - - for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ - *(data++) = COLOR(x); - - NEXT(x); - } - *data = COLOR(x); -} - -static void gradient_crossdiagonal(RrSurface *sf, gint w, gint h) -{ - register gint x, y; - RrPixel32 *data = sf->pixel_data; - RrColor left, right; - RrColor extracorner; - - VARS(lefty); - VARS(righty); - VARS(x); - - extracorner.r = (sf->primary->r + sf->secondary->r) / 2; - extracorner.g = (sf->primary->g + sf->secondary->g) / 2; - extracorner.b = (sf->primary->b + sf->secondary->b) / 2; - - SETUP(lefty, (&extracorner), sf->secondary, h); - SETUP(righty, sf->primary, (&extracorner), h); - - for (y = h - 1; y > 0; --y) { /* 0 -> h-1 */ - COLOR_RR(lefty, (&left)); - COLOR_RR(righty, (&right)); - - SETUP(x, (&left), (&right), w); - - for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ - *(data++) = COLOR(x); - - NEXT(x); - } - *(data++) = COLOR(x); - - NEXT(lefty); - NEXT(righty); - } - COLOR_RR(lefty, (&left)); - COLOR_RR(righty, (&right)); - - SETUP(x, (&left), (&right), w); - - for (x = w - 1; x > 0; --x) { /* 0 -> w-1 */ - *(data++) = COLOR(x); - - NEXT(x); - } - *data = COLOR(x); -} - -static void gradient_pyramid(RrSurface *sf, gint w, gint h) -{ - RrPixel32 *ldata, *rdata; - RrPixel32 *cp; - RrColor left, right; - RrColor extracorner; - register gint x, y, halfw, halfh, midx, midy; - - VARS(lefty); - VARS(righty); - VARS(x); - - extracorner.r = (sf->primary->r + sf->secondary->r) / 2; - extracorner.g = (sf->primary->g + sf->secondary->g) / 2; - extracorner.b = (sf->primary->b + sf->secondary->b) / 2; - - halfw = w >> 1; - halfh = h >> 1; - midx = w - halfw - halfw; /* 0 or 1, depending if w is even or odd */ - midy = h - halfh - halfh; /* 0 or 1, depending if h is even or odd */ - - SETUP(lefty, sf->primary, (&extracorner), halfh + midy); - SETUP(righty, (&extracorner), sf->secondary, halfh + midy); - - /* draw the top half - - it is faster to draw both top quarters together than to draw one and - then copy it over to the other side. - */ - - ldata = sf->pixel_data; - rdata = ldata + w - 1; - for (y = halfh + midy; y > 0; --y) { /* 0 -> (h+1)/2 */ - RrPixel32 c; - - COLOR_RR(lefty, (&left)); - COLOR_RR(righty, (&right)); - - SETUP(x, (&left), (&right), halfw + midx); - - for (x = halfw + midx - 1; x > 0; --x) { /* 0 -> (w+1)/2 */ - c = COLOR(x); - *(ldata++) = *(rdata--) = c; - - NEXT(x); - } - c = COLOR(x); - *ldata = *rdata = c; - ldata += halfw + 1; - rdata += halfw - 1 + midx + w; - - NEXT(lefty); - NEXT(righty); - } - - /* copy the top half into the bottom half, mirroring it, so we can only - copy one row at a time - - it is faster, to move the writing pointer forward, and the reading - pointer backward - - this is the current code, moving the write pointer forward and read - pointer backward - 41.78 4.26 1.78 504 3.53 3.53 gradient_pyramid2 - this is the opposite, moving the read pointer forward and the write - pointer backward - 42.27 4.40 1.86 504 3.69 3.69 gradient_pyramid2 - - */ - ldata = sf->pixel_data + (halfh - 1) * w; - cp = ldata + (midy + 1) * w; - for (y = halfh; y > 0; --y) { - memcpy(cp, ldata, w * sizeof(RrPixel32)); - ldata -= w; - cp += w; - } -} |
