Layout EPUB to match screen size, and reflow when changing orientation.

Handle screen rotation without restarting activity!

Add text size popup menu for EPUB documents.
diff --git a/lib/src/main/AndroidManifest.xml b/lib/src/main/AndroidManifest.xml
index 7ca0faf..61a9707 100644
--- a/lib/src/main/AndroidManifest.xml
+++ b/lib/src/main/AndroidManifest.xml
@@ -5,6 +5,7 @@
 	<application>
 		<activity
 			android:name=".DocumentActivity"
+			android:configChanges="orientation|screenSize|keyboardHidden"
 			>
 			<intent-filter>
 				<action android:name="android.intent.action.VIEW" />
diff --git a/lib/src/main/java/com/artifex/mupdf/viewer/DocumentActivity.java b/lib/src/main/java/com/artifex/mupdf/viewer/DocumentActivity.java
index c5470d2..382b6a9 100644
--- a/lib/src/main/java/com/artifex/mupdf/viewer/DocumentActivity.java
+++ b/lib/src/main/java/com/artifex/mupdf/viewer/DocumentActivity.java
@@ -77,6 +77,13 @@
 	private AlertDialog mAlertDialog;
 	private ArrayList<OutlineActivity.Item> mFlatOutline;
 
+	private int mLayoutEM = 10;
+	private int mLayoutW = 312;
+	private int mLayoutH = 504;
+
+	protected View mLayoutButton;
+	protected PopupMenu mLayoutPopupMenu;
+
 	private MuPDFCore openFile(String path)
 	{
 		int lastSlashPos = path.lastIndexOf('/');
@@ -234,6 +241,14 @@
 		alert.show();
 	}
 
+	public void relayoutDocument() {
+		int loc = core.layout(mDocView.mCurrent, mLayoutW, mLayoutH, mLayoutEM);
+		mFlatOutline = null;
+		mDocView.mHistory.clear();
+		mDocView.refresh();
+		mDocView.setDisplayedViewIndex(loc);
+	}
+
 	public void createUI(Bundle savedInstanceState) {
 		if (core == null)
 			return;
@@ -266,6 +281,17 @@
 			protected void onDocMotion() {
 				hideButtons();
 			}
+
+			@Override
+			public void onSizeChanged(int w, int h, int oldw, int oldh) {
+				if (core.isReflowable()) {
+					mLayoutW = w * 72 / 160;
+					mLayoutH = h * 72 / 160;
+					relayoutDocument();
+				} else {
+					refresh();
+				}
+			}
 		};
 		mDocView.setAdapter(new PageAdapter(this, core));
 
@@ -385,6 +411,37 @@
 			}
 		});
 
