| // 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.9 |
| part of ui; |
| |
| /// Defines how a list of points is interpreted when drawing a set of points. |
| /// |
| /// Used by [Canvas.drawPoints]. |
| enum PointMode { |
| /// Draw each point separately. |
| /// |
| /// If the [Paint.strokeCap] is [StrokeCap.round], then each point is drawn |
| /// as a circle with the diameter of the [Paint.strokeWidth], filled as |
| /// described by the [Paint] (ignoring [Paint.style]). |
| /// |
| /// Otherwise, each point is drawn as an axis-aligned square with sides of |
| /// length [Paint.strokeWidth], filled as described by the [Paint] (ignoring |
| /// [Paint.style]). |
| points, |
| |
| /// Draw each sequence of two points as a line segment. |
| /// |
| /// If the number of points is odd, then the last point is ignored. |
| /// |
| /// The lines are stroked as described by the [Paint] (ignoring |
| /// [Paint.style]). |
| lines, |
| |
| /// Draw the entire sequence of point as one line. |
| /// |
| /// The lines are stroked as described by the [Paint] (ignoring |
| /// [Paint.style]). |
| polygon, |
| } |
| |
| /// Defines how a new clip region should be merged with the existing clip |
| /// region. |
| /// |
| /// Used by [Canvas.clipRect]. |
| enum ClipOp { |
| /// Subtract the new region from the existing region. |
| difference, |
| |
| /// Intersect the new region from the existing region. |
| intersect, |
| } |
| |
| enum VertexMode { |
| /// Draw each sequence of three points as the vertices of a triangle. |
| triangles, |
| |
| /// Draw each sliding window of three points as the vertices of a triangle. |
| triangleStrip, |
| |
| /// Draw the first point and each sliding window of two points as the vertices of a triangle. |
| triangleFan, |
| } |
| |
| /// A set of vertex data used by [Canvas.drawVertices]. |
| class Vertices { |
| /// Creates a set of vertex data for use with [Canvas.drawVertices]. |
| /// |
| /// The [mode] and [positions] parameters must not be null. |
| /// |
| /// If the [textureCoordinates] or [colors] parameters are provided, they must |
| /// be the same length as [positions]. |
| /// |
| /// If the [indices] parameter is provided, all values in the list must be |
| /// valid index values for [positions]. |
| factory Vertices( |
| VertexMode mode, |
| List<Offset> positions, { |
| List<Offset>? textureCoordinates, |
| List<Color>? colors, |
| List<int>? indices, |
| }) { |
| if (engine.experimentalUseSkia) { |
| return engine.CkVertices(mode, positions, |
| textureCoordinates: textureCoordinates, |
| colors: colors, |
| indices: indices); |
| } |
| return engine.SurfaceVertices(mode, positions, |
| colors: colors, |
| indices: indices); |
| } |
| |
| /// Creates a set of vertex data for use with [Canvas.drawVertices], directly |
| /// using the encoding methods of [new Vertices]. |
| /// |
| /// The [mode] parameter must not be null. |
| /// |
| /// The [positions] list is interpreted as a list of repeated pairs of x,y |
| /// coordinates. It must not be null. |
| /// |
| /// The [textureCoordinates] list is interpreted as a list of repeated pairs |
| /// of x,y coordinates, and must be the same length of [positions] if it |
| /// is not null. |
| /// |
| /// The [colors] list is interpreted as a list of RGBA encoded colors, similar |
| /// to [Color.value]. It must be half length of [positions] if it is not |
| /// null. |
| /// |
| /// If the [indices] list is provided, all values in the list must be |
| /// valid index values for [positions]. |
| factory Vertices.raw( |
| VertexMode mode, |
| Float32List positions, { |
| Float32List? textureCoordinates, |
| Int32List? colors, |
| Uint16List? indices, |
| }) { |
| if (engine.experimentalUseSkia) { |
| return engine.CkVertices.raw(mode, positions, |
| textureCoordinates: textureCoordinates, |
| colors: colors, |
| indices: indices); |
| } |
| return engine.SurfaceVertices.raw(mode, positions, |
| colors: colors, |
| indices: indices); |
| } |
| } |
| |
| /// Records a [Picture] containing a sequence of graphical operations. |
| /// |
| /// To begin recording, construct a [Canvas] to record the commands. |
| /// To end recording, use the [PictureRecorder.endRecording] method. |
| abstract class PictureRecorder { |
| /// Creates a new idle PictureRecorder. To associate it with a |
| /// [Canvas] and begin recording, pass this [PictureRecorder] to the |
| /// [Canvas] constructor. |
| factory PictureRecorder() { |
| if (engine.experimentalUseSkia) { |
| return engine.CkPictureRecorder(); |
| } else { |
| return engine.EnginePictureRecorder(); |
| } |
| } |
| |
| /// Whether this object is currently recording commands. |
| /// |
| /// Specifically, this returns true if a [Canvas] object has been |
| /// created to record commands and recording has not yet ended via a |
| /// call to [endRecording], and false if either this |
| /// [PictureRecorder] has not yet been associated with a [Canvas], |
| /// or the [endRecording] method has already been called. |
| bool get isRecording; |
| |
| /// Finishes recording graphical operations. |
| /// |
| /// Returns a picture containing the graphical operations that have been |
| /// recorded thus far. After calling this function, both the picture recorder |
| /// and the canvas objects are invalid and cannot be used further. |
| Picture endRecording(); |
| } |
| |
| /// An interface for recording graphical operations. |
| /// |
| /// [Canvas] objects are used in creating [Picture] objects, which can |
| /// themselves be used with a [SceneBuilder] to build a [Scene]. In |
| /// normal usage, however, this is all handled by the framework. |
| /// |
| /// A canvas has a current transformation matrix which is applied to all |
| /// operations. Initially, the transformation matrix is the identity transform. |
| /// It can be modified using the [translate], [scale], [rotate], [skew], |
| /// and [transform] methods. |
| /// |
| /// A canvas also has a current clip region which is applied to all operations. |
| /// Initially, the clip region is infinite. It can be modified using the |
| /// [clipRect], [clipRRect], and [clipPath] methods. |
| /// |
| /// The current transform and clip can be saved and restored using the stack |
| /// managed by the [save], [saveLayer], and [restore] methods. |
| abstract class Canvas { |
| factory Canvas(PictureRecorder recorder, [Rect? cullRect]) { |
| if (engine.experimentalUseSkia) { |
| return engine.CanvasKitCanvas(recorder, cullRect); |
| } else { |
| return engine.SurfaceCanvas(recorder as engine.EnginePictureRecorder, cullRect); |
| } |
| } |
| |
| /// Saves a copy of the current transform and clip on the save stack. |
| /// |
| /// Call [restore] to pop the save stack. |
| /// |
| /// See also: |
| /// |
| /// * [saveLayer], which does the same thing but additionally also groups the |
| /// commands done until the matching [restore]. |
| void save(); |
| |
| /// Saves a copy of the current transform and clip on the save stack, and then |
| /// creates a new group which subsequent calls will become a part of. When the |
| /// save stack is later popped, the group will be flattened into a layer and |
| /// have the given `paint`'s [Paint.colorFilter] and [Paint.blendMode] |
| /// applied. |
| /// |
| /// This lets you create composite effects, for example making a group of |
| /// drawing commands semi-transparent. Without using [saveLayer], each part of |
| /// the group would be painted individually, so where they overlap would be |
| /// darker than where they do not. By using [saveLayer] to group them |
| /// together, they can be drawn with an opaque color at first, and then the |
| /// entire group can be made transparent using the [saveLayer]'s paint. |
| /// |
| /// Call [restore] to pop the save stack and apply the paint to the group. |
| /// |
| /// ## Using saveLayer with clips |
| /// |
| /// When a rectangular clip operation (from [clipRect]) is not axis-aligned |
| /// with the raster buffer, or when the clip operation is not rectalinear (e.g. |
| /// because it is a rounded rectangle clip created by [clipRRect] or an |
| /// arbitrarily complicated path clip created by [clipPath]), the edge of the |
| /// clip needs to be anti-aliased. |
| /// |
| /// If two draw calls overlap at the edge of such a clipped region, without |
| /// using [saveLayer], the first drawing will be anti-aliased with the |
| /// background first, and then the second will be anti-aliased with the result |
| /// of blending the first drawing and the background. On the other hand, if |
| /// [saveLayer] is used immediately after establishing the clip, the second |
| /// drawing will cover the first in the layer, and thus the second alone will |
| /// be anti-aliased with the background when the layer is clipped and |
| /// composited (when [restore] is called). |
| /// |
| /// For example, this [CustomPainter.paint] method paints a clean white |
| /// rounded rectangle: |
| /// |
| /// ```dart |
| /// void paint(Canvas canvas, Size size) { |
| /// Rect rect = Offset.zero & size; |
| /// canvas.save(); |
| /// canvas.clipRRect(new RRect.fromRectXY(rect, 100.0, 100.0)); |
| /// canvas.saveLayer(rect, new Paint()); |
| /// canvas.drawPaint(new Paint()..color = Colors.red); |
| /// canvas.drawPaint(new Paint()..color = Colors.white); |
| /// canvas.restore(); |
| /// canvas.restore(); |
| /// } |
| /// ``` |
| /// |
| /// On the other hand, this one renders a red outline, the result of the red |
| /// paint being anti-aliased with the background at the clip edge, then the |
| /// white paint being similarly anti-aliased with the background _including |
| /// the clipped red paint_: |
| /// |
| /// ```dart |
| /// void paint(Canvas canvas, Size size) { |
| /// // (this example renders poorly, prefer the example above) |
| /// Rect rect = Offset.zero & size; |
| /// canvas.save(); |
| /// canvas.clipRRect(new RRect.fromRectXY(rect, 100.0, 100.0)); |
| /// canvas.drawPaint(new Paint()..color = Colors.red); |
| /// canvas.drawPaint(new Paint()..color = Colors.white); |
| /// canvas.restore(); |
| /// } |
| /// ``` |
| /// |
| /// This point is moot if the clip only clips one draw operation. For example, |
| /// the following paint method paints a pair of clean white rounded |
| /// rectangles, even though the clips are not done on a separate layer: |
| /// |
| /// ```dart |
| /// void paint(Canvas canvas, Size size) { |
| /// canvas.save(); |
| /// canvas.clipRRect(new RRect.fromRectXY(Offset.zero & (size / 2.0), 50.0, 50.0)); |
| /// canvas.drawPaint(new Paint()..color = Colors.white); |
| /// canvas.restore(); |
| /// canvas.save(); |
| /// canvas.clipRRect(new RRect.fromRectXY(size.center(Offset.zero) & (size / 2.0), 50.0, 50.0)); |
| /// canvas.drawPaint(new Paint()..color = Colors.white); |
| /// canvas.restore(); |
| /// } |
| /// ``` |
| /// |
| /// (Incidentally, rather than using [clipRRect] and [drawPaint] to draw |
| /// rounded rectangles like this, prefer the [drawRRect] method. These |
| /// examples are using [drawPaint] as a proxy for "complicated draw operations |
| /// that will get clipped", to illustrate the point.) |
| /// |
| /// ## Performance considerations |
| /// |
| /// Generally speaking, [saveLayer] is relatively expensive. |
| /// |
| /// There are a several different hardware architectures for GPUs (graphics |
| /// processing units, the hardware that handles graphics), but most of them |
| /// involve batching commands and reordering them for performance. When layers |
| /// are used, they cause the rendering pipeline to have to switch render |
| /// target (from one layer to another). Render target switches can flush the |
| /// GPU's command buffer, which typically means that optimizations that one |
| /// could get with larger batching are lost. Render target switches also |
| /// generate a lot of memory churn because the GPU needs to copy out the |
| /// current frame buffer contents from the part of memory that's optimized for |
| /// writing, and then needs to copy it back in once the previous render target |
| /// (layer) is restored. |
| /// |
| /// See also: |
| /// |
| /// * [save], which saves the current state, but does not create a new layer |
| /// for subsequent commands. |
| /// * [BlendMode], which discusses the use of [Paint.blendMode] with |
| /// [saveLayer]. |
| void saveLayer(Rect? bounds, Paint paint); |
| |
| /// Pops the current save stack, if there is anything to pop. |
| /// Otherwise, does nothing. |
| /// |
| /// Use [save] and [saveLayer] to push state onto the stack. |
| /// |
| /// If the state was pushed with with [saveLayer], then this call will also |
| /// cause the new layer to be composited into the previous layer. |
| void restore(); |
| |
| /// Returns the number of items on the save stack, including the |
| /// initial state. This means it returns 1 for a clean canvas, and |
| /// that each call to [save] and [saveLayer] increments it, and that |
| /// each matching call to [restore] decrements it. |
| /// |
| /// This number cannot go below 1. |
| int getSaveCount(); |
| |
| /// Add a translation to the current transform, shifting the coordinate space |
| /// horizontally by the first argument and vertically by the second argument. |
| void translate(double dx, double dy); |
| |
| /// Add an axis-aligned scale to the current transform, scaling by the first |
| /// argument in the horizontal direction and the second in the vertical |
| /// direction. |
| /// |
| /// If [sy] is unspecified, [sx] will be used for the scale in both |
| /// directions. |
| void scale(double sx, [double? sy]); |
| |
| /// Add a rotation to the current transform. The argument is in radians clockwise. |
| void rotate(double radians); |
| |
| /// Add an axis-aligned skew to the current transform, with the first argument |
| /// being the horizontal skew in radians clockwise around the origin, and the |
| /// second argument being the vertical skew in radians clockwise around the |
| /// origin. |
| void skew(double sx, double sy); |
| |
| /// Multiply the current transform by the specified 4⨉4 transformation matrix |
| /// specified as a list of values in column-major order. |
| void transform(Float64List matrix4); |
| |
| /// Reduces the clip region to the intersection of the current clip and the |
| /// given rectangle. |
| /// |
| /// If [doAntiAlias] is true, then the clip will be anti-aliased. |
| /// |
| /// If multiple draw commands intersect with the clip boundary, this can result |
| /// in incorrect blending at the clip boundary. See [saveLayer] for a |
| /// discussion of how to address that. |
| /// |
| /// Use [ClipOp.difference] to subtract the provided rectangle from the |
| /// current clip. |
| void clipRect(Rect rect, |
| {ClipOp clipOp = ClipOp.intersect, bool doAntiAlias = true}); |
| |
| /// Reduces the clip region to the intersection of the current clip and the |
| /// given rounded rectangle. |
| /// |
| /// If [doAntiAlias] is true, then the clip will be anti-aliased. |
| /// |
| /// If multiple draw commands intersect with the clip boundary, this can result |
| /// in incorrect blending at the clip boundary. See [saveLayer] for a |
| /// discussion of how to address that and some examples of using [clipRRect]. |
| void clipRRect(RRect rrect, {bool doAntiAlias = true}); |
| |
| /// Reduces the clip region to the intersection of the current clip and the |
| /// given [Path]. |
| /// |
| /// If [doAntiAlias] is true, then the clip will be anti-aliased. |
| /// |
| /// If multiple draw commands intersect with the clip boundary, this can result |
| /// multiple draw commands intersect with the clip boundary, this can result |
| /// in incorrect blending at the clip boundary. See [saveLayer] for a |
| /// discussion of how to address that. |
| void clipPath(Path path, {bool doAntiAlias = true}); |
| |
| /// Paints the given [Color] onto the canvas, applying the given |
| /// [BlendMode], with the given color being the source and the background |
| /// being the destination. |
| void drawColor(Color color, BlendMode blendMode); |
| |
| /// Draws a line between the given points using the given paint. The line is |
| /// stroked, the value of the [Paint.style] is ignored for this call. |
| /// |
| /// The `p1` and `p2` arguments are interpreted as offsets from the origin. |
| void drawLine(Offset p1, Offset p2, Paint paint); |
| |
| /// Fills the canvas with the given [Paint]. |
| /// |
| /// To fill the canvas with a solid color and blend mode, consider |
| /// [drawColor] instead. |
| void drawPaint(Paint paint); |
| |
| /// Draws a rectangle with the given [Paint]. Whether the rectangle is filled |
| /// or stroked (or both) is controlled by [Paint.style]. |
| void drawRect(Rect rect, Paint paint); |
| |
| /// Draws a rounded rectangle with the given [Paint]. Whether the rectangle is |
| /// filled or stroked (or both) is controlled by [Paint.style]. |
| void drawRRect(RRect rrect, Paint paint); |
| |
| /// Draws a shape consisting of the difference between two rounded rectangles |
| /// with the given [Paint]. Whether this shape is filled or stroked (or both) |
| /// is controlled by [Paint.style]. |
| /// |
| /// This shape is almost but not quite entirely unlike an annulus. |
| void drawDRRect(RRect outer, RRect inner, Paint paint); |
| |
| /// Draws an axis-aligned oval that fills the given axis-aligned rectangle |
| /// with the given [Paint]. Whether the oval is filled or stroked (or both) is |
| /// controlled by [Paint.style]. |
| void drawOval(Rect rect, Paint paint); |
| |
| /// Draws a circle centered at the point given by the first argument and |
| /// that has the radius given by the second argument, with the [Paint] given in |
| /// the third argument. Whether the circle is filled or stroked (or both) is |
| /// controlled by [Paint.style]. |
| void drawCircle(Offset c, double radius, Paint paint); |
| |
| /// Draw an arc scaled to fit inside the given rectangle. It starts from |
| /// startAngle radians around the oval up to startAngle + sweepAngle |
| /// radians around the oval, with zero radians being the point on |
| /// the right hand side of the oval that crosses the horizontal line |
| /// that intersects the center of the rectangle and with positive |
| /// angles going clockwise around the oval. If useCenter is true, the arc is |
| /// closed back to the center, forming a circle sector. Otherwise, the arc is |
| /// not closed, forming a circle segment. |
| /// |
| /// This method is optimized for drawing arcs and should be faster than [Path.arcTo]. |
| void drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, |
| Paint paint); |
| |
| /// Draws the given [Path] with the given [Paint]. Whether this shape is |
| /// filled or stroked (or both) is controlled by [Paint.style]. If the path is |
| /// filled, then subpaths within it are implicitly closed (see [Path.close]). |
| void drawPath(Path path, Paint paint); |
| |
| /// Draws the given [Image] into the canvas with its top-left corner at the |
| /// given [Offset]. The image is composited into the canvas using the given [Paint]. |
| void drawImage(Image image, Offset offset, Paint paint); |
| |
| /// Draws the subset of the given image described by the `src` argument into |
| /// the canvas in the axis-aligned rectangle given by the `dst` argument. |
| /// |
| /// This might sample from outside the `src` rect by up to half the width of |
| /// an applied filter. |
| /// |
| /// Multiple calls to this method with different arguments (from the same |
| /// image) can be batched into a single call to [drawAtlas] to improve |
| /// performance. |
| void drawImageRect(Image image, Rect src, Rect dst, Paint paint); |
| |
| /// Draws the given [Image] into the canvas using the given [Paint]. |
| /// |
| /// The image is drawn in nine portions described by splitting the image by |
| /// drawing two horizontal lines and two vertical lines, where the `center` |
| /// argument describes the rectangle formed by the four points where these |
| /// four lines intersect each other. (This forms a 3-by-3 grid of regions, |
| /// the center region being described by the `center` argument.) |
| /// |
| /// The four regions in the corners are drawn, without scaling, in the four |
| /// corners of the destination rectangle described by `dst`. The remaining |
| /// five regions are drawn by stretching them to fit such that they exactly |
| /// cover the destination rectangle while maintaining their relative |
| /// positions. |
| void drawImageNine(Image image, Rect center, Rect dst, Paint paint); |
| |
| /// Draw the given picture onto the canvas. To create a picture, see |
| /// [PictureRecorder]. |
| void drawPicture(Picture picture); |
| |
| /// Draws the text in the given [Paragraph] into this canvas at the given |
| /// [Offset]. |
| /// |
| /// The [Paragraph] object must have had [Paragraph.layout] called on it |
| /// first. |
| /// |
| /// To align the text, set the `textAlign` on the [ParagraphStyle] object |
| /// passed to the [new ParagraphBuilder] constructor. For more details see |
| /// [TextAlign] and the discussion at [new ParagraphStyle]. |
| /// |
| /// If the text is left aligned or justified, the left margin will be at the |
| /// position specified by the `offset` argument's [Offset.dx] coordinate. |
| /// |
| /// If the text is right aligned or justified, the right margin will be at the |
| /// position described by adding the [ParagraphConstraints.width] given to |
| /// [Paragraph.layout], to the `offset` argument's [Offset.dx] coordinate. |
| /// |
| /// If the text is centered, the centering axis will be at the position |
| /// described by adding half of the [ParagraphConstraints.width] given to |
| /// [Paragraph.layout], to the `offset` argument's [Offset.dx] coordinate. |
| void drawParagraph(Paragraph paragraph, Offset offset); |
| |
| /// Draws a sequence of points according to the given [PointMode]. |
| /// |
| /// The `points` argument is interpreted as offsets from the origin. |
| /// |
| /// See also: |
| /// |
| /// * [drawRawPoints], which takes `points` as a [Float32List] rather than a |
| /// [List<Offset>]. |
| void drawPoints(PointMode pointMode, List<Offset> points, Paint paint); |
| |
| /// Draws a sequence of points according to the given [PointMode]. |
| /// |
| /// The `points` argument is interpreted as a list of pairs of floating point |
| /// numbers, where each pair represents an x and y offset from the origin. |
| /// |
| /// See also: |
| /// |
| /// * [drawPoints], which takes `points` as a [List<Offset>] rather than a |
| /// [List<Float32List>]. |
| void drawRawPoints(PointMode pointMode, Float32List points, Paint paint); |
| |
| void drawVertices(Vertices vertices, BlendMode blendMode, Paint paint); |
| |
| /// Draws part of an image - the [atlas] - onto the canvas. |
| /// |
| /// This method allows for optimization when you only want to draw part of an |
| /// image on the canvas, such as when using sprites or zooming. It is more |
| /// efficient than using clips or masks directly. |
| /// |
| /// All parameters must not be null. |
| /// |
| /// See also: |
| /// |
| /// * [drawRawAtlas], which takes its arguments as typed data lists rather |
| /// than objects. |
| void drawAtlas( |
| Image atlas, |
| List<RSTransform> transforms, |
| List<Rect> rects, |
| List<Color> colors, |
| BlendMode blendMode, |
| Rect? cullRect, |
| Paint paint, |
| ); |
| |
| /// Draws part of an image - the [atlas] - onto the canvas. |
| /// |
| /// This method allows for optimization when you only want to draw part of an |
| /// image on the canvas, such as when using sprites or zooming. It is more |
| /// efficient than using clips or masks directly. |
| /// |
| /// The [rstTransforms] argument is interpreted as a list of four-tuples, with |
| /// each tuple being ([RSTransform.scos], [RSTransform.ssin], |
| /// [RSTransform.tx], [RSTransform.ty]). |
| /// |
| /// The [rects] argument is interpreted as a list of four-tuples, with each |
| /// tuple being ([Rect.left], [Rect.top], [Rect.right], [Rect.bottom]). |
| /// |
| /// The [colors] argument, which can be null, is interpreted as a list of |
| /// 32-bit colors, with the same packing as [Color.value]. |
| /// |
| /// See also: |
| /// |
| /// * [drawAtlas], which takes its arguments as objects rather than typed |
| /// data lists. |
| void drawRawAtlas( |
| Image atlas, |
| Float32List rstTransforms, |
| Float32List rects, |
| Int32List colors, |
| BlendMode blendMode, |
| Rect? cullRect, |
| Paint paint, |
| ); |
| |
| /// Draws a shadow for a [Path] representing the given material elevation. |
| /// |
| /// The `transparentOccluder` argument should be true if the occluding object |
| /// is not opaque. |
| /// |
| /// The arguments must not be null. |
| void drawShadow( |
| Path path, |
| Color color, |
| double elevation, |
| bool transparentOccluder, |
| ); |
| } |
| |
| /// An object representing a sequence of recorded graphical operations. |
| /// |
| /// To create a [Picture], use a [PictureRecorder]. |
| /// |
| /// A [Picture] can be placed in a [Scene] using a [SceneBuilder], via |
| /// the [SceneBuilder.addPicture] method. A [Picture] can also be |
| /// drawn into a [Canvas], using the [Canvas.drawPicture] method. |
| abstract class Picture { |
| /// Creates an image from this picture. |
| /// |
| /// The returned image will be `width` pixels wide and `height` pixels high. |
| /// The picture is rasterized within the 0 (left), 0 (top), `width` (right), |
| /// `height` (bottom) bounds. Content outside these bounds is clipped. |
| /// |
| /// Although the image is returned synchronously, the picture is actually |
| /// rasterized the first time the image is drawn and then cached. |
| Future<Image> toImage(int width, int height); |
| |
| /// Release the resources used by this object. The object is no longer usable |
| /// after this method is called. |
| void dispose(); |
| |
| /// Returns the approximate number of bytes allocated for this object. |
| /// |
| /// The actual size of this picture may be larger, particularly if it contains |
| /// references to image or other large objects. |
| int get approximateBytesUsed; |
| } |
| |
| /// Determines the winding rule that decides how the interior of a [Path] is |
| /// calculated. |
| /// |
| /// This enum is used by the [Path.fillType] property. |
| enum PathFillType { |
| /// The interior is defined by a non-zero sum of signed edge crossings. |
| /// |
| /// For a given point, the point is considered to be on the inside of the path |
| /// if a line drawn from the point to infinity crosses lines going clockwise |
| /// around the point a different number of times than it crosses lines going |
| /// counter-clockwise around that point. |
| /// |
| /// See: <https://en.wikipedia.org/wiki/Nonzero-rule> |
| nonZero, |
| |
| /// The interior is defined by an odd number of edge crossings. |
| /// |
| /// For a given point, the point is considered to be on the inside of the path |
| /// if a line drawn from the point to infinity crosses an odd number of lines. |
| /// |
| /// See: <https://en.wikipedia.org/wiki/Even-odd_rule> |
| evenOdd, |
| } |
| |
| /// Strategies for combining paths. |
| /// |
| /// See also: |
| /// |
| /// * [Path.combine], which uses this enum to decide how to combine two paths. |
| // Must be kept in sync with SkPathOp |
| enum PathOperation { |
| /// Subtract the second path from the first path. |
| /// |
| /// For example, if the two paths are overlapping circles of equal diameter |
| /// but differing centers, the result would be a crescent portion of the |
| /// first circle that was not overlapped by the second circle. |
| /// |
| /// See also: |
| /// |
| /// * [reverseDifference], which is the same but subtracting the first path |
| /// from the second. |
| difference, |
| |
| /// Create a new path that is the intersection of the two paths, leaving the |
| /// overlapping pieces of the path. |
| /// |
| /// For example, if the two paths are overlapping circles of equal diameter |
| /// but differing centers, the result would be only the overlapping portion |
| /// of the two circles. |
| /// |
| /// See also: |
| /// * [xor], which is the inverse of this operation |
| intersect, |
| |
| /// Create a new path that is the union (inclusive-or) of the two paths. |
| /// |
| /// For example, if the two paths are overlapping circles of equal diameter |
| /// but differing centers, the result would be a figure-eight like shape |
| /// matching the outer boundaries of both circles. |
| union, |
| |
| /// Create a new path that is the exclusive-or of the two paths, leaving |
| /// everything but the overlapping pieces of the path. |
| /// |
| /// For example, if the two paths are overlapping circles of equal diameter |
| /// but differing centers, the figure-eight like shape less the overlapping |
| /// parts |
| /// |
| /// See also: |
| /// * [intersect], which is the inverse of this operation |
| xor, |
| |
| /// Subtract the first path from the second path. |
| /// |
| /// For example, if the two paths are overlapping circles of equal diameter |
| /// but differing centers, the result would be a crescent portion of the |
| /// second circle that was not overlapped by the first circle. |
| /// |
| /// See also: |
| /// |
| /// * [difference], which is the same but subtracting the second path |
| /// from the first. |
| reverseDifference, |
| } |