Back to index

scribus-ng  1.3.4.dfsg+svn20071115
art_rgb.c
Go to the documentation of this file.
00001 /* Libart_LGPL - library of basic graphic primitives
00002  * Copyright (C) 1998 Raph Levien
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 #include "scconfig.h"
00021 
00022 #include "art_rgb.h"
00023 
00024 #include <string.h>  /* for memset */
00025 
00026 /* Basic operators for manipulating 24-bit packed RGB buffers. */
00027 
00028 #define COLOR_RUN_SIMPLE
00029 
00030 #ifdef COLOR_RUN_SIMPLE
00031 /* This is really slow. Is there any way we might speed it up?
00032    Two ideas:
00033 
00034    First, maybe we should be working at 32-bit alignment. Then,
00035    this can be a simple loop over word stores.
00036 
00037    Second, we can keep working at 24-bit alignment, but have some
00038    intelligence about storing. For example, we can iterate over
00039    4-pixel chunks (aligned at 4 pixels), with an inner loop
00040    something like:
00041 
00042    *buf++ = v1;
00043    *buf++ = v2;
00044    *buf++ = v3;
00045 
00046    One source of extra complexity is the need to make sure linebuf is
00047    aligned to a 32-bit boundary.
00048 
00049    This second alternative has some complexity to it, but is
00050    appealing because it really minimizes the memory bandwidth. */
00051 void
00052 art_rgb_fill_run_ (art_u8 *buf, art_u32 rgb, int n)
00053 {
00054   int i;
00055   art_u32 *b = (art_u32 *)buf;
00056   for (i = 0; i < n; i++)
00057   {
00058     *b = rgb;
00059     b++;
00060   }
00061 }
00062 #endif
00063 
00064 #ifdef COLOR_RUN_COMPLEX
00065 /* This implements the second of the two ideas above. The test results
00066    are _very_ encouraging - it seems the speed is within 10% of
00067    memset, which is quite good! */
00082 void
00083 art_rgb_fill_run_ (art_u8 *buf, art_u32 rgb, int n)
00084 {
00085   int i;
00086   unsigned int v1, v2, v3;
00087 
00088   if (r == g && g == b)
00089     {
00090         memset (buf, g, 4*n);
00091     }
00092   else
00093     {
00094       if (n < 8)
00095        {
00096          for (i = 0; i < n; i++)
00097            {
00098              buf++;
00099              *buf++ = r;
00100              *buf++ = g;
00101              *buf++ = b;
00102            }
00103        } else {
00104          /* handle prefix up to byte alignment */
00105          /* I'm worried about this cast on sizeof(long) != sizeof(uchar *)
00106             architectures, but it _should_ work. */
00107          for (i = 0; ((unsigned long)buf) & 3; i++)
00108            {
00109          buf++;
00110              *buf++ = r;
00111              *buf++ = g;
00112              *buf++ = b;
00113            }
00114 #ifndef WORDS_BIGENDIAN
00115          v1 = r | (g << 8) | (b << 16) | (r << 24);
00116          v3 = (v1 << 8) | b;
00117          v2 = (v3 << 8) | g;
00118 #else
00119          v1 = (r << 24) | (g << 16) | (b << 8) | r;
00120          v2 = (v1 << 8) | g;
00121          v3 = (v2 << 8) | b;
00122 #endif
00123          for (; i < n - 3; i += 4)
00124            {/*
00125              ((art_u32 *)buf)[0] = v1;
00126              ((art_u32 *)buf)[1] = v2;
00127              ((art_u32 *)buf)[2] = v3;
00128              buf += 12;*/
00129              ((art_u32 *)buf)[1] = v1;
00130              ((art_u32 *)buf)[2] = v2;
00131              ((art_u32 *)buf)[3] = v3;
00132              buf += 16;
00133            }
00134          /* handle postfix */
00135          for (; i < n; i++)
00136            {
00137              buf++;
00138              *buf++ = r;
00139              *buf++ = g;
00140              *buf++ = b;
00141            }
00142        }
00143     }
00144 }
00145 #endif
00146 
00159 void
00160 art_rgb_run_alpha_ (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
00161 {
00162   int i;
00163   int v;
00164   for (i = 0; i < n; i++)
00165   {
00166     v = *buf;
00167     *buf++ = v + (((b - v) * alpha + 0x80) >> 8);
00168     v = *buf;
00169     *buf++ = v + (((g - v) * alpha + 0x80) >> 8);
00170     v = *buf;
00171     *buf++ = v + (((r - v) * alpha + 0x80) >> 8);
00172    buf++;
00173   }
00174 }
00175