blob: cce4564ea67820c66108fcaae9276abd583c319f [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.6
part of engine;
/// Implementation of [ui.Paint] used by the HTML rendering backend.
class SurfacePaint implements ui.Paint {
SurfacePaintData _paintData = SurfacePaintData();
@override
ui.BlendMode get blendMode => _paintData.blendMode ?? ui.BlendMode.srcOver;
@override
set blendMode(ui.BlendMode value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.blendMode = value;
}
@override
ui.PaintingStyle get style => _paintData.style ?? ui.PaintingStyle.fill;
@override
set style(ui.PaintingStyle value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.style = value;
}
@override
double get strokeWidth => _paintData.strokeWidth ?? 0.0;
@override
set strokeWidth(double value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.strokeWidth = value;
}
@override
ui.StrokeCap get strokeCap => _paintData.strokeCap;
@override
set strokeCap(ui.StrokeCap value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.strokeCap = value;
}
@override
ui.StrokeJoin get strokeJoin => _paintData.strokeJoin;
@override
set strokeJoin(ui.StrokeJoin value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.strokeJoin = value;
}
@override
bool get isAntiAlias => _paintData.isAntiAlias;
@override
set isAntiAlias(bool value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.isAntiAlias = value;
}
@override
ui.Color get color => _paintData.color;
@override
set color(ui.Color value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.color =
value.runtimeType == ui.Color ? value : ui.Color(value.value);
}
@override
bool get invertColors {
return false;
}
@override
set invertColors(bool value) {}
static const ui.Color _defaultPaintColor = ui.Color(0xFF000000);
@override
ui.Shader get shader => _paintData.shader;
@override
set shader(ui.Shader value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.shader = value;
}
@override
ui.MaskFilter get maskFilter => _paintData.maskFilter;
@override
set maskFilter(ui.MaskFilter value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.maskFilter = value;
}
@override
ui.FilterQuality get filterQuality => _paintData.filterQuality;
@override
set filterQuality(ui.FilterQuality value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.filterQuality = value;
}
@override
ui.ColorFilter get colorFilter => _paintData.colorFilter;
@override
set colorFilter(ui.ColorFilter value) {
if (_frozen) {
_paintData = _paintData.clone();
_frozen = false;
}
_paintData.colorFilter = value;
}
// TODO(flutter_web): see https://github.com/flutter/flutter/issues/33605
@override
double get strokeMiterLimit {
return null;
}
@override
set strokeMiterLimit(double value) {
assert(value != null);
}
@override
ui.ImageFilter get imageFilter {
// TODO(flutter/flutter#35156): Implement ImageFilter.
return null;
}
@override
set imageFilter(ui.ImageFilter value) {
// TODO(flutter/flutter#35156): Implement ImageFilter.
}
// True if Paint instance has used in RecordingCanvas.
bool _frozen = false;
// Marks this paint object as previously used.
SurfacePaintData get paintData {
// Flip bit so next time object gets mutated we create a clone of
// current paint data.
_frozen = true;
return _paintData;
}
@override
String toString() {
final StringBuffer result = StringBuffer();
String semicolon = '';
result.write('Paint(');
if (style == ui.PaintingStyle.stroke) {
result.write('$style');
if (strokeWidth != null && strokeWidth != 0.0)
result.write(' $strokeWidth');
else
result.write(' hairline');
if (strokeCap != null && strokeCap != ui.StrokeCap.butt)
result.write(' $strokeCap');
semicolon = '; ';
}
if (isAntiAlias != true) {
result.write('${semicolon}antialias off');
semicolon = '; ';
}
if (color != _defaultPaintColor) {
if (color != null)
result.write('$semicolon$color');
else
result.write('${semicolon}no color');
semicolon = '; ';
}
result.write(')');
return result.toString();
}
}
/// Private Paint context data used for recording canvas commands allowing
/// Paint to be mutated post canvas draw operations.
class SurfacePaintData {
ui.BlendMode blendMode;
ui.PaintingStyle style;
double strokeWidth;
ui.StrokeCap strokeCap;
ui.StrokeJoin strokeJoin;
bool isAntiAlias = true;
ui.Color color;
ui.Shader shader;
ui.MaskFilter maskFilter;
ui.FilterQuality filterQuality;
ui.ColorFilter colorFilter;
// Internal for recording canvas use.
SurfacePaintData clone() {
return SurfacePaintData()
..blendMode = blendMode
..filterQuality = filterQuality
..maskFilter = maskFilter
..shader = shader
..isAntiAlias = isAntiAlias
..color = color
..colorFilter = colorFilter
..strokeWidth = strokeWidth
..style = style
..strokeJoin = strokeJoin
..strokeCap = strokeCap;
}
@override
String toString() {
if (!assertionsEnabled) {
return super.toString();
} else {
final StringBuffer buffer = StringBuffer('SurfacePaintData(');
if (blendMode != null) {
buffer.write('blendMode = $blendMode; ');
}
if (style != null) {
buffer.write('style = $style; ');
}
if (strokeWidth != null) {
buffer.write('strokeWidth = $strokeWidth; ');
}
if (strokeCap != null) {
buffer.write('strokeCap = $strokeCap; ');
}
if (strokeJoin != null) {
buffer.write('strokeJoin = $strokeJoin; ');
}
if (color != null) {
buffer.write('color = ${colorToCssString(color)}; ');
}
if (shader != null) {
buffer.write('shader = $shader; ');
}
if (maskFilter != null) {
buffer.write('maskFilter = $maskFilter; ');
}
if (filterQuality != null) {
buffer.write('filterQuality = $filterQuality; ');
}
if (colorFilter != null) {
buffer.write('colorFilter = $colorFilter; ');
}
buffer.write('isAntiAlias = $isAntiAlias)');
return buffer.toString();
}
}
}