]> Pileus Git - ~andy/gtk/blob - gtk/gtkpango.c
wayland: Add another cursor (left-ptr)
[~andy/gtk] / gtk / gtkpango.c
1 /* gtktextdisplay.c - display layed-out text
2  *
3  * Copyright (c) 2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /*
20  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
21  * file for a list of people on the GTK+ Team.  See the ChangeLog
22  * files for a list of changes.  These files are distributed with
23  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
24  */
25
26 #include "config.h"
27 #include <pango/pangocairo.h>
28 #include "gtkintl.h"
29
30 #define GTK_TYPE_FILL_LAYOUT_RENDERER            (_gtk_fill_layout_renderer_get_type())
31 #define GTK_FILL_LAYOUT_RENDERER(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_FILL_LAYOUT_RENDERER, GtkFillLayoutRenderer))
32 #define GTK_IS_FILL_LAYOUT_RENDERER(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_FILL_LAYOUT_RENDERER))
33 #define GTK_FILL_LAYOUT_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILL_LAYOUT_RENDERER, GtkFillLayoutRendererClass))
34 #define GTK_IS_FILL_LAYOUT_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILL_LAYOUT_RENDERER))
35 #define GTK_FILL_LAYOUT_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILL_LAYOUT_RENDERER, GtkFillLayoutRendererClass))
36
37 typedef struct _GtkFillLayoutRenderer      GtkFillLayoutRenderer;
38 typedef struct _GtkFillLayoutRendererClass GtkFillLayoutRendererClass;
39
40 struct _GtkFillLayoutRenderer
41 {
42   PangoRenderer parent_instance;
43
44   cairo_t *cr;
45 };
46
47 struct _GtkFillLayoutRendererClass
48 {
49   PangoRendererClass parent_class;
50 };
51
52 G_DEFINE_TYPE (GtkFillLayoutRenderer, _gtk_fill_layout_renderer, PANGO_TYPE_RENDERER)
53
54 static void
55 gtk_fill_layout_renderer_draw_glyphs (PangoRenderer     *renderer,
56                                       PangoFont         *font,
57                                       PangoGlyphString  *glyphs,
58                                       int                x,
59                                       int                y)
60 {
61   GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
62
63   cairo_move_to (text_renderer->cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
64   pango_cairo_show_glyph_string (text_renderer->cr, font, glyphs);
65 }
66
67 static void
68 gtk_fill_layout_renderer_draw_glyph_item (PangoRenderer     *renderer,
69                                           const char        *text,
70                                           PangoGlyphItem    *glyph_item,
71                                           int                x,
72                                           int                y)
73 {
74   GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
75
76   cairo_move_to (text_renderer->cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
77   pango_cairo_show_glyph_item (text_renderer->cr, text, glyph_item);
78 }
79
80 static void
81 gtk_fill_layout_renderer_draw_rectangle (PangoRenderer     *renderer,
82                                          PangoRenderPart    part,
83                                          int                x,
84                                          int                y,
85                                          int                width,
86                                          int                height)
87 {
88   GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
89
90   if (part == PANGO_RENDER_PART_BACKGROUND)
91     return;
92
93   cairo_rectangle (text_renderer->cr,
94                    (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
95                    (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
96   cairo_fill (text_renderer->cr);
97 }
98
99 static void
100 gtk_fill_layout_renderer_draw_trapezoid (PangoRenderer     *renderer,
101                                          PangoRenderPart    part,
102                                          double             y1_,
103                                          double             x11,
104                                          double             x21,
105                                          double             y2,
106                                          double             x12,
107                                          double             x22)
108 {
109   GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
110   cairo_matrix_t matrix;
111   cairo_t *cr;
112
113   cr = text_renderer->cr;
114
115   cairo_save (cr);
116
117   /* use identity scale, but keep translation */
118   cairo_get_matrix (cr, &matrix);
119   matrix.xx = matrix.yy = 1;
120   matrix.xy = matrix.yx = 0;
121   cairo_set_matrix (cr, &matrix);
122
123   cairo_move_to (cr, x11, y1_);
124   cairo_line_to (cr, x21, y1_);
125   cairo_line_to (cr, x22, y2);
126   cairo_line_to (cr, x12, y2);
127   cairo_close_path (cr);
128
129   cairo_fill (cr);
130
131   cairo_restore (cr);
132 }
133
134 static void
135 gtk_fill_layout_renderer_draw_error_underline (PangoRenderer *renderer,
136                                                int            x,
137                                                int            y,
138                                                int            width,
139                                                int            height)
140 {
141   GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
142
143   pango_cairo_show_error_underline (text_renderer->cr,
144                                     (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
145                                     (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
146 }
147
148 static void
149 gtk_fill_layout_renderer_draw_shape (PangoRenderer   *renderer,
150                                      PangoAttrShape  *attr,
151                                      int              x,
152                                      int              y)
153 {
154   GtkFillLayoutRenderer *text_renderer = GTK_FILL_LAYOUT_RENDERER (renderer);
155   cairo_t *cr = text_renderer->cr;
156   PangoLayout *layout;
157   PangoCairoShapeRendererFunc shape_renderer;
158   gpointer                    shape_renderer_data;
159
160   layout = pango_renderer_get_layout (renderer);
161
162   if (!layout)
163         return;
164
165   shape_renderer = pango_cairo_context_get_shape_renderer (pango_layout_get_context (layout),
166                                                            &shape_renderer_data);
167
168   if (!shape_renderer)
169     return;
170
171   cairo_save (cr);
172
173   cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
174
175   shape_renderer (cr, attr, FALSE, shape_renderer_data);
176
177   cairo_restore (cr);
178 }
179
180 static void
181 gtk_fill_layout_renderer_finalize (GObject *object)
182 {
183   G_OBJECT_CLASS (_gtk_fill_layout_renderer_parent_class)->finalize (object);
184 }
185
186 static void
187 _gtk_fill_layout_renderer_init (GtkFillLayoutRenderer *renderer)
188 {
189 }
190
191 static void
192 _gtk_fill_layout_renderer_class_init (GtkFillLayoutRendererClass *klass)
193 {
194   GObjectClass *object_class = G_OBJECT_CLASS (klass);
195   
196   PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
197   
198   renderer_class->draw_glyphs = gtk_fill_layout_renderer_draw_glyphs;
199   renderer_class->draw_glyph_item = gtk_fill_layout_renderer_draw_glyph_item;
200   renderer_class->draw_rectangle = gtk_fill_layout_renderer_draw_rectangle;
201   renderer_class->draw_trapezoid = gtk_fill_layout_renderer_draw_trapezoid;
202   renderer_class->draw_error_underline = gtk_fill_layout_renderer_draw_error_underline;
203   renderer_class->draw_shape = gtk_fill_layout_renderer_draw_shape;
204
205   object_class->finalize = gtk_fill_layout_renderer_finalize;
206 }
207
208 void
209 _gtk_pango_fill_layout (cairo_t     *cr,
210                         PangoLayout *layout)
211 {
212   static GtkFillLayoutRenderer *renderer = NULL;
213   gboolean has_current_point;
214   double current_x, current_y;
215
216   has_current_point = cairo_has_current_point (cr);
217   cairo_get_current_point (cr, &current_x, &current_y);
218
219   if (renderer == NULL)
220     renderer = g_object_new (GTK_TYPE_FILL_LAYOUT_RENDERER, NULL);
221
222   cairo_save (cr);
223   cairo_translate (cr, current_x, current_y);
224
225   renderer->cr = cr;
226   pango_renderer_draw_layout (PANGO_RENDERER (renderer), layout, 0, 0);
227
228   cairo_restore (cr);
229
230   if (has_current_point)
231     cairo_move_to (cr, current_x, current_y);
232 }
233