+		if (core.isReflowable()) {
+			mLayoutButton.setVisibility(View.VISIBLE);
+			mLayoutPopupMenu = new PopupMenu(this, mLayoutButton);
+			mLayoutPopupMenu.getMenuInflater().inflate(R.menu.layout_menu, mLayoutPopupMenu.getMenu());
+			mLayoutPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+				public boolean onMenuItemClick(MenuItem item) {
+					float oldLayoutEM = mLayoutEM;
+					int id = item.getItemId();
+					if (id == R.id.action_layout_6pt) mLayoutEM = 6;
+					else if (id == R.id.action_layout_7pt) mLayoutEM = 7;
+					else if (id == R.id.action_layout_8pt) mLayoutEM = 8;
+					else if (id == R.id.action_layout_9pt) mLayoutEM = 9;
+					else if (id == R.id.action_layout_10pt) mLayoutEM = 10;
+					else if (id == R.id.action_layout_11pt) mLayoutEM = 11;
+					else if (id == R.id.action_layout_12pt) mLayoutEM = 12;
+					else if (id == R.id.action_layout_13pt) mLayoutEM = 13;
+					else if (id == R.id.action_layout_14pt) mLayoutEM = 14;
+					else if (id == R.id.action_layout_15pt) mLayoutEM = 15;
+					else if (id == R.id.action_layout_16pt) mLayoutEM = 16;
+					if (oldLayoutEM != mLayoutEM)
+						relayoutDocument();
+					return true;
+				}
+			});
+			mLayoutButton.setOnClickListener(new View.OnClickListener() {
+				public void onClick(View v) {
+					mLayoutPopupMenu.show();
+				}
+			});
+		}
+
 		if (core.hasOutline()) {
 			mOutlineButton.setOnClickListener(new View.OnClickListener() {
 				public void onClick(View v) {
@@ -615,6 +672,7 @@
 		mSearchClose = (ImageButton)mButtonsView.findViewById(R.id.searchClose);
 		mSearchText = (EditText)mButtonsView.findViewById(R.id.searchText);
 		mLinkButton = (ImageButton)mButtonsView.findViewById(R.id.linkButton);
+		mLayoutButton = mButtonsView.findViewById(R.id.layoutButton);
 		mTopBarSwitcher.setVisibility(View.INVISIBLE);
 		mPageNumberView.setVisibility(View.INVISIBLE);
 
diff --git a/lib/src/main/java/com/artifex/mupdf/viewer/MuPDFCore.java b/lib/src/main/java/com/artifex/mupdf/viewer/MuPDFCore.java
index 40c62be..ad08a73 100644
--- a/lib/src/main/java/com/artifex/mupdf/viewer/MuPDFCore.java
+++ b/lib/src/main/java/com/artifex/mupdf/viewer/MuPDFCore.java
@@ -30,8 +30,14 @@
 	private float pageHeight;
 	private DisplayList displayList;
 
+	/* Default to "A Format" pocket book size. */
+	private int layoutW = 312;
+	private int layoutH = 504;
+	private int layoutEM = 10;
+
 	public MuPDFCore(String filename) {
 		doc = Document.openDocument(filename);
+		doc.layout(layoutW, layoutH, layoutEM);
 		pageCount = doc.countPages();
 		resolution = 160;
 		currentPage = -1;
@@ -39,6 +45,7 @@
 
 	public MuPDFCore(byte buffer[], String magic) {
 		doc = Document.openDocument(buffer, magic);
+		doc.layout(layoutW, layoutH, layoutEM);
 		pageCount = doc.countPages();
 		resolution = 160;
 		currentPage = -1;
@@ -52,6 +59,31 @@
 		return pageCount;
 	}
 
+	public synchronized boolean isReflowable() {
+		return doc.isReflowable();
+	}
+
+	public synchronized int layout(int oldPage, int w, int h, int em) {
+		if (w != layoutW || h != layoutH || em != layoutEM) {
+			System.out.println("LAYOUT: " + w + "," + h);
+			layoutW = w;
+			layoutH = h;
+			layoutEM = em;
+			long mark = doc.makeBookmark(oldPage);
+			doc.layout(layoutW, layoutH, layoutEM);
+			currentPage = -1;
+			pageCount = doc.countPages();
+			outline = null;
+			try {
+				outline = doc.loadOutline();
+			} catch (Exception ex) {
+				/* ignore error */
+			}
+			return doc.findBookmark(mark);
+		}
+		return oldPage;
+	}
+
 	private synchronized void gotoPage(int pageNum) {
 		/* TODO: page cache */
 		if (pageNum > pageCount-1)
@@ -109,6 +141,7 @@
 
 		AndroidDrawDevice dev = new AndroidDrawDevice(bm, patchX, patchY);
 		displayList.run(dev, ctm, cookie);
+		dev.close();
 		dev.destroy();
 	}
 
diff --git a/lib/src/main/java/com/artifex/mupdf/viewer/PageAdapter.java b/lib/src/main/java/com/artifex/mupdf/viewer/PageAdapter.java
index 7b48722..35a561b 100644
--- a/lib/src/main/java/com/artifex/mupdf/viewer/PageAdapter.java
+++ b/lib/src/main/java/com/artifex/mupdf/viewer/PageAdapter.java
@@ -41,6 +41,10 @@
 		mSharedHqBm = null;
 	}
 
+	public void refresh() {
+		mPageSizes.clear();
+	}
+
 	public View getView(final int position, View convertView, ViewGroup parent) {
 		final PageView pageView;
 		if (convertView == null) {
diff --git a/lib/src/main/java/com/artifex/mupdf/viewer/ReaderView.java b/lib/src/main/java/com/artifex/mupdf/viewer/ReaderView.java
index 48b9fff..526769e 100644
--- a/lib/src/main/java/com/artifex/mupdf/viewer/ReaderView.java
+++ b/lib/src/main/java/com/artifex/mupdf/viewer/ReaderView.java
@@ -45,8 +45,8 @@
 
 	private static final boolean HORIZONTAL_SCROLLING = true;
 
-	private Adapter           mAdapter;
-	private int               mCurrent;    // Adapter's index for the current view
+	private PageAdapter           mAdapter;
+	protected int               mCurrent;    // Adapter's index for the current view
 	private boolean           mResetLayout;
 	private final SparseArray<View>
 				  mChildViews = new SparseArray<View>(3);
@@ -338,6 +338,18 @@
 		mScale = 1.0f;
 		mXScroll = mYScroll = 0;
 
+		/* All page views need recreating since both page and screen has changed size,
+		 * invalidating both sizes and bitmaps. */
+		mAdapter.refresh();
+		int numChildren = mChildViews.size();
+		for (int i = 0; i < mChildViews.size(); i++) {
+			View v = mChildViews.valueAt(i);
+			onNotInUse(v);
+			removeViewInLayout(v);
+		}
+		mChildViews.clear();
+		mViewCache.clear();
+
 		requestLayout();
 	}
 
@@ -753,15 +765,9 @@
 
 	@Override
 	public void setAdapter(Adapter adapter) {
-
-		//  release previous adapter's bitmaps
-		if (null!=mAdapter && adapter!=mAdapter) {
-			if (adapter instanceof PageAdapter){
-				((PageAdapter) adapter).releaseBitmaps();
-			}
-		}
-
-		mAdapter = adapter;
+		if (mAdapter != null && mAdapter != adapter)
+			mAdapter.releaseBitmaps();
+		mAdapter = (PageAdapter) adapter;
 
 		requestLayout();
 	}
diff --git a/lib/src/main/res/drawable/ic_format_size_white_24dp.xml b/lib/src/main/res/drawable/ic_format_size_white_24dp.xml
new file mode 100644
index 0000000..23f2f33
--- /dev/null
+++ b/lib/src/main/res/drawable/ic_format_size_white_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M9,4v3h5v12h3L17,7h5L22,4L9,4zM3,12h3v7h3v-7h3L12,9L3,9v3z"/>
+</vector>
diff --git a/lib/src/main/res/layout/document_activity.xml b/lib/src/main/res/layout/document_activity.xml
index dda2d08..06bdea3 100644
--- a/lib/src/main/res/layout/document_activity.xml
+++ b/lib/src/main/res/layout/document_activity.xml
@@ -52,6 +52,15 @@
 				/>
 
 			<ImageButton
+				android:id="@+id/layoutButton"
+				android:layout_width="wrap_content"
+				android:layout_height="wrap_content"
+				android:background="@drawable/button"
+				android:src="@drawable/ic_format_size_white_24dp"
+				android:visibility="gone"
+				/>
+
+			<ImageButton
 				android:id="@+id/outlineButton"
 				android:layout_width="wrap_content"
 				android:layout_height="wrap_content"
diff --git a/lib/src/main/res/menu/layout_menu.xml b/lib/src/main/res/menu/layout_menu.xml
new file mode 100644
index 0000000..4bc834a
--- /dev/null
+++ b/lib/src/main/res/menu/layout_menu.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+	<item android:id="@+id/action_layout_6pt" android:title="6pt" />
+	<item android:id="@+id/action_layout_7pt" android:title="7pt" />
+	<item android:id="@+id/action_layout_8pt" android:title="8pt" />
+	<item android:id="@+id/action_layout_9pt" android:title="9pt" />
+	<item android:id="@+id/action_layout_10pt" android:title="10pt" />
+	<item android:id="@+id/action_layout_11pt" android:title="11pt" />
+	<item android:id="@+id/action_layout_12pt" android:title="12pt" />
+	<item android:id="@+id/action_layout_13pt" android:title="13pt" />
+	<item android:id="@+id/action_layout_14pt" android:title="14pt" />
+	<item android:id="@+id/action_layout_15pt" android:title="15pt" />
+	<item android:id="@+id/action_layout_16pt" android:title="16pt" />
+</menu>