Bimba.git

ref: 343255d5c2e7108dd510ca9e7707d2d3d67e0bc6

app/src/main/java/xyz/apiote/bimba/czwek/repo/LineAbstract.kt


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.repo

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.Path
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.graphics.drawable.toBitmap
import xyz.apiote.bimba.czwek.R
import xyz.apiote.bimba.czwek.dpToPixel
import xyz.apiote.bimba.czwek.dpToPixelI
import kotlin.math.abs
import kotlin.math.cbrt
import kotlin.math.pow

interface LineAbstract {
	fun textColour(c: Colour): Int {
		val black = relativeLuminance(Colour(0u, 0u, 0u)) + .05
		val white = relativeLuminance(Colour(255u, 255u, 255u)) + .05
		val colour = relativeLuminance(c) + .05
		return if ((white / colour) > (colour / black)) {
			Color.WHITE
		} else {
			Color.BLACK
		}
	}

	private fun relativeLuminance(colour: Colour): Double {
		val r = fromSRGB(colour.R.toDouble() / 0xff)
		val g = fromSRGB(colour.G.toDouble() / 0xff)
		val b = fromSRGB(colour.B.toDouble() / 0xff)
		return 0.2126 * r + 0.7152 * g + 0.0722 * b
	}

	private fun fromSRGB(part: Double): Double {
		return if (part <= 0.03928) {
			part / 12.92
		} else {
			((part + 0.055) / 1.055).pow(2.4)
		}
	}

	fun icon(context: Context, type: LineType, colour: Colour, scale: Float): Bitmap {
		val drawingBitmap = Bitmap.createBitmap(
			dpToPixelI(24f / scale), dpToPixelI(24f / scale), Bitmap.Config.ARGB_8888
		)
		val canvas = Canvas(drawingBitmap)

		canvas.drawPath(getSquirclePath(
			dpToPixel(.8f / scale), dpToPixel(.8f / scale), dpToPixelI(11.2f / scale)
		), Paint().apply { color = textColour(colour) })
		canvas.drawPath(getSquirclePath(
			dpToPixel(1.6f / scale), dpToPixel(1.6f / scale), dpToPixelI(10.4f / scale)
		), Paint().apply { color = colour.toInt() })

		val iconID = when (type) {
			LineType.BUS -> R.drawable.bus_black
			LineType.TRAM -> R.drawable.tram_black
			LineType.TROLLEYBUS -> R.drawable.trolleybus_black
			LineType.METRO -> R.drawable.metro_black
			LineType.RAIL -> R.drawable.train_black
			LineType.FERRY -> R.drawable.ferry_black
			LineType.CABLE_TRAM -> TODO()
			LineType.CABLE_CAR -> TODO()
			LineType.FUNICULAR -> TODO()
			LineType.MONORAIL -> R.drawable.monorail_black
			LineType.UNKNOWN -> R.drawable.vehicle_black
		}
		val icon = AppCompatResources.getDrawable(context, iconID)?.mutate()?.apply {
			setTint(textColour(colour))
		}?.toBitmap(dpToPixelI(19.2f / scale), dpToPixelI(19.2f / scale), Bitmap.Config.ARGB_8888)
		canvas.drawBitmap(
			icon!!, dpToPixel(2.4f / scale), dpToPixel(2.4f / scale), Paint()
		)
		return drawingBitmap
	}

	private fun getSquirclePath(
		left: Float, top: Float, radius: Int
	): Path {
		val radiusToPow = (radius * radius * radius).toDouble()
		val path = Path()
		path.moveTo(-radius.toFloat(), 0f)
		for (x in -radius..radius) path.lineTo(
			x.toFloat(), cbrt(radiusToPow - abs(x * x * x)).toFloat()
		)
		for (x in radius downTo -radius) path.lineTo(
			x.toFloat(), -cbrt(radiusToPow - abs(x * x * x)).toFloat()
		)
		path.close()
		val matrix = Matrix()
		matrix.postTranslate((left + radius), (top + radius))
		path.transform(matrix)
		return path
	}
}