41a69e708a1d1b0cb5be641648e061910d12a88b
[framework/graphics/cairo.git] / test / user-font-proxy.c
1 /*
2  * Copyright © 2006, 2008 Red Hat, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software
5  * and its documentation for any purpose is hereby granted without
6  * fee, provided that the above copyright notice appear in all copies
7  * and that both that copyright notice and this permission notice
8  * appear in supporting documentation, and that the name of
9  * Red Hat, Inc. not be used in advertising or publicity pertaining to
10  * distribution of the software without specific, written prior
11  * permission. Red Hat, Inc. makes no representations about the
12  * suitability of this software for any purpose.  It is provided "as
13  * is" without express or implied warranty.
14  *
15  * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
18  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
21  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Contributor(s):
24  *      Kristian Høgsberg <krh@redhat.com>
25  *      Behdad Esfahbod <behdad@behdad.org>
26  */
27
28 #include <stdlib.h>
29 #include <stdio.h>
30
31 #include "cairo-test.h"
32
33 /*#define ROTATED 1*/
34
35 #define BORDER 10
36 #define TEXT_SIZE 64
37 #define WIDTH  (TEXT_SIZE * 12 + 2*BORDER)
38 #ifndef ROTATED
39  #define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
40 #else
41  #define HEIGHT WIDTH
42 #endif
43 #define TEXT   "geez... cairo user-font"
44
45 static cairo_user_data_key_t fallback_font_key;
46
47 static cairo_status_t
48 test_scaled_font_init (cairo_scaled_font_t  *scaled_font,
49                        cairo_t              *cr,
50                        cairo_font_extents_t *extents)
51 {
52     cairo_status_t status;
53
54     cairo_set_font_face (cr,
55                          cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
56                                                         &fallback_font_key));
57
58     status = cairo_scaled_font_set_user_data (scaled_font,
59                                               &fallback_font_key,
60                                               cairo_scaled_font_reference (cairo_get_scaled_font (cr)),
61                                               (cairo_destroy_func_t) cairo_scaled_font_destroy);
62     if (unlikely (status)) {
63         cairo_scaled_font_destroy (cairo_get_scaled_font (cr));
64         return status;
65     }
66
67     cairo_font_extents (cr, extents);
68
69     return CAIRO_STATUS_SUCCESS;
70 }
71
72 static cairo_status_t
73 test_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
74                                unsigned long         glyph,
75                                cairo_t              *cr,
76                                cairo_text_extents_t *extents)
77 {
78     cairo_glyph_t cairo_glyph;
79
80     cairo_glyph.index = glyph;
81     cairo_glyph.x = 0;
82     cairo_glyph.y = 0;
83
84     cairo_set_font_face (cr,
85                          cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
86                                                         &fallback_font_key));
87
88     cairo_show_glyphs (cr, &cairo_glyph, 1);
89     cairo_glyph_extents (cr, &cairo_glyph, 1, extents);
90
91     return CAIRO_STATUS_SUCCESS;
92 }
93
94 static cairo_status_t
95 test_scaled_font_text_to_glyphs (cairo_scaled_font_t        *scaled_font,
96                                  const char                 *utf8,
97                                  int                         utf8_len,
98                                  cairo_glyph_t             **glyphs,
99                                  int                        *num_glyphs,
100                                  cairo_text_cluster_t      **clusters,
101                                  int                        *num_clusters,
102                                  cairo_text_cluster_flags_t *cluster_flags)
103 {
104   cairo_scaled_font_t *fallback_scaled_font;
105
106   fallback_scaled_font = cairo_scaled_font_get_user_data (scaled_font,
107                                                           &fallback_font_key);
108
109   return cairo_scaled_font_text_to_glyphs (fallback_scaled_font, 0, 0,
110                                            utf8, utf8_len,
111                                            glyphs, num_glyphs,
112                                            clusters, num_clusters, cluster_flags);
113 }
114
115 static cairo_status_t
116 _user_font_face_create (cairo_font_face_t **out)
117 {
118     cairo_font_face_t *user_font_face;
119     cairo_font_face_t *fallback_font_face;
120     cairo_status_t status;
121
122     user_font_face = cairo_user_font_face_create ();
123     cairo_user_font_face_set_init_func             (user_font_face, test_scaled_font_init);
124     cairo_user_font_face_set_render_glyph_func     (user_font_face, test_scaled_font_render_glyph);
125     cairo_user_font_face_set_text_to_glyphs_func   (user_font_face, test_scaled_font_text_to_glyphs);
126
127     /* This also happens to be default font face on cairo_t, so does
128      * not make much sense here.  For demonstration only.
129      */
130     fallback_font_face = cairo_toy_font_face_create ("",
131                                                      CAIRO_FONT_SLANT_NORMAL,
132                                                      CAIRO_FONT_WEIGHT_NORMAL);
133
134     status = cairo_font_face_set_user_data (user_font_face,
135                                             &fallback_font_key,
136                                             fallback_font_face,
137                                             (cairo_destroy_func_t) cairo_font_face_destroy);
138     if (status) {
139         cairo_font_face_destroy (fallback_font_face);
140         cairo_font_face_destroy (user_font_face);
141         return status;
142     }
143
144     *out = user_font_face;
145     return CAIRO_STATUS_SUCCESS;
146 }
147
148 static cairo_test_status_t
149 draw (cairo_t *cr, int width, int height)
150 {
151     const char text[] = TEXT;
152     cairo_font_extents_t font_extents;
153     cairo_text_extents_t extents;
154     cairo_font_face_t *font_face;
155     cairo_status_t status;
156
157     cairo_set_source_rgb (cr, 1, 1, 1);
158     cairo_paint (cr);
159
160 #ifdef ROTATED
161     cairo_translate (cr, TEXT_SIZE, 0);
162     cairo_rotate (cr, .6);
163 #endif
164
165     status = _user_font_face_create (&font_face);
166     if (status) {
167         return cairo_test_status_from_status (cairo_test_get_context (cr),
168                                               status);
169     }
170
171     cairo_set_font_face (cr, font_face);
172     cairo_font_face_destroy (font_face);
173
174     cairo_set_font_size (cr, TEXT_SIZE);
175
176     cairo_font_extents (cr, &font_extents);
177     cairo_text_extents (cr, text, &extents);
178
179     /* logical boundaries in red */
180     cairo_move_to (cr, 0, BORDER);
181     cairo_rel_line_to (cr, WIDTH, 0);
182     cairo_move_to (cr, 0, BORDER + font_extents.ascent);
183     cairo_rel_line_to (cr, WIDTH, 0);
184     cairo_move_to (cr, 0, BORDER + font_extents.ascent + font_extents.descent);
185     cairo_rel_line_to (cr, WIDTH, 0);
186     cairo_move_to (cr, BORDER, 0);
187     cairo_rel_line_to (cr, 0, 2*BORDER + TEXT_SIZE);
188     cairo_move_to (cr, BORDER + extents.x_advance, 0);
189     cairo_rel_line_to (cr, 0, 2*BORDER + TEXT_SIZE);
190     cairo_set_source_rgb (cr, 1, 0, 0);
191     cairo_set_line_width (cr, 2);
192     cairo_stroke (cr);
193
194     /* ink boundaries in green */
195     cairo_rectangle (cr,
196                      BORDER + extents.x_bearing, BORDER + font_extents.ascent + extents.y_bearing,
197                      extents.width, extents.height);
198     cairo_set_source_rgb (cr, 0, 1, 0);
199     cairo_set_line_width (cr, 2);
200     cairo_stroke (cr);
201
202     /* text in gray */
203     cairo_set_source_rgb (cr, 0, 0, 0);
204     cairo_move_to (cr, BORDER, BORDER + font_extents.ascent);
205     cairo_show_text (cr, text);
206
207
208     /* filled version of text in light blue */
209     cairo_set_source_rgb (cr, 0, 0, 1);
210     cairo_move_to (cr, BORDER, BORDER + font_extents.height + BORDER + font_extents.ascent);
211     cairo_text_path (cr, text);
212     cairo_fill (cr);
213
214     return CAIRO_TEST_SUCCESS;
215 }
216
217 CAIRO_TEST (user_font_proxy,
218             "Tests a user-font using a native font in its render_glyph",
219             "font, user-font", /* keywords */
220             "cairo >= 1.7.4", /* requirements */
221             WIDTH, HEIGHT,
222             NULL, draw)