1#include <stdlib.h>
2#include <string.h>
3#include <pango/pango.h>
4#include <pango/pangocairo.h>
5
6#define WIDTH 100
7#define HEIGHT 100
8const char *text = "Hamburgerfonts\nวิวิวิวิวิวิ\nبهداد";
9
10int num_iters = 50;
11int num_threads = 5;
12
13GMutex mutex;
14
15static cairo_surface_t *
16create_surface (void)
17{
18 return cairo_image_surface_create (format: CAIRO_FORMAT_A8, WIDTH, HEIGHT);
19}
20
21static PangoLayout *
22create_layout (cairo_t *cr)
23{
24 PangoLayout *layout = pango_cairo_create_layout (cr);
25 pango_layout_set_text (layout, text, length: -1);
26 pango_layout_set_width (layout, WIDTH * PANGO_SCALE);
27 return layout;
28}
29
30static void
31draw (cairo_t *cr, PangoLayout *layout, unsigned int i)
32{
33 cairo_set_source_rgba (cr, red: 1, green: 1, blue: 1, alpha: 1);
34 cairo_paint (cr);
35 cairo_set_source_rgba (cr, red: 1, green: 1, blue: 1, alpha: 0);
36 cairo_set_operator (cr, op: CAIRO_OPERATOR_SOURCE);
37
38 cairo_identity_matrix (cr);
39 cairo_scale (cr, sx: (100 + i) / 100., sy: (100 + i) / 100.);
40 pango_cairo_update_layout (cr, layout);
41
42 pango_cairo_show_layout (cr, layout);
43}
44
45static gpointer
46thread_func (gpointer data)
47{
48 cairo_surface_t *surface = data;
49 PangoLayout *layout;
50 int i;
51
52 cairo_t *cr = cairo_create (target: surface);
53
54 layout = create_layout (cr);
55
56 g_mutex_lock (mutex: &mutex);
57 g_mutex_unlock (mutex: &mutex);
58
59 for (i = 0; i < num_iters; i++)
60 draw (cr, layout, i);
61
62 g_object_unref (object: layout);
63
64 cairo_destroy (cr);
65
66 return 0;
67}
68
69static void
70pangocairo_threads (void)
71{
72 GPtrArray *threads = g_ptr_array_new ();
73 GPtrArray *surfaces = g_ptr_array_new ();
74 int i;
75
76 g_mutex_lock (mutex: &mutex);
77
78 for (i = 0; i < num_threads; i++)
79 {
80 char buf[10];
81 cairo_surface_t *surface = create_surface ();
82 g_ptr_array_add (array: surfaces, data: surface);
83 g_snprintf (string: buf, n: sizeof (buf), format: "%d", i);
84 g_ptr_array_add (array: threads,
85 data: g_thread_new (name: buf,
86 func: thread_func,
87 data: surface));
88 }
89
90 /* Let them loose! */
91 g_mutex_unlock (mutex: &mutex);
92
93 for (i = 0; i < num_threads; i++)
94 g_thread_join (g_ptr_array_index (threads, i));
95
96 g_ptr_array_unref (array: threads);
97
98 /* Now, draw a reference image and check results. */
99 {
100 cairo_surface_t *ref_surface = create_surface ();
101 cairo_t *cr = cairo_create (target: ref_surface);
102 PangoLayout *layout = create_layout (cr);
103 unsigned char *ref_data = cairo_image_surface_get_data (surface: ref_surface);
104 unsigned int len = WIDTH * HEIGHT;
105
106 draw (cr, layout, i: num_iters - 1);
107
108 g_object_unref (object: layout);
109 cairo_destroy (cr);
110
111 /* cairo_surface_write_to_png (ref_surface, "test-pangocairo-threads-reference.png"); */
112
113 g_assert (WIDTH == cairo_format_stride_for_width (CAIRO_FORMAT_A8, WIDTH));
114
115 for (i = 0; i < num_threads; i++)
116 {
117 cairo_surface_t *surface = g_ptr_array_index (surfaces, i);
118 unsigned char *data = cairo_image_surface_get_data (surface);
119 if (memcmp (s1: ref_data, s2: data, n: len))
120 {
121 g_test_message (format: "image for thread %d different from reference image", i);
122 cairo_surface_write_to_png (surface: ref_surface, filename: "test-pangocairo-threads-reference.png");
123 cairo_surface_write_to_png (surface, filename: "test-pangocairo-threads-failed.png");
124 g_test_fail ();
125 break;
126 }
127 cairo_surface_destroy (surface);
128 }
129
130 cairo_surface_destroy (surface: ref_surface);
131 }
132
133 g_ptr_array_unref (array: surfaces);
134
135 pango_cairo_font_map_set_default (NULL);
136
137}
138
139int
140main (int argc, char **argv)
141{
142 g_test_init (argc: &argc, argv: &argv, NULL);
143
144 if (argc > 1)
145 num_threads = atoi (nptr: argv[1]);
146 if (argc > 2)
147 num_iters = atoi (nptr: argv[2]);
148
149 g_test_add_func (testpath: "/pangocairo/threads", test_func: pangocairo_threads);
150
151 return g_test_run ();
152}
153

source code of gtk/subprojects/pango/tests/test-pangocairo-threads.c