diff --git a/CHANGELOG.md b/CHANGELOG.md index b2e7015..76c2f65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.8.0 (2017-11-11) +* Add method for reading links from given page +* Add method for mapping page coordinates to screen coordinates +* Add `PdfiumCore#getPageSize(...)` method, which does not require page to be opened +* Add `Size` and `SizeF` utility classes +* Add javadoc comments to `PdfiumCore` + ## 1.7.1 (2017-10-28) * Merge pull request by [Phaestion](https://github.com/Phaestion) which prevents `UnsatisfiedLinkError` diff --git a/README.md b/README.md index fcc8f86..06183a7 100644 --- a/README.md +++ b/README.md @@ -7,18 +7,57 @@ Forked for use with [AndroidPdfViewer](https://github.com/barteksc/AndroidPdfVie API is highly compatible with original version, only additional methods were created. -## What's new in 1.7.0? -* Add rendering bitmap in RGB 565 format, which reduces memory usage (about twice) - -1.7.1 merges pull request by [Phaestion](https://github.com/Phaestion) which prevents `UnsatisfiedLinkError` +## What's new in 1.8.0? +* Add method for reading links from given page +* Add method for mapping page coordinates to screen coordinates +* Add `PdfiumCore#getPageSize(...)` method, which does not require page to be opened +* Add `Size` and `SizeF` utility classes +* Add javadoc comments to `PdfiumCore` ## Installation Add to _build.gradle_: -`compile 'com.github.barteksc:pdfium-android:1.7.1'` +`compile 'com.github.barteksc:pdfium-android:1.8.0'` Library is available in jcenter and Maven Central repositories. +## Methods inconsistency +Version 1.8.0 added method for getting page size - `PdfiumCore#getPageSize(...)`. +It is important to note, that this method does not require page to be opened. However, there are also +old `PdfiumCore#getPageWidth(...)`, `PdfiumCore#getPageWidthPoint(...)`, `PdfiumCore#getPageHeight()` +and `PdfiumCore#getPageHeightPoint()` which require page to be opened. + +This inconsistency will be resolved in next major version, which aims to redesign API. + +## Reading links +Version 1.8.0 introduces `PdfiumCore#getPageLinks(PdfDocument, int)` method, which allows to get list +of links from given page. Links are returned as `List` of type `PdfDocument.Link`. +`PdfDocument.Link` holds destination page (may be null), action URI (may be null or empty) +and link bounds in document page coordinates. To map page coordinates to screen coordinates you may use +`PdfiumCore#mapRectToDevice(...)`. See `PdfiumCore#mapPageCoordsToDevice(...)` for parameters description. + +Sample usage: +``` java +PdfiumCore core = ...; +PdfDocument document = ...; +int pageIndex = 0; +core.openPage(document, pageIndex); +List links = core.getPageLinks(document, pageIndex); +for (PdfDocument.Link link : links) { + RectF mappedRect = core.mapRectToDevice(document, pageIndex, ..., link.getBounds()) + + if (clickedArea(mappedRect)) { + String uri = link.getUri(); + if (link.getDestPageIdx() != null) { + // jump to page + } else if (uri != null && !uri.isEmpty()) { + // open URI using Intent + } + } +} + +``` + ## Simple example ``` java void openPdf() { diff --git a/build.gradle b/build.gradle index 774e2db..ceb37f1 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ ext { siteUrl = 'https://github.com/barteksc/PdfiumAndroid' gitUrl = 'https://github.com/barteksc/PdfiumAndroid.git' - libraryVersion = '1.7.1' + libraryVersion = '1.8.0' developerId = 'barteksc' developerName = 'Bartosz Schiller' @@ -44,7 +44,7 @@ android { minSdkVersion 9 targetSdkVersion 25 versionCode 1 - versionName "1.7.1" + versionName "1.8.0" } buildTypes { release { diff --git a/src/main/java/com/shockwave/pdfium/PdfDocument.java b/src/main/java/com/shockwave/pdfium/PdfDocument.java index ecacadb..b5306a6 100644 --- a/src/main/java/com/shockwave/pdfium/PdfDocument.java +++ b/src/main/java/com/shockwave/pdfium/PdfDocument.java @@ -1,5 +1,6 @@ package com.shockwave.pdfium; +import android.graphics.RectF; import android.os.ParcelFileDescriptor; import android.support.v4.util.ArrayMap; @@ -75,6 +76,30 @@ public long getPageIdx() { } } + public static class Link { + private RectF bounds; + private Integer destPageIdx; + private String uri; + + public Link(RectF bounds, Integer destPageIdx, String uri) { + this.bounds = bounds; + this.destPageIdx = destPageIdx; + this.uri = uri; + } + + public Integer getDestPageIdx() { + return destPageIdx; + } + + public String getUri() { + return uri; + } + + public RectF getBounds() { + return bounds; + } + } + /*package*/ PdfDocument() { } diff --git a/src/main/java/com/shockwave/pdfium/PdfiumCore.java b/src/main/java/com/shockwave/pdfium/PdfiumCore.java index 6e84455..07b2a04 100644 --- a/src/main/java/com/shockwave/pdfium/PdfiumCore.java +++ b/src/main/java/com/shockwave/pdfium/PdfiumCore.java @@ -2,10 +2,14 @@ import android.content.Context; import android.graphics.Bitmap; +import android.graphics.Point; +import android.graphics.RectF; import android.os.ParcelFileDescriptor; import android.util.Log; import android.view.Surface; +import com.shockwave.pdfium.util.Size; + import java.io.FileDescriptor; import java.io.IOException; import java.lang.reflect.Field; @@ -14,6 +18,8 @@ public class PdfiumCore { private static final String TAG = PdfiumCore.class.getName(); + private static final Class FD_CLASS = FileDescriptor.class; + private static final String FD_FIELD_NAME = "descriptor"; static { try { @@ -72,18 +78,24 @@ private native void nativeRenderPageBitmap(long pagePtr, Bitmap bitmap, int dpi, private native long nativeGetBookmarkDestIndex(long docPtr, long bookmarkPtr); - private static final Class FD_CLASS = FileDescriptor.class; - private static final String FD_FIELD_NAME = "descriptor"; - private static Field mFdField = null; + private native Size nativeGetPageSizeByIndex(long docPtr, int pageIndex, int dpi); + + private native long[] nativeGetPageLinks(long pagePtr); + + private native Integer nativeGetDestPageIndex(long docPtr, long linkPtr); + + private native String nativeGetLinkURI(long docPtr, long linkPtr); + + private native RectF nativeGetLinkRect(long linkPtr); + + private native Point nativePageCoordsToDevice(long pagePtr, int startX, int startY, int sizeX, + int sizeY, int rotate, double pageX, double pageY); - private int mCurrentDpi; /* synchronize native methods */ private static final Object lock = new Object(); - - public PdfiumCore(Context ctx) { - mCurrentDpi = ctx.getResources().getDisplayMetrics().densityDpi; - } + private static Field mFdField = null; + private int mCurrentDpi; public static int getNumFd(ParcelFileDescriptor fdObj) { try { @@ -102,10 +114,18 @@ public static int getNumFd(ParcelFileDescriptor fdObj) { } } + + /** Context needed to get screen density */ + public PdfiumCore(Context ctx) { + mCurrentDpi = ctx.getResources().getDisplayMetrics().densityDpi; + } + + /** Create new document from file */ public PdfDocument newDocument(ParcelFileDescriptor fd) throws IOException { return newDocument(fd, null); } + /** Create new document from file with password */ public PdfDocument newDocument(ParcelFileDescriptor fd, String password) throws IOException { PdfDocument document = new PdfDocument(); document.parcelFileDescriptor = fd; @@ -116,10 +136,12 @@ public PdfDocument newDocument(ParcelFileDescriptor fd, String password) throws return document; } + /** Create new document from bytearray */ public PdfDocument newDocument(byte[] data) throws IOException { return newDocument(data, null); } + /** Create new document from bytearray with password */ public PdfDocument newDocument(byte[] data, String password) throws IOException { PdfDocument document = new PdfDocument(); synchronized (lock) { @@ -128,12 +150,14 @@ public PdfDocument newDocument(byte[] data, String password) throws IOException return document; } + /** Get total numer of pages in document */ public int getPageCount(PdfDocument doc) { synchronized (lock) { return nativeGetPageCount(doc.mNativeDocPtr); } } + /** Open page and store native pointer in {@link PdfDocument} */ public long openPage(PdfDocument doc, int pageIndex) { long pagePtr; synchronized (lock) { @@ -144,6 +168,7 @@ public long openPage(PdfDocument doc, int pageIndex) { } + /** Open range of pages and store native pointers in {@link PdfDocument} */ public long[] openPage(PdfDocument doc, int fromIndex, int toIndex) { long[] pagesPtr; synchronized (lock) { @@ -159,6 +184,10 @@ public long[] openPage(PdfDocument doc, int fromIndex, int toIndex) { } } + /** + * Get page width in pixels.
+ * This method requires page to be opened. + */ public int getPageWidth(PdfDocument doc, int index) { synchronized (lock) { Long pagePtr; @@ -169,6 +198,10 @@ public int getPageWidth(PdfDocument doc, int index) { } } + /** + * Get page height in pixels.
+ * This method requires page to be opened. + */ public int getPageHeight(PdfDocument doc, int index) { synchronized (lock) { Long pagePtr; @@ -179,6 +212,10 @@ public int getPageHeight(PdfDocument doc, int index) { } } + /** + * Get page width in PostScript points (1/72th of an inch).
+ * This method requires page to be opened. + */ public int getPageWidthPoint(PdfDocument doc, int index) { synchronized (lock) { Long pagePtr; @@ -189,6 +226,10 @@ public int getPageWidthPoint(PdfDocument doc, int index) { } } + /** + * Get page height in PostScript points (1/72th of an inch).
+ * This method requires page to be opened. + */ public int getPageHeightPoint(PdfDocument doc, int index) { synchronized (lock) { Long pagePtr; @@ -199,11 +240,29 @@ public int getPageHeightPoint(PdfDocument doc, int index) { } } + /** + * Get size of page in pixels.
+ * This method does not require given page to be opened. + */ + public Size getPageSize(PdfDocument doc, int index) { + synchronized (lock) { + return nativeGetPageSizeByIndex(doc.mNativeDocPtr, index, mCurrentDpi); + } + } + + /** + * Render page fragment on {@link Surface}.
+ * Page must be opened before rendering. + */ public void renderPage(PdfDocument doc, Surface surface, int pageIndex, int startX, int startY, int drawSizeX, int drawSizeY) { renderPage(doc, surface, pageIndex, startX, startY, drawSizeX, drawSizeY, false); } + /** + * Render page fragment on {@link Surface}. This method allows to render annotations.
+ * Page must be opened before rendering. + */ public void renderPage(PdfDocument doc, Surface surface, int pageIndex, int startX, int startY, int drawSizeX, int drawSizeY, boolean renderAnnot) { @@ -222,11 +281,27 @@ public void renderPage(PdfDocument doc, Surface surface, int pageIndex, } } + /** + * Render page fragment on {@link Bitmap}.
+ * Page must be opened before rendering. + *

+ * Supported bitmap configurations: + *

+ */ public void renderPageBitmap(PdfDocument doc, Bitmap bitmap, int pageIndex, int startX, int startY, int drawSizeX, int drawSizeY) { renderPageBitmap(doc, bitmap, pageIndex, startX, startY, drawSizeX, drawSizeY, false); } + /** + * Render page fragment on {@link Bitmap}. This method allows to render annotations.
+ * Page must be opened before rendering. + *

+ * For more info see {@link PdfiumCore#renderPageBitmap(PdfDocument, Bitmap, int, int, int, int, int)} + */ public void renderPageBitmap(PdfDocument doc, Bitmap bitmap, int pageIndex, int startX, int startY, int drawSizeX, int drawSizeY, boolean renderAnnot) { @@ -244,6 +319,7 @@ public void renderPageBitmap(PdfDocument doc, Bitmap bitmap, int pageIndex, } } + /** Release native resources and opened file */ public void closeDocument(PdfDocument doc) { synchronized (lock) { for (Integer index : doc.mNativePagesPtr.keySet()) { @@ -264,6 +340,7 @@ public void closeDocument(PdfDocument doc) { } } + /** Get metadata for given document */ public PdfDocument.Meta getDocumentMeta(PdfDocument doc) { synchronized (lock) { PdfDocument.Meta meta = new PdfDocument.Meta(); @@ -280,6 +357,7 @@ public PdfDocument.Meta getDocumentMeta(PdfDocument doc) { } } + /** Get table of contents (bookmarks) for given document */ public List getTableOfContents(PdfDocument doc) { synchronized (lock) { List topLevel = new ArrayList<>(); @@ -308,4 +386,58 @@ private void recursiveGetBookmark(List tree, PdfDocument d recursiveGetBookmark(tree, doc, sibling); } } + + /** Get all links from given page */ + public List getPageLinks(PdfDocument doc, int pageIndex) { + synchronized (lock) { + List links = new ArrayList<>(); + long[] linkPtrs = nativeGetPageLinks(doc.mNativePagesPtr.get(pageIndex)); + for (long linkPtr : linkPtrs) { + Integer index = nativeGetDestPageIndex(doc.mNativeDocPtr, linkPtr); + String uri = nativeGetLinkURI(doc.mNativeDocPtr, linkPtr); + + RectF rect = nativeGetLinkRect(linkPtr); + if (rect != null && (index != null || uri != null)) { + links.add(new PdfDocument.Link(rect, index, uri)); + } + + } + return links; + } + } + + /** + * Map page coordinates to device screen coordinates + * + * @param doc pdf document + * @param pageIndex index of page + * @param startX left pixel position of the display area in device coordinates + * @param startY top pixel position of the display area in device coordinates + * @param sizeX horizontal size (in pixels) for displaying the page + * @param sizeY vertical size (in pixels) for displaying the page + * @param rotate page orientation: 0 (normal), 1 (rotated 90 degrees clockwise), + * 2 (rotated 180 degrees), 3 (rotated 90 degrees counter-clockwise) + * @param pageX X value in page coordinates + * @param pageY Y value in page coordinate + * @return mapped coordinates + */ + public Point mapPageCoordsToDevice(PdfDocument doc, int pageIndex, int startX, int startY, int sizeX, + int sizeY, int rotate, double pageX, double pageY) { + long pagePtr = doc.mNativePagesPtr.get(pageIndex); + return nativePageCoordsToDevice(pagePtr, startX, startY, sizeX, sizeY, rotate, pageX, pageY); + } + + /** + * @see PdfiumCore#mapPageCoordsToDevice(PdfDocument, int, int, int, int, int, int, double, double) + * @return mapped coordinates + */ + public RectF mapRectToDevice(PdfDocument doc, int pageIndex, int startX, int startY, int sizeX, + int sizeY, int rotate, RectF coords) { + + Point leftTop = mapPageCoordsToDevice(doc, pageIndex, startX, startY, sizeX, sizeY, rotate, + coords.left, coords.top); + Point rightBottom = mapPageCoordsToDevice(doc, pageIndex, startX, startY, sizeX, sizeY, rotate, + coords.right, coords.bottom); + return new RectF(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y); + } } diff --git a/src/main/java/com/shockwave/pdfium/util/Size.java b/src/main/java/com/shockwave/pdfium/util/Size.java new file mode 100644 index 0000000..2cd11b3 --- /dev/null +++ b/src/main/java/com/shockwave/pdfium/util/Size.java @@ -0,0 +1,45 @@ +package com.shockwave.pdfium.util; + +public class Size { + private final int width; + private final int height; + + public Size(int width, int height) { + this.width = width; + this.height = height; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + if (obj instanceof Size) { + Size other = (Size) obj; + return width == other.width && height == other.height; + } + return false; + } + + @Override + public String toString() { + return width + "x" + height; + } + + @Override + public int hashCode() { + // assuming most sizes are <2^16, doing a rotate will give us perfect hashing + return height ^ ((width << (Integer.SIZE / 2)) | (width >>> (Integer.SIZE / 2))); + } +} diff --git a/src/main/java/com/shockwave/pdfium/util/SizeF.java b/src/main/java/com/shockwave/pdfium/util/SizeF.java new file mode 100644 index 0000000..3f6161a --- /dev/null +++ b/src/main/java/com/shockwave/pdfium/util/SizeF.java @@ -0,0 +1,48 @@ +package com.shockwave.pdfium.util; + +public class SizeF { + private final float width; + private final float height; + + public SizeF(float width, float height) { + this.width = width; + this.height = height; + } + + public float getWidth() { + return width; + } + + public float getHeight() { + return height; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + if (obj instanceof SizeF) { + final SizeF other = (SizeF) obj; + return width == other.width && height == other.height; + } + return false; + } + + @Override + public String toString() { + return width + "x" + height; + } + + @Override + public int hashCode() { + return Float.floatToIntBits(width) ^ Float.floatToIntBits(height); + } + + public Size toSize() { + return new Size((int) width, (int) height); + } +} diff --git a/src/main/jni/src/mainJNILib.cpp b/src/main/jni/src/mainJNILib.cpp index 55a9bee..92efb64 100644 --- a/src/main/jni/src/mainJNILib.cpp +++ b/src/main/jni/src/mainJNILib.cpp @@ -17,6 +17,7 @@ using namespace android; #include #include #include +#include static Mutex sLibraryLock; @@ -141,6 +142,12 @@ jobject NewLong(JNIEnv* env, jlong value) { return env->NewObject(cls, methodID, value); } +jobject NewInteger(JNIEnv* env, jint value) { + jclass cls = env->FindClass("java/lang/Integer"); + jmethodID methodID = env->GetMethodID(cls, "", "(I)V"); + return env->NewObject(cls, methodID, value); +} + uint16_t rgbTo565(rgb *color) { return ((color->red >> 3) << 11) | ((color->green >> 2) << 5) | (color->blue >> 3); } @@ -342,14 +349,34 @@ JNI_FUNC(jint, PdfiumCore, nativeGetPageHeightPixel)(JNI_ARGS, jlong pagePtr, ji return (jint)(FPDF_GetPageHeight(page) * dpi / 72); } -JNI_FUNC(jint, PdfiumCore, nativeGetPageWidthPoint)(JNI_ARGS, jlong pagePtr, jint dpi){ +JNI_FUNC(jint, PdfiumCore, nativeGetPageWidthPoint)(JNI_ARGS, jlong pagePtr){ FPDF_PAGE page = reinterpret_cast(pagePtr); return (jint)FPDF_GetPageWidth(page); } -JNI_FUNC(jint, PdfiumCore, nativeGetPageHeightPoint)(JNI_ARGS, jlong pagePtr, jint dpi){ +JNI_FUNC(jint, PdfiumCore, nativeGetPageHeightPoint)(JNI_ARGS, jlong pagePtr){ FPDF_PAGE page = reinterpret_cast(pagePtr); return (jint)FPDF_GetPageHeight(page); } +JNI_FUNC(jobject, PdfiumCore, nativeGetPageSizeByIndex)(JNI_ARGS, jlong docPtr, jint pageIndex, jint dpi){ + DocumentFile *doc = reinterpret_cast(docPtr); + if(doc == NULL) { + LOGE("Document is null"); + + jniThrowException(env, "java/lang/IllegalStateException", + "Document is null"); + return NULL; + } + + double width, height; + FPDF_GetPageSizeByIndex(doc->pdfDocument, pageIndex, &width, &height); + + jint widthInt = (jint) (width * dpi / 72); + jint heightInt = (jint) (height * dpi / 72); + + jclass clazz = env->FindClass("com/shockwave/pdfium/util/Size"); + jmethodID constructorID = env->GetMethodID(clazz, "", "(II)V"); + return env->NewObject(clazz, constructorID, widthInt, heightInt); +} static void renderPageInternal( FPDF_PAGE page, ANativeWindow_Buffer *windowBuffer, @@ -528,14 +555,14 @@ JNI_FUNC(jstring, PdfiumCore, nativeGetDocumentMetaText)(JNI_ARGS, jlong docPtr, } DocumentFile *doc = reinterpret_cast(docPtr); - size_t buffer_bytes = FPDF_GetMetaText(doc->pdfDocument, ctag, NULL, 0); - if (buffer_bytes <= 2) { + size_t bufferLen = FPDF_GetMetaText(doc->pdfDocument, ctag, NULL, 0); + if (bufferLen <= 2) { return env->NewStringUTF(""); } std::wstring text; - FPDF_GetMetaText(doc->pdfDocument, ctag, WriteInto(&text, buffer_bytes + 1), buffer_bytes); + FPDF_GetMetaText(doc->pdfDocument, ctag, WriteInto(&text, bufferLen + 1), bufferLen); env->ReleaseStringUTFChars(tag, ctag); - return env->NewString((jchar*) text.c_str(), buffer_bytes / 2 - 1); + return env->NewString((jchar*) text.c_str(), bufferLen / 2 - 1); } JNI_FUNC(jobject, PdfiumCore, nativeGetFirstChildBookmark)(JNI_ARGS, jlong docPtr, jobject bookmarkPtr) { @@ -569,13 +596,13 @@ JNI_FUNC(jobject, PdfiumCore, nativeGetSiblingBookmark)(JNI_ARGS, jlong docPtr, JNI_FUNC(jstring, PdfiumCore, nativeGetBookmarkTitle)(JNI_ARGS, jlong bookmarkPtr) { FPDF_BOOKMARK bookmark = reinterpret_cast(bookmarkPtr); - size_t buffer_bytes = FPDFBookmark_GetTitle(bookmark, NULL, 0); - if (buffer_bytes <= 2) { + size_t bufferLen = FPDFBookmark_GetTitle(bookmark, NULL, 0); + if (bufferLen <= 2) { return env->NewStringUTF(""); } std::wstring title; - FPDFBookmark_GetTitle(bookmark, WriteInto(&title, buffer_bytes + 1), buffer_bytes); - return env->NewString((jchar*) title.c_str(), buffer_bytes / 2 - 1); + FPDFBookmark_GetTitle(bookmark, WriteInto(&title, bufferLen + 1), bufferLen); + return env->NewString((jchar*) title.c_str(), bufferLen / 2 - 1); } JNI_FUNC(jlong, PdfiumCore, nativeGetBookmarkDestIndex)(JNI_ARGS, jlong docPtr, jlong bookmarkPtr) { @@ -589,4 +616,71 @@ JNI_FUNC(jlong, PdfiumCore, nativeGetBookmarkDestIndex)(JNI_ARGS, jlong docPtr, return (jlong) FPDFDest_GetPageIndex(doc->pdfDocument, dest); } +JNI_FUNC(jlongArray, PdfiumCore, nativeGetPageLinks)(JNI_ARGS, jlong pagePtr) { + FPDF_PAGE page = reinterpret_cast(pagePtr); + int pos = 0; + std::vector links; + FPDF_LINK link; + while (FPDFLink_Enumerate(page, &pos, &link)) { + links.push_back(reinterpret_cast(link)); + } + + jlongArray result = env->NewLongArray(links.size()); + env->SetLongArrayRegion(result, 0, links.size(), &links[0]); + return result; +} + +JNI_FUNC(jobject, PdfiumCore, nativeGetDestPageIndex)(JNI_ARGS, jlong docPtr, jlong linkPtr) { + DocumentFile *doc = reinterpret_cast(docPtr); + FPDF_LINK link = reinterpret_cast(linkPtr); + FPDF_DEST dest = FPDFLink_GetDest(doc->pdfDocument, link); + if (dest == NULL) { + return NULL; + } + unsigned long index = FPDFDest_GetPageIndex(doc->pdfDocument, dest); + return NewInteger(env, (jint) index); +} + +JNI_FUNC(jstring, PdfiumCore, nativeGetLinkURI)(JNI_ARGS, jlong docPtr, jlong linkPtr){ + DocumentFile *doc = reinterpret_cast(docPtr); + FPDF_LINK link = reinterpret_cast(linkPtr); + FPDF_ACTION action = FPDFLink_GetAction(link); + if (action == NULL) { + return NULL; + } + size_t bufferLen = FPDFAction_GetURIPath(doc->pdfDocument, action, NULL, 0); + if (bufferLen <= 0) { + return env->NewStringUTF(""); + } + std::string uri; + FPDFAction_GetURIPath(doc->pdfDocument, action, WriteInto(&uri, bufferLen), bufferLen); + return env->NewStringUTF(uri.c_str()); +} + +JNI_FUNC(jobject, PdfiumCore, nativeGetLinkRect)(JNI_ARGS, jlong linkPtr) { + FPDF_LINK link = reinterpret_cast(linkPtr); + FS_RECTF fsRectF; + FPDF_BOOL result = FPDFLink_GetAnnotRect(link, &fsRectF); + + if (!result) { + return NULL; + } + + jclass clazz = env->FindClass("android/graphics/RectF"); + jmethodID constructorID = env->GetMethodID(clazz, "", "(FFFF)V"); + return env->NewObject(clazz, constructorID, fsRectF.left, fsRectF.top, fsRectF.right, fsRectF.bottom); +} + +JNI_FUNC(jobject, PdfiumCore, nativePageCoordsToDevice)(JNI_ARGS, jlong pagePtr, jint startX, jint startY, jint sizeX, + jint sizeY, jint rotate, jdouble pageX, jdouble pageY) { + FPDF_PAGE page = reinterpret_cast(pagePtr); + int deviceX, deviceY; + + FPDF_PageToDevice(page, startX, startY, sizeX, sizeY, rotate, pageX, pageY, &deviceX, &deviceY); + + jclass clazz = env->FindClass("android/graphics/Point"); + jmethodID constructorID = env->GetMethodID(clazz, "", "(II)V"); + return env->NewObject(clazz, constructorID, deviceX, deviceY); +} + }//extern C