summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Cisler <pavel@eazel.com>2001-03-20 01:27:31 +0000
committerPavel Cisler <pce@src.gnome.org>2001-03-20 01:27:31 +0000
commit08ab6d79dc50689888ee1bd70574cb243feb82f3 (patch)
tree89670770b62d9538c6d04270dff0a1a5047c1ffd
parent0302f336ee1e9ca5d600fbdf62477ed4e1334803 (diff)
downloadnautilus-08ab6d79dc50689888ee1bd70574cb243feb82f3.tar.gz
reviewed by: Gene Z. Ragan <gzr@eazel.com>
2001-03-19 Pavel Cisler <pavel@eazel.com> reviewed by: Gene Z. Ragan <gzr@eazel.com> * libnautilus-extensions/nautilus-glyph.c: (nautilus_glyph_draw_to_pixbuf): Speed up drag-selection a whole bunch by making this call 4 x faster in the anti-aliased mode.
-rw-r--r--ChangeLog9
-rw-r--r--libnautilus-extensions/nautilus-glyph.c201
-rw-r--r--libnautilus-private/nautilus-glyph.c201
3 files changed, 321 insertions, 90 deletions
diff --git a/ChangeLog b/ChangeLog
index 0d443effc..4b8436d16 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2001-03-19 Pavel Cisler <pavel@eazel.com>
+
+ reviewed by: Gene Z. Ragan <gzr@eazel.com>
+
+ * libnautilus-extensions/nautilus-glyph.c:
+ (nautilus_glyph_draw_to_pixbuf):
+ Speed up drag-selection a whole bunch by making this call
+ 4 x faster in the anti-aliased mode.
+
2001-03-19 Robin * Slomkowski <rslomkow@eazel.com>
* components/music/Makefile.am: added non-i386 files
diff --git a/libnautilus-extensions/nautilus-glyph.c b/libnautilus-extensions/nautilus-glyph.c
index 80b43e7db..cff686df3 100644
--- a/libnautilus-extensions/nautilus-glyph.c
+++ b/libnautilus-extensions/nautilus-glyph.c
@@ -213,6 +213,62 @@ glyph_is_valid (const NautilusGlyph *glyph)
&& glyph_get_height_space_safe (glyph) > 0;
}
+
+/* Color packing macros for nautilus_glyph_draw_to_pixbuf */
+#define RGBA_COLOR_PACK(r, g, b, a) \
+( ((r) << 24) | \
+ ((g) << 16) | \
+ ((b) << 8) | \
+ ((a) << 0) )
+
+#define RGB_COLOR_PACK(r, g, b) \
+( ((r) << 24) | \
+ ((g) << 16) | \
+ ((b) << 8) )
+
+#define RGBA_COLOR_PACK_ALPHA(a) (a)
+#define RGBA_COLOR_GET_RED(c) (((c) >> 24) & 0xFF)
+#define RGBA_COLOR_GET_GREEN(c) (((c) >> 16) & 0xFF)
+#define RGBA_COLOR_GET_BLUE(c) (((c) >> 8) & 0xFF)
+#define RGBA_COLOR_GET_ALPHA(c) (((c) >> 0) & 0xFF)
+
+#define ABGR_COLOR_PACK(r, g, b, a) \
+( ((a) << 24) | \
+ ((b) << 16) | \
+ ((g) << 8) | \
+ ((r) << 0) )
+
+#define BGR_COLOR_PACK(r, g, b) \
+( ((b) << 16) | \
+ ((g) << 8) | \
+ ((r) << 0) )
+
+#define ABGR_COLOR_PACK_ALPHA(a) ((a) << 24)
+#define ABGR_COLOR_GET_RED(c) (((c) >> 0) & 0xFF)
+#define ABGR_COLOR_GET_GREEN(c) (((c) >> 8) & 0xFF)
+#define ABGR_COLOR_GET_BLUE(c) (((c) >> 16) & 0xFF)
+#define ABGR_COLOR_GET_ALPHA(c) (((c) >> 24) & 0xFF)
+
+
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define PACK_COLOR_WITH_ALPHA(r, g, b, a) ABGR_COLOR_PACK(r, g, b, a)
+#define PACK_COLOR(r, g, b) BGR_COLOR_PACK(r, g, b)
+#define PACK_ALPHA(a) ABGR_COLOR_PACK_ALPHA(a)
+#define GET_RED(c) ABGR_COLOR_GET_RED(c)
+#define GET_GREEN(c) ABGR_COLOR_GET_GREEN(c)
+#define GET_BLUE(c) ABGR_COLOR_GET_BLUE(c)
+#define GET_ALPHA(c) ABGR_COLOR_GET_ALPHA(c)
+#else
+#define PACK_COLOR_WITH_ALPHA(r, g, b, a) RGBA_COLOR_PACK(r, g, b, a)
+#define PACK_COLOR(r, g, b) RGB_COLOR_PACK(r, g, b)
+#define PACK_ALPHA(a) RGBA_COLOR_PACK_ALPHA(a)
+#define GET_RED(c) RGBA_COLOR_GET_RED(c)
+#define GET_GREEN(c) RGBA_COLOR_GET_GREEN(c)
+#define GET_BLUE(c) RGBA_COLOR_GET_BLUE(c)
+#define GET_ALPHA(c) RGBA_COLOR_GET_ALPHA(c)
+#endif
+
/**
* nautilus_glyph_draw_to_pixbuf:
* @glyph: A NautilusGlyph.
@@ -342,56 +398,111 @@ nautilus_glyph_draw_to_pixbuf (const NautilusGlyph *glyph,
* and the glyph's buffer.
*/
- /* Iterate vertically */
- for (y = render_area.y0 ; y < render_area.y1; y++) {
- pixbuf_x_offset = pixbuf_y_offset;
- glyph_x_offset = glyph_y_offset;
+ if (pixbuf_has_alpha) {
+ /* Speed optimization -- avoid calling art_rgba_run_alpha, precompute
+ * src_rgb outside of the loop
+ */
+
+ guint32 src_color, dst_color;
- /* Iterate horizontally */
- for (x = render_area.x0 ; x < render_area.x1; x++) {
- const guchar point_opacity = *glyph_x_offset;
-
- /* Optimize the common fully opaque case */
- if (point_opacity == NAUTILUS_OPACITY_FULLY_OPAQUE) {
- *(pixbuf_x_offset + 0) = foreground_r;
- *(pixbuf_x_offset + 1) = foreground_g;
- *(pixbuf_x_offset + 2) = foreground_b;
- if (pixbuf_has_alpha) {
- *(pixbuf_x_offset + 3) = NAUTILUS_OPACITY_FULLY_OPAQUE;
- }
- /* If the opacity is not fully opaque or fully transparent,
- * we need to to alpha blending.
- */
- } else if (point_opacity != NAUTILUS_OPACITY_FULLY_TRANSPARENT) {
- if (pixbuf_has_alpha) {
- art_rgba_run_alpha (pixbuf_x_offset,
- foreground_r,
- foreground_g,
- foreground_b,
- point_opacity,
- 1);
+ src_color = PACK_COLOR(foreground_r, foreground_g, foreground_b);
+
+ for (y = render_area.y0 ; y < render_area.y1; y++) {
+ pixbuf_x_offset = pixbuf_y_offset;
+ glyph_x_offset = glyph_y_offset;
+
+ /* Iterate horizontally */
+ for (x = render_area.x0 ; x < render_area.x1; x++) {
+ guchar dest_alpha;
+ const guchar source_alpha = *glyph_x_offset;
+ dst_color = *(guint32 *) pixbuf_x_offset;
+ dest_alpha = GET_ALPHA (dst_color);
+
+ if (dest_alpha) {
+ int dst_r, dst_g, dst_b, tmp, a, c;
+
+ tmp = (255 - source_alpha) * (255 - dest_alpha) + 0x80;
+ a = 255 - ((tmp + (tmp >> 8)) >> 8);
+ c = ((source_alpha << 16) + (a >> 1)) / a;
+
+ dst_r = GET_RED (dst_color);
+ dst_g = GET_GREEN (dst_color);
+ dst_b = GET_BLUE (dst_color);
+
+ dst_r += (((foreground_r - dst_r) * c + 0x8000) >> 16);
+ dst_g += (((foreground_g - dst_g) * c + 0x8000) >> 16);
+ dst_b += (((foreground_b - dst_b) * c + 0x8000) >> 16);
+
+ *(guint32 *) pixbuf_x_offset = PACK_COLOR_WITH_ALPHA (dst_r, dst_g, dst_b, a);
} else {
- art_rgb_run_alpha (pixbuf_x_offset,
- foreground_r,
- foreground_g,
- foreground_b,
- point_opacity,
- 1);
+ *(guint32 *) pixbuf_x_offset = PACK_ALPHA (source_alpha) | src_color;
}
+
+ /* Advance to the next pixel */
+ pixbuf_x_offset += pixbuf_pixel_offset;
+
+ /* Advance to the next opacity */
+ glyph_x_offset++;
}
-
- /* Advance to the next pixel */
- pixbuf_x_offset += pixbuf_pixel_offset;
-
- /* Advance to the next opacity */
- glyph_x_offset++;
+
+ /* Advance to the next pixbuf pixel row */
+ pixbuf_y_offset += pixbuf_rowstride;
+
+ /* Advance to the next glyph buffer row */
+ glyph_y_offset += glyph_rowstride;
+ }
+ } else {
+ /* Iterate vertically */
+ for (y = render_area.y0 ; y < render_area.y1; y++) {
+ pixbuf_x_offset = pixbuf_y_offset;
+ glyph_x_offset = glyph_y_offset;
+
+ /* Iterate horizontally */
+ for (x = render_area.x0 ; x < render_area.x1; x++) {
+ const guchar point_opacity = *glyph_x_offset;
+
+ /* Optimize the common fully opaque case */
+ if (point_opacity == NAUTILUS_OPACITY_FULLY_OPAQUE) {
+ *(pixbuf_x_offset + 0) = foreground_r;
+ *(pixbuf_x_offset + 1) = foreground_g;
+ *(pixbuf_x_offset + 2) = foreground_b;
+ if (pixbuf_has_alpha) {
+ *(pixbuf_x_offset + 3) = NAUTILUS_OPACITY_FULLY_OPAQUE;
+ }
+ /* If the opacity is not fully opaque or fully transparent,
+ * we need to to alpha blending.
+ */
+ } else if (point_opacity != NAUTILUS_OPACITY_FULLY_TRANSPARENT) {
+ if (pixbuf_has_alpha) {
+ art_rgba_run_alpha (pixbuf_x_offset,
+ foreground_r,
+ foreground_g,
+ foreground_b,
+ point_opacity,
+ 1);
+ } else {
+ art_rgb_run_alpha (pixbuf_x_offset,
+ foreground_r,
+ foreground_g,
+ foreground_b,
+ point_opacity,
+ 1);
+ }
+ }
+
+ /* Advance to the next pixel */
+ pixbuf_x_offset += pixbuf_pixel_offset;
+
+ /* Advance to the next opacity */
+ glyph_x_offset++;
+ }
+
+ /* Advance to the next pixbuf pixel row */
+ pixbuf_y_offset += pixbuf_rowstride;
+
+ /* Advance to the next glyph buffer row */
+ glyph_y_offset += glyph_rowstride;
}
-
- /* Advance to the next pixbuf pixel row */
- pixbuf_y_offset += pixbuf_rowstride;
-
- /* Advance to the next glyph buffer row */
- glyph_y_offset += glyph_rowstride;
}
}
diff --git a/libnautilus-private/nautilus-glyph.c b/libnautilus-private/nautilus-glyph.c
index 80b43e7db..cff686df3 100644
--- a/libnautilus-private/nautilus-glyph.c
+++ b/libnautilus-private/nautilus-glyph.c
@@ -213,6 +213,62 @@ glyph_is_valid (const NautilusGlyph *glyph)
&& glyph_get_height_space_safe (glyph) > 0;
}
+
+/* Color packing macros for nautilus_glyph_draw_to_pixbuf */
+#define RGBA_COLOR_PACK(r, g, b, a) \
+( ((r) << 24) | \
+ ((g) << 16) | \
+ ((b) << 8) | \
+ ((a) << 0) )
+
+#define RGB_COLOR_PACK(r, g, b) \
+( ((r) << 24) | \
+ ((g) << 16) | \
+ ((b) << 8) )
+
+#define RGBA_COLOR_PACK_ALPHA(a) (a)
+#define RGBA_COLOR_GET_RED(c) (((c) >> 24) & 0xFF)
+#define RGBA_COLOR_GET_GREEN(c) (((c) >> 16) & 0xFF)
+#define RGBA_COLOR_GET_BLUE(c) (((c) >> 8) & 0xFF)
+#define RGBA_COLOR_GET_ALPHA(c) (((c) >> 0) & 0xFF)
+
+#define ABGR_COLOR_PACK(r, g, b, a) \
+( ((a) << 24) | \
+ ((b) << 16) | \
+ ((g) << 8) | \
+ ((r) << 0) )
+
+#define BGR_COLOR_PACK(r, g, b) \
+( ((b) << 16) | \
+ ((g) << 8) | \
+ ((r) << 0) )
+
+#define ABGR_COLOR_PACK_ALPHA(a) ((a) << 24)
+#define ABGR_COLOR_GET_RED(c) (((c) >> 0) & 0xFF)
+#define ABGR_COLOR_GET_GREEN(c) (((c) >> 8) & 0xFF)
+#define ABGR_COLOR_GET_BLUE(c) (((c) >> 16) & 0xFF)
+#define ABGR_COLOR_GET_ALPHA(c) (((c) >> 24) & 0xFF)
+
+
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define PACK_COLOR_WITH_ALPHA(r, g, b, a) ABGR_COLOR_PACK(r, g, b, a)
+#define PACK_COLOR(r, g, b) BGR_COLOR_PACK(r, g, b)
+#define PACK_ALPHA(a) ABGR_COLOR_PACK_ALPHA(a)
+#define GET_RED(c) ABGR_COLOR_GET_RED(c)
+#define GET_GREEN(c) ABGR_COLOR_GET_GREEN(c)
+#define GET_BLUE(c) ABGR_COLOR_GET_BLUE(c)
+#define GET_ALPHA(c) ABGR_COLOR_GET_ALPHA(c)
+#else
+#define PACK_COLOR_WITH_ALPHA(r, g, b, a) RGBA_COLOR_PACK(r, g, b, a)
+#define PACK_COLOR(r, g, b) RGB_COLOR_PACK(r, g, b)
+#define PACK_ALPHA(a) RGBA_COLOR_PACK_ALPHA(a)
+#define GET_RED(c) RGBA_COLOR_GET_RED(c)
+#define GET_GREEN(c) RGBA_COLOR_GET_GREEN(c)
+#define GET_BLUE(c) RGBA_COLOR_GET_BLUE(c)
+#define GET_ALPHA(c) RGBA_COLOR_GET_ALPHA(c)
+#endif
+
/**
* nautilus_glyph_draw_to_pixbuf:
* @glyph: A NautilusGlyph.
@@ -342,56 +398,111 @@ nautilus_glyph_draw_to_pixbuf (const NautilusGlyph *glyph,
* and the glyph's buffer.
*/
- /* Iterate vertically */
- for (y = render_area.y0 ; y < render_area.y1; y++) {
- pixbuf_x_offset = pixbuf_y_offset;
- glyph_x_offset = glyph_y_offset;
+ if (pixbuf_has_alpha) {
+ /* Speed optimization -- avoid calling art_rgba_run_alpha, precompute
+ * src_rgb outside of the loop
+ */
+
+ guint32 src_color, dst_color;
- /* Iterate horizontally */
- for (x = render_area.x0 ; x < render_area.x1; x++) {
- const guchar point_opacity = *glyph_x_offset;
-
- /* Optimize the common fully opaque case */
- if (point_opacity == NAUTILUS_OPACITY_FULLY_OPAQUE) {
- *(pixbuf_x_offset + 0) = foreground_r;
- *(pixbuf_x_offset + 1) = foreground_g;
- *(pixbuf_x_offset + 2) = foreground_b;
- if (pixbuf_has_alpha) {
- *(pixbuf_x_offset + 3) = NAUTILUS_OPACITY_FULLY_OPAQUE;
- }
- /* If the opacity is not fully opaque or fully transparent,
- * we need to to alpha blending.
- */
- } else if (point_opacity != NAUTILUS_OPACITY_FULLY_TRANSPARENT) {
- if (pixbuf_has_alpha) {
- art_rgba_run_alpha (pixbuf_x_offset,
- foreground_r,
- foreground_g,
- foreground_b,
- point_opacity,
- 1);
+ src_color = PACK_COLOR(foreground_r, foreground_g, foreground_b);
+
+ for (y = render_area.y0 ; y < render_area.y1; y++) {
+ pixbuf_x_offset = pixbuf_y_offset;
+ glyph_x_offset = glyph_y_offset;
+
+ /* Iterate horizontally */
+ for (x = render_area.x0 ; x < render_area.x1; x++) {
+ guchar dest_alpha;
+ const guchar source_alpha = *glyph_x_offset;
+ dst_color = *(guint32 *) pixbuf_x_offset;
+ dest_alpha = GET_ALPHA (dst_color);
+
+ if (dest_alpha) {
+ int dst_r, dst_g, dst_b, tmp, a, c;
+
+ tmp = (255 - source_alpha) * (255 - dest_alpha) + 0x80;
+ a = 255 - ((tmp + (tmp >> 8)) >> 8);
+ c = ((source_alpha << 16) + (a >> 1)) / a;
+
+ dst_r = GET_RED (dst_color);
+ dst_g = GET_GREEN (dst_color);
+ dst_b = GET_BLUE (dst_color);
+
+ dst_r += (((foreground_r - dst_r) * c + 0x8000) >> 16);
+ dst_g += (((foreground_g - dst_g) * c + 0x8000) >> 16);
+ dst_b += (((foreground_b - dst_b) * c + 0x8000) >> 16);
+
+ *(guint32 *) pixbuf_x_offset = PACK_COLOR_WITH_ALPHA (dst_r, dst_g, dst_b, a);
} else {
- art_rgb_run_alpha (pixbuf_x_offset,
- foreground_r,
- foreground_g,
- foreground_b,
- point_opacity,
- 1);
+ *(guint32 *) pixbuf_x_offset = PACK_ALPHA (source_alpha) | src_color;
}
+
+ /* Advance to the next pixel */
+ pixbuf_x_offset += pixbuf_pixel_offset;
+
+ /* Advance to the next opacity */
+ glyph_x_offset++;
}
-
- /* Advance to the next pixel */
- pixbuf_x_offset += pixbuf_pixel_offset;
-
- /* Advance to the next opacity */
- glyph_x_offset++;
+
+ /* Advance to the next pixbuf pixel row */
+ pixbuf_y_offset += pixbuf_rowstride;
+
+ /* Advance to the next glyph buffer row */
+ glyph_y_offset += glyph_rowstride;
+ }
+ } else {
+ /* Iterate vertically */
+ for (y = render_area.y0 ; y < render_area.y1; y++) {
+ pixbuf_x_offset = pixbuf_y_offset;
+ glyph_x_offset = glyph_y_offset;
+
+ /* Iterate horizontally */
+ for (x = render_area.x0 ; x < render_area.x1; x++) {
+ const guchar point_opacity = *glyph_x_offset;
+
+ /* Optimize the common fully opaque case */
+ if (point_opacity == NAUTILUS_OPACITY_FULLY_OPAQUE) {
+ *(pixbuf_x_offset + 0) = foreground_r;
+ *(pixbuf_x_offset + 1) = foreground_g;
+ *(pixbuf_x_offset + 2) = foreground_b;
+ if (pixbuf_has_alpha) {
+ *(pixbuf_x_offset + 3) = NAUTILUS_OPACITY_FULLY_OPAQUE;
+ }
+ /* If the opacity is not fully opaque or fully transparent,
+ * we need to to alpha blending.
+ */
+ } else if (point_opacity != NAUTILUS_OPACITY_FULLY_TRANSPARENT) {
+ if (pixbuf_has_alpha) {
+ art_rgba_run_alpha (pixbuf_x_offset,
+ foreground_r,
+ foreground_g,
+ foreground_b,
+ point_opacity,
+ 1);
+ } else {
+ art_rgb_run_alpha (pixbuf_x_offset,
+ foreground_r,
+ foreground_g,
+ foreground_b,
+ point_opacity,
+ 1);
+ }
+ }
+
+ /* Advance to the next pixel */
+ pixbuf_x_offset += pixbuf_pixel_offset;
+
+ /* Advance to the next opacity */
+ glyph_x_offset++;
+ }
+
+ /* Advance to the next pixbuf pixel row */
+ pixbuf_y_offset += pixbuf_rowstride;
+
+ /* Advance to the next glyph buffer row */
+ glyph_y_offset += glyph_rowstride;
}
-
- /* Advance to the next pixbuf pixel row */
- pixbuf_y_offset += pixbuf_rowstride;
-
- /* Advance to the next glyph buffer row */
- glyph_y_offset += glyph_rowstride;
}
}