summaryrefslogtreecommitdiff
path: root/src/cairo-paginated-surface-private.h
blob: b5e4d5c9b8089ad16d37887ccf543911c0f54cc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* cairo - a vector graphics library with display and print output
 *
 * 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 Red Hat, Inc.
 *
 * Contributor(s):
 *	Carl Worth <cworth@cworth.org>
 */

#ifndef CAIRO_PAGINATED_SURFACE_H
#define CAIRO_PAGINATED_SURFACE_H

#include "cairoint.h"

typedef enum {
    CAIRO_PAGINATED_MODE_ANALYZE,	/* analyze page regions */
    CAIRO_PAGINATED_MODE_RENDER		/* render page contents */
} cairo_paginated_mode_t;

typedef struct _cairo_paginated_surface_backend {
    /* Optional. Will be called once for each page.
     *
     * NOTE: With respect to the order of drawing operations as seen
     * by the target, this call will occur before any drawing
     * operations for the relevant page. However, with respect to the
     * function calls as made by the user, this call will be *after*
     * any drawing operations for the page, (that is, it will occur
     * during the user's call to cairo_show_page or cairo_copy_page).
     */
    cairo_int_status_t
    (*start_page)		(void			*surface);

    /* Required. Will be called twice for each page, once with an
     * argument of CAIRO_PAGINATED_MODE_ANALYZE and once with
     * CAIRO_PAGINATED_MODE_RENDER. See more details in the
     * documentation for _cairo_paginated_surface_create below.
     */
    void
    (*set_paginated_mode)	(void			*surface,
				 cairo_paginated_mode_t	 mode);
} cairo_paginated_surface_backend_t;

/* A cairo_paginated_surface provides a very convenient wrapper that
 * is well-suited for doing the analysis common to most surfaces that
 * have paginated output, (that is, things directed at printers, or
 * for saving content in files such as PostScript or PDF files).
 *
 * To use the paginated surface, you'll first need to create your
 * 'real' surface using _cairo_surface_init and the standard
 * cairo_surface_backend_t. Then you also call
 * _cairo_paginated_surface_create which takes its own, much simpler,
 * cairo_paginated_surface_backend. You are free to return the result
 * of _cairo_paginated_surface_create from your public
 * cairo_<foo>_surface_create. The paginated backend will be careful
 * to not let the user see that they really got a "wrapped"
 * surface. See test-paginated-surface.c for a fairly minimal example
 * of a paginated-using surface. That should be a reasonable example
 * to follow.
 *
 * What the paginated surface does is first save all drawing
 * operations for a page into a meta-surface. Then when the user calls
 * cairo_show_page, the paginated surface performs the following
 * sequence of operations (using the backend functions passed to
 * cairo_paginated_surface_create):
 *
 * 1. Calls start_page (if non NULL). At this point, it is appropriate
 *    for the target to emit any page-specific header information into
 *    its output.
 *
 * 2. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_ANALYZE
 *
 * 3. Replays the meta-surface to the target surface, (with an
 *    analysis surface inserted between which watches the return value
 *    from each operation). This analysis stage is used to decide which
 *    operations will require fallbacks.
 *
 * 4. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_RENDER
 *
 * 5. Replays a subset of the meta-surface operations to the target surface
 *
 * 6. Replays the remaining operations to an image surface, sets an
 *    appropriate clip on the target, then paints the resulting image
 *    surface to the target.
 *
 * So, the target will see drawing operations during two separate
 * stages, (ANALYZE and RENDER). During the ANALYZE phase the target
 * should not actually perform any rendering, (for example, if
 * performing output to a file, no output should be generated during
 * this stage). Instead the drawing functions simply need to return
 * CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to indicate
 * whether rendering would be supported. And it should do this as
 * quickly as possible.
 *
 * NOTE: The paginated surface layer assumes that the target surface
 * is "blank" by default at the beginning of each page, without any
 * need for an explicit erasea operation, (as opposed to an image
 * surface, for example, which might have uninitialized content
 * originally). As such, it optimizes away CLEAR operations that
 * happen at the beginning of each page---the target surface will not
 * even see these operations.
 */
cairo_private cairo_surface_t *
_cairo_paginated_surface_create (cairo_surface_t				*target,
				 cairo_content_t				 content,
				 int						 width,
				 int						 height,
				 const cairo_paginated_surface_backend_t	*backend);

cairo_private cairo_surface_t *
_cairo_paginated_surface_get_target (cairo_surface_t *surface);

cairo_private cairo_bool_t
_cairo_surface_is_paginated (cairo_surface_t *surface);

#endif /* CAIRO_PAGINATED_SURFACE_H */