Skip to content

Commit

Permalink
Add libmodpdfium recompiled with metadata and bookmarks support
Browse files Browse the repository at this point in the history
Add methods for retrieving metadata and bookmarks
Comment out native debug messages
Add CHANGELOG
Update README
Update version
  • Loading branch information
barteksc committed Jul 6, 2016
1 parent 3995d83 commit ea97a4b
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 68 deletions.
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## 1.2.0 (2016-07-06)
* `libmodpdfium` compiled with methods for retrieving bookmarks and metadata
* added `PdfiumCore#getDocumentMeta()` for retrieving document metadata
* added `PdfiumCore#getTableOfContents()` for reading whole tree of bookmarks
* comment out native rendering debug

## 1.1.0 (2016-06-27)
* fixed rendering multiple PDFs at the same time thanks to synchronization between instances
* compile Pdfium with SONAME `libmodpdfium` to prevent loading `libpdfium` from Lollipop and higher
* `newDocument()` requires `ParcelFileDescriptor` instead of `FileDescriptor` to keep file descriptor open
* changed method of loading PDFs, which should be more stable

## 1.0.3 (2016-06-17)
* probably fixed bug when pdf should open as normal but was throwing exception
* added much more descriptive exception messages

## 1.0.2 (2016-06-04)
* `newDocument()` throws IOException

## 1.0.1 (2016-06-04)
* fix loading `libpdfium` on devices with < Lollipop

## Initial changes
* Added method for rendering PDF page on bitmap

