blob: 5c32e13617028288ddbdde8e873621b939ac6679 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/paint/nine_piece_image_painter.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/nine_piece_image_grid.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/nine_piece_image.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/scoped_interpolation_quality.h"
namespace blink {
namespace {
void PaintPieces(GraphicsContext& context,
const LayoutRect& border_image_rect,
const ComputedStyle& style,
const NinePieceImage& nine_piece_image,
Image* image,
IntSize image_size,
bool include_logical_left_edge,
bool include_logical_right_edge) {
IntRectOutsets border_widths(style.BorderTopWidth(), style.BorderRightWidth(),
style.BorderBottomWidth(),
style.BorderLeftWidth());
NinePieceImageGrid grid(
nine_piece_image, image_size, PixelSnappedIntRect(border_image_rect),
border_widths, include_logical_left_edge, include_logical_right_edge);
for (NinePiece piece = kMinPiece; piece < kMaxPiece; ++piece) {
NinePieceImageGrid::NinePieceDrawInfo draw_info = grid.GetNinePieceDrawInfo(
piece, nine_piece_image.GetImage()->ImageScaleFactor());
if (draw_info.is_drawable) {
if (draw_info.is_corner_piece) {
// Since there is no way for the developer to specify decode behavior,
// use kSync by default.
context.DrawImage(image, Image::kSyncDecode, draw_info.destination,
&draw_info.source);
} else {
context.DrawTiledImage(image, draw_info.destination, draw_info.source,
draw_info.tile_scale,
draw_info.tile_rule.horizontal,
draw_info.tile_rule.vertical);
}
}
}
}
} // anonymous namespace
bool NinePieceImagePainter::Paint(GraphicsContext& graphics_context,
const ImageResourceObserver& observer,
const Document& document,
Node* node,
const LayoutRect& rect,
const ComputedStyle& style,
const NinePieceImage& nine_piece_image,
bool include_logical_left_edge,
bool include_logical_right_edge) {
StyleImage* style_image = nine_piece_image.GetImage();
if (!style_image)
return false;
if (!style_image->IsLoaded())
return true; // Never paint a nine-piece image incrementally, but don't
// paint the fallback borders either.
if (!style_image->CanRender())
return false;
// FIXME: border-image is broken with full page zooming when tiling has to
// happen, since the tiling function doesn't have any understanding of the
// zoom that is in effect on the tile.
LayoutRect rect_with_outsets = rect;
rect_with_outsets.Expand(style.ImageOutsets(nine_piece_image));
LayoutRect border_image_rect = rect_with_outsets;
// NinePieceImage returns the image slices without effective zoom applied and
// thus we compute the nine piece grid on top of the image in unzoomed
// coordinates.
//
// FIXME: The default object size passed to imageSize() should be scaled by
// the zoom factor passed in. In this case it means that borderImageRect
// should be passed in compensated by effective zoom, since the scale factor
// is one. For generated images, the actual image data (gradient stops, etc.)
// are scaled to effective zoom instead so we must take care not to cause
// scale of them again.
IntSize image_size = RoundedIntSize(
style_image->ImageSize(document, 1, border_image_rect.Size()));
scoped_refptr<Image> image =
style_image->GetImage(observer, document, style, FloatSize(image_size));
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
"data",
inspector_paint_image_event::Data(node, *style_image,
FloatRect(image->Rect()),
FloatRect(border_image_rect)));
ScopedInterpolationQuality interpolation_quality_scope(
graphics_context, style.GetInterpolationQuality());
PaintPieces(graphics_context, border_image_rect, style, nine_piece_image,
image.get(), image_size, include_logical_left_edge,
include_logical_right_edge);
return true;
}
} // namespace blink