Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(481)

Side by Side Diff: chrome/browser/ui/gtk/nine_box.cc

Issue 8779001: GTK: Make NineBox use CairoCachedSurfaces via gfx::Image. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase for merge Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/ui/gtk/nine_box.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/gtk/nine_box.h" 5 #include "chrome/browser/ui/gtk/nine_box.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/i18n/rtl.h" 8 #include "base/i18n/rtl.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "ui/base/resource/resource_bundle.h" 10 #include "ui/base/resource/resource_bundle.h"
11 #include "ui/gfx/gtk_util.h" 11 #include "ui/gfx/gtk_util.h"
12 #include "ui/gfx/image/image.h" 12 #include "ui/gfx/image/image.h"
13 #include "ui/gfx/image/cairo_cached_surface.h"
13 #include "ui/gfx/point.h" 14 #include "ui/gfx/point.h"
14 15
15 namespace { 16 namespace {
16 17
17 // Draw pixbuf |src| into |dst| at position (x, y). 18 // Draw pixbuf |src| into |dst| at position (x, y).
18 void DrawPixbuf(cairo_t* cr, GdkPixbuf* src, int x, int y, double alpha) { 19 void DrawImage(cairo_t* cr, GtkWidget* widget, gfx::Image* src,
19 gdk_cairo_set_source_pixbuf(cr, src, x, y); 20 int x, int y, double alpha) {
21 if (!src)
22 return;
23
24 src->ToCairo()->SetSource(cr, widget, x, y);
20 cairo_paint_with_alpha(cr, alpha); 25 cairo_paint_with_alpha(cr, alpha);
21 } 26 }
22 27
23 // Tile pixbuf |src| across |cr| at |x|, |y| for |width| and |height|. 28 // Tile pixbuf |src| across |cr| at |x|, |y| for |width| and |height|.
24 void TileImage(cairo_t* cr, GdkPixbuf* src, 29 void TileImage(cairo_t* cr, GtkWidget* widget, gfx::Image* src,
25 int x, int y, int width, int height, double alpha) { 30 int x, int y, int width, int height, double alpha) {
31 if (!src)
32 return;
33
26 if (alpha == 1.0) { 34 if (alpha == 1.0) {
27 gdk_cairo_set_source_pixbuf(cr, src, x, y); 35 src->ToCairo()->SetSource(cr, widget, x, y);
28 cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT); 36 cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
29 cairo_rectangle(cr, x, y, width, height); 37 cairo_rectangle(cr, x, y, width, height);
30 cairo_fill(cr); 38 cairo_fill(cr);
31 } else { 39 } else {
32 // Since there is no easy way to apply a mask to a fill operation, we create 40 // Since there is no easy way to apply a mask to a fill operation, we create
33 // a secondary surface and tile into that, then paint it with |alpha|. 41 // a secondary surface and tile into that, then paint it with |alpha|.
34 cairo_surface_t* surface = cairo_image_surface_create( 42 cairo_surface_t* target = cairo_get_target(cr);
35 CAIRO_FORMAT_ARGB32, width, height); 43 cairo_surface_t* surface = cairo_surface_create_similar(
44 target, CAIRO_CONTENT_COLOR_ALPHA, width, height);
36 cairo_t* tiled = cairo_create(surface); 45 cairo_t* tiled = cairo_create(surface);
37 gdk_cairo_set_source_pixbuf(tiled, src, 0, 0); 46 src->ToCairo()->SetSource(tiled, widget, 0, 0);
38 cairo_pattern_set_extend(cairo_get_source(tiled), CAIRO_EXTEND_REPEAT); 47 cairo_pattern_set_extend(cairo_get_source(tiled), CAIRO_EXTEND_REPEAT);
39 cairo_rectangle(tiled, 0, 0, width, height); 48 cairo_rectangle(tiled, 0, 0, width, height);
40 cairo_fill(tiled); 49 cairo_fill(tiled);
41 50
42 cairo_set_source_surface(cr, surface, x, y); 51 cairo_set_source_surface(cr, surface, x, y);
43 cairo_paint_with_alpha(cr, alpha); 52 cairo_paint_with_alpha(cr, alpha);
44 53
45 cairo_destroy(tiled); 54 cairo_destroy(tiled);
46 cairo_surface_destroy(surface); 55 cairo_surface_destroy(surface);
47 } 56 }
48 } 57 }
49 58
50 GdkPixbuf* GetPixbufImage(int resource_id) {
51 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
52 return static_cast<GdkPixbuf*>(rb.GetNativeImageNamed(resource_id));
53 }
54
55 } // namespace 59 } // namespace
56 60
57 NineBox::NineBox(int top_left, int top, int top_right, int left, int center, 61 NineBox::NineBox(int top_left, int top, int top_right, int left, int center,
58 int right, int bottom_left, int bottom, int bottom_right) 62 int right, int bottom_left, int bottom, int bottom_right)
59 : unref_pixbufs_on_destroy_(false) { 63 : unref_images_on_destroy_(false) {
60 images_[0] = top_left ? GetPixbufImage(top_left) : NULL; 64 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
61 images_[1] = top ? GetPixbufImage(top) : NULL; 65
62 images_[2] = top_right ? GetPixbufImage(top_right) : NULL; 66 images_[0] = top_left ? &rb.GetNativeImageNamed(top_left) : NULL;
63 images_[3] = left ? GetPixbufImage(left) : NULL; 67 images_[1] = top ? &rb.GetNativeImageNamed(top) : NULL;
64 images_[4] = center ? GetPixbufImage(center) : NULL; 68 images_[2] = top_right ? &rb.GetNativeImageNamed(top_right) : NULL;
65 images_[5] = right ? GetPixbufImage(right) : NULL; 69 images_[3] = left ? &rb.GetNativeImageNamed(left) : NULL;
66 images_[6] = bottom_left ? GetPixbufImage(bottom_left) : NULL; 70 images_[4] = center ? &rb.GetNativeImageNamed(center) : NULL;
67 images_[7] = bottom ? GetPixbufImage(bottom) : NULL; 71 images_[5] = right ? &rb.GetNativeImageNamed(right) : NULL;
68 images_[8] = bottom_right ? GetPixbufImage(bottom_right) : NULL; 72 images_[6] = bottom_left ? &rb.GetNativeImageNamed(bottom_left) : NULL;
73 images_[7] = bottom ? &rb.GetNativeImageNamed(bottom) : NULL;
74 images_[8] = bottom_right ? &rb.GetNativeImageNamed(bottom_right) : NULL;
69 } 75 }
70 76
71 NineBox::NineBox(int image, int top_margin, int bottom_margin, int left_margin, 77 NineBox::NineBox(int image, int top_margin, int bottom_margin, int left_margin,
72 int right_margin) 78 int right_margin)
73 : unref_pixbufs_on_destroy_(true) { 79 : unref_images_on_destroy_(true) {
74 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 80 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
75 GdkPixbuf* pixbuf = rb.GetNativeImageNamed(image); 81 GdkPixbuf* pixbuf = rb.GetNativeImageNamed(image);
76 int width = gdk_pixbuf_get_width(pixbuf); 82 int width = gdk_pixbuf_get_width(pixbuf);
77 int height = gdk_pixbuf_get_height(pixbuf); 83 int height = gdk_pixbuf_get_height(pixbuf);
78 int inset_width = left_margin + right_margin; 84 int inset_width = left_margin + right_margin;
79 int inset_height = top_margin + bottom_margin; 85 int inset_height = top_margin + bottom_margin;
80 86
81 images_[0] = gdk_pixbuf_new_subpixbuf(pixbuf, 0, 0, left_margin, top_margin); 87 images_[0] = new gfx::Image(gdk_pixbuf_new_subpixbuf(
82 images_[1] = gdk_pixbuf_new_subpixbuf(pixbuf, left_margin, 0, 88 pixbuf, 0, 0, left_margin, top_margin));
83 width - inset_width, top_margin); 89 images_[1] = new gfx::Image(gdk_pixbuf_new_subpixbuf(
84 images_[2] = gdk_pixbuf_new_subpixbuf(pixbuf, width - right_margin, 0, 90 pixbuf, left_margin, 0, width - inset_width, top_margin));
85 right_margin, top_margin); 91 images_[2] = new gfx::Image(gdk_pixbuf_new_subpixbuf(
86 images_[3] = gdk_pixbuf_new_subpixbuf(pixbuf, 0, top_margin, 92 pixbuf, width - right_margin, 0, right_margin, top_margin));
87 left_margin, height - inset_height); 93 images_[3] = new gfx::Image(gdk_pixbuf_new_subpixbuf(
88 images_[4] = gdk_pixbuf_new_subpixbuf(pixbuf, left_margin, top_margin, 94 pixbuf, 0, top_margin, left_margin, height - inset_height));
89 width - inset_width, 95 images_[4] = new gfx::Image(gdk_pixbuf_new_subpixbuf(
90 height - inset_height); 96 pixbuf, left_margin, top_margin, width - inset_width,
91 images_[5] = gdk_pixbuf_new_subpixbuf(pixbuf, width - right_margin, 97 height - inset_height));
92 top_margin, right_margin, 98 images_[5] = new gfx::Image(gdk_pixbuf_new_subpixbuf(
93 height - inset_height); 99 pixbuf, width - right_margin, top_margin, right_margin,
94 images_[6] = gdk_pixbuf_new_subpixbuf(pixbuf, 0, height - bottom_margin, 100 height - inset_height));
95 left_margin, bottom_margin); 101 images_[6] = new gfx::Image(gdk_pixbuf_new_subpixbuf(
96 images_[7] = gdk_pixbuf_new_subpixbuf(pixbuf, left_margin, 102 pixbuf, 0, height - bottom_margin, left_margin, bottom_margin));
97 height - bottom_margin, 103 images_[7] = new gfx::Image(gdk_pixbuf_new_subpixbuf(
98 width - inset_width, bottom_margin); 104 pixbuf, left_margin, height - bottom_margin,
99 images_[8] = gdk_pixbuf_new_subpixbuf(pixbuf, width - right_margin, 105 width - inset_width, bottom_margin));
100 height - bottom_margin, 106 images_[8] = new gfx::Image(gdk_pixbuf_new_subpixbuf(
101 right_margin, bottom_margin); 107 pixbuf, width - right_margin, height - bottom_margin,
108 right_margin, bottom_margin));
102 } 109 }
103 110
104 NineBox::~NineBox() { 111 NineBox::~NineBox() {
105 if (unref_pixbufs_on_destroy_) { 112 if (unref_images_on_destroy_) {
106 for (int i = 0; i < 9; i++) { 113 for (int i = 0; i < 9; i++) {
107 g_object_unref(images_[i]); 114 delete images_[i];
108 } 115 }
109 } 116 }
110 } 117 }
111 118
112 void NineBox::RenderToWidget(GtkWidget* dst) const { 119 void NineBox::RenderToWidget(GtkWidget* dst) const {
113 RenderToWidgetWithOpacity(dst, 1.0); 120 RenderToWidgetWithOpacity(dst, 1.0);
114 } 121 }
115 122
116 void NineBox::RenderToWidgetWithOpacity(GtkWidget* dst, double opacity) const { 123 void NineBox::RenderToWidgetWithOpacity(GtkWidget* dst, double opacity) const {
117 int dst_width = dst->allocation.width; 124 int dst_width = dst->allocation.width;
118 int dst_height = dst->allocation.height; 125 int dst_height = dst->allocation.height;
119 126
120 // The upper-left and lower-right corners of the center square in the 127 // The upper-left and lower-right corners of the center square in the
121 // rendering of the ninebox. 128 // rendering of the ninebox.
122 int x1 = gdk_pixbuf_get_width(images_[0]); 129 int x1 = gdk_pixbuf_get_width(images_[0]->ToGdkPixbuf());
123 int y1 = gdk_pixbuf_get_height(images_[0]); 130 int y1 = gdk_pixbuf_get_height(images_[0]->ToGdkPixbuf());
124 int x2 = images_[2] ? dst_width - gdk_pixbuf_get_width(images_[2]) : x1; 131 int x2 = images_[2] ? dst_width - gdk_pixbuf_get_width(
125 int y2 = images_[6] ? dst_height - gdk_pixbuf_get_height(images_[6]) : y1; 132 images_[2]->ToGdkPixbuf()) : x1;
133 int y2 = images_[6] ? dst_height - gdk_pixbuf_get_height(
134 images_[6]->ToGdkPixbuf()) : y1;
126 // Paint nothing if there's not enough room. 135 // Paint nothing if there's not enough room.
127 if (x2 < x1 || y2 < y1) 136 if (x2 < x1 || y2 < y1)
128 return; 137 return;
129 138
130 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(dst->window)); 139 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(dst->window));
131 // For widgets that have their own window, the allocation (x,y) coordinates 140 // For widgets that have their own window, the allocation (x,y) coordinates
132 // are GdkWindow relative. For other widgets, the coordinates are relative 141 // are GdkWindow relative. For other widgets, the coordinates are relative
133 // to their container. 142 // to their container.
134 if (GTK_WIDGET_NO_WINDOW(dst)) { 143 if (GTK_WIDGET_NO_WINDOW(dst)) {
135 // Transform our cairo from window to widget coordinates. 144 // Transform our cairo from window to widget coordinates.
136 cairo_translate(cr, dst->allocation.x, dst->allocation.y); 145 cairo_translate(cr, dst->allocation.x, dst->allocation.y);
137 } 146 }
138 147
139 if (base::i18n::IsRTL()) { 148 if (base::i18n::IsRTL()) {
140 cairo_translate(cr, dst_width, 0.0f); 149 cairo_translate(cr, dst_width, 0.0f);
141 cairo_scale(cr, -1.0f, 1.0f); 150 cairo_scale(cr, -1.0f, 1.0f);
142 } 151 }
143 152
144 // Top row, center image is horizontally tiled. 153 // Top row, center image is horizontally tiled.
145 if (images_[0]) 154 DrawImage(cr, dst, images_[0], 0, 0, opacity);
146 DrawPixbuf(cr, images_[0], 0, 0, opacity); 155 TileImage(cr, dst, images_[1], x1, 0, x2 - x1, y1, opacity);
147 if (images_[1]) 156 DrawImage(cr, dst, images_[2], x2, 0, opacity);
148 TileImage(cr, images_[1], x1, 0, x2 - x1, y1, opacity);
149 if (images_[2])
150 DrawPixbuf(cr, images_[2], x2, 0, opacity);
151 157
152 // Center row, all images are vertically tiled, center is horizontally tiled. 158 // Center row, all images are vertically tiled, center is horizontally tiled.
153 if (images_[3]) 159 TileImage(cr, dst, images_[3], 0, y1, x1, y2 - y1, opacity);
154 TileImage(cr, images_[3], 0, y1, x1, y2 - y1, opacity); 160 TileImage(cr, dst, images_[4], x1, y1, x2 - x1, y2 - y1, opacity);
155 if (images_[4]) 161 TileImage(cr, dst, images_[5], x2, y1, dst_width - x2, y2 - y1, opacity);
156 TileImage(cr, images_[4], x1, y1, x2 - x1, y2 - y1, opacity);
157 if (images_[5])
158 TileImage(cr, images_[5], x2, y1, dst_width - x2, y2 - y1, opacity);
159 162
160 // Bottom row, center image is horizontally tiled. 163 // Bottom row, center image is horizontally tiled.
161 if (images_[6]) 164 DrawImage(cr, dst, images_[6], 0, y2, opacity);
162 DrawPixbuf(cr, images_[6], 0, y2, opacity); 165 TileImage(cr, dst, images_[7], x1, y2, x2 - x1, dst_height - y2, opacity);
163 if (images_[7]) 166 DrawImage(cr, dst, images_[8], x2, y2, opacity);
164 TileImage(cr, images_[7], x1, y2, x2 - x1, dst_height - y2, opacity);
165 if (images_[8])
166 DrawPixbuf(cr, images_[8], x2, y2, opacity);
167 167
168 cairo_destroy(cr); 168 cairo_destroy(cr);
169 } 169 }
170 170
171 void NineBox::RenderTopCenterStrip(cairo_t* cr, int x, int y,
172 int width) const {
173 const int height = gdk_pixbuf_get_height(images_[1]);
174 TileImage(cr, images_[1], x, y, width, height, 1.0);
175 }
176
177 void NineBox::ContourWidget(GtkWidget* widget) const { 171 void NineBox::ContourWidget(GtkWidget* widget) const {
178 GtkAllocation allocation; 172 GtkAllocation allocation;
179 gtk_widget_get_allocation(widget, &allocation); 173 gtk_widget_get_allocation(widget, &allocation);
180 int width = allocation.width; 174 int width = allocation.width;
181 int height = allocation.height; 175 int height = allocation.height;
182 int x1 = gdk_pixbuf_get_width(images_[0]); 176 int x1 = gdk_pixbuf_get_width(images_[0]->ToGdkPixbuf());
183 int x2 = width - gdk_pixbuf_get_width(images_[2]); 177 int x2 = width - gdk_pixbuf_get_width(images_[2]->ToGdkPixbuf());
178
179 // TODO(erg): Far in the future, when we're doing the real gtk3 porting, this
180 // all needs to be switchted to pure cairo operations.
184 181
185 // Paint the left and right sides. 182 // Paint the left and right sides.
186 GdkBitmap* mask = gdk_pixmap_new(NULL, width, height, 1); 183 GdkBitmap* mask = gdk_pixmap_new(NULL, width, height, 1);
187 gdk_pixbuf_render_threshold_alpha(images_[0], mask, 184 gdk_pixbuf_render_threshold_alpha(images_[0]->ToGdkPixbuf(), mask,
188 0, 0, 185 0, 0,
189 0, 0, -1, -1, 186 0, 0, -1, -1,
190 1); 187 1);
191 gdk_pixbuf_render_threshold_alpha(images_[2], mask, 188 gdk_pixbuf_render_threshold_alpha(images_[2]->ToGdkPixbuf(), mask,
192 0, 0, 189 0, 0,
193 x2, 0, -1, -1, 190 x2, 0, -1, -1,
194 1); 191 1);
195 192
196 // Assume no transparency in the middle rectangle. 193 // Assume no transparency in the middle rectangle.
197 cairo_t* cr = gdk_cairo_create(mask); 194 cairo_t* cr = gdk_cairo_create(mask);
198 cairo_rectangle(cr, x1, 0, x2 - x1, height); 195 cairo_rectangle(cr, x1, 0, x2 - x1, height);
199 cairo_fill(cr); 196 cairo_fill(cr);
200 cairo_destroy(cr); 197 cairo_destroy(cr);
201 198
(...skipping 18 matching lines...) Expand all
220 cairo_paint(flipped_cr); 217 cairo_paint(flipped_cr);
221 cairo_destroy(flipped_cr); 218 cairo_destroy(flipped_cr);
222 219
223 // Mask the widget. 220 // Mask the widget.
224 gtk_widget_shape_combine_mask(widget, flipped_mask, 0, 0); 221 gtk_widget_shape_combine_mask(widget, flipped_mask, 0, 0);
225 g_object_unref(flipped_mask); 222 g_object_unref(flipped_mask);
226 } 223 }
227 224
228 g_object_unref(mask); 225 g_object_unref(mask);
229 } 226 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/gtk/nine_box.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698