1
/*
2
 * Copyright © 2005 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
 * Author: Carl D. Worth <cworth@cworth.org>
24
 */
25

            
26
#include "cairo-test.h"
27

            
28
#include <sys/types.h>
29
#include <sys/stat.h>
30
#ifdef HAVE_UNISTD_H
31
#include <unistd.h>
32
#endif
33

            
34
#include <cairo-ft.h>
35
#include <fontconfig/fontconfig.h>
36
#include <fontconfig/fcfreetype.h>
37

            
38
#define FONT "6x13.pcf"
39
#define TEXT_SIZE 13
40

            
41
static cairo_bool_t
42
33
font_extents_equal (const cairo_font_extents_t *A,
43
	            const cairo_font_extents_t *B)
44
{
45
    return
46
66
	CAIRO_TEST_DOUBLE_EQUALS (A->ascent,  B->ascent)  &&
47
33
	CAIRO_TEST_DOUBLE_EQUALS (A->descent, B->descent) &&
48
33
	CAIRO_TEST_DOUBLE_EQUALS (A->height,  B->height)  &&
49
99
	CAIRO_TEST_DOUBLE_EQUALS (A->max_x_advance, B->max_x_advance) &&
50
33
	CAIRO_TEST_DOUBLE_EQUALS (A->max_y_advance, B->max_y_advance);
51
}
52

            
53
static cairo_test_status_t
54
33
check_font_extents (const cairo_test_context_t *ctx, cairo_t *cr, const char *comment)
55
{
56
33
    cairo_font_extents_t font_extents, ref_font_extents = {11, 2, 13, 6, 0};
57
    cairo_status_t status;
58

            
59
33
    memset (&font_extents, 0xff, sizeof (cairo_font_extents_t));
60
33
    cairo_font_extents (cr, &font_extents);
61

            
62
33
    status = cairo_status (cr);
63
33
    if (status)
64
	return cairo_test_status_from_status (ctx, status);
65

            
66
33
    if (! font_extents_equal (&font_extents, &ref_font_extents)) {
67
	cairo_test_log (ctx, "Error: %s: cairo_font_extents(); extents (%g, %g, %g, %g, %g)\n",
68
			comment,
69
		        font_extents.ascent, font_extents.descent,
70
			font_extents.height,
71
			font_extents.max_x_advance, font_extents.max_y_advance);
72
	return CAIRO_TEST_FAILURE;
73
    }
74

            
75
33
    return CAIRO_TEST_SUCCESS;
76
}
77

            
78
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
79
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
80
#endif
81

            
82
static cairo_test_status_t
83
3
draw (cairo_t *cr, int width, int height)
84
{
85
3
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
86
    FcPattern *pattern;
87
    cairo_font_face_t *font_face;
88
    cairo_font_extents_t font_extents;
89
    cairo_font_options_t *font_options;
90
    cairo_status_t status;
91
    char *filename;
92
    int face_count;
93
    struct stat stat_buf;
94

            
95
3
    xasprintf (&filename, "%s/%s", ctx->srcdir, FONT);
96

            
97
3
    if (stat (filename, &stat_buf) || ! S_ISREG (stat_buf.st_mode)) {
98
	cairo_test_log (ctx, "Error finding font: %s: file not found?\n", filename);
99
	return CAIRO_TEST_FAILURE;
100
    }
101

            
102
3
    pattern = FcFreeTypeQuery ((unsigned char *)filename, 0, NULL, &face_count);
103
3
    if (! pattern) {
104
	cairo_test_log (ctx, "FcFreeTypeQuery failed.\n");
105
	free (filename);
106
	return cairo_test_status_from_status (ctx, CAIRO_STATUS_NO_MEMORY);
107
    }
108

            
109
3
    font_face = cairo_ft_font_face_create_for_pattern (pattern);
110
3
    FcPatternDestroy (pattern);
111

            
112
3
    status = cairo_font_face_status (font_face);
113
3
    if (status) {
114
	cairo_test_log (ctx, "Error creating font face for %s: %s\n",
115
			filename,
116
			cairo_status_to_string (status));
117
	free (filename);
118
	return cairo_test_status_from_status (ctx, status);
119
    }
120

            
121
3
    free (filename);
122
3
    if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_FT) {
123
	cairo_test_log (ctx, "Unexpected value from cairo_font_face_get_type: %d (expected %d)\n",
124
			cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_FT);
125
	cairo_font_face_destroy (font_face);
126
	return CAIRO_TEST_FAILURE;
127
    }
