Tizen 2.0 Release
[framework/graphics/cairo.git] / test / pthread-show-text.c
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 /* Test case for bug #4299:
27
28    Assertion fails in "cairo-font.c" when using multithreads
29    https://bugs.freedesktop.org/show_bug.cgi?id=4299
30 */
31
32 #include "cairo-test.h"
33
34 #include <string.h>
35 #include <stdlib.h>
36 #include <pthread.h>
37
38 #define N_THREADS 8
39 #define NUM_ITERATIONS 40
40
41 #define WIDTH 400
42 #define HEIGHT 42
43
44 typedef struct {
45   cairo_surface_t *target;
46   int id;
47 } thread_data_t;
48
49 static void *
50 draw_thread (void *arg)
51 {
52     const char *text = "Hello world. ";
53     thread_data_t *thread_data = arg;
54     cairo_surface_t *surface;
55     cairo_font_extents_t extents;
56     cairo_t *cr;
57     int i;
58
59     cr = cairo_create (thread_data->target);
60     cairo_surface_destroy (thread_data->target);
61
62     cairo_set_source_rgb (cr, 1, 1, 1);
63     cairo_paint (cr);
64     cairo_set_source_rgb (cr, 0, 0, 0);
65
66     cairo_select_font_face (cr, "serif",
67                             CAIRO_FONT_SLANT_NORMAL,
68                             CAIRO_FONT_WEIGHT_NORMAL);
69     cairo_set_font_size (cr, NUM_ITERATIONS);
70     cairo_font_extents (cr, &extents);
71
72     cairo_move_to (cr, 1, HEIGHT - extents.descent - 1);
73
74     for (i = 0; i < NUM_ITERATIONS; i++) {
75         char buf[2];
76
77         cairo_select_font_face (cr, "serif",
78                                 CAIRO_FONT_SLANT_NORMAL,
79                                 CAIRO_FONT_WEIGHT_NORMAL);
80         cairo_set_font_size (cr, i);
81
82         buf[0] = text[i%strlen(text)];
83         buf[1] = '\0';
84         cairo_show_text (cr, buf);
85     }
86
87     surface = cairo_surface_reference (cairo_get_target (cr));
88     cairo_destroy (cr);
89
90     return surface;
91 }
92
93 static cairo_test_status_t
94 draw (cairo_t *cr, int width, int height)
95 {
96     pthread_t threads[N_THREADS];
97     thread_data_t thread_data[N_THREADS];
98     cairo_test_status_t test_status = CAIRO_TEST_SUCCESS;
99     int i;
100
101     for (i = 0; i < N_THREADS; i++) {
102         thread_data[i].target = cairo_surface_create_similar (cairo_get_target (cr),
103                                                               cairo_surface_get_content (cairo_get_target (cr)),
104                                                               WIDTH, HEIGHT);
105         thread_data[i].id = i;
106         if (pthread_create (&threads[i], NULL, draw_thread, &thread_data[i]) != 0) {
107             threads[i] = pthread_self (); /* to indicate error */
108             cairo_surface_destroy (thread_data[i].target);
109             test_status = CAIRO_TEST_FAILURE;
110             break;
111         }
112     }
113
114     cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
115     cairo_paint (cr);
116
117     for (i = 0; i < N_THREADS; i++) {
118         void *surface;
119
120         if (pthread_equal (threads[i], pthread_self ()))
121             break;
122
123         if (pthread_join (threads[i], &surface) == 0) {
124             cairo_set_source_surface (cr, surface, 0, 0);
125             cairo_surface_destroy (surface);
126             cairo_paint (cr);
127
128             cairo_translate (cr, 0, HEIGHT);
129         } else {
130             test_status = CAIRO_TEST_FAILURE;
131         }
132     }
133
134     return test_status;
135 }
136
137 CAIRO_TEST (pthread_show_text,
138             "Concurrent stress test of the cairo_show_text().",
139             "thread, text", /* keywords */
140             NULL, /* requirements */
141             WIDTH, HEIGHT * N_THREADS,
142             NULL, draw)