Initial commit
This commit is contained in:
commit
6072b2ba29
844 changed files with 220532 additions and 0 deletions
1
pdfiumandroid/arrow/.gitignore
vendored
Normal file
1
pdfiumandroid/arrow/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
193
pdfiumandroid/arrow/build.gradle.kts
vendored
Normal file
193
pdfiumandroid/arrow/build.gradle.kts
vendored
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jreleaser.model.Active
|
||||
import org.jreleaser.model.Signing
|
||||
|
||||
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.detekt)
|
||||
alias(libs.plugins.kover)
|
||||
alias(libs.plugins.ktlint)
|
||||
alias(libs.plugins.jreleaser)
|
||||
`maven-publish`
|
||||
signing
|
||||
}
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_17)
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.legere.pdfiumandroid.arrow"
|
||||
compileSdk = 35
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 23
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles("consumer-rules.pro")
|
||||
}
|
||||
publishing {
|
||||
singleVariant("release") {
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro",
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility(JavaVersion.VERSION_17)
|
||||
targetCompatibility(JavaVersion.VERSION_17)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":pdfiumandroid"))
|
||||
implementation(libs.kotlinx.coroutines.android)
|
||||
implementation(libs.arrow.core)
|
||||
implementation(libs.androidx.runner)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
androidTestImplementation(libs.truth)
|
||||
androidTestImplementation(libs.kotlinx.coroutines.test)
|
||||
androidTestImplementation(libs.androidx.core.testing)
|
||||
androidTestImplementation(libs.arrow.fx.coroutines)
|
||||
}
|
||||
|
||||
fun isReleaseBuild(): Boolean = !findProject("VERSION_NAME").toString().contains("SNAPSHOT")
|
||||
|
||||
fun getReleaseRepositoryUrl(): String =
|
||||
if (rootProject.hasProperty("RELEASE_REPOSITORY_URL")) {
|
||||
rootProject.properties["RELEASE_REPOSITORY_URL"] as String
|
||||
} else {
|
||||
"https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
||||
}
|
||||
|
||||
fun getSnapshotRepositoryUrl(): String =
|
||||
if (rootProject.hasProperty("SNAPSHOT_REPOSITORY_URL")) {
|
||||
rootProject.properties["SNAPSHOT_REPOSITORY_URL"] as String
|
||||
} else {
|
||||
"https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
}
|
||||
|
||||
fun getRepositoryUrl(): String = if (isReleaseBuild()) getReleaseRepositoryUrl() else getSnapshotRepositoryUrl()
|
||||
|
||||
fun getRepositoryUsername(): String =
|
||||
if (rootProject.hasProperty("JRELEASER_MAVENCENTRAL_USERNAME")) {
|
||||
rootProject.properties["JRELEASER_MAVENCENTRAL_USERNAME"] as String
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
fun getRepositoryPassword(): String =
|
||||
if (rootProject.hasProperty("JRELEASER_MAVENCENTRAL_TOKEN")) {
|
||||
rootProject.properties["JRELEASER_MAVENCENTRAL_TOKEN"] as String
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("maven") {
|
||||
groupId = "io.legere"
|
||||
artifactId = "pdfium-android-kt-arrow"
|
||||
version = project.property("VERSION_NAME") as String
|
||||
|
||||
pom {
|
||||
name.set("pdfiumandroid.arrow")
|
||||
description.set("Arrow support for PdfiumAndroid")
|
||||
url.set(rootProject.properties["POM_URL"] as String)
|
||||
licenses {
|
||||
license {
|
||||
name.set(rootProject.properties["POM_LICENCE_NAME"] as String)
|
||||
url.set(rootProject.properties["POM_LICENCE_URL"] as String)
|
||||
distribution.set(rootProject.properties["POM_LICENCE_DIST"] as String)
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id.set(rootProject.properties["POM_DEVELOPER_ID"] as String)
|
||||
name.set(rootProject.properties["POM_DEVELOPER_NAME"] as String)
|
||||
}
|
||||
}
|
||||
scm {
|
||||
connection.set(rootProject.properties["POM_SCM_CONNECTION"] as String)
|
||||
developerConnection.set(rootProject.properties["POM_SCM_DEV_CONNECTION"] as String)
|
||||
url.set(rootProject.properties["POM_SCM_URL"] as String)
|
||||
}
|
||||
}
|
||||
afterEvaluate {
|
||||
from(components["release"])
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url =
|
||||
uri(layout.buildDirectory.dir("target/staging-deploy"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jreleaser {
|
||||
project {
|
||||
inceptionYear = "2023"
|
||||
author("@johngray1965")
|
||||
description = "Arrow support for PdfiumAndroid"
|
||||
version = rootProject.properties["VERSION_NAME"] as String
|
||||
license = "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
links {
|
||||
homepage = "https://github.com/johngray1965/PdfiumAndroidKt"
|
||||
license = "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
}
|
||||
}
|
||||
gitRootSearch = true
|
||||
signing {
|
||||
active = Active.ALWAYS
|
||||
mode = Signing.Mode.COMMAND
|
||||
armored = true
|
||||
verify = false
|
||||
command {
|
||||
executable = "gpg"
|
||||
keyName = "4BBF8FAB"
|
||||
publicKeyring = "/Users/gray/.gnupg/secring.gpg"
|
||||
}
|
||||
}
|
||||
release {
|
||||
github {
|
||||
skipRelease = true
|
||||
}
|
||||
}
|
||||
// distributions {
|
||||
// create("pdfiumandroid.arrow") {
|
||||
// artifact {
|
||||
// path = file("build/distributions/{{distributionName}}-{{projectVersion}}.zip")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
deploy {
|
||||
maven {
|
||||
mavenCentral.create("sonatype") {
|
||||
active = Active.ALWAYS
|
||||
verifyPom = false
|
||||
url = "https://central.sonatype.com/api/v1/publisher"
|
||||
stagingRepository(
|
||||
layout.buildDirectory
|
||||
.dir("target/staging-deploy")
|
||||
.get()
|
||||
.toString(),
|
||||
)
|
||||
username = getRepositoryUsername()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
0
pdfiumandroid/arrow/consumer-rules.pro
vendored
Normal file
0
pdfiumandroid/arrow/consumer-rules.pro
vendored
Normal file
4
pdfiumandroid/arrow/gradle.properties
vendored
Normal file
4
pdfiumandroid/arrow/gradle.properties
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
POM_NAME=pdfiumandroid
|
||||
POM_ARTIFACT_ID=pdfiumandroid
|
||||
POM_PACKAGING=aar
|
||||
|
||||
21
pdfiumandroid/arrow/proguard-rules.pro
vendored
Normal file
21
pdfiumandroid/arrow/proguard-rules.pro
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
BIN
pdfiumandroid/arrow/src/androidTest/assets/f01.pdf
vendored
Normal file
BIN
pdfiumandroid/arrow/src/androidTest/assets/f01.pdf
vendored
Normal file
Binary file not shown.
BIN
pdfiumandroid/arrow/src/androidTest/assets/pdf-test.pdf
vendored
Normal file
BIN
pdfiumandroid/arrow/src/androidTest/assets/pdf-test.pdf
vendored
Normal file
Binary file not shown.
135
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/PdfDocumentKtFTest.kt
vendored
Normal file
135
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/PdfDocumentKtFTest.kt
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import arrow.core.raise.either
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.legere.pdfiumandroid.PdfWriteCallback
|
||||
import io.legere.pdfiumandroid.arrow.base.BasePDFTest
|
||||
import junit.framework.TestCase
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class PdfDocumentKtFTest : BasePDFTest() {
|
||||
private lateinit var pdfDocument: PdfDocumentKtF
|
||||
private var pdfBytes: ByteArray? = null
|
||||
|
||||
@Before
|
||||
fun setUp() =
|
||||
runBlocking {
|
||||
pdfBytes = getPdfBytes("f01.pdf")
|
||||
|
||||
assertThat(pdfBytes).isNotNull()
|
||||
|
||||
pdfDocument = PdfiumCoreKtF(Dispatchers.Unconfined).newDocument(pdfBytes).getOrNull()!!
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() =
|
||||
runTest {
|
||||
pdfDocument.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageCount() =
|
||||
runTest {
|
||||
either {
|
||||
val pageCount = pdfDocument.getPageCount().bind()
|
||||
|
||||
assertThat(pageCount).isEqualTo(4)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun openPage() =
|
||||
runTest {
|
||||
either {
|
||||
val page = pdfDocument.openPage(0).bind()
|
||||
|
||||
assertThat(page).isNotNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun openPages() =
|
||||
runTest {
|
||||
either {
|
||||
val page = pdfDocument.openPages(0, 3).bind()
|
||||
|
||||
assertThat(page.size).isEqualTo(4)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getDocumentMeta() =
|
||||
runTest {
|
||||
either {
|
||||
val meta = pdfDocument.getDocumentMeta().bind()
|
||||
|
||||
assertThat(meta).isNotNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getTableOfContents() =
|
||||
runTest {
|
||||
either {
|
||||
// I don't think this test document has a table of contents
|
||||
val toc = pdfDocument.getTableOfContents().bind()
|
||||
|
||||
TestCase.assertNotNull(toc)
|
||||
assertThat(toc.size).isEqualTo(0)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun openTextPage() =
|
||||
runTest {
|
||||
either {
|
||||
val page = pdfDocument.openPage(0).bind()
|
||||
val textPage = page.openTextPage().bind()
|
||||
assertThat(textPage).isNotNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun openTextPages() =
|
||||
runTest {
|
||||
either {
|
||||
val textPages = pdfDocument.openTextPages(0, 3).bind()
|
||||
assertThat(textPages.size).isEqualTo(4)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun saveAsCopy() =
|
||||
runTest {
|
||||
pdfDocument.saveAsCopy(
|
||||
object : PdfWriteCallback {
|
||||
override fun WriteBlock(data: ByteArray?): Int {
|
||||
// Truth.assertThat(data?.size).isEqualTo(pdfBytes?.size)
|
||||
// Truth.assertThat(data).isEqualTo(pdfBytes)
|
||||
return data?.size ?: 0
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun close() =
|
||||
runTest {
|
||||
either {
|
||||
var documentAfterClose: PdfDocumentKtF?
|
||||
PdfiumCoreKtF(Dispatchers.Unconfined).newDocument(pdfBytes).bind().use {
|
||||
documentAfterClose = it
|
||||
}
|
||||
documentAfterClose?.openPage(0)
|
||||
}.mapLeft {
|
||||
assertThat(it).isInstanceOf(PdfiumKtFErrors.AlreadyClosed::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
316
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/PdfPageKtFTest.kt
vendored
Normal file
316
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/PdfPageKtFTest.kt
vendored
Normal file
|
|
@ -0,0 +1,316 @@
|
|||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Point
|
||||
import android.graphics.PointF
|
||||
import android.graphics.Rect
|
||||
import android.graphics.RectF
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import arrow.core.raise.either
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.legere.pdfiumandroid.arrow.base.BasePDFTest
|
||||
import io.legere.pdfiumandroid.util.Size
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class PdfPageKtFTest : BasePDFTest() {
|
||||
private lateinit var pdfDocument: PdfDocumentKtF
|
||||
private var pdfBytes: ByteArray? = null
|
||||
|
||||
@Before
|
||||
fun setUp() =
|
||||
runBlocking {
|
||||
pdfBytes = getPdfBytes("f01.pdf")
|
||||
|
||||
assertThat(pdfBytes).isNotNull()
|
||||
|
||||
pdfDocument = PdfiumCoreKtF(Dispatchers.Unconfined).newDocument(pdfBytes).getOrNull()!!
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
pdfDocument.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageWidth() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val pageWidth = page.getPageWidth(72).bind()
|
||||
|
||||
assertThat(pageWidth).isEqualTo(612) // 8.5 inches * 72 dpi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageHeight() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val pageWidth = page.getPageHeight(72).bind()
|
||||
|
||||
assertThat(pageWidth).isEqualTo(792) // 11 inches * 72 dpi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageWidthPoint() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val pageWidth = page.getPageWidthPoint().bind()
|
||||
|
||||
assertThat(pageWidth).isEqualTo(612) // 11 inches * 72 dpi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageHeightPoint() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val pageWidth = page.getPageHeightPoint().bind()
|
||||
|
||||
assertThat(pageWidth).isEqualTo(792) // 11 inches * 72 dpi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageCropBox() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val cropBox = page.getPageCropBox().bind()
|
||||
|
||||
assertThat(cropBox).isEqualTo(noResultRect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageMediaBox() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val mediaBox = page.getPageMediaBox().bind()
|
||||
|
||||
assertThat(mediaBox).isEqualTo(RectF(0.0f, 0.0f, 612.0f, 792.0f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageBleedBox() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val bleedBox = page.getPageBleedBox().bind()
|
||||
|
||||
assertThat(bleedBox).isEqualTo(noResultRect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageTrimBox() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val trimBox = page.getPageTrimBox().bind()
|
||||
|
||||
assertThat(trimBox).isEqualTo(noResultRect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageArtBox() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val artBox = page.getPageArtBox().bind()
|
||||
|
||||
assertThat(artBox).isEqualTo(noResultRect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageBoundingBox() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val artBox = page.getPageBoundingBox().bind()
|
||||
|
||||
assertThat(artBox).isEqualTo(RectF(0f, 792f, 612f, 0f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageSize() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val size = page.getPageSize(72).bind()
|
||||
|
||||
assertThat(size).isEqualTo(Size(612, 792))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renderPage() =
|
||||
runTest {
|
||||
// I really don't know how to test it
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRenderPage() =
|
||||
runTest {
|
||||
// I really don't know how to test it
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renderPageBitmap() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
|
||||
val conf = Bitmap.Config.RGB_565 // see other conf types
|
||||
|
||||
val bmp = Bitmap.createBitmap(612, 792, conf) // this creates a MUTABLE bitmap
|
||||
|
||||
page.renderPageBitmap(bmp, 0, 0, 612, 792)
|
||||
|
||||
// How to verify that it's correct?
|
||||
// Even if we don't verify the bitmap, we can check that it doesn't crash
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRenderPageBitmap() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
|
||||
val conf = Bitmap.Config.RGB_565 // see other conf types
|
||||
|
||||
val bmp = Bitmap.createBitmap(612, 792, conf) // this creates a MUTABLE bitmap
|
||||
|
||||
page.renderPageBitmap(bmp, 0, 0, 612, 792, renderAnnot = true, textMask = true)
|
||||
|
||||
// How to verify that it's correct?
|
||||
// Even if we don't verify the bitmap, we can check that it doesn't crash
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPageLinks() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val links = page.getPageLinks().bind()
|
||||
|
||||
assertThat(links.size).isEqualTo(0) // The test doc doesn't have links
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mapPageCoordsToDevice() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val devicePt = page.mapPageCoordsToDevice(0, 0, 100, 100, 0, 0.0, 0.0).bind()
|
||||
|
||||
assertThat(devicePt).isEqualTo(Point(0, 100))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mapDeviceCoordsToPage() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val devicePt = page.mapDeviceCoordsToPage(0, 0, 100, 100, 0, 0, 0).bind()
|
||||
|
||||
assertThat(devicePt).isEqualTo(PointF(0f, 792.00006f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mapRectToDevice() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val devicePt = page.mapRectToDevice(0, 0, 100, 100, 0, RectF(0f, 0f, 100f, 100f)).bind()
|
||||
|
||||
assertThat(devicePt).isEqualTo(
|
||||
Rect(
|
||||
// 0f in coords to 0f in device
|
||||
0,
|
||||
// 0f in corrds in at the bottom, the bottom of the device is 100f
|
||||
100,
|
||||
// 100f in coords = 100f/(8.5*72) * 100f = 16f
|
||||
16,
|
||||
// 100f in coords = 100 - 100f/(11*72) * 100f = 87f
|
||||
87,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mapRectToPage() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
val devicePt = page.mapRectToPage(0, 0, 100, 100, 0, Rect(0, 0, 100, 100)).bind()
|
||||
|
||||
assertThat(devicePt).isEqualTo(
|
||||
RectF(0.0f, 792.00006f, 612.0f, 0.0f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun close() =
|
||||
runTest {
|
||||
either {
|
||||
var pageAfterClose: PdfPageKtF?
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
pageAfterClose = page
|
||||
}
|
||||
pageAfterClose!!.getPageWidth(72)
|
||||
}.mapLeft {
|
||||
assertThat(it).isInstanceOf(PdfiumKtFErrors.AlreadyClosed::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPage() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
assertThat(page).isNotNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
114
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/PdfPageLinkKtFTest.kt
vendored
Normal file
114
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/PdfPageLinkKtFTest.kt
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import android.graphics.RectF
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import arrow.core.raise.either
|
||||
import com.google.common.truth.Truth
|
||||
import io.legere.pdfiumandroid.arrow.base.BasePDFTest
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.TestResult
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class PdfPageLinkKtFTest : BasePDFTest() {
|
||||
private lateinit var pdfDocument: PdfDocumentKtF
|
||||
private lateinit var pdfPage: PdfPageKtF
|
||||
private lateinit var pdfTextPage: PdfTextPageKtF
|
||||
private var pdfBytes: ByteArray? = null
|
||||
|
||||
@Before
|
||||
fun setUp() =
|
||||
runBlocking {
|
||||
pdfBytes = getPdfBytes("pdf-test.pdf")
|
||||
|
||||
Truth.assertThat(pdfBytes).isNotNull()
|
||||
|
||||
pdfDocument = PdfiumCoreKtF(Dispatchers.Unconfined).newDocument(pdfBytes).getOrNull()!!
|
||||
pdfPage = pdfDocument.openPage(0).getOrNull()!!
|
||||
pdfTextPage = pdfPage.openTextPage().getOrNull()!!
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
pdfTextPage.close()
|
||||
pdfPage.close()
|
||||
pdfDocument.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLink(): TestResult =
|
||||
runTest {
|
||||
either {
|
||||
pdfTextPage.loadWebLink().bind().use { links ->
|
||||
Truth.assertThat(links).isNotNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCountWebLinks(): TestResult =
|
||||
runTest {
|
||||
either {
|
||||
pdfTextPage.loadWebLink().bind().use { links ->
|
||||
Truth.assertThat(links).isNotNull()
|
||||
Truth.assertThat(links.countWebLinks().bind()).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetTextRange(): TestResult =
|
||||
runTest {
|
||||
either {
|
||||
pdfTextPage.loadWebLink().bind().use { links ->
|
||||
Truth.assertThat(links).isNotNull()
|
||||
Truth.assertThat(links.getTextRange(0).bind()).isEqualTo(Pair(351, 31))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetUrl(): TestResult =
|
||||
runTest {
|
||||
either {
|
||||
pdfTextPage.loadWebLink().bind().use { links ->
|
||||
Truth.assertThat(links).isNotNull()
|
||||
val (_, count) = links.getTextRange(0).bind()
|
||||
Truth
|
||||
.assertThat(links.getURL(0, count).bind())
|
||||
.isEqualTo("http://www.education.gov.yk.ca/")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCountRects(): TestResult =
|
||||
runTest {
|
||||
either {
|
||||
pdfTextPage.loadWebLink().bind().use { links ->
|
||||
Truth.assertThat(links).isNotNull()
|
||||
val count = links.countRects(0).bind()
|
||||
Truth.assertThat(count).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetRect(): TestResult =
|
||||
runTest {
|
||||
either {
|
||||
pdfTextPage.loadWebLink().bind().use { links ->
|
||||
Truth.assertThat(links).isNotNull()
|
||||
val count = links.getRect(0, 0).bind()
|
||||
Truth
|
||||
.assertThat(count)
|
||||
.isEqualTo(RectF(221.46f, 480.624f, 389.66394f, 469.152f))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
235
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/PdfTextPageKtTest.kt
vendored
Normal file
235
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/PdfTextPageKtTest.kt
vendored
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import android.graphics.RectF
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import arrow.core.raise.either
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.legere.pdfiumandroid.arrow.base.BasePDFTest
|
||||
import junit.framework.TestCase
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.TestResult
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class PdfTextPageKtTest : BasePDFTest() {
|
||||
private lateinit var pdfDocument: PdfDocumentKtF
|
||||
private var pdfBytes: ByteArray? = null
|
||||
|
||||
@Before
|
||||
fun setUp() =
|
||||
runBlocking {
|
||||
pdfBytes = getPdfBytes("f01.pdf")
|
||||
|
||||
TestCase.assertNotNull(pdfBytes)
|
||||
|
||||
pdfDocument = PdfiumCoreKtF(Dispatchers.Unconfined).newDocument(pdfBytes).getOrNull()!!
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
pdfDocument.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textPageCountChars() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
val charCount = textPage.textPageCountChars().bind()
|
||||
|
||||
assertThat(charCount).isEqualTo(3468)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textPageGetText() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
val text = textPage.textPageGetText(0, 100).bind()
|
||||
|
||||
assertThat(text?.length).isEqualTo(100)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textPageGetUnicode() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
val char = textPage.textPageGetUnicode(0).bind()
|
||||
|
||||
assertThat(char).isEqualTo('T')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textPageGetCharBox() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
val rect = textPage.textPageGetCharBox(0).bind()
|
||||
|
||||
assertThat(rect)
|
||||
.isEqualTo(RectF(90.314415f, 715.3187f, 103.44171f, 699.1206f))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textPageGetCharIndexAtPos() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
val characterToLookup = 0
|
||||
val rect = textPage.textPageGetCharBox(characterToLookup).bind()
|
||||
|
||||
val pos =
|
||||
textPage
|
||||
.textPageGetCharIndexAtPos(
|
||||
rect?.centerX()?.toDouble() ?: 0.0,
|
||||
rect?.centerY()?.toDouble() ?: 0.0,
|
||||
// Shouldn't need much since we're in the middle of the rect
|
||||
1.0,
|
||||
1.0,
|
||||
).bind()
|
||||
|
||||
assertThat(pos).isEqualTo(characterToLookup)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textPageCountRects() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
val rectCount = textPage.textPageCountRects(0, 100).bind()
|
||||
|
||||
assertThat(rectCount).isEqualTo(4)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textPageGetRect() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
val rect = textPage.textPageGetRect(0).bind()
|
||||
|
||||
assertThat(rect).isEqualTo(RectF(0f, 0f, 0f, 0f))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textPageGetBoundedText() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
val text = textPage.textPageGetBoundedText(RectF(0f, 97f, 100f, 100f), 100).bind()
|
||||
|
||||
assertThat(text).isEqualTo("Do")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getFontSize() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
val fontSize = textPage.getFontSize(0).bind()
|
||||
|
||||
assertThat(fontSize).isEqualTo(22.559999465942383)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun findStart(): TestResult =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
val findWhat = "children's"
|
||||
val startIndex = 0
|
||||
textPage.findStart(findWhat, emptySet(), startIndex).bind().use { findHandle ->
|
||||
var result = findHandle.findNext()
|
||||
assertThat(result.bind()).isTrue()
|
||||
var index = findHandle.getSchResultIndex().bind()
|
||||
var count = findHandle.getSchCount().bind()
|
||||
var text = textPage.textPageGetText(index, count).bind()
|
||||
assertThat(index).isEqualTo(1525)
|
||||
assertThat(count).isEqualTo(10)
|
||||
assertThat(text).isEqualTo(findWhat)
|
||||
result = findHandle.findNext()
|
||||
assertThat(result.bind()).isTrue()
|
||||
index = findHandle.getSchResultIndex().bind()
|
||||
count = findHandle.getSchCount().bind()
|
||||
text = textPage.textPageGetText(index, count).bind()
|
||||
assertThat(index).isEqualTo(2761)
|
||||
assertThat(count).isEqualTo(10)
|
||||
assertThat(text).isEqualTo(findWhat)
|
||||
result = findHandle.findNext()
|
||||
assertThat(result.bind()).isFalse()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun close() =
|
||||
runTest {
|
||||
either {
|
||||
var pageAfterClose: PdfTextPageKtF?
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
pageAfterClose = textPage
|
||||
}
|
||||
}
|
||||
pageAfterClose!!.textPageCountChars()
|
||||
}.mapLeft {
|
||||
assertThat(it).isInstanceOf(PdfiumKtFErrors.AlreadyClosed::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPage() =
|
||||
runTest {
|
||||
either {
|
||||
pdfDocument.openPage(0).bind().use { page ->
|
||||
page.openTextPage().bind().use { textPage ->
|
||||
assertThat(textPage.page).isNotNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/PdfiumCoreKtFTest.kt
vendored
Normal file
39
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/PdfiumCoreKtFTest.kt
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.legere.pdfiumandroid.arrow.base.BasePDFTest
|
||||
import io.legere.pdfiumandroid.arrow.base.ByteArrayPdfiumSource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class PdfiumCoreKtFTest : BasePDFTest() {
|
||||
@Test
|
||||
fun newDocument() =
|
||||
runTest {
|
||||
val pdfBytes = getPdfBytes("f01.pdf")
|
||||
|
||||
assertThat(pdfBytes).isNotNull()
|
||||
|
||||
val pdfiumCore = PdfiumCoreKtF(Dispatchers.Unconfined)
|
||||
val pdfDocument = pdfiumCore.newDocument(pdfBytes)
|
||||
|
||||
assertThat(pdfDocument).isNotNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun newDocumentWithCustomSource() =
|
||||
runTest {
|
||||
val pdfBytes = getPdfBytes("f01.pdf")
|
||||
|
||||
assertThat(pdfBytes).isNotNull()
|
||||
|
||||
val pdfiumCore = PdfiumCoreKtF(Dispatchers.Unconfined)
|
||||
val pdfDocument = pdfiumCore.newDocument(ByteArrayPdfiumSource(pdfBytes!!))
|
||||
|
||||
assertThat(pdfDocument).isNotNull()
|
||||
}
|
||||
}
|
||||
27
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/base/BasePDFTest.kt
vendored
Normal file
27
pdfiumandroid/arrow/src/androidTest/java/io/legere/pdfiumandroid/arrow/base/BasePDFTest.kt
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package io.legere.pdfiumandroid.arrow.base
|
||||
|
||||
import android.graphics.RectF
|
||||
import android.util.Log
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
|
||||
@Suppress("unused")
|
||||
open class BasePDFTest {
|
||||
// set to true to skip tests that are not implemented yet
|
||||
// set to false to force unimplemented tests to fail
|
||||
val notImplementedAssetValue = false
|
||||
|
||||
val noResultRect = RectF(-1f, -1f, -1f, -1f)
|
||||
|
||||
fun getPdfBytes(filename: String): ByteArray? {
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().context
|
||||
val assetManager = appContext.assets
|
||||
try {
|
||||
val input = assetManager.open(filename)
|
||||
return input.readBytes()
|
||||
} catch (e: Exception) {
|
||||
Log.e(BasePDFTest::class.simpleName, "Ugh", e)
|
||||
}
|
||||
assetManager.close()
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package io.legere.pdfiumandroid.arrow.base
|
||||
|
||||
import io.legere.pdfiumandroid.PdfiumSource
|
||||
|
||||
class ByteArrayPdfiumSource(
|
||||
private val array: ByteArray,
|
||||
) : PdfiumSource {
|
||||
override val length: Long
|
||||
get() = array.size.toLong()
|
||||
|
||||
override fun read(
|
||||
position: Long,
|
||||
buffer: ByteArray,
|
||||
size: Int,
|
||||
): Int {
|
||||
array.copyInto(
|
||||
destination = buffer,
|
||||
destinationOffset = 0,
|
||||
startIndex = position.toInt(),
|
||||
endIndex = position.toInt() + size,
|
||||
)
|
||||
return size
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
// nothing to close
|
||||
}
|
||||
}
|
||||
2
pdfiumandroid/arrow/src/main/AndroidManifest.xml
vendored
Normal file
2
pdfiumandroid/arrow/src/main/AndroidManifest.xml
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest/>
|
||||
42
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/FindResultKtF.kt
vendored
Normal file
42
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/FindResultKtF.kt
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import arrow.core.Either
|
||||
import io.legere.pdfiumandroid.FindResult
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import java.io.Closeable
|
||||
|
||||
@Suppress("unused")
|
||||
class FindResultKtF(
|
||||
private val findResult: FindResult,
|
||||
private val dispatcher: CoroutineDispatcher,
|
||||
) : Closeable {
|
||||
suspend fun findNext(): Either<PdfiumKtFErrors, Boolean> =
|
||||
wrapEither(dispatcher) {
|
||||
findResult.findNext()
|
||||
}
|
||||
|
||||
suspend fun findPrev(): Either<PdfiumKtFErrors, Boolean> =
|
||||
wrapEither(dispatcher) {
|
||||
findResult.findPrev()
|
||||
}
|
||||
|
||||
suspend fun getSchResultIndex(): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
findResult.getSchResultIndex()
|
||||
}
|
||||
|
||||
suspend fun getSchCount(): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
findResult.getSchCount()
|
||||
}
|
||||
|
||||
suspend fun closeFind() {
|
||||
wrapEither(dispatcher) {
|
||||
findResult.closeFind()
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
findResult.closeFind()
|
||||
}
|
||||
}
|
||||
150
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfDocumentKtF.kt
vendored
Normal file
150
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfDocumentKtF.kt
vendored
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
@file:Suppress("unused", "CanBeVal")
|
||||
|
||||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import android.graphics.Matrix
|
||||
import android.graphics.RectF
|
||||
import android.view.Surface
|
||||
import arrow.core.Either
|
||||
import io.legere.pdfiumandroid.PdfDocument
|
||||
import io.legere.pdfiumandroid.PdfWriteCallback
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.Closeable
|
||||
|
||||
/**
|
||||
* PdfDocumentKtF represents a PDF file and allows you to load pages from it.
|
||||
* @property document the [PdfDocument] to wrap
|
||||
* @property dispatcher the [CoroutineDispatcher] to use for suspending calls
|
||||
* @constructor create a [PdfDocumentKtF] from a [PdfDocument]
|
||||
*/
|
||||
@Suppress("TooManyFunctions", "CanBeVal")
|
||||
class PdfDocumentKtF(
|
||||
val document: PdfDocument,
|
||||
private val dispatcher: CoroutineDispatcher,
|
||||
) : Closeable {
|
||||
/**
|
||||
* suspend version of [PdfDocument.getPageCount]
|
||||
*/
|
||||
suspend fun getPageCount(): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
document.getPageCount()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfDocument.getPageCharCounts]
|
||||
*/
|
||||
suspend fun getPageCharCounts(): Either<PdfiumKtFErrors, IntArray> =
|
||||
wrapEither(dispatcher) {
|
||||
document.getPageCharCounts()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfDocument.openPage]
|
||||
*/
|
||||
suspend fun openPage(pageIndex: Int): Either<PdfiumKtFErrors, PdfPageKtF> =
|
||||
wrapEither(dispatcher) {
|
||||
PdfPageKtF(document.openPage(pageIndex), dispatcher)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfDocument.openPages]
|
||||
*/
|
||||
suspend fun openPages(
|
||||
fromIndex: Int,
|
||||
toIndex: Int,
|
||||
): Either<PdfiumKtFErrors, List<PdfPageKtF>> =
|
||||
wrapEither(dispatcher) {
|
||||
document.openPages(fromIndex, toIndex).map { PdfPageKtF(it, dispatcher) }
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfDocument.renderPages]
|
||||
*/
|
||||
@Suppress("LongParameterList", "ComplexMethod", "ComplexCondition")
|
||||
suspend fun renderPages(
|
||||
surface: Surface?,
|
||||
pages: List<PdfPageKtF>,
|
||||
matrices: List<Matrix>,
|
||||
clipRects: List<RectF>,
|
||||
renderAnnot: Boolean = false,
|
||||
textMask: Boolean = false,
|
||||
canvasColor: Int = 0xFF848484.toInt(),
|
||||
pageBackgroundColor: Int = 0xFFFFFFFF.toInt(),
|
||||
renderCoroutinesDispatcher: CoroutineDispatcher,
|
||||
): Boolean {
|
||||
return withContext(renderCoroutinesDispatcher) {
|
||||
return@withContext surface
|
||||
?.let {
|
||||
document.renderPages(
|
||||
surface,
|
||||
pages.map { page -> page.page },
|
||||
matrices,
|
||||
clipRects,
|
||||
renderAnnot,
|
||||
textMask,
|
||||
canvasColor,
|
||||
pageBackgroundColor,
|
||||
)
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfDocument.deletePage]
|
||||
*/
|
||||
suspend fun deletePage(pageIndex: Int): Unit =
|
||||
withContext(dispatcher) {
|
||||
document.deletePage(pageIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfDocument.getDocumentMeta]
|
||||
*/
|
||||
suspend fun getDocumentMeta(): Either<PdfiumKtFErrors, PdfDocument.Meta> =
|
||||
wrapEither(dispatcher) {
|
||||
document.getDocumentMeta()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfDocument.getTableOfContents]
|
||||
*/
|
||||
suspend fun getTableOfContents(): Either<PdfiumKtFErrors, List<PdfDocument.Bookmark>> =
|
||||
wrapEither(dispatcher) {
|
||||
document.getTableOfContents()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfDocument.openTextPages]
|
||||
*/
|
||||
suspend fun openTextPages(
|
||||
fromIndex: Int,
|
||||
toIndex: Int,
|
||||
): Either<PdfiumKtFErrors, List<PdfTextPageKtF>> =
|
||||
wrapEither(dispatcher) {
|
||||
document.openTextPages(fromIndex, toIndex).map { PdfTextPageKtF(it, dispatcher) }
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfDocument.saveAsCopy]
|
||||
*/
|
||||
suspend fun saveAsCopy(callback: PdfWriteCallback): Either<PdfiumKtFErrors, Boolean> =
|
||||
wrapEither(dispatcher) {
|
||||
document.saveAsCopy(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the document
|
||||
* @throws IllegalArgumentException if document is closed
|
||||
*/
|
||||
override fun close() {
|
||||
document.close()
|
||||
}
|
||||
|
||||
fun safeClose(): Either<PdfiumKtFErrors, Boolean> =
|
||||
Either
|
||||
.catch {
|
||||
document.close()
|
||||
true
|
||||
}.mapLeft { exceptionToPdfiumKtFError(it) }
|
||||
}
|
||||
384
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfPageKtF.kt
vendored
Normal file
384
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfPageKtF.kt
vendored
Normal file
|
|
@ -0,0 +1,384 @@
|
|||
@file:Suppress("unused")
|
||||
|
||||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Matrix
|
||||
import android.graphics.Point
|
||||
import android.graphics.PointF
|
||||
import android.graphics.Rect
|
||||
import android.graphics.RectF
|
||||
import android.view.Surface
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import io.legere.pdfiumandroid.Logger
|
||||
import io.legere.pdfiumandroid.PdfDocument
|
||||
import io.legere.pdfiumandroid.PdfPage
|
||||
import io.legere.pdfiumandroid.PdfiumCore
|
||||
import io.legere.pdfiumandroid.util.Size
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.Closeable
|
||||
|
||||
/**
|
||||
* PdfPageKtF represents a single page of a PDF file.
|
||||
* @property page the [PdfPage] to wrap
|
||||
* @property dispatcher the [CoroutineDispatcher] to use for suspending calls
|
||||
*/
|
||||
@Suppress("TooManyFunctions")
|
||||
class PdfPageKtF(
|
||||
val page: PdfPage,
|
||||
private val dispatcher: CoroutineDispatcher,
|
||||
) : Closeable {
|
||||
/**
|
||||
* Open a text page
|
||||
* @throws IllegalArgumentException if document is closed or the page cannot be loaded
|
||||
*/
|
||||
suspend fun openTextPage(): Either<PdfiumKtFErrors, PdfTextPageKtF> =
|
||||
wrapEither(dispatcher) {
|
||||
PdfTextPageKtF(page.openTextPage(), dispatcher)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageWidth]
|
||||
*/
|
||||
suspend fun getPageWidth(screenDpi: Int): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageWidth(screenDpi)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageHeight]
|
||||
*/
|
||||
suspend fun getPageHeight(screenDpi: Int): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageHeight(screenDpi)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageWidthPoint]
|
||||
*/
|
||||
suspend fun getPageWidthPoint(): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageWidthPoint()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageHeightPoint]
|
||||
*/
|
||||
suspend fun getPageHeightPoint(): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageHeightPoint()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageMatrix]
|
||||
*/
|
||||
suspend fun getPageMatrix(): Either<PdfiumKtFErrors, Matrix> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageMatrix() ?: error("Page matrix is null")
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageRotation]
|
||||
*/
|
||||
suspend fun getPageRotation(): Either<PdfiumKtFErrors, Int> =
|
||||
withContext(dispatcher) {
|
||||
Either
|
||||
.catch {
|
||||
val rotation = page.getPageRotation()
|
||||
if (rotation < 0) {
|
||||
error("Invalid rotation: $rotation")
|
||||
}
|
||||
rotation
|
||||
}.mapLeft {
|
||||
exceptionToPdfiumKtFError(it)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageCropBox]
|
||||
*/
|
||||
suspend fun getPageCropBox(): Either<PdfiumKtFErrors, RectF> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageCropBox()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageMediaBox]
|
||||
*/
|
||||
suspend fun getPageMediaBox(): Either<PdfiumKtFErrors, RectF> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageMediaBox()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageBleedBox]
|
||||
*/
|
||||
suspend fun getPageBleedBox(): Either<PdfiumKtFErrors, RectF> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageBleedBox()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageTrimBox]
|
||||
*/
|
||||
suspend fun getPageTrimBox(): Either<PdfiumKtFErrors, RectF> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageTrimBox()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageArtBox]
|
||||
*/
|
||||
suspend fun getPageArtBox(): Either<PdfiumKtFErrors, RectF> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageArtBox()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageBoundingBox]
|
||||
*/
|
||||
suspend fun getPageBoundingBox(): Either<PdfiumKtFErrors, RectF> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageBoundingBox()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageSize]
|
||||
*/
|
||||
suspend fun getPageSize(screenDpi: Int): Either<PdfiumKtFErrors, Size> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageSize(screenDpi)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.renderPage]
|
||||
*/
|
||||
@Suppress("LongParameterList", "ComplexCondition")
|
||||
suspend fun renderPage(
|
||||
surface: Surface?,
|
||||
startX: Int,
|
||||
startY: Int,
|
||||
drawSizeX: Int,
|
||||
drawSizeY: Int,
|
||||
canvasColor: Int = 0xFF848484.toInt(),
|
||||
pageBackgroundColor: Int = 0xFFFFFFFF.toInt(),
|
||||
renderCoroutinesDispatcher: CoroutineDispatcher,
|
||||
): Either<PdfiumKtFErrors, Boolean> {
|
||||
val sizes = IntArray(2)
|
||||
val pointers = LongArray(2)
|
||||
return withContext(renderCoroutinesDispatcher) {
|
||||
surface?.let {
|
||||
PdfPage.lockSurface(
|
||||
it,
|
||||
sizes,
|
||||
pointers,
|
||||
)
|
||||
val nativeWindow = pointers[0]
|
||||
val bufferPtr = pointers[1]
|
||||
val surfaceWidth = sizes[0]
|
||||
val surfaceHeight = sizes[1]
|
||||
Logger.d(
|
||||
"PdfPageKtF",
|
||||
"page: ${page.pageIndex}, surfaceWidth: $surfaceWidth, " +
|
||||
"surfaceHeight: $surfaceHeight, nativeWindow: $nativeWindow, " +
|
||||
"bufferPtr: $bufferPtr, nativeWindow: $nativeWindow",
|
||||
)
|
||||
if (bufferPtr == 0L || bufferPtr == -1L || nativeWindow == 0L || nativeWindow == -1L) {
|
||||
PdfiumKtFErrors.ConstraintError.left()
|
||||
}
|
||||
val result =
|
||||
page.renderPage(
|
||||
bufferPtr,
|
||||
startX,
|
||||
startY,
|
||||
drawSizeX,
|
||||
drawSizeY,
|
||||
canvasColor = canvasColor,
|
||||
pageBackgroundColor = pageBackgroundColor,
|
||||
)
|
||||
PdfPage.unlockSurface(longArrayOf(nativeWindow, bufferPtr))
|
||||
if (!result) {
|
||||
PdfiumKtFErrors.ConstraintError.left()
|
||||
}
|
||||
true.right()
|
||||
} ?: PdfiumKtFErrors.ConstraintError.left()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.renderPage]
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
suspend fun renderPage(
|
||||
surface: Surface?,
|
||||
matrix: Matrix,
|
||||
clipRect: RectF,
|
||||
renderAnnot: Boolean = false,
|
||||
textMask: Boolean = false,
|
||||
canvasColor: Int = 0xFF848484.toInt(),
|
||||
pageBackgroundColor: Int = 0xFFFFFFFF.toInt(),
|
||||
renderCoroutinesDispatcher: CoroutineDispatcher,
|
||||
): Either<PdfiumKtFErrors, Boolean> {
|
||||
return PdfiumCore.surfaceMutex.withLock {
|
||||
withContext(renderCoroutinesDispatcher) {
|
||||
return@withContext surface?.let {
|
||||
val retValue =
|
||||
page.renderPage(
|
||||
surface,
|
||||
matrix,
|
||||
clipRect,
|
||||
renderAnnot,
|
||||
textMask,
|
||||
canvasColor,
|
||||
pageBackgroundColor,
|
||||
)
|
||||
if (!retValue) {
|
||||
PdfiumKtFErrors.ConstraintError.left()
|
||||
} else {
|
||||
true.right()
|
||||
}
|
||||
} ?: PdfiumKtFErrors.ConstraintError.left()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
/**
|
||||
* suspend version of [PdfPage.renderPageBitmap]
|
||||
*/
|
||||
suspend fun renderPageBitmap(
|
||||
bitmap: Bitmap,
|
||||
startX: Int,
|
||||
startY: Int,
|
||||
drawSizeX: Int,
|
||||
drawSizeY: Int,
|
||||
renderAnnot: Boolean = false,
|
||||
textMask: Boolean = false,
|
||||
canvasColor: Int = 0xFF848484.toInt(),
|
||||
pageBackgroundColor: Int = 0xFFFFFFFF.toInt(),
|
||||
): Either<PdfiumKtFErrors, Boolean> =
|
||||
wrapEither(dispatcher) {
|
||||
page.renderPageBitmap(
|
||||
bitmap,
|
||||
startX,
|
||||
startY,
|
||||
drawSizeX,
|
||||
drawSizeY,
|
||||
renderAnnot,
|
||||
textMask,
|
||||
canvasColor,
|
||||
pageBackgroundColor,
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
/**
|
||||
* suspend version of [PdfPage.renderPageBitmap]
|
||||
*/
|
||||
suspend fun renderPageBitmap(
|
||||
bitmap: Bitmap?,
|
||||
matrix: Matrix,
|
||||
clipRect: RectF,
|
||||
renderAnnot: Boolean = false,
|
||||
textMask: Boolean = false,
|
||||
canvasColor: Int = 0xFF848484.toInt(),
|
||||
pageBackgroundColor: Int = 0xFFFFFFFF.toInt(),
|
||||
): Either<PdfiumKtFErrors, Boolean> =
|
||||
wrapEither(dispatcher) {
|
||||
page.renderPageBitmap(bitmap, matrix, clipRect, renderAnnot, textMask, canvasColor, pageBackgroundColor)
|
||||
true
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.getPageLinks]
|
||||
*/
|
||||
suspend fun getPageLinks(): Either<PdfiumKtFErrors, List<PdfDocument.Link>> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getPageLinks()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfPage.mapPageCoordsToDevice]
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
suspend fun mapPageCoordsToDevice(
|
||||
startX: Int,
|
||||
startY: Int,
|
||||
sizeX: Int,
|
||||
sizeY: Int,
|
||||
rotate: Int,
|
||||
pageX: Double,
|
||||
pageY: Double,
|
||||
): Either<PdfiumKtFErrors, Point> =
|
||||
wrapEither(dispatcher) {
|
||||
page.mapPageCoordsToDevice(startX, startY, sizeX, sizeY, rotate, pageX, pageY)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
/**
|
||||
* suspend version of [PdfPage.mapDeviceCoordsToPage]
|
||||
*/
|
||||
suspend fun mapDeviceCoordsToPage(
|
||||
startX: Int,
|
||||
startY: Int,
|
||||
sizeX: Int,
|
||||
sizeY: Int,
|
||||
rotate: Int,
|
||||
deviceX: Int,
|
||||
deviceY: Int,
|
||||
): Either<PdfiumKtFErrors, PointF> =
|
||||
wrapEither(dispatcher) {
|
||||
page.mapDeviceCoordsToPage(startX, startY, sizeX, sizeY, rotate, deviceX, deviceY)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
/**
|
||||
* suspend version of [PdfPage.mapRectToDevice]
|
||||
*/
|
||||
suspend fun mapRectToDevice(
|
||||
startX: Int,
|
||||
startY: Int,
|
||||
sizeX: Int,
|
||||
sizeY: Int,
|
||||
rotate: Int,
|
||||
coords: RectF,
|
||||
): Either<PdfiumKtFErrors, Rect> =
|
||||
wrapEither(dispatcher) {
|
||||
page.mapRectToDevice(startX, startY, sizeX, sizeY, rotate, coords)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
/**
|
||||
* suspend version of [PdfPage.mapRectToPage]
|
||||
*/
|
||||
suspend fun mapRectToPage(
|
||||
startX: Int,
|
||||
startY: Int,
|
||||
sizeX: Int,
|
||||
sizeY: Int,
|
||||
rotate: Int,
|
||||
coords: Rect,
|
||||
): Either<PdfiumKtFErrors, RectF> =
|
||||
wrapEither(dispatcher) {
|
||||
page.mapRectToPage(startX, startY, sizeX, sizeY, rotate, coords)
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the page
|
||||
*/
|
||||
override fun close() {
|
||||
page.close()
|
||||
}
|
||||
|
||||
fun safeClose(): Either<PdfiumKtFErrors, Boolean> =
|
||||
Either
|
||||
.catch {
|
||||
page.close()
|
||||
true
|
||||
}.mapLeft { exceptionToPdfiumKtFError(it) }
|
||||
}
|
||||
47
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfPageLinkKtF.kt
vendored
Normal file
47
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfPageLinkKtF.kt
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import android.graphics.RectF
|
||||
import arrow.core.Either
|
||||
import io.legere.pdfiumandroid.PdfPageLink
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import java.io.Closeable
|
||||
|
||||
class PdfPageLinkKtF(
|
||||
val pageLink: PdfPageLink,
|
||||
private val dispatcher: CoroutineDispatcher,
|
||||
) : Closeable {
|
||||
suspend fun countWebLinks(): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
pageLink.countWebLinks()
|
||||
}
|
||||
|
||||
suspend fun getURL(
|
||||
index: Int,
|
||||
length: Int,
|
||||
): Either<PdfiumKtFErrors, String?> =
|
||||
wrapEither(dispatcher) {
|
||||
pageLink.getURL(index, length)
|
||||
}
|
||||
|
||||
suspend fun countRects(index: Int): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
pageLink.countRects(index)
|
||||
}
|
||||
|
||||
suspend fun getRect(
|
||||
linkIndex: Int,
|
||||
rectIndex: Int,
|
||||
): Either<PdfiumKtFErrors, RectF> =
|
||||
wrapEither(dispatcher) {
|
||||
pageLink.getRect(linkIndex, rectIndex)
|
||||
}
|
||||
|
||||
suspend fun getTextRange(index: Int): Either<PdfiumKtFErrors, Pair<Int, Int>> =
|
||||
wrapEither(dispatcher) {
|
||||
pageLink.getTextRange(index)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
pageLink.close()
|
||||
}
|
||||
}
|
||||
149
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfTextPageKtF.kt
vendored
Normal file
149
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfTextPageKtF.kt
vendored
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
@file:Suppress("unused")
|
||||
|
||||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import android.graphics.RectF
|
||||
import arrow.core.Either
|
||||
import io.legere.pdfiumandroid.FindFlags
|
||||
import io.legere.pdfiumandroid.PdfTextPage
|
||||
import io.legere.pdfiumandroid.WordRangeRect
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import java.io.Closeable
|
||||
|
||||
/**
|
||||
* PdfTextPageKtF represents a single text page of a PDF file.
|
||||
* @property page the [PdfTextPage] to wrap
|
||||
* @property dispatcher the [CoroutineDispatcher] to use for suspending calls
|
||||
*/
|
||||
@Suppress("TooManyFunctions")
|
||||
class PdfTextPageKtF(
|
||||
val page: PdfTextPage,
|
||||
private val dispatcher: CoroutineDispatcher,
|
||||
) : Closeable {
|
||||
/**
|
||||
* suspend version of [PdfTextPage.textPageCountChars]
|
||||
*/
|
||||
suspend fun textPageCountChars(): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
page.textPageCountChars()
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfTextPage.textPageGetText]
|
||||
*/
|
||||
suspend fun textPageGetText(
|
||||
startIndex: Int,
|
||||
length: Int,
|
||||
): Either<PdfiumKtFErrors, String?> =
|
||||
wrapEither(dispatcher) {
|
||||
page.textPageGetText(startIndex, length)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfTextPage.textPageGetUnicode]
|
||||
*/
|
||||
suspend fun textPageGetUnicode(index: Int): Either<PdfiumKtFErrors, Char> =
|
||||
wrapEither(dispatcher) {
|
||||
page.textPageGetUnicode(index)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfTextPage.textPageGetCharBox]
|
||||
*/
|
||||
suspend fun textPageGetCharBox(index: Int): Either<PdfiumKtFErrors, RectF?> =
|
||||
wrapEither(dispatcher) {
|
||||
page.textPageGetCharBox(index)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfTextPage.textPageGetCharIndexAtPos]
|
||||
*/
|
||||
suspend fun textPageGetCharIndexAtPos(
|
||||
x: Double,
|
||||
y: Double,
|
||||
xTolerance: Double,
|
||||
yTolerance: Double,
|
||||
): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
page.textPageGetCharIndexAtPos(x, y, xTolerance, yTolerance)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfTextPage.textPageCountRects]
|
||||
*/
|
||||
suspend fun textPageCountRects(
|
||||
startIndex: Int,
|
||||
count: Int,
|
||||
): Either<PdfiumKtFErrors, Int> =
|
||||
wrapEither(dispatcher) {
|
||||
page.textPageCountRects(startIndex, count)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfTextPage.textPageGetRect]
|
||||
*/
|
||||
suspend fun textPageGetRect(rectIndex: Int): Either<PdfiumKtFErrors, RectF?> =
|
||||
wrapEither(dispatcher) {
|
||||
page.textPageGetRect(rectIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfTextPage.textPageGetRectsForRanges]
|
||||
*/
|
||||
suspend fun textPageGetRectsForRanges(wordRanges: IntArray): Either<PdfiumKtFErrors, List<WordRangeRect>?> =
|
||||
wrapEither(dispatcher) {
|
||||
page.textPageGetRectsForRanges(wordRanges)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfTextPage.textPageGetBoundedText]
|
||||
*/
|
||||
suspend fun textPageGetBoundedText(
|
||||
rect: RectF,
|
||||
length: Int,
|
||||
): Either<PdfiumKtFErrors, String?> =
|
||||
wrapEither(dispatcher) {
|
||||
page.textPageGetBoundedText(rect, length)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfTextPage.getFontSize]
|
||||
*/
|
||||
suspend fun getFontSize(charIndex: Int): Either<PdfiumKtFErrors, Double> =
|
||||
wrapEither(dispatcher) {
|
||||
page.getFontSize(charIndex)
|
||||
}
|
||||
|
||||
suspend fun findStart(
|
||||
findWhat: String,
|
||||
flags: Set<FindFlags>,
|
||||
startIndex: Int,
|
||||
): Either<PdfiumKtFErrors, FindResultKtF> =
|
||||
wrapEither(dispatcher) {
|
||||
val findResult = page.findStart(findWhat, flags, startIndex)
|
||||
if (findResult == null) {
|
||||
error("findResult is null")
|
||||
} else {
|
||||
FindResultKtF(findResult, dispatcher)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun loadWebLink(): Either<PdfiumKtFErrors, PdfPageLinkKtF> =
|
||||
wrapEither(dispatcher) {
|
||||
PdfPageLinkKtF(page.loadWebLink(), dispatcher)
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the page and free all resources.
|
||||
*/
|
||||
override fun close() {
|
||||
page.close()
|
||||
}
|
||||
|
||||
fun safeClose(): Either<PdfiumKtFErrors, Boolean> =
|
||||
Either
|
||||
.catch {
|
||||
page.close()
|
||||
true
|
||||
}.mapLeft { exceptionToPdfiumKtFError(it) }
|
||||
}
|
||||
18
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfiumArrorwExt.kt
vendored
Normal file
18
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfiumArrorwExt.kt
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import arrow.core.Either
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
suspend inline fun <reified T> wrapEither(
|
||||
dispatcher: CoroutineDispatcher,
|
||||
crossinline block: () -> T,
|
||||
): Either<PdfiumKtFErrors, T> =
|
||||
withContext(dispatcher) {
|
||||
Either
|
||||
.catch {
|
||||
block()
|
||||
}.mapLeft {
|
||||
exceptionToPdfiumKtFError(it)
|
||||
}
|
||||
}
|
||||
79
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfiumCoreKtF.kt
vendored
Normal file
79
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfiumCoreKtF.kt
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
@file:Suppress("unused")
|
||||
|
||||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
import android.os.ParcelFileDescriptor
|
||||
import arrow.core.Either
|
||||
import io.legere.pdfiumandroid.PdfiumCore
|
||||
import io.legere.pdfiumandroid.PdfiumSource
|
||||
import io.legere.pdfiumandroid.util.Config
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
|
||||
/**
|
||||
* PdfiumCoreKtF is the main entry-point for access to the PDFium API.
|
||||
* @property dispatcher the [CoroutineDispatcher] to use for suspending calls
|
||||
* @constructor create a [PdfiumCoreKtF] from a [PdfiumCore]
|
||||
*/
|
||||
class PdfiumCoreKtF(
|
||||
private val dispatcher: CoroutineDispatcher,
|
||||
config: Config = Config(),
|
||||
) {
|
||||
private val coreInternal = PdfiumCore(config = config)
|
||||
|
||||
/**
|
||||
* suspend version of [PdfiumCore.newDocument]
|
||||
*/
|
||||
suspend fun newDocument(fd: ParcelFileDescriptor): Either<PdfiumKtFErrors, PdfDocumentKtF> =
|
||||
wrapEither(dispatcher) {
|
||||
PdfDocumentKtF(coreInternal.newDocument(fd), dispatcher)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfiumCore.newDocument]
|
||||
*/
|
||||
suspend fun newDocument(
|
||||
fd: ParcelFileDescriptor,
|
||||
password: String?,
|
||||
): Either<PdfiumKtFErrors, PdfDocumentKtF> =
|
||||
wrapEither(dispatcher) {
|
||||
PdfDocumentKtF(coreInternal.newDocument(fd, password), dispatcher)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfiumCore.newDocument]
|
||||
*/
|
||||
suspend fun newDocument(data: ByteArray?): Either<PdfiumKtFErrors, PdfDocumentKtF> =
|
||||
wrapEither(dispatcher) {
|
||||
PdfDocumentKtF(coreInternal.newDocument(data), dispatcher)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfiumCore.newDocument]
|
||||
*/
|
||||
suspend fun newDocument(
|
||||
data: ByteArray?,
|
||||
password: String?,
|
||||
): Either<PdfiumKtFErrors, PdfDocumentKtF> =
|
||||
wrapEither(dispatcher) {
|
||||
PdfDocumentKtF(coreInternal.newDocument(data, password), dispatcher)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfiumCore.newDocument]
|
||||
*/
|
||||
suspend fun newDocument(data: PdfiumSource): Either<PdfiumKtFErrors, PdfDocumentKtF> =
|
||||
wrapEither(dispatcher) {
|
||||
PdfDocumentKtF(coreInternal.newDocument(data), dispatcher)
|
||||
}
|
||||
|
||||
/**
|
||||
* suspend version of [PdfiumCore.newDocument]
|
||||
*/
|
||||
suspend fun newDocument(
|
||||
data: PdfiumSource,
|
||||
password: String?,
|
||||
): Either<PdfiumKtFErrors, PdfDocumentKtF> =
|
||||
wrapEither(dispatcher) {
|
||||
PdfDocumentKtF(coreInternal.newDocument(data, password), dispatcher)
|
||||
}
|
||||
}
|
||||
20
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfiumKtFErrors.kt
vendored
Normal file
20
pdfiumandroid/arrow/src/main/java/io/legere/pdfiumandroid/arrow/PdfiumKtFErrors.kt
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package io.legere.pdfiumandroid.arrow
|
||||
|
||||
sealed class PdfiumKtFErrors {
|
||||
data class RuntimeException(
|
||||
val message: String,
|
||||
) : PdfiumKtFErrors()
|
||||
|
||||
data class AlreadyClosed(
|
||||
val message: String,
|
||||
) : PdfiumKtFErrors()
|
||||
|
||||
data object ConstraintError : PdfiumKtFErrors()
|
||||
}
|
||||
|
||||
fun exceptionToPdfiumKtFError(e: Throwable): PdfiumKtFErrors =
|
||||
if (e is IllegalStateException && e.message?.contains("Already closed") == true) {
|
||||
PdfiumKtFErrors.AlreadyClosed(e.message ?: "Unknown error")
|
||||
} else {
|
||||
PdfiumKtFErrors.RuntimeException(e.message ?: "Unknown error")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue