From a5821515093d34667ff8fa3976407637600f42cf Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Mon, 29 Aug 2022 12:59:43 -0700 Subject: [PATCH] Add tests, publishing --- .github/workflows/continous-build.yml | 19 ++++ README.md | 18 ++- build.gradle | 60 +--------- gradle.properties | 2 + .../romainguy/graphics/v9/PathResizerTest.kt | 107 ++++++++++++++++++ .../graphics/v9/ResizablePathTest.kt | 28 ----- .../dev/romainguy/graphics/v9/PathResizer.kt | 18 +++ 7 files changed, 166 insertions(+), 86 deletions(-) create mode 100644 .github/workflows/continous-build.yml create mode 100644 v9/src/androidTest/java/dev/romainguy/graphics/v9/PathResizerTest.kt delete mode 100644 v9/src/androidTest/java/dev/romainguy/graphics/v9/ResizablePathTest.kt diff --git a/.github/workflows/continous-build.yml b/.github/workflows/continous-build.yml new file mode 100644 index 0000000..fe49e3f --- /dev/null +++ b/.github/workflows/continous-build.yml @@ -0,0 +1,19 @@ +name: Android + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Build library + run: ./gradlew assembleRelease diff --git a/README.md b/README.md index 94b5f01..ab71a0c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # v9 +[![v9](https://maven-badges.herokuapp.com/maven-central/dev.romainguy/v9/badge.svg?subject=v9)](https://maven-badges.herokuapp.com/maven-central/dev.romainguy/v9) +[![Android build status](https://github.com/romainguy/v9/workflows/Android/badge.svg)](https://github.com/romainguy/v9/actions?query=workflow%3AAndroid) + v9 is an Android library that provides the ability to dynamically resize [Path](https://developer.android.com/reference/android/graphics/Path) objects as you would [9-patch bitmaps](https://developer.android.com/studio/write/draw9patch). In the example below, @@ -14,11 +17,24 @@ using multiple slices: https://user-images.githubusercontent.com/869684/186995070-32021ebd-d085-406f-8905-f035ce4559f5.mov When multiple slices are used, the amount of stretch applied is proportional to the size of -each slice. This behavior is using in the example above to keep the dark bars centered vertically +each slice. This behavior is used in the example above to keep the dark bars centered vertically and to spaced them equally horizontally, thus properly preserving details inside the path. v9 is compatible with API 21+. +## Maven + +```gradle +repositories { + // ... + mavenCentral() +} + +dependencies { + implementation 'dev.romainguy:v9:0.1.0' +} +``` + ## How to use Slicing a `Path` gives you a `PathResizer`. The easiest way to slice is to use a single vertical diff --git a/build.gradle b/build.gradle index 8e17228..de66b04 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,3 @@ -import org.jetbrains.dokka.gradle.DokkaMultiModuleTask - buildscript { ext { compose_version = '1.3.0-alpha03' @@ -13,60 +11,8 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:7.2.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10" - classpath "com.vanniktech:gradle-maven-publish-plugin:0.18.0" - classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.0" - } -} - -apply plugin: 'org.jetbrains.dokka' - -tasks.withType(DokkaMultiModuleTask).configureEach { - outputDirectory = rootProject.file('docs/api') - failOnWarning = true -} - -afterEvaluate { - if (tasks.findByName('dokkaHtmlPartial') == null) { - // If dokka isn't enabled on this module, skip - return - } - - tasks.named('dokkaHtmlPartial') { - dokkaSourceSets.configureEach { - reportUndocumented.set(true) - skipEmptyPackages.set(true) - skipDeprecated.set(true) - jdkVersion.set(8) - - // Add Android SDK packages - noAndroidSdkLink.set(false) - - // AndroidX + Compose docs - externalDocumentationLink { - url.set(new URL("https://developer.android.com/reference/")) - packageListUrl.set(new URL("https://developer.android.com/reference/androidx/package-list")) - } - externalDocumentationLink { - url.set(new URL("https://developer.android.com/reference/kotlin/")) - packageListUrl.set(new URL("https://developer.android.com/reference/kotlin/androidx/package-list")) - } - - sourceLink { - localDirectory.set(project.file("src/main/java")) - // URL showing where the source code can be accessed through the web browser - remoteUrl.set(new URL("https://github.com/romainguy/v9/blob/main/${project.name}/src/main/java")) - // Suffix which is used to append the line number to the URL. Use #L for GitHub - remoteLineSuffix.set("#L") - } - } - } -} - -allprojects { - plugins.withId("com.vanniktech.maven.publish") { - mavenPublish { - sonatypeHost = "S01" - } + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10' + classpath 'com.vanniktech:gradle-maven-publish-plugin:0.21.0' + classpath 'org.jetbrains.dokka:dokka-gradle-plugin:1.6.0' } } diff --git a/gradle.properties b/gradle.properties index 47fbdab..d008852 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,8 @@ GROUP=dev.romainguy VERSION_NAME=0.1.0 +SONATYPE_HOST=S01 + POM_DESCRIPTION=Vector 9-patches for Android POM_URL=https://github.com/romainguy/v9 diff --git a/v9/src/androidTest/java/dev/romainguy/graphics/v9/PathResizerTest.kt b/v9/src/androidTest/java/dev/romainguy/graphics/v9/PathResizerTest.kt new file mode 100644 index 0000000..c97b5b4 --- /dev/null +++ b/v9/src/androidTest/java/dev/romainguy/graphics/v9/PathResizerTest.kt @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2022 Romain Guy + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dev.romainguy.graphics.v9 + +import android.graphics.Rect +import android.graphics.RectF +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class PathResizerTest { + @Test + fun emptySlice() { + val slice = Slice(0.0f, 0.0f) + assertEquals(0.0f, slice.size) + } + + @Test(expected = IllegalArgumentException::class) + fun startMustBeLessThanEnd() { + val slice = Slice(2.0f, 1.0f) + assertEquals(1.0f, slice.size) + } + + @Test + fun sliceFromIntRect() { + val slices = Slices(Rect(0, 0, 4, 4)) + assertEquals(1, slices.verticalSlices.size) + assertEquals(Slice(0.0f, 4.0f), slices.verticalSlices[0]) + assertEquals(1, slices.horizontalSlices.size) + assertEquals(Slice(0.0f, 4.0f), slices.horizontalSlices[0]) + } + + @Test + fun sliceFromInt() { + val slices = Slices(0, 0, 4, 4) + assertEquals(1, slices.verticalSlices.size) + assertEquals(Slice(0.0f, 4.0f), slices.verticalSlices[0]) + assertEquals(1, slices.horizontalSlices.size) + assertEquals(Slice(0.0f, 4.0f), slices.horizontalSlices[0]) + } + + @Test + fun sliceFromFloatRect() { + val slices = Slices(RectF(0.0f, 0.0f, 4.0f, 4.0f)) + assertEquals(1, slices.verticalSlices.size) + assertEquals(Slice(0.0f, 4.0f), slices.verticalSlices[0]) + assertEquals(1, slices.horizontalSlices.size) + assertEquals(Slice(0.0f, 4.0f), slices.horizontalSlices[0]) + } + + @Test + fun sliceFromFloat() { + val slices = Slices(0.0f, 0.0f, 4.0f, 4.0f) + assertEquals(1, slices.verticalSlices.size) + assertEquals(Slice(0.0f, 4.0f), slices.verticalSlices[0]) + assertEquals(1, slices.horizontalSlices.size) + assertEquals(Slice(0.0f, 4.0f), slices.horizontalSlices[0]) + } + + @Test(expected = IllegalArgumentException::class) + fun emptyVerticalSlices() { + Slices(listOf(), listOf(Slice(0.0f, 1.0f))) + } + + @Test(expected = IllegalArgumentException::class) + fun emptyHorizontalSlices() { + Slices(listOf(Slice(0.0f, 1.0f)), listOf()) + } + + @Test + fun slices() { + val slices = Slices( + listOf(Slice(0.0f, 1.0f), Slice(2.0f, 3.0f)), + listOf(Slice(0.0f, 1.0f), Slice(2.0f, 3.0f)) + ) + assertEquals(2, slices.verticalSlices.size) + assertEquals(2, slices.horizontalSlices.size) + } + + @Test + fun filterEmptySlices() { + val slices = Slices( + listOf(Slice(0.0f, 0.0f), Slice(2.0f, 3.0f)), + listOf(Slice(0.0f, 0.0f), Slice(2.0f, 3.0f)) + ) + assertEquals(1, slices.verticalSlices.size) + assertEquals(1, slices.horizontalSlices.size) + } + + // TODO: test path resizing +} diff --git a/v9/src/androidTest/java/dev/romainguy/graphics/v9/ResizablePathTest.kt b/v9/src/androidTest/java/dev/romainguy/graphics/v9/ResizablePathTest.kt deleted file mode 100644 index 8f9d50d..0000000 --- a/v9/src/androidTest/java/dev/romainguy/graphics/v9/ResizablePathTest.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2022 Romain Guy - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.romainguy.graphics.v9 - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class ResizablePathTest { - @Test - fun emptyIterator() { - } -} diff --git a/v9/src/main/java/dev/romainguy/graphics/v9/PathResizer.kt b/v9/src/main/java/dev/romainguy/graphics/v9/PathResizer.kt index 870fd73..e329996 100644 --- a/v9/src/main/java/dev/romainguy/graphics/v9/PathResizer.kt +++ b/v9/src/main/java/dev/romainguy/graphics/v9/PathResizer.kt @@ -36,6 +36,24 @@ class Slice(val start: Float, val end: Float) { } override fun toString(): String = "Slice(start=$start, end=$end)" + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as Slice + + if (start != other.start) return false + if (end != other.end) return false + + return true + } + + override fun hashCode(): Int { + var result = start.hashCode() + result = 31 * result + end.hashCode() + return result + } } fun Slices(slices: Rect) = Slices(