⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo-ps-surface.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 5 页
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2003 University of Southern California * Copyright © 2005 Red Hat, Inc * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation * (the "LGPL") or, at your option, under the terms of the Mozilla * Public License Version 1.1 (the "MPL"). If you do not alter this * notice, a recipient may use your version of this file under either * the MPL or the LGPL. * * You should have received a copy of the LGPL along with this library * in the file COPYING-LGPL-2.1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * You should have received a copy of the MPL along with this library * in the file COPYING-MPL-1.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY * OF ANY KIND, either express or implied. See the LGPL or the MPL for * the specific language governing rights and limitations. * * The Original Code is the cairo graphics library. * * The Initial Developer of the Original Code is University of Southern * California. * * Contributor(s): *	Carl D. Worth <cworth@cworth.org> *	Kristian Høgsberg <krh@redhat.com> *	Keith Packard <keithp@keithp.com> */#include "cairoint.h"#include "cairo-ps.h"#include "cairo-ps-test.h"#include "cairo-scaled-font-subsets-private.h"#include "cairo-paginated-surface-private.h"#include "cairo-meta-surface-private.h"#include "cairo-ft-private.h"#include "cairo-output-stream-private.h"#include <time.h>#include <zlib.h>static const cairo_surface_backend_t cairo_ps_surface_backend;static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;typedef struct cairo_ps_surface {    cairo_surface_t base;    /* Here final_stream corresponds to the stream/file passed to     * cairo_ps_surface_create surface is built. Meanwhile stream is a     * temporary stream in which the file output is built, (so that     * the header can be built and inserted into the target stream     * before the contents of the temporary stream are copied). */    cairo_output_stream_t *final_stream;    FILE *tmpfile;    cairo_output_stream_t *stream;    double width;    double height;    double max_width;    double max_height;    int num_pages;    cairo_paginated_mode_t paginated_mode;    cairo_scaled_font_subsets_t *font_subsets;    cairo_array_t dsc_header_comments;    cairo_array_t dsc_setup_comments;    cairo_array_t dsc_page_setup_comments;    cairo_array_t *dsc_comment_target;} cairo_ps_surface_t;#define PS_SURFACE_MAX_GLYPHS_PER_FONT	256/* A word wrap stream can be used as a filter to do word wrapping on * top of an existing output stream. The word wrapping is quite * simple, using isspace to determine characters that separate * words. Any word that will cause the column count exceeed the given * max_column will have a '\n' character emitted before it. * * The stream is careful to maintain integrity for words that cross * the boundary from one call to write to the next. * * Note: This stream does not guarantee that the output will never * exceed max_column. In particular, if a single word is larger than * max_column it will not be broken up. */typedef struct _word_wrap_stream {    cairo_output_stream_t base;    cairo_output_stream_t *output;    int max_column;    int column;    cairo_bool_t last_write_was_space;} word_wrap_stream_t;static int_count_word_up_to (const unsigned char *s, int length){    int word = 0;    while (length--) {	if (! isspace (*s++))	    word++;	else	    return word;    }    return word;}static cairo_status_t_word_wrap_stream_write (cairo_output_stream_t  *base,			 const unsigned char	*data,			 unsigned int		 length){    word_wrap_stream_t *stream = (word_wrap_stream_t *) base;    cairo_bool_t newline;    int word;    while (length) {	if (isspace (*data)) {	    newline =  (*data == '\n' || *data == '\r');	    if (! newline && stream->column >= stream->max_column) {		_cairo_output_stream_printf (stream->output, "\n");		stream->column = 0;	    }	    _cairo_output_stream_write (stream->output, data, 1);	    data++;	    length--;	    if (newline)		stream->column = 0;	    else		stream->column++;	    stream->last_write_was_space = TRUE;	} else {	    word = _count_word_up_to (data, length);	    /* Don't wrap if this word is a continuation of a word	     * from a previous call to write. */	    if (stream->column + word >= stream->max_column &&		stream->last_write_was_space)	    {		_cairo_output_stream_printf (stream->output, "\n");		stream->column = 0;	    }	    _cairo_output_stream_write (stream->output, data, word);	    data += word;	    length -= word;	    stream->column += word;	    stream->last_write_was_space = FALSE;	}    }    return _cairo_output_stream_get_status (stream->output);}static cairo_status_t_word_wrap_stream_close (cairo_output_stream_t *base){    word_wrap_stream_t *stream = (word_wrap_stream_t *) base;    return _cairo_output_stream_get_status (stream->output);}static cairo_output_stream_t *_word_wrap_stream_create (cairo_output_stream_t *output, int max_column){    word_wrap_stream_t *stream;    stream = malloc (sizeof (word_wrap_stream_t));    if (stream == NULL)	return (cairo_output_stream_t *) &cairo_output_stream_nil;    _cairo_output_stream_init (&stream->base,			       _word_wrap_stream_write,			       _word_wrap_stream_close);    stream->output = output;    stream->max_column = max_column;    stream->column = 0;    stream->last_write_was_space = FALSE;    return &stream->base;}typedef struct _ps_path_info {    cairo_ps_surface_t *surface;    cairo_output_stream_t *stream;    cairo_line_cap_t line_cap;    cairo_point_t last_move_to_point;    cairo_bool_t has_sub_path;} ps_path_info_t;static cairo_status_t_cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point){    ps_path_info_t *path_info = closure;    path_info->last_move_to_point = *point;    path_info->has_sub_path = FALSE;    _cairo_output_stream_printf (path_info->stream,				 "%f %f moveto ",				 _cairo_fixed_to_double (point->x),				 _cairo_fixed_to_double (point->y));    return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point){    ps_path_info_t *path_info = closure;    if (path_info->line_cap != CAIRO_LINE_CAP_ROUND &&	! path_info->has_sub_path &&	point->x == path_info->last_move_to_point.x &&	point->y == path_info->last_move_to_point.y)    {	return CAIRO_STATUS_SUCCESS;    }    path_info->has_sub_path = TRUE;    _cairo_output_stream_printf (path_info->stream,				 "%f %f lineto ",				 _cairo_fixed_to_double (point->x),				 _cairo_fixed_to_double (point->y));    return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_ps_surface_path_curve_to (void          *closure,				 cairo_point_t *b,				 cairo_point_t *c,				 cairo_point_t *d){    ps_path_info_t *path_info = closure;    path_info->has_sub_path = TRUE;    _cairo_output_stream_printf (path_info->stream,				 "%f %f %f %f %f %f curveto ",				 _cairo_fixed_to_double (b->x),				 _cairo_fixed_to_double (b->y),				 _cairo_fixed_to_double (c->x),				 _cairo_fixed_to_double (c->y),				 _cairo_fixed_to_double (d->x),				 _cairo_fixed_to_double (d->y));    return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_ps_surface_path_close_path (void *closure){    ps_path_info_t *path_info = closure;    if (path_info->line_cap != CAIRO_LINE_CAP_ROUND &&	! path_info->has_sub_path)    {	return CAIRO_STATUS_SUCCESS;    }    _cairo_output_stream_printf (path_info->stream,				 "closepath\n");    return CAIRO_STATUS_SUCCESS;}/* The line cap value is needed to workaround the fact that PostScript * semnatics for stroking degenerate sub-paths do not match cairo * semantics. (PostScript draws something for any line cap value, * while cairo draws something only for round caps). * * When using this function to emit a path to be filled, rather than * stroked, simply pass CAIRO_LINE_CAP_ROUND which will guarantee that * the stroke workaround will not modify the path being emitted. */static cairo_status_t_cairo_ps_surface_emit_path (cairo_ps_surface_t	   *surface,			     cairo_output_stream_t *stream,			     cairo_path_fixed_t    *path,			     cairo_line_cap_t	    line_cap){    cairo_output_stream_t *word_wrap;    cairo_status_t status;    ps_path_info_t path_info;    word_wrap = _word_wrap_stream_create (stream, 79);    path_info.surface = surface;    path_info.stream = word_wrap;    path_info.line_cap = line_cap;    status = _cairo_path_fixed_interpret (path,					  CAIRO_DIRECTION_FORWARD,					  _cairo_ps_surface_path_move_to,					  _cairo_ps_surface_path_line_to,					  _cairo_ps_surface_path_curve_to,					  _cairo_ps_surface_path_close_path,					  &path_info);    _cairo_output_stream_destroy (word_wrap);    return status;}static void_cairo_ps_surface_emit_header (cairo_ps_surface_t *surface){    time_t now;    char **comments;    int i, num_comments;    now = time (NULL);    _cairo_output_stream_printf (surface->final_stream,				 "%%!PS-Adobe-3.0\n"				 "%%%%Creator: cairo (http://cairographics.org)\n"				 "%%%%CreationDate: %s"				 "%%%%Pages: %d\n"				 "%%%%BoundingBox: %d %d %d %d\n",				 ctime (&now),				 surface->num_pages,				 0, 0,				 (int) ceil (surface->max_width),				 (int) ceil (surface->max_height));    _cairo_output_stream_printf (surface->final_stream,				 "%%%%DocumentData: Clean7Bit\n"				 "%%%%LanguageLevel: 2\n");    num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);    comments = _cairo_array_index (&surface->dsc_header_comments, 0);    for (i = 0; i < num_comments; i++) {	_cairo_output_stream_printf (surface->final_stream,				     "%s\n", comments[i]);	free (comments[i]);	comments[i] = NULL;    }    _cairo_output_stream_printf (surface->final_stream,				 "%%%%EndComments\n");    _cairo_output_stream_printf (surface->final_stream,				 "%%%%BeginProlog\n"				 "/C{curveto}bind def\n"				 "/F{fill}bind def\n"				 "/G{setgray}bind def\n"				 "/L{lineto}bind def\n"				 "/M{moveto}bind def\n"				 "/P{closepath}bind def\n"				 "/R{setrgbcolor}bind def\n"				 "/S{show}bind def\n"				 "%%%%EndProlog\n");    num_comments = _cairo_array_num_elements (&surface->dsc_setup_comments);    if (num_comments) {	_cairo_output_stream_printf (surface->final_stream,				     "%%%%BeginSetup\n");	comments = _cairo_array_index (&surface->dsc_setup_comments, 0);	for (i = 0; i < num_comments; i++) {	    _cairo_output_stream_printf (surface->final_stream,					 "%s\n", comments[i]);	    free (comments[i]);	    comments[i] = NULL;	}	_cairo_output_stream_printf (surface->final_stream,				     "%%%%EndSetup\n");    }}static cairo_status_t_cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t		*surface,					  cairo_scaled_font_subset_t	*font_subset){    cairo_type1_subset_t subset;    cairo_status_t status;    int length;    char name[64];    snprintf (name, sizeof name, "CairoFont-%d-%d",	      font_subset->font_id, font_subset->subset_id);    status = _cairo_type1_subset_init (&subset, name, font_subset);    if (status)	return status;    /* FIXME: Figure out document structure convention for fonts */    _cairo_output_stream_printf (surface->final_stream,				 "%% _cairo_ps_surface_emit_type1_font_subset\n");    length = subset.header_length + subset.data_length + subset.trailer_length;    _cairo_output_stream_write (surface->final_stream, subset.data, length);    _cairo_type1_subset_fini (&subset);    return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t		*surface,					     cairo_scaled_font_subset_t	*font_subset){    cairo_truetype_subset_t subset;    cairo_status_t status;    int i;    status = _cairo_truetype_subset_init (&subset, font_subset);    if (status)	return status;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -