This source file includes following definitions.
- IsSolidColorPaint
- IsFullQuad
- SetForceNotSolid
- SetForceNotTransparent
- clear
- drawPaint
- drawPoints
- drawRect
- drawOval
- drawRRect
- drawPath
- drawBitmap
- drawBitmapRectToRect
- drawBitmapMatrix
- drawBitmapNine
- drawSprite
- drawText
- drawPosText
- drawPosTextH
- drawTextOnPath
- drawVertices
- MakeEmptyBitmap
- has_text_
- GetColorIfSolid
- HasText
- abortDrawing
- onClipRect
- onClipPath
- onClipRRect
- willSave
- willSaveLayer
- willRestore
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "skia/ext/analysis_canvas.h"
#include "third_party/skia/include/core/SkDraw.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/src/core/SkRasterClip.h"
#include "ui/gfx/rect_conversions.h"
namespace {
const int kNoLayer = -1;
bool IsSolidColorPaint(const SkPaint& paint) {
SkXfermode::Mode xfermode;
SkXfermode::AsMode(paint.getXfermode(), &xfermode);
return (paint.getAlpha() == 255 &&
!paint.getShader() &&
!paint.getLooper() &&
!paint.getMaskFilter() &&
!paint.getColorFilter() &&
!paint.getImageFilter() &&
paint.getStyle() == SkPaint::kFill_Style &&
(xfermode == SkXfermode::kSrc_Mode ||
xfermode == SkXfermode::kSrcOver_Mode));
}
bool IsFullQuad(SkCanvas* canvas, const SkRect& drawn_rect) {
if (!canvas->isClipRect())
return false;
SkIRect clip_irect;
canvas->getClipDeviceBounds(&clip_irect);
if (!clip_irect.contains(SkIRect::MakeSize(canvas->getDeviceSize())))
return false;
const SkMatrix& matrix = canvas->getTotalMatrix();
if (!matrix.rectStaysRect())
return false;
SkRect device_rect;
matrix.mapRect(&device_rect, drawn_rect);
SkRect clip_rect;
clip_rect.set(clip_irect);
return device_rect.contains(clip_rect);
}
}
namespace skia {
void AnalysisCanvas::SetForceNotSolid(bool flag) {
is_forced_not_solid_ = flag;
if (is_forced_not_solid_)
is_solid_color_ = false;
}
void AnalysisCanvas::SetForceNotTransparent(bool flag) {
is_forced_not_transparent_ = flag;
if (is_forced_not_transparent_)
is_transparent_ = false;
}
void AnalysisCanvas::clear(SkColor color) {
is_transparent_ = (!is_forced_not_transparent_ && SkColorGetA(color) == 0);
has_text_ = false;
if (!is_forced_not_solid_ && SkColorGetA(color) == 255) {
is_solid_color_ = true;
color_ = color;
} else {
is_solid_color_ = false;
}
}
void AnalysisCanvas::drawPaint(const SkPaint& paint) {
if (isClipEmpty())
return;
is_solid_color_ = false;
is_transparent_ = false;
}
void AnalysisCanvas::drawPoints(SkCanvas::PointMode mode,
size_t count,
const SkPoint points[],
const SkPaint& paint) {
is_solid_color_ = false;
is_transparent_ = false;
}
void AnalysisCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
if (paint.nothingToDraw())
return;
bool does_cover_canvas = IsFullQuad(this, rect);
SkXfermode::Mode xfermode;
SkXfermode::AsMode(paint.getXfermode(), &xfermode);
if (does_cover_canvas &&
!is_forced_not_transparent_ &&
xfermode == SkXfermode::kClear_Mode) {
is_transparent_ = true;
has_text_ = false;
} else if (paint.getAlpha() != 0 || xfermode != SkXfermode::kSrc_Mode) {
is_transparent_ = false;
}
if (!is_forced_not_solid_ && IsSolidColorPaint(paint) && does_cover_canvas) {
is_solid_color_ = true;
color_ = paint.getColor();
has_text_ = false;
} else {
is_solid_color_ = false;
}
}
void AnalysisCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
is_solid_color_ = false;
is_transparent_ = false;
}
void AnalysisCanvas::drawRRect(const SkRRect& rr, const SkPaint& paint) {
is_solid_color_ = false;
is_transparent_ = false;
}
void AnalysisCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
is_solid_color_ = false;
is_transparent_ = false;
}
void AnalysisCanvas::drawBitmap(const SkBitmap& bitmap,
SkScalar left,
SkScalar top,
const SkPaint*) {
is_solid_color_ = false;
is_transparent_ = false;
}
void AnalysisCanvas::drawBitmapRectToRect(const SkBitmap&,
const SkRect* src,
const SkRect& dst,
const SkPaint* paint,
DrawBitmapRectFlags flags) {
SkPaint tmpPaint;
if (!paint)
paint = &tmpPaint;
drawRect(dst, *paint);
is_solid_color_ = false;
}
void AnalysisCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
const SkMatrix& matrix,
const SkPaint* paint) {
is_solid_color_ = false;
is_transparent_ = false;
}
void AnalysisCanvas::drawBitmapNine(const SkBitmap& bitmap,
const SkIRect& center,
const SkRect& dst,
const SkPaint* paint) {
is_solid_color_ = false;
is_transparent_ = false;
}
void AnalysisCanvas::drawSprite(const SkBitmap& bitmap,
int left,
int top,
const SkPaint* paint) {
is_solid_color_ = false;
is_transparent_ = false;
}
void AnalysisCanvas::drawText(const void* text,
size_t len,
SkScalar x,
SkScalar y,
const SkPaint& paint) {
is_solid_color_ = false;
is_transparent_ = false;
has_text_ = true;
}
void AnalysisCanvas::drawPosText(const void* text,
size_t byteLength,
const SkPoint pos[],
const SkPaint& paint) {
is_solid_color_ = false;
is_transparent_ = false;
has_text_ = true;
}
void AnalysisCanvas::drawPosTextH(const void* text,
size_t byteLength,
const SkScalar xpos[],
SkScalar constY,
const SkPaint& paint) {
is_solid_color_ = false;
is_transparent_ = false;
has_text_ = true;
}
void AnalysisCanvas::drawTextOnPath(const void* text,
size_t len,
const SkPath& path,
const SkMatrix* matrix,
const SkPaint& paint) {
is_solid_color_ = false;
is_transparent_ = false;
has_text_ = true;
}
void AnalysisCanvas::drawVertices(SkCanvas::VertexMode,
int vertex_count,
const SkPoint verts[],
const SkPoint texs[],
const SkColor colors[],
SkXfermode* xmode,
const uint16_t indices[],
int index_count,
const SkPaint& paint) {
is_solid_color_ = false;
is_transparent_ = false;
}
static SkBitmap MakeEmptyBitmap(int width, int height) {
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kNo_Config, width, height);
return bitmap;
}
AnalysisCanvas::AnalysisCanvas(int width, int height)
: INHERITED(MakeEmptyBitmap(width, height)),
saved_stack_size_(0),
force_not_solid_stack_level_(kNoLayer),
force_not_transparent_stack_level_(kNoLayer),
is_forced_not_solid_(false),
is_forced_not_transparent_(false),
is_solid_color_(true),
is_transparent_(true),
has_text_(false) {}
AnalysisCanvas::~AnalysisCanvas() {}
bool AnalysisCanvas::GetColorIfSolid(SkColor* color) const {
if (is_transparent_) {
*color = SK_ColorTRANSPARENT;
return true;
}
if (is_solid_color_) {
*color = color_;
return true;
}
return false;
}
bool AnalysisCanvas::HasText() const { return has_text_; }
bool AnalysisCanvas::abortDrawing() {
return HasText();
}
void AnalysisCanvas::onClipRect(const SkRect& rect, SkRegion::Op op,
ClipEdgeStyle edge_style) {
INHERITED::onClipRect(rect, op, edge_style);
}
void AnalysisCanvas::onClipPath(const SkPath& path, SkRegion::Op op,
ClipEdgeStyle edge_style) {
if (force_not_solid_stack_level_ == kNoLayer) {
force_not_solid_stack_level_ = saved_stack_size_;
SetForceNotSolid(true);
}
if (force_not_transparent_stack_level_ == kNoLayer) {
force_not_transparent_stack_level_ = saved_stack_size_;
SetForceNotTransparent(true);
}
INHERITED::onClipRect(path.getBounds(), op, edge_style);
}
void AnalysisCanvas::onClipRRect(const SkRRect& rrect,
SkRegion::Op op,
ClipEdgeStyle edge_style) {
if (force_not_solid_stack_level_ == kNoLayer) {
force_not_solid_stack_level_ = saved_stack_size_;
SetForceNotSolid(true);
}
if (force_not_transparent_stack_level_ == kNoLayer) {
force_not_transparent_stack_level_ = saved_stack_size_;
SetForceNotTransparent(true);
}
INHERITED::onClipRect(rrect.getBounds(), op, edge_style);
}
void AnalysisCanvas::willSave(SkCanvas::SaveFlags flags) {
++saved_stack_size_;
INHERITED::willSave(flags);
}
SkCanvas::SaveLayerStrategy AnalysisCanvas::willSaveLayer(
const SkRect* bounds,
const SkPaint* paint,
SkCanvas::SaveFlags flags) {
++saved_stack_size_;
SkIRect canvas_ibounds = SkIRect::MakeSize(this->getDeviceSize());
SkRect canvas_bounds;
canvas_bounds.set(canvas_ibounds);
if ((paint && !IsSolidColorPaint(*paint)) ||
(bounds && !bounds->contains(canvas_bounds))) {
if (force_not_solid_stack_level_ == kNoLayer) {
force_not_solid_stack_level_ = saved_stack_size_;
SetForceNotSolid(true);
}
}
SkXfermode::Mode xfermode = SkXfermode::kSrc_Mode;
if (paint)
SkXfermode::AsMode(paint->getXfermode(), &xfermode);
if (xfermode != SkXfermode::kSrc_Mode) {
if (force_not_transparent_stack_level_ == kNoLayer) {
force_not_transparent_stack_level_ = saved_stack_size_;
SetForceNotTransparent(true);
}
}
INHERITED::willSaveLayer(bounds, paint, flags);
return kNoLayer_SaveLayerStrategy;
}
void AnalysisCanvas::willRestore() {
DCHECK(saved_stack_size_);
if (saved_stack_size_) {
--saved_stack_size_;
if (saved_stack_size_ < force_not_solid_stack_level_) {
SetForceNotSolid(false);
force_not_solid_stack_level_ = kNoLayer;
}
if (saved_stack_size_ < force_not_transparent_stack_level_) {
SetForceNotTransparent(false);
force_not_transparent_stack_level_ = kNoLayer;
}
}
INHERITED::willRestore();
}
}