• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Collabora Ltd.
3  * Copyright (C) 2010 Igalia, S.L.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Library 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  *  Library General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Library General Public License
16  *  along with this library; see the file COPYING.LIB.  If not, write to
17  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  *  Boston, MA 02110-1301, USA.
19  */
20 
21 #include "GtkVersioning.h"
22 
23 #include <gtk/gtk.h>
24 
25 #if !GTK_CHECK_VERSION(2, 14, 0)
gtk_adjustment_set_value(GtkAdjustment * adjusment,gdouble value)26 void gtk_adjustment_set_value(GtkAdjustment* adjusment, gdouble value)
27 {
28         m_adjustment->value = m_currentPos;
29         gtk_adjustment_value_changed(m_adjustment);
30 }
31 
gtk_adjustment_configure(GtkAdjustment * adjustment,gdouble value,gdouble lower,gdouble upper,gdouble stepIncrement,gdouble pageIncrement,gdouble pageSize)32 void gtk_adjustment_configure(GtkAdjustment* adjustment, gdouble value, gdouble lower, gdouble upper,
33                               gdouble stepIncrement, gdouble pageIncrement, gdouble pageSize)
34 {
35     g_object_freeze_notify(G_OBJECT(adjustment));
36 
37     g_object_set(adjustment,
38                  "lower", lower,
39                  "upper", upper,
40                  "step-increment", stepIncrement,
41                  "page-increment", pageIncrement,
42                  "page-size", pageSize,
43                  NULL);
44 
45     g_object_thaw_notify(G_OBJECT(adjustment));
46 
47     gtk_adjustment_changed(adjustment);
48     gtk_adjustment_value_changed(adjustment);
49 }
50 #endif
51 
getDefaultGDKPointerDevice(GdkWindow * window)52 GdkDevice *getDefaultGDKPointerDevice(GdkWindow* window)
53 {
54 #ifndef GTK_API_VERSION_2
55     GdkDeviceManager *manager =  gdk_display_get_device_manager(gdk_window_get_display(window));
56     return gdk_device_manager_get_client_pointer(manager);
57 #else
58     return gdk_device_get_core_pointer();
59 #endif // GTK_API_VERSION_2
60 }
61 
62 #if !GTK_CHECK_VERSION(2, 17, 3)
gdk_window_get_root_coords(GdkWindow * window,gint x,gint y,gint * rootX,gint * rootY)63 void gdk_window_get_root_coords(GdkWindow* window, gint x, gint y, gint* rootX, gint* rootY)
64 {
65     gdk_window_get_root_origin(window, rootX, rootY);
66     *rootX = *rootX + x;
67     *rootY = *rootY + y;
68 }
69 #endif
70 
blankCursor()71 GdkCursor * blankCursor()
72 {
73 #if GTK_CHECK_VERSION(2, 16, 0)
74     return gdk_cursor_new(GDK_BLANK_CURSOR);
75 #else
76     GdkCursor * cursor;
77     GdkPixmap * source;
78     GdkPixmap * mask;
79     GdkColor foreground = { 0, 65535, 0, 0 }; // Red.
80     GdkColor background = { 0, 0, 0, 65535 }; // Blue.
81     static gchar cursorBits[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
82 
83     source = gdk_bitmap_create_from_data(0, cursorBits, 8, 8);
84     mask = gdk_bitmap_create_from_data(0, cursorBits, 8, 8);
85     cursor = gdk_cursor_new_from_pixmap(source, mask, &foreground, &background, 8, 8);
86     gdk_pixmap_unref(source);
87     gdk_pixmap_unref(mask);
88     return cursor;
89 #endif // GTK_CHECK_VERSION(2, 16, 0)
90 }
91 
92 #if !GTK_CHECK_VERSION(2, 16, 0)
gtk_menu_item_get_label(GtkMenuItem * menuItem)93 const gchar* gtk_menu_item_get_label(GtkMenuItem* menuItem)
94 {
95     GtkWidget * label = gtk_bin_get_child(GTK_BIN(menuItem));
96     if (GTK_IS_LABEL(label))
97         return gtk_label_get_text(GTK_LABEL(label));
98     return 0;
99 }
100 #endif // GTK_CHECK_VERSION(2, 16, 0)
101 
102 #ifdef GTK_API_VERSION_2
103 static cairo_format_t
gdk_cairo_format_for_content(cairo_content_t content)104 gdk_cairo_format_for_content(cairo_content_t content)
105 {
106     switch (content) {
107     case CAIRO_CONTENT_COLOR:
108         return CAIRO_FORMAT_RGB24;
109     case CAIRO_CONTENT_ALPHA:
110         return CAIRO_FORMAT_A8;
111     case CAIRO_CONTENT_COLOR_ALPHA:
112     default:
113         return CAIRO_FORMAT_ARGB32;
114     }
115 }
116 
117 static cairo_surface_t*
gdk_cairo_surface_coerce_to_image(cairo_surface_t * surface,cairo_content_t content,int width,int height)118 gdk_cairo_surface_coerce_to_image(cairo_surface_t* surface,
119                                   cairo_content_t content,
120                                   int width,
121                                   int height)
122 {
123     cairo_surface_t * copy;
124     cairo_t * cr;
125 
126     if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE
127         && cairo_surface_get_content(surface) == content
128         && cairo_image_surface_get_width(surface) >= width
129         && cairo_image_surface_get_height(surface) >= height)
130         return cairo_surface_reference(surface);
131 
132     copy = cairo_image_surface_create(gdk_cairo_format_for_content(content),
133                                       width,
134                                       height);
135 
136     cr = cairo_create(copy);
137     cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
138     cairo_set_source_surface(cr, surface, 0, 0);
139     cairo_paint(cr);
140     cairo_destroy(cr);
141 
142     return copy;
143 }
144 
145 static void
convert_alpha(guchar * destData,int destStride,guchar * srcData,int srcStride,int srcX,int srcY,int width,int height)146 convert_alpha(guchar * destData, int destStride,
147               guchar * srcData, int srcStride,
148               int srcX, int srcY, int width, int height)
149 {
150     int x, y;
151 
152     srcData += srcStride * srcY + srcY * 4;
153 
154     for (y = 0; y < height; y++) {
155         guint32 * src = (guint32 *) srcData;
156 
157         for (x = 0; x < width; x++) {
158             guint alpha = src[x] >> 24;
159 
160             if (!alpha) {
161                 destData[x * 4 + 0] = 0;
162                 destData[x * 4 + 1] = 0;
163                 destData[x * 4 + 2] = 0;
164             } else {
165                 destData[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
166                 destData[x * 4 + 1] = (((src[x] & 0x00ff00) >>  8) * 255 + alpha / 2) / alpha;
167                 destData[x * 4 + 2] = (((src[x] & 0x0000ff) >>  0) * 255 + alpha / 2) / alpha;
168             }
169             destData[x * 4 + 3] = alpha;
170         }
171 
172         srcData += srcStride;
173         destData += destStride;
174     }
175 }
176 
177 static void
convert_no_alpha(guchar * destData,int destStride,guchar * srcData,int srcStride,int srcX,int srcY,int width,int height)178 convert_no_alpha(guchar * destData, int destStride, guchar * srcData,
179                  int srcStride, int srcX, int srcY,
180                  int width, int height)
181 {
182     int x, y;
183 
184     srcData += srcStride * srcY + srcX * 4;
185 
186     for (y = 0; y < height; y++) {
187         guint32 * src = (guint32 *) srcData;
188 
189         for (x = 0; x < width; x++) {
190             destData[x * 3 + 0] = src[x] >> 16;
191             destData[x * 3 + 1] = src[x] >>  8;
192             destData[x * 3 + 2] = src[x];
193         }
194 
195         srcData += srcStride;
196         destData += destStride;
197     }
198 }
199 
200 /**
201  * gdk_pixbuf_get_from_surface:
202  * @surface: surface to copy from
203  * @src_x: Source X coordinate within @surface
204  * @src_y: Source Y coordinate within @surface
205  * @width: Width in pixels of region to get
206  * @height: Height in pixels of region to get
207  *
208  * Transfers image data from a #cairo_surface_t and converts it to an RGB(A)
209  * representation inside a #GdkPixbuf. This allows you to efficiently read
210  * individual pixels from cairo surfaces. For #GdkWindows, use
211  * gdk_pixbuf_get_from_window() instead.
212  *
213  * This function will create an RGB pixbuf with 8 bits per channel. The pixbuf
214  * will contain an alpha channel if the @surface contains one.
215  *
216  * Return value: (transfer full): A newly-created pixbuf with a reference count
217  * of 1, or %NULL on error
218  **/
219 GdkPixbuf*
gdk_pixbuf_get_from_surface(cairo_surface_t * surface,int srcX,int srcY,int width,int height)220 gdk_pixbuf_get_from_surface(cairo_surface_t * surface,
221                             int srcX, int srcY,
222                             int width, int height)
223 {
224     cairo_content_t content;
225     GdkPixbuf * dest;
226 
227     /* General sanity checks */
228     g_return_val_if_fail(surface, NULL);
229     g_return_val_if_fail(srcX >= 0 && srcY >= 0, NULL);
230     g_return_val_if_fail(width > 0 && height > 0, NULL);
231 
232     content = cairo_surface_get_content(surface) | CAIRO_CONTENT_COLOR;
233     dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
234                           !!(content & CAIRO_CONTENT_ALPHA),
235                           8,
236                           width, height);
237 
238     surface = gdk_cairo_surface_coerce_to_image(surface, content, srcX + width, srcY + height);
239     cairo_surface_flush(surface);
240     if (cairo_surface_status(surface) || !dest) {
241         cairo_surface_destroy(surface);
242         return NULL;
243     }
244 
245     if (gdk_pixbuf_get_has_alpha(dest))
246         convert_alpha(gdk_pixbuf_get_pixels(dest),
247                        gdk_pixbuf_get_rowstride(dest),
248                        cairo_image_surface_get_data(surface),
249                        cairo_image_surface_get_stride(surface),
250                        srcX, srcY,
251                        width, height);
252     else
253         convert_no_alpha(gdk_pixbuf_get_pixels(dest),
254                           gdk_pixbuf_get_rowstride(dest),
255                           cairo_image_surface_get_data(surface),
256                           cairo_image_surface_get_stride(surface),
257                           srcX, srcY,
258                           width, height);
259 
260     cairo_surface_destroy(surface);
261     return dest;
262 }
263 
264 #endif // GTK_API_VERSION_2
265 
266 #if !GLIB_CHECK_VERSION(2, 27, 1)
g_signal_accumulator_first_wins(GSignalInvocationHint * invocationHint,GValue * returnAccumulator,const GValue * handlerReturn,gpointer data)267 gboolean g_signal_accumulator_first_wins(GSignalInvocationHint *invocationHint, GValue *returnAccumulator, const GValue *handlerReturn, gpointer data)
268 {
269     g_value_copy(handlerReturn, returnAccumulator);
270     return FALSE;
271 }
272 #endif
273 
274 #if !GTK_CHECK_VERSION(2, 22, 0)
gdk_window_create_similar_surface(GdkWindow * window,cairo_content_t content,int width,int height)275 cairo_surface_t *gdk_window_create_similar_surface(GdkWindow *window, cairo_content_t content, int width, int height)
276 {
277     cairo_t *cairoContext = gdk_cairo_create(window);
278     cairo_surface_t *cairoSurface = cairo_get_target(cairoContext);
279     cairo_surface_t *newSurface = cairo_surface_create_similar(cairoSurface, content, width, height);
280     cairo_destroy(cairoContext);
281     return newSurface;
282 }
283 #endif // GTK_CHECK_VERSION(2, 22, 0)
284