OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/gtk/nine_box.h" | 5 #include "chrome/browser/gtk/nine_box.h" |
6 | 6 |
7 #include "base/gfx/gtk_util.h" | 7 #include "base/gfx/gtk_util.h" |
8 #include "base/gfx/point.h" | 8 #include "base/gfx/point.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "chrome/common/resource_bundle.h" | 10 #include "chrome/common/resource_bundle.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 images_[4] = center ? rb.GetPixbufNamed(center) : NULL; | 44 images_[4] = center ? rb.GetPixbufNamed(center) : NULL; |
45 images_[5] = right ? rb.GetPixbufNamed(right) : NULL; | 45 images_[5] = right ? rb.GetPixbufNamed(right) : NULL; |
46 images_[6] = bottom_left ? rb.GetPixbufNamed(bottom_left) : NULL; | 46 images_[6] = bottom_left ? rb.GetPixbufNamed(bottom_left) : NULL; |
47 images_[7] = bottom ? rb.GetPixbufNamed(bottom) : NULL; | 47 images_[7] = bottom ? rb.GetPixbufNamed(bottom) : NULL; |
48 images_[8] = bottom_right ? rb.GetPixbufNamed(bottom_right) : NULL; | 48 images_[8] = bottom_right ? rb.GetPixbufNamed(bottom_right) : NULL; |
49 } | 49 } |
50 | 50 |
51 NineBox::~NineBox() { | 51 NineBox::~NineBox() { |
52 } | 52 } |
53 | 53 |
54 void NineBox::RenderToWidget(GtkWidget* dst) { | 54 void NineBox::RenderToWidget(GtkWidget* dst) const { |
55 // TODO(evanm): this is stupid; it should just be implemented with SkBitmaps | 55 // TODO(evanm): this is stupid; it should just be implemented with SkBitmaps |
56 // and convert to a GdkPixbuf at the last second. | 56 // and convert to a GdkPixbuf at the last second. |
57 | 57 |
58 int dst_width = dst->allocation.width; | 58 int dst_width = dst->allocation.width; |
59 int dst_height = dst->allocation.height; | 59 int dst_height = dst->allocation.height; |
60 | 60 |
61 // This function paints one row at a time. | 61 // This function paints one row at a time. |
62 // To make indexing sane, |images| points at the current row of images, | 62 // To make indexing sane, |images| points at the current row of images, |
63 // so images[0] always refers to the left-most image of the current row. | 63 // so images[0] always refers to the left-most image of the current row. |
64 GdkPixbuf** images = &images_[0]; | 64 GdkPixbuf* const* images = &images_[0]; |
65 | 65 |
66 // The upper-left and lower-right corners of the center square in the | 66 // The upper-left and lower-right corners of the center square in the |
67 // rendering of the ninebox. | 67 // rendering of the ninebox. |
68 const int x1 = gdk_pixbuf_get_width(images[0]); | 68 const int x1 = gdk_pixbuf_get_width(images[0]); |
69 const int y1 = gdk_pixbuf_get_height(images[0]); | 69 const int y1 = gdk_pixbuf_get_height(images[0]); |
70 const int x2 = images[2] ? dst_width - gdk_pixbuf_get_width(images[2]) : x1; | 70 const int x2 = images[2] ? dst_width - gdk_pixbuf_get_width(images[2]) : x1; |
71 const int y2 = images[6] ? dst_height - gdk_pixbuf_get_height(images[6]) : y1; | 71 const int y2 = images[6] ? dst_height - gdk_pixbuf_get_height(images[6]) : y1; |
72 DCHECK_GE(x2, x1); | 72 DCHECK_GE(x2, x1); |
73 DCHECK_GE(y2, y1); | 73 DCHECK_GE(y2, y1); |
74 | 74 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 DrawPixbuf(dst, images[0], 0, y2); | 106 DrawPixbuf(dst, images[0], 0, y2); |
107 if (images[1]) { | 107 if (images[1]) { |
108 TileImage(dst, images[1], | 108 TileImage(dst, images[1], |
109 x1, y2, | 109 x1, y2, |
110 x2, y2); | 110 x2, y2); |
111 } | 111 } |
112 if (images[2]) | 112 if (images[2]) |
113 DrawPixbuf(dst, images[2], x2, y2); | 113 DrawPixbuf(dst, images[2], x2, y2); |
114 } | 114 } |
115 | 115 |
116 void NineBox::RenderTopCenterStrip(GtkWidget* dst, int x1, int x2, int y1) { | 116 void NineBox::RenderTopCenterStrip(GtkWidget* dst, int x1, |
| 117 int x2, int y1) const { |
117 TileImage(dst, images_[1], | 118 TileImage(dst, images_[1], |
118 x1, y1, | 119 x1, y1, |
119 x2, y1); | 120 x2, y1); |
120 } | 121 } |
121 | 122 |
| 123 void NineBox::ChangeWhiteToTransparent() { |
| 124 for (int image_idx = 0; image_idx < 9; ++image_idx) { |
| 125 GdkPixbuf* pixbuf = images_[image_idx]; |
| 126 if (!pixbuf) |
| 127 continue; |
| 128 |
| 129 guchar* pixels = gdk_pixbuf_get_pixels(pixbuf); |
| 130 int rowstride = gdk_pixbuf_get_rowstride(pixbuf); |
| 131 |
| 132 for (int i = 0; i < gdk_pixbuf_get_height(pixbuf); ++i) { |
| 133 for (int j = 0; j < gdk_pixbuf_get_width(pixbuf); ++j) { |
| 134 guchar* pixel = &pixels[i * rowstride + j * 4]; |
| 135 if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) { |
| 136 pixel[3] = 0; |
| 137 } |
| 138 } |
| 139 } |
| 140 } |
| 141 } |
| 142 |
| 143 void NineBox::ContourWidget(GtkWidget* widget) const { |
| 144 int x1 = gdk_pixbuf_get_width(images_[0]); |
| 145 int x2 = widget->allocation.width - gdk_pixbuf_get_width(images_[2]); |
| 146 |
| 147 // Paint the left and right sides. |
| 148 GdkBitmap* mask = gdk_pixmap_new(NULL, widget->allocation.width, |
| 149 widget->allocation.height, 1); |
| 150 gdk_pixbuf_render_threshold_alpha(images_[0], mask, |
| 151 0, 0, |
| 152 0, 0, -1, -1, |
| 153 1); |
| 154 gdk_pixbuf_render_threshold_alpha(images_[2], mask, |
| 155 0, 0, |
| 156 x2, 0, -1, -1, |
| 157 1); |
| 158 |
| 159 // Assume no transparency in the middle rectangle. |
| 160 cairo_t* cr = gdk_cairo_create(mask); |
| 161 cairo_rectangle(cr, x1, 0, x2 - x1, widget->allocation.height); |
| 162 cairo_fill(cr); |
| 163 |
| 164 // Mask the widget's window's shape. |
| 165 gtk_widget_shape_combine_mask(widget, mask, 0, 0); |
| 166 |
| 167 g_object_unref(mask); |
| 168 cairo_destroy(cr); |
| 169 } |
| 170 |
122 void NineBox::TileImage(GtkWidget* dst, GdkPixbuf* src, | 171 void NineBox::TileImage(GtkWidget* dst, GdkPixbuf* src, |
123 int x1, int y1, int x2, int y2) { | 172 int x1, int y1, int x2, int y2) const { |
124 GdkGC* gc = dst->style->fg_gc[GTK_WIDGET_STATE(dst)]; | 173 GdkGC* gc = dst->style->fg_gc[GTK_WIDGET_STATE(dst)]; |
125 const int src_width = gdk_pixbuf_get_width(src); | 174 const int src_width = gdk_pixbuf_get_width(src); |
126 const int src_height = gdk_pixbuf_get_height(src); | 175 const int src_height = gdk_pixbuf_get_height(src); |
127 const int dst_width = dst->allocation.width; | 176 const int dst_width = dst->allocation.width; |
128 const int dst_height = dst->allocation.height; | 177 const int dst_height = dst->allocation.height; |
129 | 178 |
130 gfx::Point offset = GetWindowRelativeCoords(dst); | 179 gfx::Point offset = GetWindowRelativeCoords(dst); |
131 | 180 |
132 // We only tile along one axis (see above TODO about nuking all this code), | 181 // We only tile along one axis (see above TODO about nuking all this code), |
133 // dx or dy will be nonzero along that axis. | 182 // dx or dy will be nonzero along that axis. |
134 int dx = 0, dy = 0; | 183 int dx = 0, dy = 0; |
135 if (x2 > x1) | 184 if (x2 > x1) |
136 dx = src_width; | 185 dx = src_width; |
137 if (y2 > y1) | 186 if (y2 > y1) |
138 dy = src_height; | 187 dy = src_height; |
139 DCHECK(dx == 0 || dy == 0); | 188 DCHECK(dx == 0 || dy == 0); |
140 | 189 |
141 for (int x = x1, y = y1; x < x2 || y < y2; x += dx, y += dy) { | 190 for (int x = x1, y = y1; x < x2 || y < y2; x += dx, y += dy) { |
142 gdk_draw_pixbuf(dst->window, gc, src, 0, 0, | 191 gdk_draw_pixbuf(dst->window, gc, src, 0, 0, |
143 offset.x() + x, offset.y() + y, | 192 offset.x() + x, offset.y() + y, |
144 dx ? std::min(src_width, dst_width - x) : src_width, | 193 dx ? std::min(src_width, dst_width - x) : src_width, |
145 dy ? std::min(src_height, dst_height - y) : src_height, | 194 dy ? std::min(src_height, dst_height - y) : src_height, |
146 GDK_RGB_DITHER_NONE, 0, 0); | 195 GDK_RGB_DITHER_NONE, 0, 0); |
147 } | 196 } |
148 } | 197 } |
OLD | NEW |