``` java
void renderPageBitmap(PdfDocument doc, Bitmap bitmap, int pageIndex,
int startX, int startY, int drawSizeX, int drawSizeY);
```
* Added methods to get width and height of page in points (1/72") (like in `PdfRenderer.Page` class):
* `int getPageWidthPoint(PdfDocument doc, int index);`
* `int getPageHeightPoint(PdfDocument doc, int index);`
92 changes: 54 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,61 +5,77 @@ The demo app (for not modified lib) is [here](https://github.com/mshockwave/Pdfi

Forked for use with [AndroidPdfViewer](https://github.com/barteksc/AndroidPdfViewer) project.

## Changes in this fork:
* Added method for rendering PDF page on bitmap

``` java
void renderPageBitmap(PdfDocument doc, Bitmap bitmap, int pageIndex,
int startX, int startY, int drawSizeX, int drawSizeY);
```
* Added methods to get width and height of page in points (1/72") (like in `PdfRenderer.Page` class):
* `int getPageWidthPoint(PdfDocument doc, int index);`
* `int getPageHeightPoint(PdfDocument doc, int index);`
* `newDocument()` throws IOException
* `newDocument()` requires `ParcelFileDescriptor` instead of `FileDescriptor`
* synchronize PdfiumCore between instances, which allows to render multiple PDFs at the same time
* compile Pdfium with SONAME `libmodpdfium` - it ensures that our build of pdfium is not replaced by system version available since Lollipop
API is highly compatible with original version, only additional methods were created.

## What's new in 1.1.0?
* fixed rendering multiple PDFs at the same time thanks to synchronization between instances
* compile Pdfium with SONAME `libmodpdfium`
* `newDocument()` requires `ParcelFileDescriptor` instead of `FileDescriptor` to keep file descriptor open
* changed method of loading PDFs, which should be more stable
## What's new in 1.2.0?
* `libmodpdfium` compiled with methods for retrieving bookmarks and metadata
* added `PdfiumCore#getDocumentMeta` for retrieving document metadata
* added `PdfiumCore#getTableOfContents` for reading whole tree of bookmarks
* comment out native rendering debug

## Installation
Add to _build.gradle_:

`compile 'com.github.barteksc:pdfium-android:1.1.0'`
`compile 'com.github.barteksc:pdfium-android:1.2.0'`

Library is available in jcenter and Maven Central repositories.

## Simple example
``` java
ImageView iv = (ImageView) findViewById(R.id.imageView);
ParcelFileDescriptor fd = ...;
int pageNum = 0;
PdfiumCore pdfiumCore = new PdfiumCore(context);
try {
PdfDocument pdfDocument = pdfiumCore.newDocument(fd);
void openPdf() {
ImageView iv = (ImageView) findViewById(R.id.imageView);
ParcelFileDescriptor fd = ...;
int pageNum = 0;
PdfiumCore pdfiumCore = new PdfiumCore(context);
try {
PdfDocument pdfDocument = pdfiumCore.newDocument(fd);

pdfiumCore.openPage(pdfDocument, pageNum);

int width = pdfiumCore.getPageWidthPoint(pdfDocument, pageNum);
int height = pdfiumCore.getPageHeightPoint(pdfDocument, pageNum);

pdfiumCore.openPage(pdfDocument, pageNum);
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
pdfiumCore.renderPageBitmap(pdfDocument, bitmap, pageNum, 0, 0,
width, height);

int width = pdfiumCore.getPageWidthPoint(pdfDocument, pageNum);
int height = pdfiumCore.getPageHeightPoint(pdfDocument, pageNum);
iv.setImageBitmap(bitmap);

printInfo(pdfiumCore, pdfDocument);

pdfiumCore.closeDocument(pdfDocument); // important!
} catch(IOException ex) {
ex.printStackTrace();
}
}

Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
pdfiumCore.renderPageBitmap(pdfDocument, bitmap, pageNum, 0, 0,
width, height);
public void printInfo(PdfiumCore core, PdfDocument doc) {
PdfDocument.Meta meta = core.getDocumentMeta(doc);
Log.e(TAG, "title = " + meta.getTitle());
Log.e(TAG, "author = " + meta.getAuthor());
Log.e(TAG, "subject = " + meta.getSubject());
Log.e(TAG, "keywords = " + meta.getKeywords());
Log.e(TAG, "creator = " + meta.getCreator());
Log.e(TAG, "producer = " + meta.getProducer());
Log.e(TAG, "creationDate = " + meta.getCreationDate());
Log.e(TAG, "modDate = " + meta.getModDate());

iv.setImageBitmap(bitmap);
printBookmarksTree(core.getTableOfContents(doc), "-");

pdfiumCore.closeDocument(pdfDocument); // important!
} catch(IOException ex) {
ex.printStackTrace();
}

public void printBookmarksTree(List<PdfDocument.Bookmark> tree, String sep) {
for (PdfDocument.Bookmark b : tree) {

Log.e(TAG, String.format("%s %s, p %d", sep, b.getTitle(), b.getPageIdx()));

if (b.hasChildren()) {
printBookmarksTree(b.getChildren(), sep + "-");
}
}
}

```
## Build native part
Go to `PROJECT_PATH/src/main/jni` and run command `$ ndk-build`.
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ ext {
siteUrl = 'https://github.com/barteksc/PdfiumAndroid'
gitUrl = 'https://github.com/barteksc/PdfiumAndroid.git'

libraryVersion = '1.1.0'
libraryVersion = '1.2.0'

developerId = 'barteksc'
developerName = 'Bartosz Schiller'
Expand All @@ -44,7 +44,7 @@ android {
minSdkVersion 9
targetSdkVersion 21
versionCode 1
versionName "1.1.0"
versionName "1.2.0"
}
buildTypes {
release {
Expand Down
69 changes: 68 additions & 1 deletion src/main/java/com/shockwave/pdfium/PdfDocument.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,77 @@
import android.os.ParcelFileDescriptor;
import android.support.v4.util.ArrayMap;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class PdfDocument {
public final Object Lock = new Object();

public static class Meta {
String title;
String author;
String subject;
String keywords;
String creator;
String producer;
String creationDate;
String modDate;

public String getTitle() {
return title;
}

public String getAuthor() {
return author;
}

public String getSubject() {
return subject;
}

public String getKeywords() {
return keywords;
}

public String getCreator() {
return creator;
}

public String getProducer() {
return producer;
}

public String getCreationDate() {
return creationDate;
}

public String getModDate() {
return modDate;
}
}

public static class Bookmark {
private List<Bookmark> children = new ArrayList<>();
String title;
long pageIdx;
long mNativePtr;

public List<Bookmark> getChildren() {
return children;
}

public boolean hasChildren() {
return !children.isEmpty();
}

public String getTitle() {
return title;
}

public long getPageIdx() {
return pageIdx;
}
}

/*package*/ PdfDocument() {
}
Expand Down
61 changes: 57 additions & 4 deletions src/main/java/com/shockwave/pdfium/PdfiumCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class PdfiumCore {
private static final String TAG = PdfiumCore.class.getName();
Expand Down Expand Up @@ -50,6 +52,16 @@ private native void nativeRenderPageBitmap(long pagePtr, Bitmap bitmap, int dpi,
int startX, int startY,
int drawSizeHor, int drawSizeVer);

private native String nativeGetDocumentMetaText(long docPtr, String tag);

private native Long nativeGetFirstChildBookmark(long docPtr, Long bookmarkPtr);

private native Long nativeGetSiblingBookmark(long docPtr, long bookmarkPtr);

private native String nativeGetBookmarkTitle(long bookmarkPtr);

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;
Expand Down Expand Up @@ -100,8 +112,6 @@ public long openPage(PdfDocument doc, int pageIndex) {
long pagePtr;
synchronized (lock) {
pagePtr = nativeLoadPage(doc.mNativeDocPtr, pageIndex);
}
synchronized (doc.Lock) {
doc.mNativePagesPtr.put(pageIndex, pagePtr);
return pagePtr;
}
Expand All @@ -112,8 +122,6 @@ public long[] openPage(PdfDocument doc, int fromIndex, int toIndex) {
long[] pagesPtr;
synchronized (lock) {
pagesPtr = nativeLoadPages(doc.mNativeDocPtr, fromIndex, toIndex);
}
synchronized (doc.Lock) {
int pageIndex = fromIndex;
for (long page : pagesPtr) {
if (pageIndex > toIndex) break;
Expand Down Expand Up @@ -215,4 +223,49 @@ public void closeDocument(PdfDocument doc) {
doc.parcelFileDescriptor = null;
}
}

public PdfDocument.Meta getDocumentMeta(PdfDocument doc) {
synchronized (lock) {
PdfDocument.Meta meta = new PdfDocument.Meta();
meta.title = nativeGetDocumentMetaText(doc.mNativeDocPtr, "Title");
meta.author = nativeGetDocumentMetaText(doc.mNativeDocPtr, "Author");
meta.subject = nativeGetDocumentMetaText(doc.mNativeDocPtr, "Subject");
meta.keywords = nativeGetDocumentMetaText(doc.mNativeDocPtr, "Keywords");
meta.creator = nativeGetDocumentMetaText(doc.mNativeDocPtr, "Creator");
meta.producer = nativeGetDocumentMetaText(doc.mNativeDocPtr, "Producer");
meta.creationDate = nativeGetDocumentMetaText(doc.mNativeDocPtr, "CreationDate");
meta.modDate = nativeGetDocumentMetaText(doc.mNativeDocPtr, "ModDate");

return meta;
}
}

public List<PdfDocument.Bookmark> getTableOfContents(PdfDocument doc) {
synchronized (lock) {
List<PdfDocument.Bookmark> topLevel = new ArrayList<>();
Long first = nativeGetFirstChildBookmark(doc.mNativeDocPtr, null);
if (first != null) {
recursiveGetBookmark(topLevel, doc, first);
}
return topLevel;
}
}

private void recursiveGetBookmark(List<PdfDocument.Bookmark> tree, PdfDocument doc, long bookmarkPtr) {
PdfDocument.Bookmark bookmark = new PdfDocument.Bookmark();
bookmark.mNativePtr = bookmarkPtr;
bookmark.title = nativeGetBookmarkTitle(bookmarkPtr);
bookmark.pageIdx = nativeGetBookmarkDestIndex(doc.mNativeDocPtr, bookmarkPtr);
tree.add(bookmark);

Long child = nativeGetFirstChildBookmark(doc.mNativeDocPtr, bookmarkPtr);
if (child != null) {
recursiveGetBookmark(bookmark.getChildren(), doc, child);
}

Long sibling = nativeGetSiblingBookmark(doc.mNativeDocPtr, bookmarkPtr);
if (sibling != null) {
recursiveGetBookmark(tree, doc, sibling);
}
}
}
41 changes: 40 additions & 1 deletion src/main/jni/include/fpdfdoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,45 @@
extern "C" {
#endif

// Function: FPDFBookmark_GetFirstChild
// Get the first child of a bookmark item, or the first top level bookmark item.
// Parameters:
// document - Handle to the document. Returned by FPDF_LoadDocument or FPDF_LoadMemDocument.
// bookmark - Handle to the current bookmark. Can be NULL if you want to get the first top level item.
// Return value:
// Handle to the first child or top level bookmark item. NULL if no child or top level bookmark found.
//
DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark);

// Function: FPDFBookmark_GetNextSibling
// Get next bookmark item at the same level.
// Parameters:
// document - Handle to the document. Returned by FPDF_LoadDocument or FPDF_LoadMemDocument.
// bookmark - Handle to the current bookmark. Cannot be NULL.
// Return value:
// Handle to the next bookmark item at the same level. NULL if this is the last bookmark at this level.
//
DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark);

// Function: FPDFBookmark_GetTitle
// Get title of a bookmark.
// Parameters:
// bookmark - Handle to the bookmark.
// buffer - Buffer for the title. Can be NULL.
// buflen - The length of the buffer in bytes. Can be 0.
// Return value:
// Number of bytes the title consumes, including trailing zeros.
// Comments:
// Regardless of the platform, the title is always in UTF-16LE encoding. That means the buffer
// can be treated as an array of WORD (on Intel and compatible CPUs), each WORD representing the Unicode of
// a character(some special Unicode may take 2 WORDs).The string is followed by two bytes of zero
// indicating the end of the string.
//
// The return value always indicates the number of bytes required for the buffer, even if no buffer is specified
// or the buffer size is less then required. In these cases, the buffer will not be modified.
//
DLLEXPORT unsigned long STDCALL FPDFBookmark_GetTitle(FPDF_BOOKMARK bookmark, void* buffer, unsigned long buflen);

// Function: FPDFBookmark_Find
// Find a bookmark in the document, using the bookmark title.
// Parameters:
Expand Down Expand Up @@ -152,7 +191,7 @@ DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK link);
DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page, int* startPos, FPDF_LINK* linkAnnot);

// Function: FPDFLink_GetAnnotRect
// Get the annotation rectangle. (Specified by the ¡°Rect¡± entry of annotation dictionary).
// Get the annotation rectangle. (Specified by the ��Rect�� entry of annotation dictionary).
// Parameters:
// linkAnnot[in] - Handle to the link annotation.
// rect[out] - The annotation rect.
Expand Down
Binary file modified src/main/jni/lib/arm64/libmodpdfium.so
Binary file not shown.
Binary file modified src/main/jni/lib/armeabi/libmodpdfium.so
Binary file not shown.
Binary file modified src/main/jni/lib/mips/libmodpdfium.so
Binary file not shown.
Binary file modified src/main/jni/lib/x86/libmodpdfium.so
Binary file not shown.
Binary file modified src/main/jni/lib/x86_64/libmodpdfium.so
Binary file not shown.
Loading

0 comments on commit ea97a4b

Please sign in to comment.