Java tutorial
//--------------------------------------------------------------------------------------- // Copyright (c) 2001-2016 by PDFTron Systems Inc. All Rights Reserved. // Consult legal.txt regarding legal and license information. //------------------------------------------------------------------------- package com.pdftron.pdf.controls; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.util.Log; import android.view.Display; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.AlphaAnimation; import android.view.animation.LinearInterpolator; import android.widget.Button; import android.widget.FrameLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.pdftron.common.Matrix2D; import com.pdftron.common.PDFNetException; import com.pdftron.pdf.PDFDoc; import com.pdftron.pdf.PDFRasterizer; import com.pdftron.pdf.PDFViewCtrl; import com.pdftron.pdf.Page; import com.pdftron.pdf.PageIterator; import com.pdftron.pdf.Point; import com.pdftron.pdf.Rect; import com.pdftron.pdf.tools.R; import com.pdftron.pdf.utils.AnalyticsHandlerAdapter; import com.pdftron.pdf.utils.CustomAsyncTask; import com.pdftron.pdf.utils.ImageMemoryCache; import com.pdftron.pdf.utils.Utils; import com.pdftron.pdf.widget.ContentLoadingRelativeLayout; import com.pdftron.pdf.utils.UserCropUtilities; public class UserCropDialogFragment extends DialogFragment { public interface UserCropDialogListener { void onUserCropDialogDismiss(int pageNumberAtDismiss); } // Default memory cache size in kilobytes private static final int DEFAULT_MEM_CACHE_SIZE = 1024 * 50; // 50MB // The number of images to render ahead and behind the current page private static final int MAX_PAGES_TO_PRERENDER_PER_DIRECTION = 4; private static final long MILLISECONDS_BEFORE_SHOWING_PROGRESS = 500; private boolean mRemoveCropHelperMode; private UserCropDialogListener mListener; private String mLayoutName; private boolean mIsActive; private boolean mIsCroppingConfirmed = false; // used for analytics private int mCurrentPage = 0; private int mTotalPages = 0; private PDFViewCtrl mPdfViewCtrl; // layout parameters private RelativeLayout mCropPageHost; private View mBlankPagePlaceholder; private ContentLoadingRelativeLayout mBlankPageSpinnerHost; private View mCropImageBorder; private com.edmodo.cropper.CropImageView mCropImageView; // TODO - Acknowledge in legal private TextView mPageNumberTextView; // Progress private View mDisablingOverlay; private View mProgressBarHost; private boolean mDisablingOverlayShowing; private boolean mSpinnerShowing; // Pre-rendering private int mPagesToPreRenderPerDirection; // Page Properites ///////////////////////////////////////////////////////// private class PageCropProperties { public Rect mUserCropBox; public Rect mCropBox; public int mRotation; public PageCropProperties() { } } private PageCropProperties[] mPageProperties; // Bitmap Handling ///////////////////////////////////////////////////////// ImageMemoryCache mImageCache; public static UserCropDialogFragment newInstance() { UserCropDialogFragment dialog = new UserCropDialogFragment(); dialog.mRemoveCropHelperMode = false; return dialog; } public static UserCropDialogFragment newInstanceAsRemoveCropHelper() { UserCropDialogFragment dialog = new UserCropDialogFragment(); dialog.mRemoveCropHelperMode = true; return dialog; } public UserCropDialogFragment() { // Required empty public constructor } public UserCropDialogFragment initParams(PDFViewCtrl ctrl) { mIsActive = true; mPdfViewCtrl = ctrl; mCurrentPage = ctrl.getCurrentPage(); mTotalPages = ctrl.getPageCount(); int totalItems = mTotalPages + 1; mPageProperties = new PageCropProperties[totalItems]; mDisablingOverlayShowing = false; mSpinnerShowing = false; mPagesToPreRenderPerDirection = 0; if (!mRemoveCropHelperMode) { mImageCache = new ImageMemoryCache(DEFAULT_MEM_CACHE_SIZE); } return this; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null && mPdfViewCtrl == null) { this.dismiss(); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.fragment_user_crop_dialog, null); if (mRemoveCropHelperMode) { getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(0)); } else { int width = 10; int height = 10; WindowManager wm = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); if (android.os.Build.VERSION.SDK_INT >= 13) { android.graphics.Point size = new android.graphics.Point(); display.getSize(size); width = size.x - 10; height = size.y - 10; } else { width = display.getWidth() - 10; height = display.getHeight() - 10; } int maxImageSize = width * height * 4; if (maxImageSize > 0) { int maxImages = (DEFAULT_MEM_CACHE_SIZE * 1000) / maxImageSize; if (maxImages > 0) { mPagesToPreRenderPerDirection = Math.min(MAX_PAGES_TO_PRERENDER_PER_DIRECTION, (maxImages - 1) / 2); } } } initUI(view); return view; } private void initUI(final View view) { final FrameLayout layout = (FrameLayout) view.findViewById(R.id.layout_root); mPageNumberTextView = (TextView) view.findViewById(R.id.page_num_text_view); mLayoutName = layout.getTag().toString(); mDisablingOverlay = view.findViewById(R.id.disabling_overlay); mProgressBarHost = view.findViewById(R.id.progress_bar_host); mDisablingOverlay.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; // ensure the user can't click buttons } }); mCropPageHost = (RelativeLayout) view.findViewById(R.id.page_crop_host); mCropImageBorder = view.findViewById(R.id.image_crop_border); mCropImageView = (com.edmodo.cropper.CropImageView) view.findViewById(R.id.image_crop_view); mCropImageView.setGuidelines(0); // off mCropImageBorder.setVisibility(View.GONE); mBlankPagePlaceholder = view.findViewById(R.id.blank_page_placeholder); mBlankPageSpinnerHost = (ContentLoadingRelativeLayout) view.findViewById(R.id.blank_page_progress_bar_host); if (mRemoveCropHelperMode) { View manualCropRoot = view.findViewById(R.id.manual_crop_root_layout); manualCropRoot.setVisibility(View.GONE); setCropBoxAndClose(); } else { mCropPageHost.postDelayed(new Runnable() { @Override public void run() { if (mIsActive) { if (mLayoutName.equals("layout-sw480dp-port") || mLayoutName.equals("layout-sw480dp-land")) { if (view.getWidth() < 540) { View buttonHost = view.findViewById(R.id.page_buttons_host); int[] location = new int[2]; buttonHost.getLocationInWindow(location); int buttonsLeft = location[0]; View pageNumText = view.findViewById(R.id.page_num_text_view); pageNumText.getLocationInWindow(location); int pageNumRight = location[0] + pageNumText.getWidth(); if (pageNumRight > buttonsLeft - 10) { RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) buttonHost .getLayoutParams(); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE); layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL, 0); } } } mCropImageBorder.setVisibility(View.VISIBLE); setPage(mCurrentPage); } } }, 200); // Extra delay to ensure that view has time to settle. post alone doesn't work. } getButtons(view); if (mDisablingOverlayShowing) { mDisablingOverlay.setVisibility(View.VISIBLE); } if (mSpinnerShowing) { mProgressBarHost.setVisibility(View.VISIBLE); } } private void getButtons(final View view) { final View nextButton = view.findViewById(R.id.next_button); nextButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (mDisablingOverlayShowing) { return; } switchPage(true); } }); final View prevButton = view.findViewById(R.id.prev_button); prevButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (mDisablingOverlayShowing) { return; } switchPage(false); } }); final Button doneButton = (Button) view.findViewById(R.id.done_button); doneButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (mDisablingOverlayShowing) { return; } mIsCroppingConfirmed = true; setCropBoxAndClose(); } }); final Button cancelButton = (Button) view.findViewById(R.id.cancel_button); cancelButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { UserCropDialogFragment.this.dismiss(); return; } }); final Button cropAllButton = (Button) view.findViewById(R.id.crop_all_button); cropAllButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (mDisablingOverlayShowing) { return; } applyCropToAllPagesAndFlash(); } }); } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (UserCropDialogListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement " + e.getClass().toString()); } } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (mCurrentJob != null && !mCurrentJob.isDone()) { mCurrentJob.cancelRasterizing(); } mCurrentJob = null; // if (mCropImageView.hasBitmap()) { // updatePageCropFromImageView(mPageProperties[mCurrentPage], mCropImageView.getCropRectPercentageMargins()); // Bitmap bitmap = mCropImageView.getImageBitmapAndClear(); // } mImageCache.evictAll(); if (mSpinnerAlphaAnimation != null && !mSpinnerAlphaAnimation.hasEnded()) { mSpinnerAlphaAnimation.cancel(); } if (mDisablingOverlayShowing) { mDisablingOverlay.setVisibility(View.VISIBLE); } if (mSpinnerShowing) { mProgressBarHost.setVisibility(View.VISIBLE); } ViewGroup viewGroup = (ViewGroup) getView(); viewGroup.removeAllViewsInLayout(); View view = onCreateView(getActivity().getLayoutInflater(), viewGroup, null); viewGroup.addView(view); } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); if (mCurrentJob != null && !mCurrentJob.isDone()) { mCurrentJob.cancelRasterizing(); } mListener.onUserCropDialogDismiss(mCurrentPage); } @Override public void onDestroy() { mIsActive = false; if (mImageCache != null) { mImageCache.evictAll(); } super.onDestroy(); } private void switchPage(boolean next) { if (next && mCurrentPage < mPdfViewCtrl.getPageCount()) { setPage(mCurrentPage + 1); } else if (!next && mCurrentPage > 1) { setPage(mCurrentPage - 1); } } // Bitmap Acquisition ////////////////////////////////////////////////////// private DrawImageTask mCurrentJob; private class DrawImageTask extends CustomAsyncTask<Void, Void, Bitmap> { private int mPageNumber; private PDFRasterizer mRasterizer; private Point mViewDimensions; private PDFDoc mPdfDoc; private boolean mGotBitmap; private boolean mIsCancelled; public int getPageNumber() { return mPageNumber; } public boolean cancelRasterizing() { Log.i("USER_CROP", "Canceling image rendering for page " + mPageNumber); if (mRasterizer != null) { try { mRasterizer.setCancel(true); } catch (com.pdftron.common.PDFNetException e) { } } return this.cancel(false); } /** * Returns true if the task is finished or cancelled */ public boolean isDone() { return mGotBitmap || isCancelled(); } public DrawImageTask(Context context, int pageNumber, Point viewDimensions, PDFDoc doc) { super(context); mPageNumber = pageNumber; mViewDimensions = viewDimensions; mPdfDoc = doc; mGotBitmap = false; mIsCancelled = false; if (viewDimensions.x <= 0 || viewDimensions.y <= 0) { Log.e("USER_CROP", "Dimensions are 0 or less"); } try { mRasterizer = new PDFRasterizer(); mRasterizer.setDrawAnnotations(true); } catch (com.pdftron.common.PDFNetException e) { } } @Override protected Bitmap doInBackground(Void... jobParam) { if (mPageNumber > 0) { try { if (isCancelled() || mRasterizer == null) { return null; } mPdfDoc.lockRead(); Page page = mPdfDoc.getPage(mPageNumber); double scaleFactor = 1; Rect bbox = page.getCropBox(); bbox.normalize(); double pageWidth = page.getPageWidth(); double pageHeight = page.getPageHeight(); double pageScaleFactorX = mViewDimensions.x / pageWidth; double pageScaleFactorY = mViewDimensions.y / pageHeight; scaleFactor *= Math.max(pageScaleFactorX, pageScaleFactorY); if (scaleFactor <= 0) { return null; } // Will make the picture right side up, at the correct scale. Matrix2D mtx = new Matrix2D(scaleFactor, 0, 0, scaleFactor, 0, 0); mtx = mtx.multiply(page.getDefaultMatrix(true, Page.e_crop, Page.e_0)); int width = (int) (pageWidth * scaleFactor); int height = (int) (pageHeight * scaleFactor); int comps = 4; // BGRA int stride = ((width * comps + 3) / 4) * 4; if (isCancelled()) { return null; } Log.i("USER_CROP", "Creating image for page " + mPageNumber + " of dimensions " + width + " x " + height); int[] img = new int[stride * height]; mRasterizer.rasterize(page, img, width, height, false, mtx, bbox); if (isCancelled()) { return null; } Bitmap bitmap = Bitmap.createBitmap(img, width, height, Bitmap.Config.ARGB_8888); return bitmap; } catch (com.pdftron.common.PDFNetException e) { } finally { try { mPdfDoc.unlockRead(); } catch (com.pdftron.common.PDFNetException e) { } } } return null; } @Override protected void onCancelled(Bitmap result) { super.onCancelled(result); } @Override protected void onPostExecute(Bitmap result) { // TODO I seem to have failed this check once even though I cancelled this task // is this a matter of perfect timing (cancel called after this has been posted, but before it's been executed? // Added the mIsCancelled and !mIsActive checks since, let's keep monitoring. if (isCancelled() || result == null || mIsCancelled || !mIsActive) { return; } mGotBitmap = true; if (mCurrentPage == mPageNumber) { mImageCache.put("" + mPageNumber, new BitmapDrawable(getContext().getResources(), result)); readyNextPage(mPageNumber, result); } else { mImageCache.put("" + mPageNumber, new BitmapDrawable(getContext().getResources(), result)); preRenderIfNecessary(); } } } // Implementation Details ////////////////////////////////////////////////// private void setPage(int pageNumber) { if (pageNumber != mCurrentPage) { // if (mPageProperties[mCurrentPage] != null) { // if (mCropImageView.hasBitmap()) { // updatePageCropFromImageView(mPageProperties[mCurrentPage], mCropImageView.getCropRectPercentageMargins()); // Bitmap oldBitmap = mCropImageView.getImageBitmapAndClear(); // } // } mCurrentPage = pageNumber; } mBlankPageSpinnerHost.hide(true, false); mBlankPageSpinnerHost.show(); mPageNumberTextView.setText(String.format( getActivity().getResources().getString(R.string.user_crop_manual_crop_page_label), pageNumber)); PDFDoc doc = mPdfViewCtrl.getDoc(); try { doc.lockRead(); Page page = doc.getPage(pageNumber); PageCropProperties currentProperties = getCropPropertiesForPage(pageNumber); Log.i("USER_CROP", "Just set page to + " + pageNumber + ". Calculating page size..."); Log.i("USER_CROP", String.format("UserCropView size is (%1d, %2d)", mCropImageView.getMeasuredWidth(), mCropImageView.getMeasuredHeight())); Point newPageSize = calculateBlankPageSize(page.getPageWidth(), page.getPageHeight()); resizePageProperties((int) newPageSize.x, (int) newPageSize.y); BitmapDrawable drawable = mImageCache.get("" + pageNumber); if (drawable != null) { readyNextPage(pageNumber, drawable.getBitmap()); } else { if (mCurrentJob == null || mCurrentJob.getPageNumber() != pageNumber) { if (mCurrentJob != null && !mCurrentJob.isDone()) { Log.i("USER_CROP", "Cancelling job for page " + mCurrentJob.mPageNumber); mCurrentJob.cancelRasterizing(); } mCurrentJob = new DrawImageTask(getActivity(), pageNumber, newPageSize, doc); Log.i("USER_CROP", "Starting render job for page " + mCurrentJob.mPageNumber); mCurrentJob.execute(); } else { Log.i("USER_CROP", "Page " + mCurrentJob.mPageNumber + " is already being rendered"); } } } catch (com.pdftron.common.PDFNetException e) { } finally { try { doc.unlockRead(); } catch (com.pdftron.common.PDFNetException e) { } } } private PageCropProperties getCropPropertiesForPage(int pageNumber) { PDFDoc doc = mPdfViewCtrl.getDoc(); try { doc.lockRead(); Page page = doc.getPage(pageNumber); PageCropProperties currentProperties = mPageProperties[pageNumber]; if (currentProperties == null) { currentProperties = new PageCropProperties(); mPageProperties[pageNumber] = currentProperties; } if (currentProperties.mCropBox == null) { currentProperties.mCropBox = page.getCropBox(); currentProperties.mUserCropBox = page.getBox(Page.e_user_crop); currentProperties.mRotation = page.getRotation(); } return currentProperties; } catch (com.pdftron.common.PDFNetException e) { Log.d("USER_CROP", e.getStackTrace().toString()); } finally { try { doc.unlockRead(); } catch (com.pdftron.common.PDFNetException e) { } } return null; } private void readyNextPage(int pageNumber, Bitmap newBitmap) { if (pageNumber == mCurrentPage && newBitmap != null) { //Bitmap oldBitmap = mCropImageView.getImageBitmapAndClear(); mCropImageView.setImageBitmap(newBitmap); // setting the iamge bitmap above seems to auto-resize the mCropImageView to // the old size, so we need to set it again. resizePageProperties(newBitmap.getWidth(), newBitmap.getHeight()); SetCropRectOnView(); } preRenderIfNecessary(); } private void preRenderIfNecessary() { if (mCurrentJob != null && !mCurrentJob.isDone()) { return; } int pageToRender = getNextPageToPreRender(mCurrentPage); while (pageToRender > 0 && pageToRender <= mTotalPages && Math.abs(pageToRender - mCurrentPage) <= mPagesToPreRenderPerDirection) { BitmapDrawable drawable = mImageCache.get("" + pageToRender); if (drawable == null) { Log.i("USER_CROP", "Pre-rendering page " + pageToRender); PDFDoc doc = mPdfViewCtrl.getDoc(); try { doc.lockRead(); Page page = doc.getPage(pageToRender); Log.i("USER_CROP", "Calculating page size for page " + pageToRender); Point newPageSize = calculateBlankPageSize(page.getPageWidth(), page.getPageHeight()); mCurrentJob = new DrawImageTask(getActivity(), pageToRender, newPageSize, mPdfViewCtrl.getDoc()); mCurrentJob.execute(); } catch (com.pdftron.common.PDFNetException e) { Log.d("USER_CROP", e.getStackTrace().toString()); } finally { try { doc.unlockRead(); } catch (com.pdftron.common.PDFNetException e) { } } return; } pageToRender = getNextPageToPreRender(pageToRender); } } private int getNextPageToPreRender(int lastRenderedPage) { if (lastRenderedPage < 1 || lastRenderedPage > mTotalPages) { return -1; } if (lastRenderedPage > mCurrentPage) { int pageDiff = Math.abs(mCurrentPage - lastRenderedPage); int nextPage = lastRenderedPage - pageDiff - pageDiff; if (nextPage < 1) { return lastRenderedPage + 1; } return nextPage; } else { int pageDiff = Math.abs(mCurrentPage - lastRenderedPage); int nextPage = lastRenderedPage + pageDiff + pageDiff + 1; if (nextPage > mTotalPages) { return lastRenderedPage - 1; } return nextPage; } } private void SetCropRectOnView() { if (mPageProperties[mCurrentPage].mUserCropBox != null) { try { Rect cropBox = mPageProperties[mCurrentPage].mCropBox; if (cropBox.getWidth() > 0 && cropBox.getHeight() > 0) { Rect userCropBox = mPageProperties[mCurrentPage].mUserCropBox; RectF cropPercentageRect = new RectF(); cropPercentageRect.left = (float) ((userCropBox.getX1() - cropBox.getX1()) / cropBox.getWidth()); cropPercentageRect.right = (float) ((cropBox.getX2() - userCropBox.getX2()) / cropBox.getWidth()); cropPercentageRect.bottom = (float) ((userCropBox.getY1() - cropBox.getY1()) / cropBox.getHeight()); cropPercentageRect.top = (float) ((cropBox.getY2() - userCropBox.getY2()) / cropBox.getHeight()); rotateRectangle(cropPercentageRect, mPageProperties[mCurrentPage].mRotation); //mCropImageView.setCropRectPercentageMargins(cropPercentageRect); } } catch (com.pdftron.common.PDFNetException e) { } } } private void updatePageCropFromImageView(PageCropProperties properties, RectF percentageRect) { if (properties != null) { try { int rot = Page.subtractRotations(Page.e_0, properties.mRotation); rotateRectangle(percentageRect, rot); Rect cropBox = properties.mCropBox; if (cropBox != null && cropBox.getWidth() > 0 && cropBox.getHeight() > 0) { if (properties.mUserCropBox == null) { properties.mUserCropBox = new Rect(); } properties.mUserCropBox.setX1(cropBox.getX1() + (percentageRect.left * cropBox.getWidth())); properties.mUserCropBox.setX2(cropBox.getX2() - (percentageRect.right * cropBox.getWidth())); properties.mUserCropBox.setY1(cropBox.getY1() + (percentageRect.bottom * cropBox.getHeight())); properties.mUserCropBox.setY2(cropBox.getY2() - (percentageRect.top * cropBox.getHeight())); } } catch (com.pdftron.common.PDFNetException e) { } } } private Point calculateBlankPageSize(double pageWidth, double pageHeight) { //int marginSize = mCropImageView.getMarginSize(); // double hostWidth = mCropPageHost.getMeasuredWidth() - (2 * marginSize); // double hostHeight = mCropPageHost.getMeasuredHeight() - (2 * marginSize); // calculate size of page // double widthScale = hostWidth / pageWidth; // double heightScale = hostHeight / pageHeight; // // if (widthScale < heightScale) { // return new Point((int)hostWidth, (int)(pageHeight * widthScale)); // } // else { // return new Point((int)(pageWidth * heightScale), (int)hostHeight); // } return new Point(0.0, 0.0); } private void resizePageProperties(int pageWidth, int pageHeight) { //int margin = mCropImageView.getMarginSize(); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mCropImageView.getLayoutParams(); // layoutParams.width = pageWidth + margin + margin; // layoutParams.height = pageHeight + margin + margin; mCropImageView.setLayoutParams(layoutParams); layoutParams = (FrameLayout.LayoutParams) mBlankPagePlaceholder.getLayoutParams(); layoutParams.width = pageWidth; layoutParams.height = pageHeight; mBlankPagePlaceholder.setLayoutParams(layoutParams); } // Cropping //////////////////////////////////////////////////////////////// private SetCropBoxTask mCropBoxTask; private ApplyCropToAllPagesTask mApplyCropTask; private void setCropBoxAndClose() { if (mDisablingOverlayShowing) { return; } if (mCurrentJob != null && !mCurrentJob.isDone()) { mCurrentJob.cancelRasterizing(); } mIsActive = true; // if (mPageProperties[mCurrentPage] != null) // { // if (mCropImageView.hasBitmap()) { // updatePageCropFromImageView(mPageProperties[mCurrentPage], mCropImageView.getCropRectPercentageMargins()); // } // } PDFDoc doc = mPdfViewCtrl.getDoc(); mPdfViewCtrl.cancelRendering(); mCropBoxTask = new SetCropBoxTask(getActivity(), doc); mCropBoxTask.execute(); } void applyCropToAllPagesAndFlash() { if (mDisablingOverlayShowing) { return; } // if (mCropImageView.hasBitmap() && mPageProperties[mCurrentPage] != null) { // RectF percentageRect = mCropImageView.getCropRectPercentageMargins(); // // // Ensure the current page has the correct value now. // updatePageCropFromImageView(mPageProperties[mCurrentPage], percentageRect); // // try { // int rot = Page.subtractRotations(Page.e_0, mPageProperties[mCurrentPage].mRotation); // rotateRectangle(percentageRect, rot); // // Rect cropBox = mPageProperties[mCurrentPage].mCropBox; // if (cropBox != null && cropBox.getWidth() > 0 && cropBox.getHeight() > 0) { // Rect cropMargins = new Rect(percentageRect.left * cropBox.getWidth(), // percentageRect.bottom * cropBox.getHeight(), // percentageRect.right * cropBox.getWidth(), // percentageRect.top * cropBox.getHeight()); // // mApplyCropTask = new ApplyCropToAllPagesTask(getActivity(), cropMargins, mPdfViewCtrl.getDoc()); // mApplyCropTask.execute(); // Utils.showToast(getActivity(), getCropAllInfoString()); // // } // // } // catch (PDFNetException e){ // Log.d("USER_CROP", e.getStackTrace().toString()); // } // } return; } /** * Used to modify the user crop box to all the pages in a background thread. * */ private class SetCropBoxTask extends CustomAsyncTask<Void, Integer, Boolean> { private PDFDoc mDoc; private long mTaskStartTime; public SetCropBoxTask(Context context, PDFDoc doc) { super(context); mDoc = doc; } @Override protected void onPreExecute() { super.onPreExecute(); mDisablingOverlay.setVisibility(View.VISIBLE); mDisablingOverlayShowing = true; mTaskStartTime = System.nanoTime() / 1000000; } @Override protected Boolean doInBackground(Void... params) { long startTime = System.nanoTime(); boolean success = true; try { mDoc.lock(); if (mRemoveCropHelperMode) { removeCropHelper(); } else { cropPagesHelper(); } } catch (com.pdftron.common.PDFNetException e) { Log.d("USER_CROP", e.getStackTrace().toString()); success = false; } finally { try { mDoc.unlock(); } catch (com.pdftron.common.PDFNetException e) { Log.d("USER_CROP", e.getStackTrace().toString()); } } long endTime = System.nanoTime(); long duration = (endTime - startTime) / 1000000; Log.i("USER_CROP", "Permanently cropped all pages: It took " + duration + "milliseconds"); return Boolean.valueOf(success); } private void cropPagesHelper() throws PDFNetException { int currPageNum = 1; PageIterator itr = mDoc.getPageIterator(); while (itr.hasNext()) { Object obj = itr.next(); Page page = (Page) obj; PageCropProperties pageProperties = mPageProperties[currPageNum]; if (pageProperties != null && pageProperties.mUserCropBox != null) { try { if (pageProperties.mUserCropBox.getX1() - pageProperties.mCropBox.getX1() <= 0.1 && pageProperties.mCropBox.getX2() - pageProperties.mUserCropBox.getX2() <= 0.1 && pageProperties.mUserCropBox.getY1() - pageProperties.mCropBox.getY1() <= 0.1 && pageProperties.mCropBox.getY2() - pageProperties.mUserCropBox.getY2() <= 0.1) { //Log.i("USER_CROP", "Permanently removing crop from page " + currPageNum); com.pdftron.pdf.utils.UserCropUtilities.removeUserCropFromPage(page); } else { //Log.i("USER_CROP", "Permanently cropping page " + currPageNum); page.setBox(Page.e_user_crop, pageProperties.mUserCropBox); } } catch (com.pdftron.common.PDFNetException e) { Log.d("USER_CROP", e.getStackTrace().toString()); } } if (currPageNum % 100 == 99) { publishProgress(Integer.valueOf(currPageNum)); } currPageNum++; } } private void removeCropHelper() throws PDFNetException { int currPageNum = 1; PageIterator itr = mDoc.getPageIterator(); while (itr.hasNext()) { Object obj = itr.next(); Page page = (Page) obj; try { UserCropUtilities.removeUserCropFromPage(page); } catch (com.pdftron.common.PDFNetException e) { Log.d("USER_CROP", e.getStackTrace().toString()); } if (currPageNum % 100 == 99) { publishProgress(Integer.valueOf(currPageNum)); } currPageNum++; } } @Override protected void onCancelled(Boolean succeeded) { super.onCancelled(succeeded.booleanValue()); removeSpinner(); } @Override protected void onPostExecute(Boolean succeeded) { super.onPostExecute(succeeded); removeSpinner(); try { mPdfViewCtrl.updatePageLayout(); } catch (Exception e) { AnalyticsHandlerAdapter.getInstance().sendException(e); } if (succeeded.booleanValue()) { UserCropDialogFragment.this.dismiss(); } removeSpinner(); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); long now = System.nanoTime() / 1000000; if (now - mTaskStartTime > MILLISECONDS_BEFORE_SHOWING_PROGRESS) { showSpinner(); } } } /** * Used to apply the crop box to each page's properties */ private class ApplyCropToAllPagesTask extends CustomAsyncTask<Void, Integer, Boolean> { private Rect mMarginRect; private PDFDoc mDoc; private long mTaskStartTime; public ApplyCropToAllPagesTask(Context context, Rect marginRect, PDFDoc doc) { super(context); mMarginRect = marginRect; mDoc = doc; } @Override protected void onPreExecute() { super.onPreExecute(); mDisablingOverlay.setVisibility(View.VISIBLE); mDisablingOverlayShowing = true; mTaskStartTime = System.nanoTime() / 1000000; } @Override protected Boolean doInBackground(Void... params) { boolean success = applyCropToAllPages(mMarginRect, mDoc); return Boolean.valueOf(success); } boolean applyCropToAllPages(Rect marginRect, PDFDoc doc) { long startTime = System.nanoTime(); boolean success = false; // Getting a page (e.g. PDFDoc.getPage(n)) is O(n). Therefore, we create an iterator since // we might have to look at every page try { doc.lockRead(); PageIterator itr = doc.getPageIterator(); int pageNumber = 1; while (itr.hasNext() && !isCancelled()) { Object pageObj = itr.next(); Page page = (Page) pageObj; if (mPageProperties[pageNumber] == null) { PageCropProperties cropProperties = new PageCropProperties(); cropProperties.mCropBox = page.getCropBox(); cropProperties.mRotation = page.getRotation(); cropProperties.mUserCropBox = new Rect(); mPageProperties[pageNumber] = cropProperties; } Rect userCrop = mPageProperties[pageNumber].mUserCropBox; Rect crop = mPageProperties[pageNumber].mCropBox; if (marginRect.getX1() + marginRect.getX2() + 10 > crop.getWidth()) { userCrop.setX1(crop.getX1()); userCrop.setX2(crop.getX2()); } else { userCrop.setX1(crop.getX1() + marginRect.getX1()); userCrop.setX2(crop.getX2() - marginRect.getX2()); } if (marginRect.getY1() + marginRect.getY2() + 10 > crop.getHeight()) { userCrop.setY1(crop.getY1()); userCrop.setY2(crop.getY2()); } else { userCrop.setY1(crop.getY1() + marginRect.getY1()); userCrop.setY2(crop.getY2() - marginRect.getY2()); } pageNumber++; if (pageNumber % 100 == 99) { publishProgress(Integer.valueOf(pageNumber)); } } success = true; } catch (PDFNetException e) { Log.d("USER_CROP", e.getStackTrace().toString()); } finally { try { doc.unlockRead(); } catch (com.pdftron.common.PDFNetException e) { Log.d("USER_CROP", e.getStackTrace().toString()); } } long endTime = System.nanoTime(); long duration = (endTime - startTime) / 1000000; Log.i("USER_CROP", "Applied crop to all pages. It took " + duration + "milliseconds"); return success; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); long now = System.nanoTime() / 1000000; if (now - mTaskStartTime > MILLISECONDS_BEFORE_SHOWING_PROGRESS) { showSpinner(); } } @Override protected void onCancelled(Boolean aBoolean) { super.onCancelled(aBoolean); removeSpinner(); } @Override protected void onPostExecute(Boolean aBoolean) { super.onPostExecute(aBoolean); removeSpinner(); } } private AlphaAnimation mSpinnerAlphaAnimation; private void showSpinner() { this.setCancelable(false); if (mSpinnerShowing) { return; } mSpinnerShowing = true; mProgressBarHost.setVisibility(View.VISIBLE); mSpinnerAlphaAnimation = new AlphaAnimation(0.0f, 1.0f); mSpinnerAlphaAnimation.setDuration(500); mSpinnerAlphaAnimation.setInterpolator(new LinearInterpolator()); mProgressBarHost.startAnimation(mSpinnerAlphaAnimation); } private void removeSpinner() { this.setCancelable(true); mProgressBarHost.setVisibility(View.GONE); mDisablingOverlay.setVisibility(View.GONE); mDisablingOverlayShowing = false; if (mSpinnerAlphaAnimation != null && !mSpinnerAlphaAnimation.hasEnded()) { mSpinnerAlphaAnimation.cancel(); } if (mSpinnerShowing) { mSpinnerShowing = false; } } // Utility Functions /////////////////////////////////////////////////////// void rotateRectangle(RectF rect, int rotation) { float temp; switch (rotation) { case Page.e_0: return; case Page.e_90: temp = rect.left; rect.left = rect.bottom; rect.bottom = rect.right; rect.right = rect.top; rect.top = temp; return; case Page.e_180: temp = rect.left; rect.left = rect.right; rect.right = temp; temp = rect.bottom; rect.bottom = rect.top; rect.top = temp; return; case Page.e_270: temp = rect.left; rect.left = rect.top; rect.top = rect.right; rect.right = rect.bottom; rect.bottom = temp; return; } } private String getCropAllInfoString() { return String.format(getActivity().getResources().getString(R.string.user_crop_manual_crop_crop_all_toast), getString(R.string.user_crop_manual_crop_done)); } }