mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Copy platform.{gui,io,time} from core; implement AndroidCanvas
This commit is contained in:
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.platform.gui
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
import org.junit.Test
|
||||
|
||||
class AndroidCanvasTest : BaseViewTest() {
|
||||
@Test
|
||||
fun testDrawTestImage() {
|
||||
similarityCutoff = 0.0005
|
||||
val bmp = Bitmap.createBitmap(1000, 800, Bitmap.Config.ARGB_8888)
|
||||
val canvas = AndroidCanvas()
|
||||
canvas.context = testContext
|
||||
canvas.density = 2.0
|
||||
canvas.innerCanvas = android.graphics.Canvas(bmp)
|
||||
canvas.innerBitmap = bmp
|
||||
canvas.drawTestImage()
|
||||
assertRenders(bmp, "CanvasTest.png")
|
||||
}
|
||||
}
|
||||
@@ -47,11 +47,14 @@ public class BaseViewTest extends BaseAndroidTest
|
||||
protected void assertRenders(View view, String expectedImagePath)
|
||||
throws IOException
|
||||
{
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
expectedImagePath = "views/" + expectedImagePath;
|
||||
Bitmap actual = renderView(view);
|
||||
if(actual == null) throw new IllegalStateException("actual is null");
|
||||
assertRenders(actual, expectedImagePath);
|
||||
}
|
||||
|
||||
protected void assertRenders(Bitmap actual, String expectedImagePath) throws IOException {
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
expectedImagePath = "views/" + expectedImagePath;
|
||||
try
|
||||
{
|
||||
Bitmap expected = getBitmapFromAssets(expectedImagePath);
|
||||
@@ -145,7 +148,7 @@ public class BaseViewTest extends BaseAndroidTest
|
||||
}
|
||||
}
|
||||
|
||||
distance /= (0xff * 16) * b1.getWidth() * b1.getHeight();
|
||||
distance /= 255.0 * 16 * b1.getWidth() * b1.getHeight();
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.platform.gui
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Rect
|
||||
import android.graphics.Typeface
|
||||
import android.text.TextPaint
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome
|
||||
|
||||
class AndroidCanvas : Canvas {
|
||||
|
||||
lateinit var innerCanvas: android.graphics.Canvas
|
||||
lateinit var context: Context
|
||||
var innerBitmap: Bitmap? = null
|
||||
var density = 1.0
|
||||
var paint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
}
|
||||
var textPaint = TextPaint().apply {
|
||||
isAntiAlias = true
|
||||
}
|
||||
var textBounds = Rect()
|
||||
|
||||
private fun Double.toDp() = (this * density).toFloat()
|
||||
|
||||
override fun setColor(color: Color) {
|
||||
paint.color = color.toInt()
|
||||
textPaint.color = color.toInt()
|
||||
}
|
||||
|
||||
override fun drawLine(x1: Double, y1: Double, x2: Double, y2: Double) {
|
||||
innerCanvas.drawLine(
|
||||
x1.toDp(),
|
||||
y1.toDp(),
|
||||
x2.toDp(),
|
||||
y2.toDp(),
|
||||
paint,
|
||||
)
|
||||
}
|
||||
|
||||
override fun drawText(text: String, x: Double, y: Double) {
|
||||
textPaint.getTextBounds(text, 0, text.length, textBounds)
|
||||
innerCanvas.drawText(
|
||||
text,
|
||||
x.toDp(),
|
||||
y.toDp() - textBounds.exactCenterY(),
|
||||
textPaint,
|
||||
)
|
||||
}
|
||||
|
||||
override fun fillRect(x: Double, y: Double, width: Double, height: Double) {
|
||||
paint.style = Paint.Style.FILL
|
||||
rect(x, y, width, height)
|
||||
}
|
||||
|
||||
override fun drawRect(x: Double, y: Double, width: Double, height: Double) {
|
||||
paint.style = Paint.Style.STROKE
|
||||
rect(x, y, width, height)
|
||||
}
|
||||
|
||||
private fun rect(x: Double, y: Double, width: Double, height: Double) {
|
||||
innerCanvas.drawRect(
|
||||
x.toDp(),
|
||||
y.toDp(),
|
||||
(x + width).toDp(),
|
||||
(y + height).toDp(),
|
||||
paint,
|
||||
)
|
||||
}
|
||||
|
||||
override fun getHeight(): Double {
|
||||
return innerCanvas.height / density
|
||||
}
|
||||
|
||||
override fun getWidth(): Double {
|
||||
return innerCanvas.width / density
|
||||
}
|
||||
|
||||
override fun setFont(font: Font) {
|
||||
textPaint.typeface = when (font) {
|
||||
Font.REGULAR -> Typeface.DEFAULT
|
||||
Font.BOLD -> Typeface.DEFAULT_BOLD
|
||||
Font.FONT_AWESOME -> getFontAwesome(context)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setFontSize(size: Double) {
|
||||
textPaint.textSize = size.toDp() * 1.07f
|
||||
}
|
||||
|
||||
override fun setStrokeWidth(size: Double) {
|
||||
paint.strokeWidth = size.toDp()
|
||||
}
|
||||
|
||||
override fun fillArc(
|
||||
centerX: Double,
|
||||
centerY: Double,
|
||||
radius: Double,
|
||||
startAngle: Double,
|
||||
swipeAngle: Double,
|
||||
) {
|
||||
paint.style = Paint.Style.FILL
|
||||
innerCanvas.drawArc(
|
||||
(centerX - radius).toDp(),
|
||||
(centerY - radius).toDp(),
|
||||
(centerX + radius).toDp(),
|
||||
(centerY + radius).toDp(),
|
||||
-startAngle.toFloat(),
|
||||
-swipeAngle.toFloat(),
|
||||
true,
|
||||
paint,
|
||||
)
|
||||
}
|
||||
|
||||
override fun fillCircle(
|
||||
centerX: Double,
|
||||
centerY: Double,
|
||||
radius: Double,
|
||||
) {
|
||||
paint.style = Paint.Style.FILL
|
||||
innerCanvas.drawCircle(centerX.toDp(), centerY.toDp(), radius.toDp(), paint)
|
||||
}
|
||||
|
||||
override fun setTextAlign(align: TextAlign) {
|
||||
textPaint.textAlign = when (align) {
|
||||
TextAlign.LEFT -> Paint.Align.LEFT
|
||||
TextAlign.CENTER -> Paint.Align.CENTER
|
||||
TextAlign.RIGHT -> Paint.Align.RIGHT
|
||||
}
|
||||
}
|
||||
|
||||
override fun toImage(): Image {
|
||||
val bmp = innerBitmap ?: throw UnsupportedOperationException()
|
||||
return AndroidImage(bmp)
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidCanvasTestView(context: Context, attrs: AttributeSet) : View(context, attrs) {
|
||||
val canvas = AndroidCanvas()
|
||||
|
||||
override fun onDraw(canvas: android.graphics.Canvas) {
|
||||
this.canvas.context = context
|
||||
this.canvas.innerCanvas = canvas
|
||||
this.canvas.density = resources.displayMetrics.density.toDouble()
|
||||
this.canvas.drawTestImage()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* This file is part of Loop Habit Tracker.
|
||||
*
|
||||
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.platform.gui
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class AndroidImage(private val bmp: Bitmap) : Image {
|
||||
override val width: Int
|
||||
get() = bmp.width
|
||||
|
||||
override val height: Int
|
||||
get() = bmp.height
|
||||
|
||||
override fun getPixel(x: Int, y: Int): Color {
|
||||
return Color(bmp.getPixel(x, y))
|
||||
}
|
||||
|
||||
override fun setPixel(x: Int, y: Int, color: Color) {
|
||||
bmp.setPixel(x, y, color.toInt())
|
||||
}
|
||||
|
||||
override suspend fun export(path: String) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
public fun Color.toInt(): Int {
|
||||
return android.graphics.Color.argb(
|
||||
(255 * this.alpha).roundToInt(),
|
||||
(255 * this.red).roundToInt(),
|
||||
(255 * this.green).roundToInt(),
|
||||
(255 * this.blue).roundToInt(),
|
||||
)
|
||||
}
|
||||
28
android/uhabits-android/src/main/res/layout/canvas_test.xml
Normal file
28
android/uhabits-android/src/main/res/layout/canvas_test.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||
~
|
||||
~ This file is part of Loop Habit Tracker.
|
||||
~
|
||||
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by the
|
||||
~ Free Software Foundation, either version 3 of the License, or (at your
|
||||
~ option) any later version.
|
||||
~
|
||||
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
~ more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License along
|
||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<org.isoron.platform.gui.AndroidCanvasTestView
|
||||
android:layout_width="500dp"
|
||||
android:layout_height="400dp" />
|
||||
</LinearLayout>
|
||||
Reference in New Issue
Block a user