source: trunk/third/librsvg/test-ft.c @ 17277

Revision 17277, 10.4 KB checked in by amb, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17276, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3   test-ft.c: Testbed for freetype/libart integration.
4 
5   Copyright (C) 2000 Eazel, Inc.
6 
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11 
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   General Public License for more details.
16 
17   You should have received a copy of the GNU General Public
18   License along with this program; if not, write to the
19   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20   Boston, MA 02111-1307, USA.
21 
22   Author: Raph Levien <raph@artofcode.com>
23*/
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <png.h>
28#include <popt.h>
29#include <math.h>
30
31#include <gdk-pixbuf/gdk-pixbuf.h>
32
33#include <freetype/freetype.h>
34
35#include <libart_lgpl/art_misc.h>
36#include <libart_lgpl/art_rect.h>
37#include <libart_lgpl/art_alphagamma.h>
38#include <libart_lgpl/art_affine.h>
39#include <libart_lgpl/art_affine.h>
40#include "art_render.h"
41#include "art_render_mask.h"
42
43#include "rsvg.h"
44#include "rsvg-ft.h"
45
46#if 0
47typedef struct _ArtMaskSourceFT ArtMaskSourceFT;
48
49struct _ArtMaskSourceFT {
50        ArtMaskSource super;
51        ArtRender *render;
52        art_boolean first;
53        const RsvgFTFont *font;
54        const char *text;
55};
56
57void
58art_render_freetype(ArtRender * render, const RsvgFTFont * font,
59                    const char *text, double sx, double sy,
60                    const double affine[6]);
61
62static void
63art_render_ft_done(ArtRenderCallback * self, ArtRender * render)
64{
65        art_free(self);
66}
67
68static int
69art_render_ft_can_drive(ArtMaskSource * self, ArtRender * render)
70{
71        return 0;
72}
73
74static void
75art_render_ft_render(ArtRenderCallback * self, ArtRender * render,
76                     art_u8 * dest, int y)
77{
78}
79
80static void
81art_render_ft_prepare(ArtMaskSource *self, ArtRender *render,
82                      art_boolean first)
83{
84        ArtMaskSourceFT *z = (ArtMaskSourceFT *) self;
85
86        z->first = first;
87        z->super.super.render = art_render_ft_render;
88}
89
90void
91art_render_freetype(ArtRender * render, const RsvgFTFont *font,
92                    const char *text, double sx, double sy,
93                    const double affine[6])
94{
95        ArtMaskSourceFT *mask_source = art_new(ArtMaskSourceFT, 1);
96
97        mask_source->super.super.render = NULL;
98        mask_source->super.super.done = art_render_ft_done;
99        mask_source->super.can_drive = art_render_ft_can_drive;
100        mask_source->super.invoke_driver = NULL;
101        mask_source->super.prepare = art_render_ft_prepare;
102        mask_source->render = render;
103        mask_source->font = font;
104        mask_source->text = text;
105
106        art_render_add_mask_source(render, &mask_source->super);
107}
108#endif
109
110/* The following routine is lifted wholesale from nautilus-icon-factory.c.
111   It should find a permanent home somewhere else, at which point it should
112   be deleted here and simply linked. -RLL
113*/
114
115/* utility routine for saving a pixbuf to a png file.
116 * This was adapted from Iain Holmes' code in gnome-iconedit, and probably
117 * should be in a utility library, possibly in gdk-pixbuf itself.
118 *
119 * It is split up into save_pixbuf_to_file and save_pixbuf_to_file_internal
120 * to work around a gcc warning about handle possibly getting clobbered by
121 * longjmp. Declaring handle 'volatile FILE *' didn't work as it should have.
122 */
123static gboolean
124save_pixbuf_to_file_internal (GdkPixbuf *pixbuf, char *filename, FILE *handle)
125{
126        char *buffer;
127        gboolean has_alpha;
128        int width, height, depth, rowstride;
129        guchar *pixels;
130        png_structp png_ptr;
131        png_infop info_ptr;
132        png_text text[2];
133        int i;
134       
135        png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
136        if (png_ptr == NULL) {
137                return FALSE;
138        }
139
140        info_ptr = png_create_info_struct (png_ptr);
141        if (info_ptr == NULL) {
142                png_destroy_write_struct (&png_ptr, (png_infopp)NULL);
143                return FALSE;
144        }
145
146        if (setjmp (png_ptr->jmpbuf)) {
147                png_destroy_write_struct (&png_ptr, &info_ptr);
148                return FALSE;
149        }
150
151        png_init_io (png_ptr, (FILE *)handle);
152
153        has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
154        width = gdk_pixbuf_get_width (pixbuf);
155        height = gdk_pixbuf_get_height (pixbuf);
156        depth = gdk_pixbuf_get_bits_per_sample (pixbuf);
157        pixels = gdk_pixbuf_get_pixels (pixbuf);
158        rowstride = gdk_pixbuf_get_rowstride (pixbuf);
159
160        png_set_IHDR (png_ptr, info_ptr, width, height,
161                        depth, PNG_COLOR_TYPE_RGB_ALPHA,
162                        PNG_INTERLACE_NONE,
163                        PNG_COMPRESSION_TYPE_DEFAULT,
164                        PNG_FILTER_TYPE_DEFAULT);
165
166        /* Some text to go with the png image */
167        text[0].key = "Title";
168        text[0].text = filename;
169        text[0].compression = PNG_TEXT_COMPRESSION_NONE;
170        text[1].key = "Software";
171        text[1].text = "Test-Rsvg";
172        text[1].compression = PNG_TEXT_COMPRESSION_NONE;
173        png_set_text (png_ptr, info_ptr, text, 2);
174
175        /* Write header data */
176        png_write_info (png_ptr, info_ptr);
177
178        /* if there is no alpha in the data, allocate buffer to expand into */
179        if (has_alpha) {
180                buffer = NULL;
181        } else {
182                buffer = g_malloc(4 * width);
183        }
184       
185        /* pump the raster data into libpng, one scan line at a time */
186        for (i = 0; i < height; i++) {
187                if (has_alpha) {
188                        png_bytep row_pointer = pixels;
189                        png_write_row (png_ptr, row_pointer);
190                } else {
191                        /* expand RGB to RGBA using an opaque alpha value */
192                        int x;
193                        char *buffer_ptr = buffer;
194                        char *source_ptr = pixels;
195                        for (x = 0; x < width; x++) {
196                                *buffer_ptr++ = *source_ptr++;
197                                *buffer_ptr++ = *source_ptr++;
198                                *buffer_ptr++ = *source_ptr++;
199                                *buffer_ptr++ = 255;
200                        }
201                        png_write_row (png_ptr, (png_bytep) buffer);           
202                }
203                pixels += rowstride;
204        }
205       
206        png_write_end (png_ptr, info_ptr);
207        png_destroy_write_struct (&png_ptr, &info_ptr);
208       
209        g_free (buffer);
210
211        return TRUE;
212}
213
214static gboolean
215save_pixbuf_to_file (GdkPixbuf *pixbuf, char *filename)
216{
217        FILE *handle;
218        gboolean result;
219
220        g_return_val_if_fail (pixbuf != NULL, FALSE);
221        g_return_val_if_fail (filename != NULL, FALSE);
222        g_return_val_if_fail (filename[0] != '\0', FALSE);
223
224        if (!strcmp (filename, "-")) {
225                handle = stdout;
226        } else {
227                handle = fopen (filename, "wb");
228        }
229
230        if (handle == NULL) {
231                return FALSE;
232        }
233
234        result = save_pixbuf_to_file_internal (pixbuf, filename, handle);
235        if (!result || handle != stdout)
236                fclose (handle);
237
238        return result;
239}
240
241static void test_pixmap_destroy(guchar * pixels, gpointer data)
242{
243        g_free(pixels);
244}
245
246#if 0
247/**
248 * pixbuf_from_rsvg_ft_glyph: Create a GdkPixbuf from a glyph.
249 * @glyph: The glyph to render as a pixbuf.
250 * @rgb: Foreground color for rendering.
251 *
252 * Renders a glyph as a transparent pixbuf, with foreground color @rgb.
253 *
254 * Return value: the resulting GdkPixbuf.
255 **/
256static GdkPixbuf *
257pixbuf_from_rsvg_ft_glyph (RsvgFTGlyph *glyph, guint32 rgb)
258{
259        GdkPixbuf *pixbuf;
260        int width = glyph->x1 - glyph->x0;
261        int height = glyph->y1 - glyph->y0;
262        int rowstride;
263        art_u8 *pixels;
264        int x, y;
265        const guchar *src_line;
266        art_u8 *dst_line;
267        const art_u8 r = (rgb >> 16) & 0xff;
268        const art_u8 g = (rgb >> 8) & 0xff;
269        const art_u8 b = rgb & 0xff;
270
271        fprintf (stderr, "xpen, ypen = (%f, %f)\n", glyph->xpen, glyph->ypen);
272
273        rowstride = width << 2;
274        pixels = g_new (art_u8, rowstride * height);
275        src_line = glyph->buf;
276        dst_line = pixels;
277        for (y = 0; y < height; y++) {
278                for (x = 0; x < width; x++) {
279                        dst_line[x * 4] = r;
280                        dst_line[x * 4 + 1] = g;
281                        dst_line[x * 4 + 2] = b;
282                        dst_line[x * 4 + 3] = src_line[x];
283                }
284                src_line += glyph->rowstride;
285                dst_line += rowstride;
286        }
287        pixbuf = gdk_pixbuf_new_from_data (pixels,
288                                           GDK_COLORSPACE_RGB,
289                                           1, 8,
290                                           width, height, rowstride,
291                                           test_pixmap_destroy,
292                                           NULL);
293        return pixbuf;
294}
295#endif
296
297static GdkPixbuf *
298glyph_render_test (RsvgFTGlyph *glyph, int glyph_xy[2]) {
299        GdkPixbuf *pixbuf;
300        art_u8 *pixels;
301        int width;
302        int height;
303        int rowstride;
304        ArtRender *render;
305        ArtPixMaxDepth color[3] = {ART_PIX_MAX_FROM_8(0x80), 0, 0 };
306
307        width = glyph->width;
308        height = glyph->height;
309
310        width = 200;
311        height = 200;
312
313        rowstride = width << 2;
314        pixels = g_new (art_u8, rowstride * height);
315
316        render = art_render_new (0, 0, width, height,
317                                 pixels, rowstride,
318                                 3, 8, ART_ALPHA_SEPARATE, NULL);
319        art_render_image_solid (render, color);
320        art_render_mask (render,
321                         glyph_xy[0], glyph_xy[1],
322                         glyph_xy[0] + glyph->width, glyph_xy[1] + glyph->height,
323                         glyph->buf, glyph->rowstride);
324        art_render_invoke (render);
325
326        pixbuf = gdk_pixbuf_new_from_data (pixels,
327                                           GDK_COLORSPACE_RGB,
328                                           1, 8,
329                                           width, height, rowstride,
330                                           test_pixmap_destroy,
331                                           NULL);
332        return pixbuf;
333}
334
335int main(int argc, char **argv)
336{
337        char *out_fn;
338        GdkPixbuf *pixbuf;
339        char *zoom_str = "1.0";
340        int n_iter = 1;
341       
342        gint    font_width = 36;
343        gint    font_height = 36;
344        char    *font_file_name = "/usr/share/fonts/default/Type1/n021003l.pfb";
345
346        poptContext optCtx;
347        struct poptOption optionsTable[] =
348        {
349                {"zoom", 'z', POPT_ARG_STRING, &zoom_str, 0, NULL, "zoom factor"},
350                {"num-iter", 'n', POPT_ARG_INT, &n_iter, 0, NULL, "number of iterations"},
351                {"font-width", 'w', POPT_ARG_INT, &font_width, 0, NULL, "Font Width"},
352                {"font-height", 'h', POPT_ARG_INT, &font_height, 0, NULL, "Font Height"},
353                {"font-file-name", 'f', POPT_ARG_STRING, &font_file_name, 0, NULL, "Font File Name"},
354                POPT_AUTOHELP {NULL, 0, 0, NULL, 0}
355        };
356        char c;
357        const char *const *args;
358        int i;
359
360        RsvgFTCtx *ctx;
361        RsvgFTFontHandle fh;
362
363#if 1
364        const double affine[6] = { .707, -.707, .707, .707, 10, 150 };
365#else
366        double affine[6];
367        art_affine_identity (affine);
368#endif
369
370        optCtx =
371            poptGetContext("test-ft", argc, (const char **) argv,
372                           optionsTable, 0);
373
374        c = poptGetNextOpt(optCtx);
375        args = poptGetArgs(optCtx);
376
377        if (args == NULL || args[0] == NULL)
378                out_fn = "-";
379        else
380                out_fn = (char *) args[0];
381
382        ctx = rsvg_ft_ctx_new ();
383        fh = rsvg_ft_intern (ctx, font_file_name);
384
385        for (i = 0; i < n_iter; i++) {
386                RsvgFTGlyph *glyph;
387                int glyph_xy[2];
388
389
390                glyph = rsvg_ft_render_string (ctx, fh,
391                                               "graphic(s)",
392                                               strlen ("graphic(s)"),
393                                               font_width,
394                                               font_height,
395                                               affine,
396                                               glyph_xy);
397
398/*              fprintf (stderr, "xpen, ypen = (%f, %f)\n", glyph->xpen, glyph->ypen); */
399/*              fprintf (stderr, "glyph_xy = (%d, %d)\n", glyph_xy[0], glyph_xy[1]); */
400
401                glyph_xy[0] = 0; /* += glyph->xpen; */
402                glyph_xy[1] = 0; /* += glyph->ypen; */
403
404                pixbuf = glyph_render_test (glyph, glyph_xy);
405
406                if (pixbuf != NULL) {
407                        if (n_iter > 1)
408                                gdk_pixbuf_unref(pixbuf);
409                        else
410                                save_pixbuf_to_file(pixbuf, out_fn);
411                } else {
412                        fprintf(stderr, "Error rendering.\n");
413                        return 1;
414                }
415        }
416
417        return 0;
418}
Note: See TracBrowser for help on using the repository browser.