Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Canvas Drawing

Ryan Harter
November 05, 2017

Canvas Drawing

Introduction to 2D drawing on Android using the Canvas API from #droidconSF.

Ryan Harter

November 05, 2017
Tweet

More Decks by Ryan Harter

Other Decks in Technology

Transcript

  1. Canvas Drawing
    Ryan Harter
    @rharter

    View Slide

  2. Canvas Drawing

    View Slide

  3. How Android Draws
    Views

    View Slide

  4. How Android Draws
    Views
    Canvas

    View Slide

  5. How Android Draws
    Views
    Canvas
    Skia

    View Slide

  6. How Android Draws
    Views
    Canvas
    Skia OpenGLRenderer

    View Slide

  7. How To Get A Canvas
    class CustomView(...) : View(...) {
    override fun onDraw(canvas: Canvas?) {
    }
    }

    View Slide

  8. How To Get A Canvas
    class CustomView(...) : View(...) {
    override fun onDraw(canvas: Canvas?) {
    }
    }
    class CustomDrawable : Drawable() {
    override fun draw(canvas: Canvas?) {
    }
    }

    View Slide

  9. How To Get A Canvas
    class CustomView(...) : View(...) {
    override fun onDraw(canvas: Canvas?) {
    }
    }
    class CustomDrawable : Drawable() {
    override fun draw(canvas: Canvas?) {
    }
    }
    val image = Bitmap.createBitmap(100, 100, ARGB_8888)
    val canvas = Canvas(image)

    View Slide

  10. How To Get A Canvas
    class CustomView(...) : View(...) {
    override fun onDraw(canvas: Canvas?) {
    }
    }
    class CustomDrawable : Drawable() {
    override fun draw(canvas: Canvas?) {
    }
    }
    val image = Bitmap.createBitmap(100, 100, ARGB_8888)
    val canvas = Canvas(image)

    View Slide

  11. Canvas Drawing

    View Slide

  12. Canvas Drawing

    View Slide

  13. Canvas Drawing

    View Slide

  14. Canvas Drawing

    View Slide

  15. Canvas Drawing

    View Slide

  16. Canvas Drawing

    View Slide

  17. Canvas Drawing

    View Slide

  18. Canvas Drawing

    View Slide

  19. Canvas Drawing

    View Slide

  20. Canvas Drawing

    View Slide

  21. Canvas Drawing

    View Slide

  22. Canvas Drawing

    View Slide

  23. Canvas Drawing

    View Slide

  24. Canvas Drawing

    View Slide

  25. Canvas Drawing
    Circle

    View Slide

  26. Canvas Drawing
    Circle
    Other Circle

    View Slide

  27. Canvas Drawing

    View Slide

  28. Canvas Drawing

    View Slide

  29. private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    Canvas Drawing

    View Slide

  30. private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    Canvas Drawing

    View Slide

  31. private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    Canvas Drawing

    View Slide

  32. private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    Canvas Drawing
    what

    View Slide

  33. private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    Canvas Drawing
    what
    how

    View Slide

  34. private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    Canvas Drawing

    View Slide

  35. private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    Canvas Drawing

    View Slide

  36. private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    private val basePaint = Paint().apply {
    color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    Canvas Drawing

    View Slide

  37. private val basePaint = Paint().also {
    it.color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    Canvas Drawing
    private val basePaint = Paint().also {
    it.color = 0xFFc6853b.toInt()
    }\
    canvas.drawCircle(
    bounds.exactCenterX(), // center x
    bounds.exactCenterY(), // center y
    bounds.width() / 2f, // radius
    basePaint)
    // draw the base

    View Slide

  38. // draw the base
    Canvas Drawing

    View Slide

  39. // draw the base
    Canvas Drawing

    View Slide

  40. // draw the base
    Canvas Drawing
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)

    View Slide

  41. canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    // draw the base
    Canvas Drawing

    View Slide

  42. canvas.clipPath(holePath,
    Region.Op.INTERSECT)
    canvas.clipPath(holePath,
    Region.Op.INTERSECT)
    // draw the base
    Canvas Drawing

    View Slide

  43. // draw the base
    Canvas Drawing
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)

    View Slide

  44. // draw the base
    Canvas Drawing
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)

    View Slide

  45. // draw the base
    Canvas Drawing
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    private val holePath = Path()

    View Slide

  46. fun onBoundsChange(bounds: Rect?) {
    super.onBoundsChange(bounds)
    bounds?.let {
    holePath.reset()
    holePath.addCircle(
    it.exactCenterX(),
    it.exactCenterY(),
    it.width() / 6F,
    Path.Direction.CW)
    }\
    }\
    fun onBoundsChange(bounds: Rect?) {
    super.onBoundsChange(bounds)
    bounds?.let {
    holePath.reset()
    holePath.addCircle(
    it.exactCenterX(),
    it.exactCenterY(),
    it.width() / 6F,
    Path.Direction.CW)
    }\
    }\
    Canvas Drawing
    canvas.clipPath(holePath,
    canvas.clipPath(holePath,
    private val holePath = Path()
    private val holePath = Path()

    View Slide

  47. fun onBoundsChange(bounds: Rect?) {
    super.onBoundsChange(bounds)
    bounds?.let {
    holePath.reset()
    holePath.addCircle(
    it.exactCenterX(),
    it.exactCenterY(),
    it.width() / 6F,
    Path.Direction.CW)
    }\
    }\
    fun onBoundsChange(bounds: Rect?) {
    super.onBoundsChange(bounds)
    bounds?.let {
    holePath.reset()
    holePath.addCircle(
    it.exactCenterX(),
    it.exactCenterY(),
    it.width() / 6F,
    Path.Direction.CW)
    }\
    }\
    Canvas Drawing
    canvas.clipPath(holePath,
    canvas.clipPath(holePath,
    private val holePath = Path()
    private val holePath = Path()

    View Slide

  48. // draw the base
    Canvas Drawing
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)

    View Slide

  49. // draw the base
    Canvas Drawing
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    // draw the stache

    View Slide

  50. // draw the base
    Canvas Drawing
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    // draw the stache

    View Slide

  51. // draw the base
    Canvas Drawing
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    // draw the stache
    canvas.save()
    canvas.restore()
    canvas.save()
    canvas.restore()
    // draw the base
    // draw the stache

    View Slide

  52. // draw the base
    Canvas Drawing
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    // draw the stache
    canvas.save()
    canvas.restore()
    canvas.save()
    canvas.restore()
    // draw the base
    // draw the stache

    View Slide

  53. // draw the base
    Canvas Drawing
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.clipPath(holePath,
    Region.Op.DIFFERENCE)
    canvas.save()
    canvas.restore()
    canvas.save()
    canvas.restore()
    // draw the base

    View Slide

  54. // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base

    View Slide

  55. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base

    View Slide

  56. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base

    View Slide

  57. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    DiscretePathEffect(60f, 25f)
    DiscretePathEffect(60f, 25f)

    View Slide

  58. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    DiscretePathEffect(60f, 25f)
    DiscretePathEffect(60f, 25f)

    View Slide

  59. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    DiscretePathEffect(60f, 25f)
    DiscretePathEffect(60f, 25f)

    View Slide

  60. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    DiscretePathEffect(60f, 25f)
    DiscretePathEffect(60f, 25f)

    View Slide

  61. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    DiscretePathEffect(60f, 25f)
    DiscretePathEffect(60f, 25f)

    View Slide

  62. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    DiscretePathEffect(60f, 25f)
    DiscretePathEffect(60f, 25f)
    CornerPathEffect(40f)
    CornerPathEffect(40f)

    View Slide

  63. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    DiscretePathEffect(60f, 25f)
    DiscretePathEffect(60f, 25f)
    CornerPathEffect(40f)
    CornerPathEffect(40f)

    View Slide

  64. ,
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    DiscretePathEffect(60f, 25f)
    DiscretePathEffect(60f, 25f)
    CornerPathEffect(40f)
    CornerPathEffect(40f)
    ComposePathEffect(
    ComposePathEffect(
    )
    )
    ,

    View Slide

  65. ,
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    DiscretePathEffect(60f, 25f)
    DiscretePathEffect(60f, 25f)
    CornerPathEffect(40f)
    CornerPathEffect(40f)
    ComposePathEffect(
    ComposePathEffect(
    )
    )
    ,

    View Slide

  66. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    ComposePathEffect(
    ComposePathEffect()
    )

    View Slide

  67. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    ComposePathEffect(
    ComposePathEffect()
    )
    canvas.drawCircle(
    bounds.exactCenterX(),
    bounds.exactCenterY(),
    bounds.width() / 2.1f,
    icingPaint)

    View Slide

  68. // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    Canvas Drawing
    // draw the base
    ComposePathEffect(
    ComposePathEffect()
    )
    canvas.drawCircle(
    bounds.exactCenterX(),
    bounds.exactCenterY(),
    bounds.width() / 2.1f,
    icingPaint)

    View Slide

  69. Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base

    View Slide

  70. Canvas Drawing
    // draw the sprinkles!
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!

    View Slide

  71. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    }
    }

    View Slide

  72. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // calculate the position
    // calculate the position
    }
    }

    View Slide

  73. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // move the canvas
    // move the canvas
    // calculate the position
    // calculate the position
    }
    }

    View Slide

  74. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // move the canvas
    // move the canvas
    // draw the sprinkle
    // draw the sprinkle
    // calculate the position
    // calculate the position
    }
    }

    View Slide

  75. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // move the canvas
    // move the canvas
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    }
    }

    View Slide

  76. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // move the canvas
    // move the canvas
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    // calculate the position
    // calculate the position
    }
    }

    View Slide

  77. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  78. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // calculate the position
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  79. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  80. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  81. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  82. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  83. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  84. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  85. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  86. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  87. // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    }
    }

    View Slide

  88. sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    }
    }
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)

    View Slide

  89. sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    }
    }

    View Slide

  90. sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    // restore the canvas
    // restore the canvas
    }
    }

    View Slide

  91. sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.restore()
    canvas.restore()
    }
    }

    View Slide

  92. sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.restore()
    canvas.restore()
    }
    }

    View Slide

  93. sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    sprinklePaint.color = it.color
    canvas.drawRoundRect(
    cx - 7f, cy - 22f,
    cx + 7f, cy + 22f,
    10f, 10f, sprinklePaint)
    // draw the sprinkles!
    // draw the sprinkles!
    Canvas Drawing
    sprinkles.forEach {
    sprinkles.forEach {
    // draw the sprinkle
    // draw the sprinkle
    // restore the canvas
    // restore the canvas
    // calculate the position
    // calculate the position
    // move the canvas
    // move the canvas
    val modDistance = holeRadius + padding
    + (ringRadius - padding * 2)
    * it.distance
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.save()
    canvas.rotate(it.angle, cx, cy)
    canvas.translate(0f, modDistance)
    canvas.rotate(it.rotation, cx, cy)
    canvas.restore()
    canvas.restore()
    }
    }

    View Slide

  94. // draw the sprinkles!
    Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!

    View Slide

  95. // draw the sprinkles!
    Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!

    View Slide

  96. // draw the sprinkles!
    Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!
    canvas.scale(0.5f, 0.5f,
    bounds.width() / 2f,
    bounds.height() / 2f)

    View Slide

  97. // draw the sprinkles!
    Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!
    canvas.scale(0.5f, 0.5f,
    bounds.width() / 2f,
    bounds.height() / 2f)
    canvas.restore()
    canvas.save()

    View Slide

  98. // draw the sprinkles!
    Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!
    canvas.restore()
    canvas.save()
    canvas.scale(0.5f, 0.5f,
    bounds.width() / 2f,
    bounds.height() / 2f)

    View Slide

  99. canvas.scale(scale, scale,
    bounds.width() / 2f,
    bounds.height() / 2f)
    canvas.scale(scale, scale,
    bounds.width() / 2f,
    bounds.height() / 2f)
    // draw the sprinkles!
    Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!
    canvas.restore()
    canvas.save()

    View Slide

  100. canvas.scale(scale, scale,
    bounds.width() / 2f,
    bounds.height() / 2f)
    canvas.scale(scale, scale,
    bounds.width() / 2f,
    bounds.height() / 2f)
    // draw the sprinkles!
    Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!
    canvas.restore()
    canvas.save()

    View Slide

  101. canvas.scale(scale, scale,
    bounds.width() / 2f,
    bounds.height() / 2f)
    canvas.scale(scale, scale,
    bounds.width() / 2f,
    bounds.height() / 2f)
    // draw the sprinkles!
    Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!
    canvas.restore()
    canvas.save()

    View Slide

  102. // draw the sprinkles!
    Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!
    canvas.restore()
    canvas.save()
    canvas.scale(scale, scale,
    bounds.width() / 2f,
    bounds.height() / 2f)
    canvas.scale(scale, scale,
    bounds.width() / 2f,
    bounds.height() / 2f)

    View Slide

  103. // draw the sprinkles!
    Canvas Drawing
    // draw the icing
    // draw the icing
    // clip the hole
    // Clip the hole
    // draw the base
    // draw the base
    // draw the sprinkles!

    View Slide

  104. Canvas Drawing
    Ryan Harter
    @rharter

    View Slide