// Copyright 2014 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.

// This example shows how to use the ui.Canvas interface to draw various shapes
// with gradients and transforms.

import 'dart:math' as math;
import 'dart:typed_data';
import 'dart:ui' as ui;

ui.Picture paint(ui.Rect paintBounds) {
  // First we create a PictureRecorder to record the commands we're going to
  // feed in the canvas. The PictureRecorder will eventually produce a Picture,
  // which is an immutable record of those commands.
  final ui.PictureRecorder recorder = ui.PictureRecorder();

  // Next, we create a canvas from the recorder. The canvas is an interface
  // which can receive drawing commands. The canvas interface is modeled after
  // the SkCanvas interface from Skia. The paintBounds establishes a "cull rect"
  // for the canvas, which lets the implementation discard any commands that
  // are entirely outside this rectangle.
  final ui.Canvas canvas = ui.Canvas(recorder, paintBounds);

  final ui.Paint paint = ui.Paint();
  canvas.drawPaint(ui.Paint()..color = const ui.Color(0xFFFFFFFF));

  final ui.Size size = paintBounds.size;
  final ui.Offset mid = size.center(ui.Offset.zero);
  final double radius = size.shortestSide / 2.0;

  final double devicePixelRatio = ui.window.devicePixelRatio;
  final ui.Size logicalSize = ui.window.physicalSize / devicePixelRatio;

  // Saves a copy of current transform onto the save stack
  canvas.save();

  // Note that transforms that occur after this point apply only to the
  // yellow-bluish rectangle

  // This line will cause the transform to shift entirely outside the paint
  // boundaries, which will cause the canvas interface to discard its
  // commands. Comment it out to see it on screen.
  canvas.translate(-mid.dx / 2.0, logicalSize.height * 2.0);

  // Clips the current transform
  canvas.clipRect(
    ui.Rect.fromLTRB(0, radius + 50, logicalSize.width, logicalSize.height),
    clipOp: ui.ClipOp.difference,
  );

  // Shifts the coordinate space of and rotates the current transform
  canvas.translate(mid.dx, mid.dy);
  canvas.rotate(math.pi/4);

  final ui.Gradient yellowBlue = ui.Gradient.linear(
    ui.Offset(-radius, -radius),
    ui.Offset.zero,
    <ui.Color>[const ui.Color(0xFFFFFF00), const ui.Color(0xFF0000FF)],
  );

  // Draws a yellow-bluish rectangle
  canvas.drawRect(
    ui.Rect.fromLTRB(-radius, -radius, radius, radius),
    ui.Paint()..shader = yellowBlue,
  );

  // Note that transforms that occur after this point apply only to the
  // yellow circle

  // Scale x and y by 0.5.
  final Float64List scaleMatrix = Float64List.fromList(<double>[
      0.5, 0.0, 0.0, 0.0,
      0.0, 0.5, 0.0, 0.0,
      0.0, 0.0, 1.0, 0.0,
      0.0, 0.0, 0.0, 1.0,
  ]);
  canvas.transform(scaleMatrix);

  // Sets paint to transparent yellow
  paint.color = const ui.Color.fromARGB(128, 0, 255, 0);

  // Draws a transparent yellow circle
  canvas.drawCircle(ui.Offset.zero, radius, paint);

  // Restores the transform from before `save` was called
  canvas.restore();

  // Sets paint to transparent red
  paint.color = const ui.Color.fromARGB(128, 255, 0, 0);

  // Note that this circle is drawn on top of the previous layer that contains
  // the rectangle and smaller circle
  canvas.drawCircle(const ui.Offset(150.0, 300.0), radius, paint);

  // When we're done issuing painting commands, we end the recording an receive
  // a Picture, which is an immutable record of the commands we've issued. You
  // can draw a Picture into another canvas or include it as part of a
  // composited scene.
  return recorder.endRecording();
}

ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) {
  final double devicePixelRatio = ui.window.devicePixelRatio;
  final Float64List deviceTransform = Float64List(16)
    ..[0] = devicePixelRatio
    ..[5] = devicePixelRatio
    ..[10] = 1.0
    ..[15] = 1.0;
  final ui.SceneBuilder sceneBuilder = ui.SceneBuilder()
    ..pushTransform(deviceTransform)
    ..addPicture(ui.Offset.zero, picture)
    ..pop();
  return sceneBuilder.build();
}

void beginFrame(Duration timeStamp) {
  final ui.Rect paintBounds = ui.Offset.zero & (ui.window.physicalSize / ui.window.devicePixelRatio);
  final ui.Picture picture = paint(paintBounds);
  final ui.Scene scene = composite(picture, paintBounds);
  ui.window.render(scene);
}

void main() {
  ui.PlatformDispatcher.instance
    ..onBeginFrame = beginFrame
    ..scheduleFrame();
}
