blob: 5b653a64a2c965b34822b2cbd7aeb0cbd269f89a [file] [log] [blame]
// Copyright 2016 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 "platform/graphics/PlaceholderImage.h"
#include "platform/geometry/FloatRect.h"
#include "platform/geometry/IntPoint.h"
#include "platform/geometry/IntRect.h"
#include "platform/graphics/BitmapImage.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/ImageObserver.h"
#include "platform/graphics/paint/PaintCanvas.h"
#include "platform/graphics/paint/PaintFlags.h"
#include "platform/graphics/paint/PaintRecord.h"
#include "platform/graphics/paint/PaintRecorder.h"
#include "platform/wtf/StdLibExtras.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkSize.h"
namespace blink {
PlaceholderImage::PlaceholderImage(ImageObserver* observer, const IntSize& size)
: Image(observer), size_(size) {}
PlaceholderImage::~PlaceholderImage() {}
PaintImage PlaceholderImage::PaintImageForCurrentFrame() {
auto builder = CreatePaintImageBuilder().set_completion_state(
PaintImage::CompletionState::DONE);
const IntRect dest_rect(0, 0, size_.Width(), size_.Height());
if (paint_record_for_current_frame_) {
return builder
.set_paint_record(paint_record_for_current_frame_, dest_rect,
paint_record_content_id_)
.TakePaintImage();
}
PaintRecorder paint_recorder;
Draw(paint_recorder.beginRecording(FloatRect(dest_rect)), PaintFlags(),
FloatRect(dest_rect), FloatRect(dest_rect),
kDoNotRespectImageOrientation, kClampImageToSourceRect, kSyncDecode);
paint_record_for_current_frame_ = paint_recorder.finishRecordingAsPicture();
paint_record_content_id_ = PaintImage::GetNextContentId();
return builder
.set_paint_record(paint_record_for_current_frame_, dest_rect,
paint_record_content_id_)
.TakePaintImage();
}
void PlaceholderImage::Draw(PaintCanvas* canvas,
const PaintFlags& base_flags,
const FloatRect& dest_rect,
const FloatRect& src_rect,
RespectImageOrientationEnum respect_orientation,
ImageClampingMode image_clamping_mode,
ImageDecodingMode decode_mode) {
if (!src_rect.Intersects(FloatRect(0.0f, 0.0f,
static_cast<float>(size_.Width()),
static_cast<float>(size_.Height())))) {
return;
}
// Placeholder image visual specifications:
// https://docs.google.com/document/d/1BHeA1azbgCdZgCnr16VN2g7A9MHPQ_dwKn5szh8evMQ/edit
PaintFlags flags(base_flags);
flags.setStyle(PaintFlags::kFill_Style);
flags.setColor(SkColorSetARGB(0x80, 0xD9, 0xD9, 0xD9));
canvas->drawRect(dest_rect, flags);
constexpr int kIconWidth = 24;
constexpr int kIconHeight = 24;
constexpr int kIconPaddingX = 8;
constexpr int kIconPaddingY = 5;
if (dest_rect.Width() < kIconWidth + 2 * kIconPaddingX ||
dest_rect.Height() < kIconHeight + 2 * kIconPaddingY) {
return;
}
DEFINE_STATIC_REF(Image, icon_image,
(Image::LoadPlatformResource("placeholderIcon")));
DCHECK(!icon_image->IsNull());
FloatRect icon_dest_rect(
dest_rect.X() + (dest_rect.Width() - kIconWidth) / 2.0f,
dest_rect.Y() + (dest_rect.Height() - kIconHeight) / 2.0f, kIconWidth,
kIconHeight);
// Note that the |icon_image| is not scaled according to dest_rect / src_rect,
// and is always drawn at the same size. This is so that placeholder icons are
// visible (e.g. when replacing a large image that's scaled down to a small
// area) and so that all placeholder images on the same page look consistent.
canvas->drawImageRect(icon_image->PaintImageForCurrentFrame(),
IntRect(IntPoint::Zero(), icon_image->Size()),
icon_dest_rect, &base_flags,
PaintCanvas::kFast_SrcRectConstraint);
}
void PlaceholderImage::DrawPattern(GraphicsContext& context,
const FloatRect& src_rect,
const FloatSize& scale,
const FloatPoint& phase,
SkBlendMode mode,
const FloatRect& dest_rect,
const FloatSize& repeat_spacing) {
DCHECK(context.Canvas());
PaintFlags flags = context.FillFlags();
flags.setBlendMode(mode);
// Ignore the pattern specifications and just draw a single placeholder image
// over the whole |dest_rect|. This is done in order to prevent repeated icons
// from cluttering tiled background images.
Draw(context.Canvas(), flags, dest_rect, src_rect,
kDoNotRespectImageOrientation, kClampImageToSourceRect,
kUnspecifiedDecode);
}
void PlaceholderImage::DestroyDecodedData() {
paint_record_for_current_frame_.reset();
}
} // namespace blink