15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner// Use of this source code is governed by a BSD-style license that can be 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner// found in the LICENSE file. 45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "ui/wm/core/image_grid.h" 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <algorithm> 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "third_party/skia/include/core/SkColor.h" 105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "third_party/skia/include/core/SkXfermode.h" 115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "ui/compositor/dip_util.h" 125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "ui/gfx/canvas.h" 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "ui/gfx/image/image.h" 145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "ui/gfx/image/image_skia_operations.h" 15e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "ui/gfx/rect.h" 16031d655004e505a15e92580a16a181d1d247c4d5David 'Digit' Turner#include "ui/gfx/rect_conversions.h" 17d0edecb426b34ddb9b10b81dea19aee04a61a385David 'Digit' Turner#include "ui/gfx/size.h" 18d413fa5f2916a2a46494edb320340486b262644cDavid 'Digit' Turner#include "ui/gfx/size_conversions.h" 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "ui/gfx/transform.h" 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerusing std::max; 225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerusing std::min; 23a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner 245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnernamespace wm { 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnernamespace { 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner// Sets the scaling for the transform applied to a layer. The left, top, 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner// right and bottom layers are stretched to the height or width of the 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner// center image. 305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid ScaleWidth(gfx::Size center, ui::Layer* layer, gfx::Transform& transform) { 325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner float layer_width = layer->bounds().width() * layer->device_scale_factor(); 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner float scale = static_cast<float>(center.width()) / layer_width; 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner transform.Scale(scale, 1.0); 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 377627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turnervoid ScaleHeight(gfx::Size center, 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui::Layer* layer, 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Transform& transform) { 40a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner float layer_height = layer->bounds().height() * layer->device_scale_factor(); 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner float scale = static_cast<float>(center.height()) / layer_height; 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner transform.Scale(1.0, scale); 435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner// Returns the dimensions of |image| if non-NULL or gfx::Size(0, 0) otherwise. 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnergfx::Size GetImageSize(const gfx::Image* image) { 47a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner return image ? gfx::Size(image->ToImageSkia()->width(), 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner image->ToImageSkia()->height()) 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner : gfx::Size(); 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner// Returns true if |layer|'s bounds don't fit within |size|. 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerbool LayerExceedsSize(const ui::Layer* layer, const gfx::Size& size) { 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return layer->bounds().width() > size.width() || 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner layer->bounds().height() > size.height(); 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} // namespace 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 607627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turnergfx::RectF ImageGrid::TestAPI::GetTransformedLayerBounds( 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const ui::Layer& layer) { 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::RectF bounds = layer.bounds(); 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner layer.transform().TransformRect(&bounds); 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return bounds; 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerImageGrid::ImageGrid() 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner : layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)), 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner top_image_height_(0), 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bottom_image_height_(0), 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner left_image_width_(0), 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner right_image_width_(0), 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner base_top_row_height_(0), 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner base_bottom_row_height_(0), 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner base_left_column_width_(0), 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner base_right_column_width_(0) { 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 78a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner 79aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' TurnerImageGrid::~ImageGrid() { 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid ImageGrid::SetImages(const gfx::Image* top_left_image, 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const gfx::Image* top_image, 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const gfx::Image* top_right_image, 85aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner const gfx::Image* left_image, 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const gfx::Image* center_image, 87a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner const gfx::Image* right_image, 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const gfx::Image* bottom_left_image, 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const gfx::Image* bottom_image, 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const gfx::Image* bottom_right_image) { 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SetImage(top_left_image, &top_left_layer_, &top_left_painter_, NONE); 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SetImage(top_image, &top_layer_, &top_painter_, HORIZONTAL); 937627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner SetImage(top_right_image, &top_right_layer_, &top_right_painter_, NONE); 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SetImage(left_image, &left_layer_, &left_painter_, VERTICAL); 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SetImage(center_image, ¢er_layer_, ¢er_painter_, NONE); 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SetImage(right_image, &right_layer_, &right_painter_, VERTICAL); 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SetImage(bottom_left_image, &bottom_left_layer_, &bottom_left_painter_, NONE); 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SetImage(bottom_image, &bottom_layer_, &bottom_painter_, HORIZONTAL); 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SetImage( 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bottom_right_image, &bottom_right_layer_, &bottom_right_painter_, NONE); 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner top_image_height_ = GetImageSize(top_image).height(); 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bottom_image_height_ = GetImageSize(bottom_image).height(); 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner left_image_width_ = GetImageSize(left_image).width(); 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner right_image_width_ = GetImageSize(right_image).width(); 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner base_top_row_height_ = max(GetImageSize(top_left_image).height(), 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner max(GetImageSize(top_image).height(), 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner GetImageSize(top_right_image).height())); 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner base_bottom_row_height_ = max(GetImageSize(bottom_left_image).height(), 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner max(GetImageSize(bottom_image).height(), 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner GetImageSize(bottom_right_image).height())); 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner base_left_column_width_ = max(GetImageSize(top_left_image).width(), 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner max(GetImageSize(left_image).width(), 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner GetImageSize(bottom_left_image).width())); 116a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner base_right_column_width_ = max(GetImageSize(top_right_image).width(), 1177627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner max(GetImageSize(right_image).width(), 1187627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner GetImageSize(bottom_right_image).width())); 1197627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // Invalidate previous |size_| so calls to SetSize() will recompute it. 1217627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner size_.SetSize(0, 0); 1227627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner} 1237627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner 1247627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turnervoid ImageGrid::SetSize(const gfx::Size& size) { 1257627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner if (size_ == size) 1267627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner return; 1277627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner 1287627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner size_ = size; 1297627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner 1307627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner gfx::Rect updated_bounds = layer_->bounds(); 1317627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner updated_bounds.set_size(size); 1327627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner layer_->SetBounds(updated_bounds); 1337627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner 1347627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner // Calculate the available amount of space for corner images on all sides of 1357627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner // the grid. If the images don't fit, we need to clip them. 1367627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner const int left = min(base_left_column_width_, size_.width() / 2); 1377627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner const int right = min(base_right_column_width_, size_.width() - left); 1387627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner const int top = min(base_top_row_height_, size_.height() / 2); 1397627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner const int bottom = min(base_bottom_row_height_, size_.height() - top); 1407627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner 1417627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner // The remaining space goes to the center image. 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int center_width = std::max(size.width() - left - right, 0); 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int center_height = std::max(size.height() - top - bottom, 0); 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // At non-integer scale factors, the ratio of dimensions in DIP is not 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // necessarily the same as the ratio in physical pixels due to rounding. Set 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // the transform on each of the layers based on dimensions in pixels. 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Size center_size_in_pixels = gfx::ToFlooredSize(gfx::ScaleSize( 1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Size(center_width, center_height), layer_->device_scale_factor())); 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (top_layer_.get()) { 1527627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner if (center_width > 0) { 1537627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner gfx::Transform transform; 1547627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner transform.Translate(left, 0); 1557627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner ScaleWidth(center_size_in_pixels, top_layer_.get(), transform); 1567627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner top_layer_->SetTransform(transform); 1577627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner } 1587627ed7924456c88d3e8631c2cddcc7d54107ffaDavid Turner top_layer_->SetVisible(center_width > 0); 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bottom_layer_.get()) { 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (center_width > 0) { 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Transform transform; 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner transform.Translate( 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner left, size.height() - bottom_layer_->bounds().height()); 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ScaleWidth(center_size_in_pixels, bottom_layer_.get(), transform); 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bottom_layer_->SetTransform(transform); 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 168a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner bottom_layer_->SetVisible(center_width > 0); 1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (left_layer_.get()) { 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (center_height > 0) { 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Transform transform; 1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner transform.Translate(0, top); 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ScaleHeight(center_size_in_pixels, left_layer_.get(), transform); 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner left_layer_->SetTransform(transform); 1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner left_layer_->SetVisible(center_height > 0); 1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (right_layer_.get()) { 1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (center_height > 0) { 1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Transform transform; 1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner transform.Translate( 1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size.width() - right_layer_->bounds().width(), top); 1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ScaleHeight(center_size_in_pixels, right_layer_.get(), transform); 1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner right_layer_->SetTransform(transform); 186cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije } 187cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije right_layer_->SetVisible(center_height > 0); 188cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije } 189cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije 190cc19d3eeef59cbd354c1c618f7421d6fe5e0a098Ot ten Thije if (top_left_layer_.get()) { 1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner // No transformation needed; it should be at (0, 0) and unscaled. 1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner top_left_painter_->SetClipRect( 1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner LayerExceedsSize(top_left_layer_.get(), gfx::Size(left, top)) ? 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Rect(gfx::Rect(0, 0, left, top)) : 1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Rect(), 1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner top_left_layer_.get()); 1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (top_right_layer_.get()) { 1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Transform transform; 200a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner transform.Translate(size.width() - top_right_layer_->bounds().width(), 0.0); 2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner top_right_layer_->SetTransform(transform); 2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner top_right_painter_->SetClipRect( 2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner LayerExceedsSize(top_right_layer_.get(), gfx::Size(right, top)) ? 2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Rect(top_right_layer_->bounds().width() - right, 0, 2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner right, top) : 2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Rect(), 2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner top_right_layer_.get()); 2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bottom_left_layer_.get()) { 2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Transform transform; 2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner transform.Translate( 2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 0.0, size.height() - bottom_left_layer_->bounds().height()); 2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bottom_left_layer_->SetTransform(transform); 2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bottom_left_painter_->SetClipRect( 2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner LayerExceedsSize(bottom_left_layer_.get(), gfx::Size(left, bottom)) ? 216a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner gfx::Rect(0, bottom_left_layer_->bounds().height() - bottom, 2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner left, bottom) : 2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Rect(), 219a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner bottom_left_layer_.get()); 220aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner } 2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bottom_right_layer_.get()) { 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Transform transform; 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner transform.Translate( 2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size.width() - bottom_right_layer_->bounds().width(), 2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size.height() - bottom_right_layer_->bounds().height()); 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bottom_right_layer_->SetTransform(transform); 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bottom_right_painter_->SetClipRect( 2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner LayerExceedsSize(bottom_right_layer_.get(), gfx::Size(right, bottom)) ? 2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gfx::Rect(bottom_right_layer_->bounds().width() - right, 230 bottom_right_layer_->bounds().height() - bottom, 231 right, bottom) : 232 gfx::Rect(), 233 bottom_right_layer_.get()); 234 } 235 236 if (center_layer_.get()) { 237 if (center_width > 0 && center_height > 0) { 238 gfx::Transform transform; 239 transform.Translate(left, top); 240 transform.Scale(center_width / center_layer_->bounds().width(), 241 center_height / center_layer_->bounds().height()); 242 center_layer_->SetTransform(transform); 243 } 244 center_layer_->SetVisible(center_width > 0 && center_height > 0); 245 } 246} 247 248void ImageGrid::SetContentBounds(const gfx::Rect& content_bounds) { 249 250 SetSize(gfx::Size( 251 content_bounds.width() + left_image_width_ + right_image_width_, 252 content_bounds.height() + top_image_height_ + 253 bottom_image_height_)); 254 layer_->SetBounds( 255 gfx::Rect(content_bounds.x() - left_image_width_, 256 content_bounds.y() - top_image_height_, 257 layer_->bounds().width(), 258 layer_->bounds().height())); 259} 260 261void ImageGrid::ImagePainter::SetClipRect(const gfx::Rect& clip_rect, 262 ui::Layer* layer) { 263 if (clip_rect != clip_rect_) { 264 clip_rect_ = clip_rect; 265 layer->SchedulePaint(layer->bounds()); 266 } 267} 268 269void ImageGrid::ImagePainter::OnPaintLayer(gfx::Canvas* canvas) { 270 if (!clip_rect_.IsEmpty()) 271 canvas->ClipRect(clip_rect_); 272 canvas->DrawImageInt(image_, 0, 0); 273} 274 275void ImageGrid::ImagePainter::OnDelegatedFrameDamage( 276 const gfx::Rect& damage_rect_in_dip) { 277} 278 279void ImageGrid::ImagePainter::OnDeviceScaleFactorChanged( 280 float device_scale_factor) { 281 // Redrawing will take care of scale factor change. 282} 283 284base::Closure ImageGrid::ImagePainter::PrepareForLayerBoundsChange() { 285 return base::Closure(); 286} 287 288void ImageGrid::SetImage(const gfx::Image* image, 289 scoped_ptr<ui::Layer>* layer_ptr, 290 scoped_ptr<ImagePainter>* painter_ptr, 291 ImageType type) { 292 // Minimum width (for HORIZONTAL) or height (for VERTICAL) of the 293 // |image| so that layers are scaled property if the device scale 294 // factor is non integral. 295 const int kMinimumSize = 20; 296 297 // Clean out old layers and painters. 298 if (layer_ptr->get()) 299 layer_->Remove(layer_ptr->get()); 300 layer_ptr->reset(); 301 painter_ptr->reset(); 302 303 // If we're not using an image, we're done. 304 if (!image) 305 return; 306 307 gfx::ImageSkia image_skia = image->AsImageSkia(); 308 switch (type) { 309 case HORIZONTAL: 310 if (image_skia.width() < kMinimumSize) { 311 image_skia = gfx::ImageSkiaOperations::CreateResizedImage( 312 image_skia, 313 skia::ImageOperations::RESIZE_GOOD, 314 gfx::Size(kMinimumSize, image_skia.height())); 315 } 316 break; 317 case VERTICAL: 318 if (image_skia.height() < kMinimumSize) { 319 image_skia = gfx::ImageSkiaOperations::CreateResizedImage( 320 image_skia, 321 skia::ImageOperations::RESIZE_GOOD, 322 gfx::Size(image_skia.width(), kMinimumSize)); 323 } 324 break; 325 case NONE: 326 break; 327 } 328 329 // Set up the new layer and painter. 330 layer_ptr->reset(new ui::Layer(ui::LAYER_TEXTURED)); 331 332 const gfx::Size size = image_skia.size(); 333 layer_ptr->get()->SetBounds(gfx::Rect(0, 0, size.width(), size.height())); 334 335 painter_ptr->reset(new ImagePainter(image_skia)); 336 layer_ptr->get()->set_delegate(painter_ptr->get()); 337 layer_ptr->get()->SetFillsBoundsOpaquely(false); 338 layer_ptr->get()->SetVisible(true); 339 layer_->Add(layer_ptr->get()); 340} 341 342} // namespace wm 343