flutter/packages/flutter_sprites/lib/src/nine_slice_sprite.dart

196 lines
5.1 KiB
Dart

// 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.
part of flutter_sprites;
/// A NineSliceSprite is similar to a [Sprite], but it it can strech its
/// inner area to fit the size of the [Node]. This is ideal for fast drawing
/// of things like buttons.
class NineSliceSprite extends NodeWithSize with SpritePaint {
/// Creates a new NineSliceSprite from the privided [texture], [size], and
/// texture [insets].
NineSliceSprite(Texture texture, Size size, EdgeInsets insets) : super(size) {
assert(texture != null && !texture.rotated);
assert(size != null);
assert(insets != null);
pivot = const Point(0.5, 0.5);
this.texture = texture;
this.insets = insets;
}
/// Creates a new NineSliceSprite from the provided [image], [size], and
/// texture [insets].
NineSliceSprite.fromImage(ui.Image image, Size size, EdgeInsets insets)
: this(new Texture(image), size, insets);
/// The texture that the sprite will render to screen. Cannot be null.
///
/// my9Sprite.texture = myTexture;
Texture get texture => _texture;
Texture _texture;
set texture(Texture texture) {
_texture = texture;
_isDirty = true;
if (texture == null) {
_cachedPaint = new Paint();
} else {
Matrix4 matrix = new Matrix4.identity();
ImageShader shader = new ImageShader(texture.image,
TileMode.repeated, TileMode.repeated, matrix.storage);
_cachedPaint = new Paint()
..shader = shader;
}
}
/// The insets of the texture as normalized values. The insets define the
/// areas of the texture that will not be deformed as the sprite stretches.
EdgeInsets get insets => _insets;
EdgeInsets _insets;
set insets(EdgeInsets insets) {
assert(insets != null);
_insets = insets;
_isDirty = true;
}
/// If true, the center part of the sprite will be drawn, this is the default
/// behavior.
bool get drawCenterPart => _drawCenterPart;
bool _drawCenterPart = true;
set drawCenterPart(bool drawCenterPart) {
_drawCenterPart = drawCenterPart;
_isDirty = true;
}
@override
set size(Size size) {
super.size = size;
_isDirty = true;
}
Paint _cachedPaint = new Paint()
..filterQuality = FilterQuality.low
..isAntiAlias = false;
// Cached values.
bool _isDirty = true;
List<Point> _vertices;
List<Point> _textureCoordinates;
List<Color> _colors;
List<int> _indices;
@override
void paint(Canvas canvas) {
applyTransformForPivot(canvas);
// Setup paint object for opacity and transfer mode.
_updatePaint(_cachedPaint);
if (_isDirty) {
// Calcuate vertices and indices.
_vertices = <Point>[
Point.origin,
];
// Texture width and height.
double tw = texture.frame.width;
double th = texture.frame.height;
_textureCoordinates = <Point>[];
_vertices = <Point>[];
_colors = <Color>[];
for (int y = 0; y < 4; y += 1) {
double vy;
double ty;
switch(y) {
case 0:
vy = 0.0;
ty = texture.frame.top;
break;
case 1:
vy = insets.top * th;
ty = texture.frame.top + insets.top * th;
break;
case 2:
vy = size.height - insets.bottom * th;
ty = texture.frame.bottom - insets.bottom * th;
break;
case 3:
vy = size.height;
ty = texture.frame.bottom;
break;
}
for (int x = 0; x < 4; x += 1) {
double vx;
double tx;
switch(x) {
case 0:
vx = 0.0;
tx = texture.frame.left;
break;
case 1:
vx = insets.left * tw;
tx = texture.frame.left + insets.left * tw;
break;
case 2:
vx = size.width - insets.right * tw;
tx = texture.frame.right - insets.right * tw;
break;
case 3:
vx = size.width;
tx = texture.frame.right;
break;
}
_vertices.add(new Point(vx, vy));
_textureCoordinates.add(new Point(tx, ty));
_colors.add(const Color(0xffffffff));
}
}
// Build indices.
_indices = <int>[];
for (int y = 0; y < 3; y += 1) {
for (int x = 0; x < 3; x += 1) {
// Check if we should skip the middle rectangle.
if (!drawCenterPart && x == 1 && y == 1)
continue;
// Add a rectangle (two triangles).
int index = y * 4 + x;
_indices.add(index);
_indices.add(index + 1);
_indices.add(index + 4);
_indices.add(index + 1);
_indices.add(index + 5);
_indices.add(index + 4);
}
}
}
canvas.drawVertices(
VertexMode.triangles,
_vertices,
_textureCoordinates,
_colors,
TransferMode.modulate,
_indices,
_cachedPaint
);
}
}