source: trunk/third/libart_lgpl/art_rgb.c @ 18256

Revision 18256, 4.3 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18255, which included commits to RCS files with non-trunk default branches.
Line 
1/* Libart_LGPL - library of basic graphic primitives
2 * Copyright (C) 1998 Raph Levien
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20#include "config.h"
21#include "art_rgb.h"
22
23#include <string.h>     /* for memset */
24
25/* Basic operators for manipulating 24-bit packed RGB buffers. */
26
27#define COLOR_RUN_COMPLEX
28
29#ifdef COLOR_RUN_SIMPLE
30/* This is really slow. Is there any way we might speed it up?
31   Two ideas:
32
33   First, maybe we should be working at 32-bit alignment. Then,
34   this can be a simple loop over word stores.
35
36   Second, we can keep working at 24-bit alignment, but have some
37   intelligence about storing. For example, we can iterate over
38   4-pixel chunks (aligned at 4 pixels), with an inner loop
39   something like:
40
41   *buf++ = v1;
42   *buf++ = v2;
43   *buf++ = v3;
44
45   One source of extra complexity is the need to make sure linebuf is
46   aligned to a 32-bit boundary.
47
48   This second alternative has some complexity to it, but is
49   appealing because it really minimizes the memory bandwidth. */
50void
51art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, gint n)
52{
53  int i;
54
55  if (r == g && g == b)
56    {
57      memset (buf, g, n + n + n);
58    }
59  else
60    {
61      for (i = 0; i < n; i++)
62        {
63          *buf++ = r;
64          *buf++ = g;
65          *buf++ = b;
66        }
67    }
68}
69#endif
70
71#ifdef COLOR_RUN_COMPLEX
72/* This implements the second of the two ideas above. The test results
73   are _very_ encouraging - it seems the speed is within 10% of
74   memset, which is quite good! */
75/**
76 * art_rgb_fill_run: fill a buffer a solid RGB color.
77 * @buf: Buffer to fill.
78 * @r: Red, range 0..255.
79 * @g: Green, range 0..255.
80 * @b: Blue, range 0..255.
81 * @n: Number of RGB triples to fill.
82 *
83 * Fills a buffer with @n copies of the (@r, @g, @b) triple. Thus,
84 * locations @buf (inclusive) through @buf + 3 * @n (exclusive) are
85 * written.
86 *
87 * The implementation of this routine is very highly optimized.
88 **/
89void
90art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
91{
92  int i;
93  unsigned int v1, v2, v3;
94
95  if (r == g && g == b)
96    {
97      memset (buf, g, n + n + n);
98    }
99  else
100    {
101      if (n < 8)
102        {
103          for (i = 0; i < n; i++)
104            {
105              *buf++ = r;
106              *buf++ = g;
107              *buf++ = b;
108            }
109        } else {
110          /* handle prefix up to byte alignment */
111          /* I'm worried about this cast on sizeof(long) != sizeof(uchar *)
112             architectures, but it _should_ work. */
113          for (i = 0; ((unsigned long)buf) & 3; i++)
114            {
115              *buf++ = r;
116              *buf++ = g;
117              *buf++ = b;
118            }
119#ifndef WORDS_BIGENDIAN
120          v1 = r | (g << 8) | (b << 16) | (r << 24);
121          v3 = (v1 << 8) | b;
122          v2 = (v3 << 8) | g;
123#else
124          v1 = (r << 24) | (g << 16) | (b << 8) | r;
125          v2 = (v1 << 8) | g;
126          v3 = (v2 << 8) | b;
127#endif
128          for (; i < n - 3; i += 4)
129            {
130              ((art_u32 *)buf)[0] = v1;
131              ((art_u32 *)buf)[1] = v2;
132              ((art_u32 *)buf)[2] = v3;
133              buf += 12;
134            }
135          /* handle postfix */
136          for (; i < n; i++)
137            {
138              *buf++ = r;
139              *buf++ = g;
140              *buf++ = b;
141            }
142        }
143    }
144}
145#endif
146
147/**
148 * art_rgb_run_alpha: Render semitransparent color over RGB buffer.
149 * @buf: Buffer for rendering.
150 * @r: Red, range 0..255.
151 * @g: Green, range 0..255.
152 * @b: Blue, range 0..255.
153 * @alpha: Alpha, range 0..256.
154 * @n: Number of RGB triples to render.
155 *
156 * Renders a sequential run of solid (@r, @g, @b) color over @buf with
157 * opacity @alpha.
158 **/
159void
160art_rgb_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
161{
162  int i;
163  int v;
164
165  for (i = 0; i < n; i++)
166    {
167      v = *buf;
168      *buf++ = v + (((r - v) * alpha + 0x80) >> 8);
169      v = *buf;
170      *buf++ = v + (((g - v) * alpha + 0x80) >> 8);
171      v = *buf;
172      *buf++ = v + (((b - v) * alpha + 0x80) >> 8);
173    }
174}
175
Note: See TracBrowser for help on using the repository browser.