From f9e5bd6a9d41c4607291cbbd88280129184ab325 Mon Sep 17 00:00:00 2001 From: oetiker Date: Mon, 11 Apr 2005 09:51:22 +0000 Subject: [PATCH] * we are now creating true RGBA pngs * removed all memory leeks from rrd_gfx git-svn-id: svn://svn.oetiker.ch/rrdtool/branches/1.2/program@393 a5681a0c-68f1-0310-ab6d-d61299d08faa --- src/Makefile.am | 9 +- src/art_rgb_affine_private.h | 39 +++++ src/art_rgba_rgba_affine.c | 150 +++++++++++++++++++ src/art_rgba_rgba_affine.h | 80 +++++++++++ src/art_rgba_svp.c | 332 +++++++++++++++++++++++++++++++++++++++++++ src/art_rgba_svp.h | 17 +++ src/rrd_gfx.c | 84 ++++++++--- src/rrd_gfx.h | 5 +- src/rrd_graph.c | 4 +- 9 files changed, 698 insertions(+), 22 deletions(-) create mode 100644 src/art_rgb_affine_private.h create mode 100644 src/art_rgba_rgba_affine.c create mode 100644 src/art_rgba_rgba_affine.h create mode 100644 src/art_rgba_svp.c create mode 100644 src/art_rgba_svp.h diff --git a/src/Makefile.am b/src/Makefile.am index df9aa94..6f3928c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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/src/art_rgb_affine_private.h b/src/art_rgb_affine_private.h new file mode 100644 index 0000000..edaf0e3 --- /dev/null +++ b/src/art_rgb_affine_private.h @@ -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/src/art_rgba_rgba_affine.c b/src/art_rgba_rgba_affine.c new file mode 100644 index 0000000..b6e6f48 --- /dev/null +++ b/src/art_rgba_rgba_affine.c @@ -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 +#include +#include +#include + +#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/src/art_rgba_rgba_affine.h b/src/art_rgba_rgba_affine.h new file mode 100644 index 0000000..3afc120 --- /dev/null +++ b/src/art_rgba_rgba_affine.h @@ -0,0 +1,80 @@ +#ifndef SP_ART_RGBA_RGBA_AFFINE_H +#define SP_ART_RGBA_RGBA_AFFINE_H + +/* + * Lauris Kaplinski + * + * 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 +#include +#include +#include + +/* 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/src/art_rgba_svp.c b/src/art_rgba_svp.c new file mode 100644 index 0000000..81457d0 --- /dev/null +++ b/src/art_rgba_svp.c @@ -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 + * Lauris Kaplinski + * + * Copyright (C) 1998 Raph Levien + * + */ + +#define SP_ART_RGBA_SVP_C + +/* Render a sorted vector path into an RGBA buffer. */ + +#include +#include +#include +#include + +#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/src/art_rgba_svp.h b/src/art_rgba_svp.h new file mode 100644 index 0000000..4cac175 --- /dev/null +++ b/src/art_rgba_svp.h @@ -0,0 +1,17 @@ +#ifndef SP_ART_RGBA_SVP_H +#define SP_ART_RGBA_SVP_H + +#include +#include +#include +#include +#include + +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 */ diff --git a/src/rrd_gfx.c b/src/rrd_gfx.c index 5a8c289..778ba08 100644 --- a/src/rrd_gfx.c +++ b/src/rrd_gfx.c @@ -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; + itype) { @@ -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; } diff --git a/src/rrd_gfx.h b/src/rrd_gfx.h index 2912132..8dfc6d3 100644 --- a/src/rrd_gfx.h +++ b/src/rrd_gfx.h @@ -9,6 +9,8 @@ #define LIBART_COMPILATION #include +#include +#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 */ diff --git a/src/rrd_graph.c b/src/rrd_graph.c index 64d2e60..a0748ad 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -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; -- 2.11.0