diff options
author | Svetoslav <svetoslavganov@google.com> | 2014-10-31 19:54:02 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-10-31 19:54:05 +0000 |
commit | 93134ce87e7b33e599c9ef9ed8b19ec2556ca8f1 (patch) | |
tree | c6aba8a01062d9685aa666cec168f8d1d743103d /packages/PrintSpooler/src | |
parent | b1ecf0d776a2dce5d60802f83fb97c893ba42bf1 (diff) | |
parent | bec22beb99b279d381f720d761ca75fe3e7414dc (diff) | |
download | frameworks_base-93134ce87e7b33e599c9ef9ed8b19ec2556ca8f1.zip frameworks_base-93134ce87e7b33e599c9ef9ed8b19ec2556ca8f1.tar.gz frameworks_base-93134ce87e7b33e599c9ef9ed8b19ec2556ca8f1.tar.bz2 |
Merge "Save to a PDF file should look like print preview." into lmp-mr1-dev
Diffstat (limited to 'packages/PrintSpooler/src')
3 files changed, 134 insertions, 15 deletions
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl index b450ccb..01cabe1 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl +++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl @@ -18,6 +18,7 @@ package com.android.printspooler.renderer; import android.os.ParcelFileDescriptor; import android.print.PageRange; +import android.print.PrintAttributes; /** * Interface for communication with a remote pdf editor. @@ -25,6 +26,7 @@ import android.print.PageRange; interface IPdfEditor { int openDocument(in ParcelFileDescriptor source); void removePages(in PageRange[] pages); + void applyPrintAttributes(in PrintAttributes attributes); void write(in ParcelFileDescriptor destination); void closeDocument(); } diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java index 00e5051..0462e4d 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java +++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java @@ -87,7 +87,7 @@ public final class PdfManipulationService extends Service { } mRenderer = new PdfRenderer(source); return mRenderer.getPageCount(); - } catch (IOException|IllegalStateException e) { + } catch (IOException | IllegalStateException e) { IoUtils.closeQuietly(source); Log.e(LOG_TAG, "Cannot open file", e); return MALFORMED_PDF_FILE_ERROR; @@ -217,7 +217,7 @@ public final class PdfManipulationService extends Service { } mEditor = new PdfEditor(source); return mEditor.getPageCount(); - } catch (IOException|IllegalStateException e) { + } catch (IOException | IllegalStateException e) { IoUtils.closeQuietly(source); Log.e(LOG_TAG, "Cannot open file", e); throw new RemoteException(e.toString()); @@ -246,6 +246,111 @@ public final class PdfManipulationService extends Service { } @Override + public void applyPrintAttributes(PrintAttributes attributes) { + synchronized (mLock) { + throwIfNotOpened(); + if (DEBUG) { + Log.i(LOG_TAG, "applyPrintAttributes()"); + } + + Rect mediaBox = new Rect(); + Rect cropBox = new Rect(); + Matrix transform = new Matrix(); + + final boolean contentPortrait = attributes.getMediaSize().isPortrait(); + + final boolean layoutDirectionRtl = getResources().getConfiguration() + .getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + + // We do not want to rotate the media box, so take into account orientation. + final int dstWidthPts = contentPortrait + ? pointsFromMils(attributes.getMediaSize().getWidthMils()) + : pointsFromMils(attributes.getMediaSize().getHeightMils()); + final int dstHeightPts = contentPortrait + ? pointsFromMils(attributes.getMediaSize().getHeightMils()) + : pointsFromMils(attributes.getMediaSize().getWidthMils()); + + final boolean scaleForPrinting = mEditor.shouldScaleForPrinting(); + + final int pageCount = mEditor.getPageCount(); + for (int i = 0; i < pageCount; i++) { + if (!mEditor.getPageMediaBox(i, mediaBox)) { + Log.e(LOG_TAG, "Malformed PDF file"); + return; + } + + final int srcWidthPts = mediaBox.width(); + final int srcHeightPts = mediaBox.height(); + + // Update the media box with the desired size. + mediaBox.right = dstWidthPts; + mediaBox.bottom = dstHeightPts; + mEditor.setPageMediaBox(i, mediaBox); + + // Make sure content is top-left after media box resize. + transform.setTranslate(0, srcHeightPts - dstHeightPts); + + // Rotate the content if in landscape. + if (!contentPortrait) { + transform.postRotate(270); + transform.postTranslate(0, dstHeightPts); + } + + // Scale the content if document allows it. + final float scale; + if (scaleForPrinting) { + if (contentPortrait) { + scale = Math.min((float) dstWidthPts / srcWidthPts, + (float) dstHeightPts / srcHeightPts); + transform.postScale(scale, scale); + } else { + scale = Math.min((float) dstWidthPts / srcHeightPts, + (float) dstHeightPts / srcWidthPts); + transform.postScale(scale, scale, mediaBox.left, mediaBox.bottom); + } + } else { + scale = 1.0f; + } + + // Update the crop box relatively to the media box change, if needed. + if (mEditor.getPageCropBox(i, cropBox)) { + cropBox.left = (int) (cropBox.left * scale + 0.5f); + cropBox.top = (int) (cropBox.top * scale + 0.5f); + cropBox.right = (int) (cropBox.right * scale + 0.5f); + cropBox.bottom = (int) (cropBox.bottom * scale + 0.5f); + cropBox.intersect(mediaBox); + mEditor.setPageCropBox(i, cropBox); + } + + // If in RTL mode put the content in the logical top-right corner. + if (layoutDirectionRtl) { + final float dx = contentPortrait + ? dstWidthPts - (int) (srcWidthPts * scale + 0.5f) : 0; + final float dy = contentPortrait + ? 0 : - (dstHeightPts - (int) (srcWidthPts * scale + 0.5f)); + transform.postTranslate(dx, dy); + } + + // Adjust the physical margins if needed. + Margins minMargins = attributes.getMinMargins(); + final int paddingLeftPts = pointsFromMils(minMargins.getLeftMils()); + final int paddingTopPts = pointsFromMils(minMargins.getTopMils()); + final int paddingRightPts = pointsFromMils(minMargins.getRightMils()); + final int paddingBottomPts = pointsFromMils(minMargins.getBottomMils()); + + Rect clip = new Rect(mediaBox); + clip.left += paddingLeftPts; + clip.top += paddingTopPts; + clip.right -= paddingRightPts; + clip.bottom -= paddingBottomPts; + + // Apply the accumulated transforms. + mEditor.setTransformAndClip(i, transform, clip); + } + } + } + + @Override public void write(ParcelFileDescriptor destination) throws RemoteException { synchronized (mLock) { try { diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java index 15ea9a7..f361884 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java @@ -592,7 +592,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat mDestinationSpinner.post(new Runnable() { @Override public void run() { - shredPagesAndFinish(uri); + transformDocumentAndFinish(uri); } }); } else if (resultCode == RESULT_CANCELED) { @@ -922,7 +922,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) { startCreateDocumentActivity(); } else { - shredPagesAndFinish(null); + transformDocumentAndFinish(null); } } @@ -1597,8 +1597,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat return true; } - private void shredPagesAndFinish(final Uri writeToUri) { - new PageShredder(this, mPrintJob, mFileProvider, new Runnable() { + private void transformDocumentAndFinish(final Uri writeToUri) { + // If saving to PDF, apply the attibutes as we are acting as a print service. + PrintAttributes attributes = mDestinationSpinnerAdapter.getPdfPrinter() == mCurrentPrinter + ? mPrintJob.getAttributes() : null; + new DocumentTransformer(this, mPrintJob, mFileProvider, attributes, new Runnable() { @Override public void run() { if (writeToUri != null) { @@ -1606,7 +1609,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat } doFinish(); } - }).shred(); + }).transform(); } private void doFinish() { @@ -2329,7 +2332,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat } } - private static final class PageShredder implements ServiceConnection { + private static final class DocumentTransformer implements ServiceConnection { private static final String TEMP_FILE_PREFIX = "print_job"; private static final String TEMP_FILE_EXTENSION = ".pdf"; @@ -2341,20 +2344,24 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat private final PageRange[] mPagesToShred; + private final PrintAttributes mAttributesToApply; + private final Runnable mCallback; - public PageShredder(Context context, PrintJobInfo printJob, - MutexFileProvider fileProvider, Runnable callback) { + public DocumentTransformer(Context context, PrintJobInfo printJob, + MutexFileProvider fileProvider, PrintAttributes attributes, + Runnable callback) { mContext = context; mPrintJob = printJob; mFileProvider = fileProvider; mCallback = callback; mPagesToShred = computePagesToShred(mPrintJob); + mAttributesToApply = attributes; } - public void shred() { + public void transform() { // If we have only the pages we want, done. - if (mPagesToShred.length <= 0) { + if (mPagesToShred.length <= 0 && mAttributesToApply == null) { mCallback.run(); return; } @@ -2376,14 +2383,14 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat // final and this code is the last one to touch // them as shredding is the very last step, so the // UI is not interactive at this point. - shredPages(editor); + doTransform(editor); updatePrintJob(); return null; } @Override protected void onPostExecute(Void aVoid) { - mContext.unbindService(PageShredder.this); + mContext.unbindService(DocumentTransformer.this); mCallback.run(); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); @@ -2394,7 +2401,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat /* do nothing */ } - private void shredPages(IPdfEditor editor) { + private void doTransform(IPdfEditor editor) { File tempFile = null; ParcelFileDescriptor src = null; ParcelFileDescriptor dst = null; @@ -2413,6 +2420,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat // Drop the pages. editor.removePages(mPagesToShred); + // Apply print attributes if needed. + if (mAttributesToApply != null) { + editor.applyPrintAttributes(mAttributesToApply); + } + // Write the modified PDF to a temp file. tempFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_EXTENSION, mContext.getCacheDir()); |