summaryrefslogtreecommitdiff
blob: a8587fc1c51ab8d0266d320921719d0bd6e37468 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
From cc5fce6315dcc1127a3e2106223305ff763be815 Mon Sep 17 00:00:00 2001
From: Hans Petter Jansson <hpj@copyleft.no>
Date: Thu, 10 Nov 2005 19:13:00 +0000
Subject: [PATCH] pixops: Special-case compositing/copying with no scaling

When there is no scaling involved, make gdk_pixbuf_composite_color()
faster by avoiding the scaling code path.

https://bugzilla.gnome.org/show_bug.cgi?id=80927
---
 gdk-pixbuf/pixops/pixops.c | 95 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 90 insertions(+), 5 deletions(-)

diff --git a/gdk-pixbuf/pixops/pixops.c b/gdk-pixbuf/pixops/pixops.c
index 993223e..29a1c14 100644
--- a/gdk-pixbuf/pixops/pixops.c
+++ b/gdk-pixbuf/pixops/pixops.c
@@ -421,6 +421,86 @@ pixops_composite_nearest (guchar        *dest_buf,
 }
 
 static void
+pixops_composite_nearest_noscale (guchar        *dest_buf,
+				  int            render_x0,
+				  int            render_y0,
+				  int            render_x1,
+				  int            render_y1,
+				  int            dest_rowstride,
+				  int            dest_channels,
+				  gboolean       dest_has_alpha,
+				  const guchar  *src_buf,
+				  int            src_width,
+				  int            src_height,
+				  int            src_rowstride,
+				  int            src_channels,
+				  gboolean       src_has_alpha,
+				  int            overall_alpha)
+{
+  int i, j;
+  int x;
+
+  for (i = 0; i < (render_y1 - render_y0); i++)
+    {
+      const guchar *src  = src_buf + (i + render_y0) * src_rowstride;
+      guchar       *dest = dest_buf + i * dest_rowstride;
+
+      x = render_x0 * src_channels;
+
+      for (j=0; j < (render_x1 - render_x0); j++)
+	{
+	  const guchar *p = src + x;
+	  unsigned int  a0;
+
+	  if (src_has_alpha)
+	    a0 = (p[3] * overall_alpha) / 0xff;
+	  else
+	    a0 = overall_alpha;
+
+	  switch (a0)
+	    {
+	    case 0:
+	      break;
+	    case 255:
+	      dest[0] = p[0];
+	      dest[1] = p[1];
+	      dest[2] = p[2];
+	      if (dest_has_alpha)
+		dest[3] = 0xff;
+	      break;
+	    default:
+	      if (dest_has_alpha)
+	        {
+		  unsigned int w0 = 0xff * a0;
+		  unsigned int w1 = (0xff - a0) * dest[3];
+		  unsigned int w = w0 + w1;
+
+		  dest[0] = (w0 * p[0] + w1 * dest[0]) / w;
+		  dest[1] = (w0 * p[1] + w1 * dest[1]) / w;
+		  dest[2] = (w0 * p[2] + w1 * dest[2]) / w;
+		  dest[3] = w / 0xff;
+	        }
+	      else
+	        {
+		  unsigned int a1 = 0xff - a0;
+		  unsigned int tmp;
+
+		  tmp = a0 * p[0] + a1 * dest[0] + 0x80;
+		  dest[0] = (tmp + (tmp >> 8)) >> 8;
+		  tmp = a0 * p[1] + a1 * dest[1] + 0x80;
+		  dest[1] = (tmp + (tmp >> 8)) >> 8;
+		  tmp = a0 * p[2] + a1 * dest[2] + 0x80;
+		  dest[2] = (tmp + (tmp >> 8)) >> 8;
+	        }
+	      break;
+	    }
+	  dest += dest_channels;
+	  x += src_channels;
+	}
+    }
+}
+
+static void
 pixops_composite_color_nearest (guchar        *dest_buf,
 				int            render_x0,
 				int            render_y0,
@@ -1781,11 +1861,16 @@ _pixops_composite_real (guchar          *dest_buf,
 
   if (interp_type == PIXOPS_INTERP_NEAREST)
     {
-      pixops_composite_nearest (dest_buf, render_x0, render_y0, render_x1,
-				render_y1, dest_rowstride, dest_channels,
-				dest_has_alpha, src_buf, src_width, src_height,
-				src_rowstride, src_channels, src_has_alpha,
-				scale_x, scale_y, overall_alpha);
+      if (scale_x == 1.0 && scale_y == 1.0)
+	pixops_composite_nearest_noscale (dest_buf, render_x0, render_y0, render_x1, render_y1,
+					  dest_rowstride, dest_channels, dest_has_alpha,
+					  src_buf, src_width, src_height, src_rowstride, src_channels,
+					  src_has_alpha, overall_alpha);
+      else
+	pixops_composite_nearest (dest_buf, render_x0, render_y0, render_x1, render_y1,
+				  dest_rowstride, dest_channels, dest_has_alpha,
+				  src_buf, src_width, src_height, src_rowstride, src_channels,
+				  src_has_alpha, scale_x, scale_y, overall_alpha);
       return;
     }
   
-- 
2.5.1