Code

* we are now creating true RGBA pngs
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Mon, 11 Apr 2005 09:51:22 +0000 (09:51 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Mon, 11 Apr 2005 09:51:22 +0000 (09:51 +0000)
* removed all memory leeks from rrd_gfx

git-svn-id: svn://svn.oetiker.ch/rrdtool/branches/1.2@393 a5681a0c-68f1-0310-ab6d-d61299d08faa

program/src/Makefile.am
program/src/art_rgb_affine_private.h [new file with mode: 0644]
program/src/art_rgba_rgba_affine.c [new file with mode: 0644]
program/src/art_rgba_rgba_affine.h [new file with mode: 0644]
program/src/art_rgba_svp.c [new file with mode: 0644]
program/src/art_rgba_svp.h [new file with mode: 0644]
program/src/rrd_gfx.c
program/src/rrd_gfx.h
program/src/rrd_graph.c

index df9aa9404fe1dbd28ffe51030ee443dd2b07d9d8..6f3928c86d25b9549bc8c20b99be78c2d68fc520 100644 (file)
@@ -39,6 +39,11 @@ RRD_C_FILES =                \
        rrd_update.c    \
        rrd_xport.c     \
        rrd_nan_inf.c   \
+        art_rgba_rgba_affine.c \
+        art_rgba_svp.c \
+        art_rgb_affine_private.h \
+       art_rgba_rgba_affine.h \
+        art_rgba_svp.h \
        rrd_gfx.c rrd_gfx.h \
        rrd_afm.c rrd_afm_data.c \
        getopt.h parsetime.h \
@@ -92,4 +97,6 @@ rrdtool_SOURCES =
 rrdtool_DEPENDENCIES = rrd_tool.o
 rrdtool_LDADD  = librrd.la
 
-EXTRA_DIST= rrdtool.dsp rrdtool.dsw $(fonts_DATA)
+# strftime is here because we do not usually need it. unices have propper
+# iso date support
+EXTRA_DIST= rrdtool.dsp rrdtool.dsw strftime.c strftime.h $(fonts_DATA)
diff --git a/program/src/art_rgb_affine_private.h b/program/src/art_rgb_affine_private.h
new file mode 100644 (file)
index 0000000..edaf0e3
--- /dev/null
@@ -0,0 +1,39 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_AFFINE_PRIVATE_H__
+#define __ART_RGB_AFFINE_PRIVATE_H__
+
+/* This module handles compositing of affine-transformed rgb images
+   over rgb pixel buffers. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_affine_run (int *p_x0, int *p_x1, int y,
+                   int src_width, int src_height,
+                   const double affine[6]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/program/src/art_rgba_rgba_affine.c b/program/src/art_rgba_rgba_affine.c
new file mode 100644 (file)
index 0000000..b6e6f48
--- /dev/null
@@ -0,0 +1,150 @@
+#define ART_RGBA_RGBA_AFFINE_C
+
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include <libart_lgpl/art_misc.h>
+#include <libart_lgpl/art_point.h>
+#include <libart_lgpl/art_affine.h>
+
+#include "art_rgb_affine_private.h"
+#include "art_rgba_rgba_affine.h"
+
+/* This module handles compositing of affine-transformed rgba images
+   over rgba pixel buffers. */
+
+/* Composite the source image over the destination image, applying the
+   affine transform. */
+
+/**
+ * gnome_print_art_rgba_rgba_affine: Affine transform source RGBA image and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image RGBA buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
+ * of this rectangle are included, and the right and bottom edges are
+ * excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be
+ * done in a gamma-corrected color space. In the current
+ * implementation, it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+gnome_print_art_rgba_rgba_affine (art_u8 *dst,
+                    int x0, int y0, int x1, int y1, int dst_rowstride,
+                    const art_u8 *src,
+                    int src_width, int src_height, int src_rowstride,
+                    const double affine[6],
+                    ArtFilterLevel level,
+                    ArtAlphaGamma *alphagamma)
+{
+  /* Note: this is a slow implementation, and is missing all filter
+     levels other than NEAREST. It is here for clarity of presentation
+     and to establish the interface. */
+  int x, y;
+  double inv[6];
+  art_u8 *dst_p, *dst_linestart;
+  const art_u8 *src_p;
+  ArtPoint pt, src_pt;
+  int src_x, src_y;
+  int alpha;
+  art_u8 bg_r, bg_g, bg_b, bg_a, cr, cg, cb;
+  art_u8 fg_r, fg_g, fg_b;
+  int tmp;
+  int run_x0, run_x1;
+
+  dst_linestart = dst;
+  art_affine_invert (inv, affine);
+  for (y = y0; y < y1; y++)
+    {
+      pt.y = y + 0.5;
+      run_x0 = x0;
+      run_x1 = x1;
+      art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+                         inv);
+      dst_p = dst_linestart + (run_x0 - x0) * 4;
+      for (x = run_x0; x < run_x1; x++)
+       {
+         pt.x = x + 0.5;
+         art_affine_point (&src_pt, &pt, inv);
+         src_x = floor (src_pt.x);
+         src_y = floor (src_pt.y);
+         src_p = src + (src_y * src_rowstride) + src_x * 4;
+         if (src_x >= 0 && src_x < src_width &&
+             src_y >= 0 && src_y < src_height)
+           {
+
+         alpha = src_p[3];
+         if (alpha)
+           {
+             if (alpha == 255)
+               {
+                 dst_p[0] = src_p[0];
+                 dst_p[1] = src_p[1];
+                 dst_p[2] = src_p[2];
+                 dst_p[3] = 255;
+               }
+             else
+               {
+                 bg_r = dst_p[0];
+                 bg_g = dst_p[1];
+                 bg_b = dst_p[2];
+                 bg_a = dst_p[3];
+                 
+                       cr = (bg_r * bg_a + 0x80) >> 8;
+                       cg = (bg_g * bg_g + 0x80) >> 8;
+                       cb = (bg_b * bg_b + 0x80) >> 8;
+
+                 tmp = (src_p[0] - bg_r) * alpha;
+                 fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
+                 tmp = (src_p[1] - bg_g) * alpha;
+                 fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
+                 tmp = (src_p[2] - bg_b) * alpha;
+                 fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
+                 
+                 dst_p[0] = fg_r;
+                 dst_p[1] = fg_g;
+                 dst_p[2] = fg_b;
+                 dst_p[3] = bg_a + (((255 - bg_a) * alpha + 0x80) >> 8);
+               }
+           }
+           } else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; dst_p[3] = 255;}
+         dst_p += 4;
+       }
+      dst_linestart += dst_rowstride;
+    }
+}
diff --git a/program/src/art_rgba_rgba_affine.h b/program/src/art_rgba_rgba_affine.h
new file mode 100644 (file)
index 0000000..3afc120
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef SP_ART_RGBA_RGBA_AFFINE_H
+#define SP_ART_RGBA_RGBA_AFFINE_H
+
+/*
+ * Lauris Kaplinski <lauris@ariman.ee>
+ *
+ * A slightly modified version of art_rgb_rgba_affine to render into
+ * rgba buffer
+ */
+
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include <libart_lgpl/art_misc.h>
+#include <libart_lgpl/art_filterlevel.h>
+#include <libart_lgpl/art_alphagamma.h>
+
+/* This module handles compositing of affine-transformed rgba images
+   over rgb pixel buffers. */
+
+/* Composite the source image over the destination image, applying the
+   affine transform. */
+
+/**
+ * gnome_print_art_rgba_rgba_affine: Affine transform source RGBA image and composite.
+ * @dst: Destination image RGBA buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image RGBA buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
+ * of this rectangle are included, and the right and bottom edges are
+ * excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be
+ * done in a gamma-corrected color space. In the current
+ * implementation, it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+gnome_print_art_rgba_rgba_affine (art_u8 *dst,
+                    int x0, int y0, int x1, int y1, int dst_rowstride,
+                    const art_u8 *src,
+                    int src_width, int src_height, int src_rowstride,
+                    const double affine[6],
+                    ArtFilterLevel level,
+                    ArtAlphaGamma *alphagamma);
+
+#endif
diff --git a/program/src/art_rgba_svp.c b/program/src/art_rgba_svp.c
new file mode 100644 (file)
index 0000000..81457d0
--- /dev/null
@@ -0,0 +1,332 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ *  art_rgba_svp.c: A slightly modified version of art_rgb_svp to render into rgba buffer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Authors:
+ *    Raph Levien <raph@acm.org>
+ *    Lauris Kaplinski <lauris@ariman.ee>
+ *
+ *  Copyright (C) 1998 Raph Levien
+ *
+ */
+
+#define SP_ART_RGBA_SVP_C
+
+/* Render a sorted vector path into an RGBA buffer. */
+
+#include <libart_lgpl/art_misc.h>
+#include <libart_lgpl/art_svp.h>
+#include <libart_lgpl/art_svp_render_aa.h>
+#include <libart_lgpl/art_rgb.h>
+
+#include "art_rgba_svp.h"
+
+static void art_rgba_fill_run (art_u8 * linebuf, art_u8 r, art_u8 g, art_u8 b, int n);
+static void art_rgba_run_alpha (art_u8 * linebuf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n);
+
+typedef struct _ArtRgbaSVPAlphaData ArtRgbaSVPAlphaData;
+
+struct _ArtRgbaSVPAlphaData {
+  int alphatab[256];
+  art_u8 r, g, b, alpha;
+  art_u8 *buf;
+  int rowstride;
+  int x0, x1;
+};
+
+static void
+art_rgba_svp_alpha_callback (void *callback_data, int y,
+                           int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+  ArtRgbaSVPAlphaData *data = callback_data;
+  art_u8 *linebuf;
+  int run_x0, run_x1;
+  art_u32 running_sum = start;
+  int x0, x1;
+  int k;
+  art_u8 r, g, b;
+  int *alphatab;
+  int alpha;
+
+  linebuf = data->buf;
+  x0 = data->x0;
+  x1 = data->x1;
+
+  r = data->r;
+  g = data->g;
+  b = data->b;
+  alphatab = data->alphatab;
+
+  if (n_steps > 0)
+    {
+      run_x1 = steps[0].x;
+      if (run_x1 > x0)
+       {
+         alpha = (running_sum >> 16) & 0xff;
+         if (alpha)
+           art_rgba_run_alpha (linebuf,
+                              r, g, b, alphatab[alpha],
+                              run_x1 - x0);
+       }
+
+      /* render the steps into tmpbuf */
+      for (k = 0; k < n_steps - 1; k++)
+       {
+         running_sum += steps[k].delta;
+         run_x0 = run_x1;
+         run_x1 = steps[k + 1].x;
+         if (run_x1 > run_x0)
+           {
+             alpha = (running_sum >> 16) & 0xff;
+             if (alpha)
+               art_rgba_run_alpha (linebuf + (run_x0 - x0) * 4,
+                                  r, g, b, alphatab[alpha],
+                                  run_x1 - run_x0);
+           }
+       }
+      running_sum += steps[k].delta;
+      if (x1 > run_x1)
+       {
+         alpha = (running_sum >> 16) & 0xff;
+         if (alpha)
+           art_rgba_run_alpha (linebuf + (run_x1 - x0) * 4,
+                              r, g, b, alphatab[alpha],
+                              x1 - run_x1);
+       }
+    }
+  else
+    {
+      alpha = (running_sum >> 16) & 0xff;
+      if (alpha)
+       art_rgba_run_alpha (linebuf,
+                          r, g, b, alphatab[alpha],
+                          x1 - x0);
+    }
+
+  data->buf += data->rowstride;
+}
+
+static void
+art_rgba_svp_alpha_opaque_callback (void *callback_data, int y,
+                                  int start,
+                                  ArtSVPRenderAAStep *steps, int n_steps)
+{
+  ArtRgbaSVPAlphaData *data = callback_data;
+  art_u8 *linebuf;
+  int run_x0, run_x1;
+  art_u32 running_sum = start;
+  int x0, x1;
+  int k;
+  art_u8 r, g, b;
+  int *alphatab;
+  int alpha;
+
+  linebuf = data->buf;
+  x0 = data->x0;
+  x1 = data->x1;
+
+  r = data->r;
+  g = data->g;
+  b = data->b;
+  alphatab = data->alphatab;
+
+  if (n_steps > 0)
+    {
+      run_x1 = steps[0].x;
+      if (run_x1 > x0)
+       {
+         alpha = running_sum >> 16;
+         if (alpha)
+           {
+             if (alpha >= 255)
+               art_rgba_fill_run (linebuf,
+                                 r, g, b,
+                                 run_x1 - x0);
+             else
+               art_rgba_run_alpha (linebuf,
+                                  r, g, b, alphatab[alpha],
+                                  run_x1 - x0);
+           }
+       }
+
+      /* render the steps into tmpbuf */
+      for (k = 0; k < n_steps - 1; k++)
+       {
+         running_sum += steps[k].delta;
+         run_x0 = run_x1;
+         run_x1 = steps[k + 1].x;
+         if (run_x1 > run_x0)
+           {
+             alpha = running_sum >> 16;
+             if (alpha)
+               {
+                 if (alpha >= 255)
+                   art_rgba_fill_run (linebuf + (run_x0 - x0) * 4,
+                                     r, g, b,
+                                     run_x1 - run_x0);
+                 else
+                   art_rgba_run_alpha (linebuf + (run_x0 - x0) * 4,
+                                      r, g, b, alphatab[alpha],
+                                      run_x1 - run_x0);
+               }
+           }
+       }
+      running_sum += steps[k].delta;
+      if (x1 > run_x1)
+       {
+         alpha = running_sum >> 16;
+         if (alpha)
+           {
+             if (alpha >= 255)
+               art_rgba_fill_run (linebuf + (run_x1 - x0) * 4,
+                                 r, g, b,
+                                 x1 - run_x1);
+             else
+               art_rgba_run_alpha (linebuf + (run_x1 - x0) * 4,
+                                  r, g, b, alphatab[alpha],
+                                  x1 - run_x1);
+           }
+       }
+    }
+  else
+    {
+      alpha = running_sum >> 16;
+      if (alpha)
+       {
+         if (alpha >= 255)
+           art_rgba_fill_run (linebuf,
+                             r, g, b,
+                             x1 - x0);
+         else
+           art_rgba_run_alpha (linebuf,
+                              r, g, b, alphatab[alpha],
+                              x1 - x0);
+       }
+    }
+
+  data->buf += data->rowstride;
+}
+
+/**
+ * gnome_print_art_rgba_svp_alpha: Alpha-composite sorted vector path over RGBA buffer.
+ * @svp: The source sorted vector path.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @rgba: Color in 0xRRGGBBAA format.
+ * @buf: Destination RGB buffer.
+ * @rowstride: Rowstride of @buf buffer.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Renders the shape specified with @svp over the @buf RGB buffer.
+ * @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
+ * of the rectangle rendered. The new pixels are stored starting at
+ * the first byte of @buf. Thus, the @x0 and @y0 parameters specify
+ * an offset within @svp, and may be tweaked as a way of doing
+ * integer-pixel translations without fiddling with @svp itself.
+ *
+ * The @rgba argument specifies the color for the rendering. Pixels of
+ * entirely 0 winding number are left untouched. Pixels of entirely
+ * 1 winding number have the color @rgba composited over them (ie,
+ * are replaced by the red, green, blue components of @rgba if the alpha
+ * component is 0xff). Pixels of intermediate coverage are interpolated
+ * according to the rule in @alphagamma, or default to linear if
+ * @alphagamma is NULL.
+ **/
+void
+gnome_print_art_rgba_svp_alpha (const ArtSVP *svp,
+                               int x0, int y0, int x1, int y1,
+                               art_u32 rgba,
+                               art_u8 *buf, int rowstride,
+                               ArtAlphaGamma *alphagamma)
+{
+  ArtRgbaSVPAlphaData data;
+  int r, g, b, alpha;
+  int i;
+  int a, da;
+
+  r = rgba >> 24;
+  g = (rgba >> 16) & 0xff;
+  b = (rgba >> 8) & 0xff;
+  alpha = rgba & 0xff;
+
+  data.r = r;
+  data.g = g;
+  data.b = b;
+  data.alpha = alpha;
+
+  a = 0x8000;
+  da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
+
+  for (i = 0; i < 256; i++)
+    {
+      data.alphatab[i] = a >> 16;
+      a += da;
+    }
+
+  data.buf = buf;
+  data.rowstride = rowstride;
+  data.x0 = x0;
+  data.x1 = x1;
+  if (alpha == 255)
+    art_svp_render_aa (svp, x0, y0, x1, y1, art_rgba_svp_alpha_opaque_callback,
+                      &data);
+  else
+    art_svp_render_aa (svp, x0, y0, x1, y1, art_rgba_svp_alpha_callback, &data);
+}
+
+static void
+art_rgba_fill_run (art_u8 * buf, art_u8 r, art_u8 g, art_u8 b, int n)
+{
+       int i;
+
+       for (i = 0; i < n; i++) {
+               * buf++ = r;
+               * buf++ = g;
+               * buf++ = b;
+               * buf++ = 255;
+       }
+}
+
+/* fixme: this */
+
+static void
+art_rgba_run_alpha (art_u8 * buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
+{
+       int i;
+       int br, bg, bb, ba;
+       int cr, cg, cb;
+
+       for (i = 0; i < n; i++) {
+               br = * (buf + 0);
+               bg = * (buf + 1);
+               bb = * (buf + 2);
+               ba = * (buf + 3);
+
+               cr = (br * ba + 0x80) >> 8;
+               cg = (bg * ba + 0x80) >> 8;
+               cb = (bb * ba + 0x80) >> 8;
+
+               * buf++ = cr + (((r - cr) * alpha + 0x80) >> 8);
+               * buf++ = cg + (((g - cg) * alpha + 0x80) >> 8);
+               * buf++ = cb + (((b - cb) * alpha + 0x80) >> 8);
+               * buf++ = ba + (((255 - ba) * alpha + 0x80) >> 8);
+       }
+}
+
+
diff --git a/program/src/art_rgba_svp.h b/program/src/art_rgba_svp.h
new file mode 100644 (file)
index 0000000..4cac175
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef SP_ART_RGBA_SVP_H
+#define SP_ART_RGBA_SVP_H
+
+#include <libart_lgpl/art_misc.h>
+#include <libart_lgpl/art_alphagamma.h>
+#include <libart_lgpl/art_affine.h>
+#include <libart_lgpl/art_svp.h>
+#include <libart_lgpl/art_uta.h>
+
+void
+gnome_print_art_rgba_svp_alpha (const ArtSVP *svp,
+                               int x0, int y0, int x1, int y1,
+                               art_u32 rgba,
+                               art_u8 *buf, int rowstride,
+                               ArtAlphaGamma *alphagamma);
+
+#endif /* SP_ART_RGBA_SVP_H */
index 5a8c289dffcb31d54e2bfac406e8a209ab6efcc8..778ba0800d6298d440f905294b14420b99d2afd8 100644 (file)
@@ -62,7 +62,6 @@ gfx_node_t *gfx_new_node( gfx_canvas_t *canvas,enum gfx_en type){
   node->points = 0;
   node->points_max =0;
   node->closed_path = 0;
-  node->svp = NULL;         /* svp */
   node->filename = NULL;             /* font or image filename */
   node->text = NULL;
   node->x = 0.0;
@@ -114,7 +113,7 @@ gfx_node_t  *gfx_new_dashed_line(gfx_canvas_t *canvas,
   if (vec == NULL) return NULL;
   vec[0].code = ART_MOVETO_OPEN; vec[0].x=X0+LINEOFFSET; vec[0].y=Y0+LINEOFFSET;
   vec[1].code = ART_LINETO; vec[1].x=X1+LINEOFFSET; vec[1].y=Y1+LINEOFFSET;
-  vec[2].code = ART_END;
+  vec[2].code = ART_END; vec[2].x=0;vec[2].y=0;
   
   node->points = 3;
   node->points_max = 3;
@@ -143,7 +142,7 @@ gfx_node_t   *gfx_new_area   (gfx_canvas_t *canvas,
   vec[1].code = ART_LINETO; vec[1].x=X1; vec[1].y=Y1;
   vec[2].code = ART_LINETO; vec[2].x=X2; vec[2].y=Y2;
   vec[3].code = ART_LINETO; vec[3].x=X0; vec[3].y=Y0;
-  vec[4].code = ART_END;
+  vec[4].code = ART_END; vec[4].x=0; vec[4].y=0;
   
   node->points = 5;
   node->points_max = 5;
@@ -496,14 +495,23 @@ int           gfx_render_png (gfx_canvas_t *canvas,
     
     FT_Library    library;
     gfx_node_t *node = canvas->firstnode;    
+    /*
     art_u8 red = background >> 24, green = (background >> 16) & 0xff;
     art_u8 blue = (background >> 8) & 0xff, alpha = ( background & 0xff );
+    */
     unsigned long pys_width = width * canvas->zoom;
     unsigned long pys_height = height * canvas->zoom;
-    const int bytes_per_pixel = 3;
+    const int bytes_per_pixel = 4;
     unsigned long rowstride = pys_width*bytes_per_pixel; /* bytes per pixel */
     art_u8 *buffer = art_new (art_u8, rowstride*pys_height);
-    art_rgb_run_alpha (buffer, red, green, blue, alpha, pys_width*pys_height);
+    /* fill that buffer with out background color */
+    gfx_color_t *buffp;
+    long i;
+    for (i=0,buffp=(gfx_color_t *)buffer;
+         i<pys_width*pys_height;
+        i++){
+       *(buffp++)=background;
+    }
     FT_Init_FreeType( &library );
     while(node){
         switch (node->type) {
@@ -526,20 +534,21 @@ int           gfx_render_png (gfx_canvas_t *canvas,
             } else {
                 svp  = art_svp_from_vpath ( pvec );
                 svpt = art_svp_uncross( svp );
-                art_free(svp);
+                art_svp_free(svp);
                svp  = art_svp_rewind_uncrossed(svpt,ART_WIND_RULE_NONZERO); 
-                art_free(svpt);
+                art_svp_free(svpt);
             }
             art_free(pvec);
-            art_rgb_svp_alpha (svp ,0,0, pys_width, pys_height,
-                               node->color, buffer, rowstride, NULL);
-            art_free(svp);
+           /* this is from gnome since libart does not have this yet */
+            gnome_print_art_rgba_svp_alpha (svp ,0,0, pys_width, pys_height,
+                                node->color, buffer, rowstride, NULL);
+            art_svp_free(svp);
             break;
         }
         case GFX_TEXT: {
             unsigned int  n;
             int  error;
-            art_u8 fcolor[3],falpha;
+            art_u8 fcolor[4],falpha;
             FT_Face       face;
             gfx_char      glyph;
             gfx_string    string;
@@ -547,7 +556,7 @@ int           gfx_render_png (gfx_canvas_t *canvas,
 
             float pen_x = 0.0 , pen_y = 0.0;
             /* double x,y; */
-            long   ix,iy,iz;
+            long   ix,iy;
             
             fcolor[0] = node->color >> 24;
             fcolor[1] = (node->color >> 16) & 0xff;
@@ -601,7 +610,7 @@ int           gfx_render_png (gfx_canvas_t *canvas,
                 int gr;
                 FT_Glyph        image;
                 FT_BitmapGlyph  bit;
-
+               /* long buf_x,comp_n; */
                /* make copy to transform */
                 if (! glyph->image) {
                   fprintf (stderr, "no image\n");
@@ -618,9 +627,44 @@ int           gfx_render_png (gfx_canvas_t *canvas,
                 FT_Vector_Transform (&vec, &string->transform);
 
                 bit = (FT_BitmapGlyph) image;
-
                 gr = bit->bitmap.num_grays -1;
-                for (iy=0; iy < bit->bitmap.rows; iy++){
+/* 
+               buf_x = (pen_x + 0.5) + (double)bit->left;
+               comp_n = buf_x + bit->bitmap.width > pys_width ? pys_width - buf_x : bit->bitmap.width;
+                if (buf_x < 0 || buf_x >= (long)pys_width) continue;
+               buf_x *=  bytes_per_pixel ;
+               for (iy=0; iy < bit->bitmap.rows; iy++){                    
+                   long buf_y = iy+(pen_y+0.5)-(double)bit->top;
+                   if (buf_y < 0 || buf_y >= (long)pys_height) continue;
+                    buf_y *= rowstride;
+                   for (ix=0;ix < bit->bitmap.width;ix++){             
+                       *(letter + (ix*bytes_per_pixel+3)) = *(bit->bitmap.buffer + iy * bit->bitmap.width + ix);
+                   }
+                   art_rgba_rgba_composite(buffer + buf_y + buf_x ,letter,comp_n);
+                }
+                art_free(letter);
+*/
+
+                for (iy=0; iy < bit->bitmap.rows; iy++){                   
+                    long buf_y = iy+(pen_y+0.5)-bit->top;
+                    if (buf_y < 0 || buf_y >= (long)pys_height) continue;
+                    buf_y *= rowstride;
+                    for (ix=0;ix < bit->bitmap.width;ix++){
+                        long buf_x = ix + (pen_x + 0.5) + (double)bit->left ;
+                        art_u8 font_alpha;
+                        
+                        if (buf_x < 0 || buf_x >= (long)pys_width) continue;
+                        buf_x *=  bytes_per_pixel ;
+                        font_alpha =  *(bit->bitmap.buffer + iy * bit->bitmap.width + ix);
+                       if (font_alpha > 0){
+                               fcolor[3] =  (art_u8)((double)font_alpha / gr * falpha);
+                               art_rgba_rgba_composite(buffer + buf_y + buf_x ,fcolor,1);
+                        }
+                    }
+                }
+
+/*
+                for (iy=0; iy < bit->bitmap.rows; iy++){                   
                     long buf_y = iy+(pen_y+0.5)-bit->top;
                     if (buf_y < 0 || buf_y >= (long)pys_height) continue;
                     buf_y *= rowstride;
@@ -639,6 +683,7 @@ int           gfx_render_png (gfx_canvas_t *canvas,
                         }
                     }
                 }
+*/
                 FT_Done_Glyph (image);
             }
             gfx_string_destroy(string);
@@ -660,12 +705,12 @@ gfx_destroy    (gfx_canvas_t *canvas){
   while(node){
     next = node->next;
     art_free(node->path);
-    art_free(node->svp);
     free(node->text);
     free(node->filename);
     art_free(node);
     node = next;
   }
+  art_free(canvas);
   return 0;
 }
  
@@ -692,6 +737,7 @@ static int gfx_save_png (art_u8 *buffer, FILE *fp,  long width, long height, lon
 
   if (info_ptr == NULL)
     {
+      png_free(png_ptr,row_pointers);
       png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
       return (1);
     }
@@ -705,7 +751,7 @@ static int gfx_save_png (art_u8 *buffer, FILE *fp,  long width, long height, lon
 
   png_init_io(png_ptr, fp);
   png_set_IHDR (png_ptr, info_ptr,width, height,
-                8, PNG_COLOR_TYPE_RGB,
+                8, PNG_COLOR_TYPE_RGB_ALPHA,
                 PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT,
                 PNG_FILTER_TYPE_DEFAULT);
@@ -716,8 +762,9 @@ static int gfx_save_png (art_u8 *buffer, FILE *fp,  long width, long height, lon
   png_set_text (png_ptr, info_ptr, text, 1);
 
   /* lets make this fast */
+  png_set_filter(png_ptr,0,PNG_FILTER_NONE);
   png_set_compression_level(png_ptr,1);
-  png_set_filter(png_ptr,PNG_FILTER_TYPE_BASE,PNG_NO_FILTERS);
+  png_set_compression_strategy(png_ptr,Z_HUFFMAN_ONLY);
   /* 
   png_set_filter(png_ptr,PNG_FILTER_TYPE_BASE,PNG_FILTER_SUB);
   png_set_compression_strategy(png_ptr,Z_HUFFMAN_ONLY);
@@ -730,6 +777,7 @@ static int gfx_save_png (art_u8 *buffer, FILE *fp,  long width, long height, lon
   
   png_write_image(png_ptr, row_pointers);
   png_write_end(png_ptr, info_ptr);
+  png_free(png_ptr,row_pointers);
   png_destroy_write_struct(&png_ptr, &info_ptr);
   return 1;
 }
index 29121328cbf89c1b31f6d9f592bd3cf356e5b7da..8dfc6d3dc8517c3b44ad148a5165bb9da4bb665f 100644 (file)
@@ -9,6 +9,8 @@
 #define LIBART_COMPILATION
 
 #include <libart_lgpl/libart.h>
+#include <libart_lgpl/art_rgba.h>
+#include "art_rgba_svp.h"
 
 enum gfx_if_en {IF_PNG=0,IF_SVG,IF_EPS,IF_PDF};
 enum gfx_en { GFX_LINE=0,GFX_AREA,GFX_TEXT };
@@ -21,13 +23,12 @@ typedef struct  gfx_node_t {
   gfx_color_t   color;        /* color of element  0xRRGGBBAA  alpha 0xff is solid*/
   double        size;         /* font size, line width */
   double        dash_on, dash_off; /* dash line fragments lengths */
-  ArtVpath      *path;        /* path */
   int           closed_path;
   int           points;
   int           points_max;
-  ArtSVP        *svp;         /* svp */
   char *filename;             /* font or image filename */
   char *text;
+  ArtVpath      *path;        /* path */
   double        x,y;          /* position */
   double        angle;        /* text angle */
   enum gfx_h_align_en halign; /* text alignement */
index 64d2e60a7fa645cade1117d4b9bff432c6c1f71e..a0748ad800059c892fa133c079991ded45a2f767 100644 (file)
@@ -2728,7 +2728,9 @@ rrd_graph_init(image_desc_t *im)
 #ifdef HAVE_SETLOCALE
     setlocale(LC_TIME,"");
 #endif
-
+    im->yorigin=0;
+    im->xorigin=0;
+    im->minval=0;
     im->xlab_user.minsec = -1;
     im->ximg=0;
     im->yimg=0;