| // 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 |
| ); |
| } |
| } |