128

            
129
3
    cairo_set_font_face (cr, font_face);
130
3
    cairo_font_face_destroy (font_face);
131
3
    cairo_set_font_size (cr, 13);
132

            
133
3
    font_options = cairo_font_options_create ();
134

            
135
#define CHECK_FONT_EXTENTS(comment) do {\
136
    cairo_test_status_t test_status; \
137
    test_status = check_font_extents (ctx, cr, (comment)); \
138
    if (test_status != CAIRO_TEST_SUCCESS) { \
139
	cairo_font_options_destroy (font_options); \
140
	return test_status; \
141
    } \
142
} while (0)
143

            
144
3
    cairo_font_extents (cr, &font_extents);
145
3
    CHECK_FONT_EXTENTS ("default");
146

            
147
3
    cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON);
148
3
    cairo_set_font_options (cr, font_options);
149

            
150
3
    CHECK_FONT_EXTENTS ("HINT_METRICS_ON");
151

            
152
3
    cairo_move_to (cr, 1, font_extents.ascent - 1);
153
3
    cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */
154

            
155
3
    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
156
3
    cairo_set_font_options (cr, font_options);
157
3
    CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_NONE");
158
3
    cairo_show_text (cr, "the ");
159

            
160
3
    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_SLIGHT);
161
3
    cairo_set_font_options (cr, font_options);
162
3
    CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_SLIGHT");
163
3
    cairo_show_text (cr, "quick ");
164

            
165
3
    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_MEDIUM);
166
3
    cairo_set_font_options (cr, font_options);
167
3
    CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_MEDIUM");
168
3
    cairo_show_text (cr, "brown");
169

            
170
3
    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_FULL);
171
3
    cairo_set_font_options (cr, font_options);
172
3
    CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_FULL");
173
3
    cairo_show_text (cr, " fox");
174

            
175
    /* Switch from show_text to text_path/fill to exercise bug #7889 */
176
3
    cairo_text_path (cr, " jumps over a lazy dog");
177
3
    cairo_fill (cr);
178

            
179
    /* And test it rotated as well for the sake of bug #7888 */
180

            
181
3
    cairo_translate (cr, width, height);
182
3
    cairo_rotate (cr, M_PI);
183

            
184
3
    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_DEFAULT);
185
3
    cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
186
3
    cairo_set_font_options (cr, font_options);
187
3
    CHECK_FONT_EXTENTS ("HINT_METRICS_OFF");
188

            
189
3
    cairo_move_to (cr, 1, font_extents.height - font_extents.descent - 1);
190

            
191
3
    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
192
3
    cairo_set_font_options (cr, font_options);
193
3
    CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_NONE");
194
3
    cairo_show_text (cr, "the ");
195

            
196
3
    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_SLIGHT);
197
3
    cairo_set_font_options (cr, font_options);
198
3
    CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_SLIGHT");
199
3
    cairo_show_text (cr, "quick");
200

            
201
3
    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_MEDIUM);
202
3
    cairo_set_font_options (cr, font_options);
203
3
    CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_MEDIUM");
204
3
    cairo_show_text (cr, " brown");
205

            
206
3
    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_FULL);
207
3
    cairo_set_font_options (cr, font_options);
208
3
    CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_FULL");
209
3
    cairo_show_text (cr, " fox");
210

            
211
3
    cairo_text_path (cr, " jumps over");
212
3
    cairo_text_path (cr, " a lazy dog");
213
3
    cairo_fill (cr);
214

            
215
3
    cairo_font_options_destroy (font_options);
216

            
217
3
    return CAIRO_TEST_SUCCESS;
218
}
219

            
220
1
CAIRO_TEST (bitmap_font,
221
	    "Test drawing with a font consisting only of bitmaps"
222
	    "\nThe PDF and PS backends embed a slightly distorted font for the rotated case.",
223
	    "text", /* keywords */
224
	    "ft", /* requirements */
225
	    246 + 1, 2 * TEXT_SIZE,
226
	    NULL, draw)