-
-
Save jiulongw/68537473e475e79cb9df413517553da3 to your computer and use it in GitHub Desktop.
Backup of experiment code Kotlin Drawing with variable width stroke
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Stroke(val start: Segment) { | |
data class Segment(val point: PointF, val width: Float, val direction: PointF) | |
private val vertices = ArrayList<Float>() | |
fun addPoint(point: PointF, width: Float) { | |
if (vertices.isEmpty()) { | |
start.direction.set(direction(start.point, point)) | |
val (a, b) = edgeOf(start.point, start.direction, start.width) | |
vertices.add(a.x) | |
vertices.add(a.y) | |
vertices.add(b.x) | |
vertices.add(b.y) | |
} | |
addVertices(point, width) | |
} | |
fun drawTo(canvas: Canvas, paint: Paint) { | |
if (vertices.isEmpty()) { | |
canvas.drawCircle(start.point.x, start.point.y, start.width / 2, paint) | |
} else { | |
val extent = start.width / 2 | |
val p = PointF(-start.direction.y, start.direction.x) | |
var angle = Math.toDegrees(Math.acos(p.x.toDouble())).toFloat() | |
if (p.y < 0) { | |
angle = -angle | |
} | |
val path = Path() | |
path.moveTo(vertices[0], vertices[1]) | |
var i = 1 | |
while (i * 4 < vertices.size) { | |
val x = vertices[i * 4] | |
val y = vertices[i * 4 + 1] | |
path.lineTo(x, y) | |
i++ | |
} | |
i-- | |
while (i >= 0) { | |
val x = vertices[i * 4 + 2] | |
val y = vertices[i * 4 + 3] | |
path.lineTo(x, y) | |
i-- | |
} | |
canvas.drawPath(path, paint) | |
// canvas.drawArc(start.point.x - extent, start.point.y - extent, start.point.x + extent, start.point.y + extent, angle, 180f, true, paint) | |
// | |
// canvas.drawVertices(Canvas.VertexMode.TRIANGLES, vertices.size, vertices.toFloatArray(), 0, vertices.toFloatArray(), 0, null, 0, triangles.toShortArray(), 0, triangles.size, paint) | |
} | |
} | |
private fun direction(from: PointF, to: PointF): PointF { | |
val d = PointF(to.x - from.x, to.y - from.y) | |
val length = d.length() | |
return if (length > 0) { | |
PointF(d.x / length, d.y / length) | |
} else { | |
PointF(1f, 0f) | |
} | |
} | |
private fun edgeOf(point: PointF, direction: PointF, width: Float): Pair<PointF, PointF> { | |
val p = PointF(-direction.y, direction.x) | |
return Pair( | |
PointF(point.x + p.x * width, point.y + p.y * width), | |
PointF(point.x - p.x * width, point.y - p.y * width) | |
) | |
} | |
private fun addVertices(to: PointF, width: Float) { | |
assert(vertices.size >= 2 * 2) | |
val ia = (vertices.size / 2) - 2 | |
val ib = ia + 1 | |
val a = PointF(vertices[ia * 2], vertices[ia * 2 + 1]) | |
val b = PointF(vertices[ib * 2], vertices[ib * 2 + 1]) | |
val from = PointF((a.x + b.x) / 2, (a.y + b.y) / 2) | |
val dir = direction(from, to) | |
val (c, d) = edgeOf(to, dir, width) | |
vertices.add(c.x) | |
vertices.add(c.y) | |
vertices.add(d.x) | |
vertices.add(d.y) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private fun updateLayerSize(layer: Layer?, size: Size, keepContent: Boolean): Layer { | |
if (layer == null) { | |
val bitmap = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888) | |
val canvas = Canvas(bitmap) | |
return Layer(bitmap, canvas) | |
} else if (layer.bitmap.width != size.width || layer.bitmap.height != size.height) { | |
val bitmap = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888) | |
val canvas = Canvas(bitmap) | |
if (keepContent) { | |
canvas.drawBitmap(layer.bitmap, null, Rect(0, 0, size.width, size.height), paint) | |
} | |
layer.bitmap.recycle() | |
return Layer(bitmap, canvas) | |
} else { | |
return layer | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ai.inlight.board.app | |
import android.graphics.* | |
import android.util.Log | |
/** | |
* Created by jiulongw on 12/20/17. | |
*/ | |
class Stroke(point: PointF, width: Float) { | |
data class Segment(val point: PointF, val width: Float, val direction: PointF) | |
private val start = Segment(point, width, PointF()) | |
private val vertices = ArrayList<Float>() | |
fun addPoint(point: PointF, width: Float) { | |
if (vertices.isEmpty()) { | |
start.direction.set(direction(start.point, point)) | |
val (a, b) = edgeOf(start.point, start.direction, start.width) | |
vertices.add(a.x) | |
vertices.add(a.y) | |
vertices.add(b.x) | |
vertices.add(b.y) | |
} | |
addVertices(point, width) | |
} | |
fun drawTo(canvas: Canvas, paint: Paint) { | |
if (vertices.isEmpty()) { | |
canvas.drawCircle(start.point.x, start.point.y, start.width / 2, paint) | |
} else { | |
// val extent = start.width / 2 | |
// val p = PointF(-start.direction.y, start.direction.x) | |
// var angle = Math.toDegrees(Math.acos(p.x.toDouble())).toFloat() | |
// if (p.y < 0) { | |
// angle = -angle | |
// } | |
// | |
// canvas.drawArc(start.point.x - extent, start.point.y - extent, start.point.x + extent, start.point.y + extent, angle, 180f, true, paint) | |
// val points = FloatArray(vertices.size * 6) | |
val path = Path() | |
path.moveTo(vertices[0], vertices[1]) | |
for (i in 0 until vertices.size / 2 - 2 step 2) { | |
val k = i * 2 | |
path.lineTo(vertices[k + 4], vertices[k + 5]) | |
// val j = i * 12 | |
// val k = i * 2 | |
// | |
// points[j] = vertices[k] | |
// points[j + 1] = vertices[k + 1] | |
// points[j + 2] = vertices[k + 2] | |
// points[j + 3] = vertices[k + 3] | |
// | |
// points[j + 4] = vertices[k + 2] | |
// points[j + 5] = vertices[k + 3] | |
// points[j + 6] = vertices[k + 4] | |
// points[j + 7] = vertices[k + 5] | |
// | |
// points[j + 8] = vertices[k + 4] | |
// points[j + 9] = vertices[k + 5] | |
// points[j + 10] = vertices[k] | |
// points[j + 11] = vertices[k + 1] | |
// | |
// points[j + 12] = vertices[k + 2] | |
// points[j + 13] = vertices[k + 3] | |
// points[j + 14] = vertices[k + 4] | |
// points[j + 15] = vertices[k + 5] | |
// | |
// points[j + 16] = vertices[k + 4] | |
// points[j + 17] = vertices[k + 5] | |
// points[j + 18] = vertices[k + 6] | |
// points[j + 19] = vertices[k + 7] | |
// | |
// points[j + 20] = vertices[k + 6] | |
// points[j + 21] = vertices[k + 7] | |
// points[j + 22] = vertices[k + 2] | |
// points[j + 23] = vertices[k + 3] | |
} | |
for (i in vertices.size / 2 - 1 downTo 0 step 2) { | |
val k = i * 2 | |
path.lineTo(vertices[k], vertices[k + 1]) | |
} | |
canvas.drawPath(path, paint) | |
// canvas.drawPath(path, paint) | |
// canvas.drawLines(points, paint) | |
// while (i * 4 < vertices.size) { | |
// val x = vertices[i * 4] | |
// val y = vertices[i * 4 + 1] | |
// | |
// path.lineTo(x, y) | |
// i++ | |
// } | |
// | |
// i-- | |
// | |
// while (i >= 0) { | |
// val x = vertices[i * 4 + 2] | |
// val y = vertices[i * 4 + 3] | |
// | |
// path.lineTo(x, y) | |
// i-- | |
// } | |
// | |
// canvas.drawPath(path, paint) | |
// | |
// canvas.drawVertices(Canvas.VertexMode.TRIANGLES, vertices.size, vertices.toFloatArray(), 0, vertices.toFloatArray(), 0, null, 0, triangles.toShortArray(), 0, triangles.size, paint) | |
} | |
} | |
private fun direction(from: PointF, to: PointF): PointF { | |
val d = PointF(to.x - from.x, to.y - from.y) | |
val length = d.length() | |
return if (length > 0) { | |
PointF(d.x / length, d.y / length) | |
} else { | |
PointF(1f, 0f) | |
} | |
} | |
private fun edgeOf(point: PointF, direction: PointF, width: Float): Pair<PointF, PointF> { | |
val p = PointF(-direction.y, direction.x) | |
return Pair( | |
PointF(point.x + p.x * width, point.y + p.y * width), | |
PointF(point.x - p.x * width, point.y - p.y * width) | |
) | |
} | |
private fun addVertices(to: PointF, width: Float) { | |
assert(vertices.size >= 2 * 2) | |
val ia = (vertices.size / 2) - 2 | |
val ib = ia + 1 | |
val a = PointF(vertices[ia * 2], vertices[ia * 2 + 1]) | |
val b = PointF(vertices[ib * 2], vertices[ib * 2 + 1]) | |
val from = PointF((a.x + b.x) / 2, (a.y + b.y) / 2) | |
val dir = direction(from, to) | |
val (c, d) = edgeOf(to, dir, width) | |
vertices.add(c.x) | |
vertices.add(c.y) | |
vertices.add(d.x) | |
vertices.add(d.y) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private fun handleMotionEvent(m: MotionEvent) { | |
when (m.actionMasked) { | |
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> { | |
val index = m.actionIndex | |
val id = m.getPointerId(index) | |
val x = m.getX(index) - offset.x | |
val y = m.getY(index) - offset.y | |
val path = Path() | |
val rect = RectF() | |
path.moveTo(x, y) | |
rect.offsetTo(x, y) | |
rect.inset(-extent, -extent) | |
contents[id] = DrawContent(path, rect, PointF(x, y), true) | |
} | |
MotionEvent.ACTION_MOVE -> { | |
Log.i("CanvasView", "Move: ${m.pointerCount}") | |
var ccc = 0 | |
for (i in 0 until m.pointerCount) { | |
ccc++ | |
val id = m.getPointerId(i) | |
val x = m.getX(i) - offset.x | |
val y = m.getY(i) - offset.y | |
Log.i("CanvasView", "i: $i, id: $id, x: $x, y: $y, ccc: $ccc") | |
val rect = RectF() | |
rect.offsetTo(x, y) | |
rect.inset(-extent, -extent) | |
val content = contents[id]!! | |
content.path.lineTo(x, y) | |
content.rect.union(rect) | |
content.lastPoint.set(x, y) | |
content.dirty = true | |
} | |
} | |
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> { | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment