1b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav/* 2b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Copyright (C) 2013 The Android Open Source Project 3b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 4b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Licensed under the Apache License, Version 2.0 (the "License"); 5b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * you may not use this file except in compliance with the License. 6b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * You may obtain a copy of the License at 7b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 8b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * http://www.apache.org/licenses/LICENSE-2.0 9b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 10b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Unless required by applicable law or agreed to in writing, software 11b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * distributed under the License is distributed on an "AS IS" BASIS, 12b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * See the License for the specific language governing permissions and 14b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * limitations under the License. 15b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 16b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 17b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavpackage android.support.v4.print; 18b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 19b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.content.Context; 20b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.graphics.Bitmap; 21b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.graphics.BitmapFactory; 22b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.graphics.Matrix; 23b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.graphics.RectF; 24b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.graphics.pdf.PdfDocument.Page; 25b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.net.Uri; 26975c49f182d754dfe1a38ba0457d6e603b125570John Hofordimport android.os.AsyncTask; 27b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.os.Bundle; 28b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.os.CancellationSignal; 29b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.os.ParcelFileDescriptor; 30b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.PageRange; 31b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.PrintAttributes; 32b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.PrintDocumentAdapter; 33b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.PrintDocumentInfo; 34b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.PrintManager; 35b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.print.pdf.PrintedPdfDocument; 36b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport android.util.Log; 37b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 38b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport java.io.FileNotFoundException; 39b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport java.io.FileOutputStream; 40b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport java.io.IOException; 41b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslavimport java.io.InputStream; 42b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 43b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav/** 44b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Kitkat specific PrintManager API implementation. 45b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 46975c49f182d754dfe1a38ba0457d6e603b125570John Hofordclass PrintHelperKitkat { 47b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav private static final String LOG_TAG = "PrintHelperKitkat"; 48b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // will be <= 300 dpi on A4 (8.3×11.7) paper (worst case of 150 dpi) 49b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav private final static int MAX_PRINT_SIZE = 3500; 50b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav final Context mContext; 51975c49f182d754dfe1a38ba0457d6e603b125570John Hoford BitmapFactory.Options mDecodeOptions = null; 52975c49f182d754dfe1a38ba0457d6e603b125570John Hoford private final Object mLock = new Object(); 53b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 54b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * image will be scaled but leave white space 55b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 56b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public static final int SCALE_MODE_FIT = 1; 57b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 58b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * image will fill the paper and be cropped (default) 59b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 60b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public static final int SCALE_MODE_FILL = 2; 61b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 6209ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov /** 63975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * select landscape (default) 64975c49f182d754dfe1a38ba0457d6e603b125570John Hoford */ 65975c49f182d754dfe1a38ba0457d6e603b125570John Hoford public static final int ORIENTATION_LANDSCAPE = 1; 66975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 67975c49f182d754dfe1a38ba0457d6e603b125570John Hoford /** 68975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * select portrait 69975c49f182d754dfe1a38ba0457d6e603b125570John Hoford */ 70975c49f182d754dfe1a38ba0457d6e603b125570John Hoford public static final int ORIENTATION_PORTRAIT = 2; 71975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 72975c49f182d754dfe1a38ba0457d6e603b125570John Hoford /** 7309ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * this is a black and white image 7409ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov */ 7509ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov public static final int COLOR_MODE_MONOCHROME = 1; 7609ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov /** 7709ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * this is a color image (default) 7809ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov */ 7909ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov public static final int COLOR_MODE_COLOR = 2; 8009ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov 81b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov public interface OnPrintFinishCallback { 82b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov public void onFinish(); 83b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov } 84b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov 85b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav int mScaleMode = SCALE_MODE_FILL; 86b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 8709ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov int mColorMode = COLOR_MODE_COLOR; 8809ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov 89975c49f182d754dfe1a38ba0457d6e603b125570John Hoford int mOrientation = ORIENTATION_LANDSCAPE; 90975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 91b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintHelperKitkat(Context context) { 92b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav mContext = context; 93b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 94b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 95b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 96b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Selects whether the image will fill the paper and be cropped 97975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * <p/> 98b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * {@link #SCALE_MODE_FIT} 99b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * or whether the image will be scaled but leave white space 100b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * {@link #SCALE_MODE_FILL}. 101b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 102b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param scaleMode {@link #SCALE_MODE_FIT} or 103b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * {@link #SCALE_MODE_FILL} 104b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 105b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public void setScaleMode(int scaleMode) { 106b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav mScaleMode = scaleMode; 107b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 108b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 109b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 110b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Returns the scale mode with which the image will fill the paper. 111b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 112b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @return The scale Mode: {@link #SCALE_MODE_FIT} or 113b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * {@link #SCALE_MODE_FILL} 114b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 115b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public int getScaleMode() { 116b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return mScaleMode; 117b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 118b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 119b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 12009ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * Sets whether the image will be printed in color (default) 12109ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * {@link #COLOR_MODE_COLOR} or in back and white 12209ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * {@link #COLOR_MODE_MONOCHROME}. 12309ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * 12409ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * @param colorMode The color mode which is one of 125975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * {@link #COLOR_MODE_COLOR} and {@link #COLOR_MODE_MONOCHROME}. 12609ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov */ 12709ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov public void setColorMode(int colorMode) { 12809ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov mColorMode = colorMode; 12909ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov } 13009ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov 13109ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov /** 132975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * Sets whether to select landscape (default), {@link #ORIENTATION_LANDSCAPE} 133975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * or portrait {@link #ORIENTATION_PORTRAIT} 134975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * @param orientation The page orientation which is one of 135975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}. 136975c49f182d754dfe1a38ba0457d6e603b125570John Hoford */ 137975c49f182d754dfe1a38ba0457d6e603b125570John Hoford public void setOrientation(int orientation) { 138975c49f182d754dfe1a38ba0457d6e603b125570John Hoford mOrientation = orientation; 139975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 140975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 141975c49f182d754dfe1a38ba0457d6e603b125570John Hoford /** 142975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * Gets the page orientation with which the image will be printed. 143975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * 144975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * @return The preferred orientation which is one of 145975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT} 146975c49f182d754dfe1a38ba0457d6e603b125570John Hoford */ 147975c49f182d754dfe1a38ba0457d6e603b125570John Hoford public int getOrientation() { 148975c49f182d754dfe1a38ba0457d6e603b125570John Hoford return mOrientation; 149975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 150975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 151975c49f182d754dfe1a38ba0457d6e603b125570John Hoford /** 15209ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * Gets the color mode with which the image will be printed. 15309ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * 15409ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * @return The color mode which is one of {@link #COLOR_MODE_COLOR} 15509ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov * and {@link #COLOR_MODE_MONOCHROME}. 15609ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov */ 15709ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov public int getColorMode() { 15809ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov return mColorMode; 15909ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov } 16009ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov 16109ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov /** 162b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Prints a bitmap. 163b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 164b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param jobName The print job name. 165b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param bitmap The bitmap to print. 166b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov * @param callback Optional callback to observe when printing is finished. 167b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 168b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov public void printBitmap(final String jobName, final Bitmap bitmap, 169b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov final OnPrintFinishCallback callback) { 170b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (bitmap == null) { 171b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return; 172b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 173b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav final int fittingMode = mScaleMode; // grab the fitting mode at time of call 174b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintManager printManager = (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE); 175b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintAttributes.MediaSize mediaSize = PrintAttributes.MediaSize.UNKNOWN_PORTRAIT; 176b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (bitmap.getWidth() > bitmap.getHeight()) { 177b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav mediaSize = PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE; 178b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 17909ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov PrintAttributes attr = new PrintAttributes.Builder() 18009ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov .setMediaSize(mediaSize) 18109ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov .setColorMode(mColorMode) 18209ad64345349f27bdeb53c536f178e46bb7ce5acSvetoslav Ganov .build(); 183b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 184b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav printManager.print(jobName, 185b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav new PrintDocumentAdapter() { 186b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav private PrintAttributes mAttributes; 187b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 188b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav @Override 189b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public void onLayout(PrintAttributes oldPrintAttributes, 190b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintAttributes newPrintAttributes, 191b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav CancellationSignal cancellationSignal, 192b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav LayoutResultCallback layoutResultCallback, 193b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav Bundle bundle) { 194b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 195b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav mAttributes = newPrintAttributes; 196b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 197b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName) 198b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO) 199b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav .setPageCount(1) 200b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav .build(); 201b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav boolean changed = !newPrintAttributes.equals(oldPrintAttributes); 202b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav layoutResultCallback.onLayoutFinished(info, changed); 203b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 204b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 205b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav @Override 206b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor fileDescriptor, 207b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav CancellationSignal cancellationSignal, 208b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav WriteResultCallback writeResultCallback) { 209b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav PrintedPdfDocument pdfDocument = new PrintedPdfDocument(mContext, 210b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav mAttributes); 211b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav try { 212b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav Page page = pdfDocument.startPage(1); 213b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 214b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav RectF content = new RectF(page.getInfo().getContentRect()); 215b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 216975c49f182d754dfe1a38ba0457d6e603b125570John Hoford Matrix matrix = getMatrix(bitmap.getWidth(), bitmap.getHeight(), 217975c49f182d754dfe1a38ba0457d6e603b125570John Hoford content, fittingMode); 218b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 219b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Draw the bitmap. 220b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav page.getCanvas().drawBitmap(bitmap, matrix, null); 221b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 222b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Finish the page. 223b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav pdfDocument.finishPage(page); 224b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 225b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav try { 226b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Write the document. 227b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav pdfDocument.writeTo(new FileOutputStream( 228b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav fileDescriptor.getFileDescriptor())); 229b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Done. 230b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav writeResultCallback.onWriteFinished( 231b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav new PageRange[]{PageRange.ALL_PAGES}); 232b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } catch (IOException ioe) { 233b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Failed. 234b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav Log.e(LOG_TAG, "Error writing printed content", ioe); 235b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav writeResultCallback.onWriteFailed(null); 236b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 237b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } finally { 238b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (pdfDocument != null) { 239b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav pdfDocument.close(); 240b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 241b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (fileDescriptor != null) { 242b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav try { 243b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav fileDescriptor.close(); 244b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } catch (IOException ioe) { 245b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /* ignore */ 246b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 247b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 248b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 249b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 250b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov 251b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov @Override 252b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov public void onFinish() { 253b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov if (callback != null) { 254b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov callback.onFinish(); 255b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov } 256b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov } 257b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav }, attr); 258b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 259b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 260b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 261975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * Calculates the transform the print an Image to fill the page 262975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * 263975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * @param imageWidth with of bitmap 264975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * @param imageHeight height of bitmap 265975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * @param content The output page dimensions 266975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * @param fittingMode The mode of fitting {@link #SCALE_MODE_FILL} vs {@link #SCALE_MODE_FIT} 267975c49f182d754dfe1a38ba0457d6e603b125570John Hoford * @return Matrix to be used in canvas.drawBitmap(bitmap, matrix, null) call 268975c49f182d754dfe1a38ba0457d6e603b125570John Hoford */ 269975c49f182d754dfe1a38ba0457d6e603b125570John Hoford private Matrix getMatrix(int imageWidth, int imageHeight, RectF content, int fittingMode) { 270975c49f182d754dfe1a38ba0457d6e603b125570John Hoford Matrix matrix = new Matrix(); 271975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 272975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // Compute and apply scale to fill the page. 273975c49f182d754dfe1a38ba0457d6e603b125570John Hoford float scale = content.width() / imageWidth; 274975c49f182d754dfe1a38ba0457d6e603b125570John Hoford if (fittingMode == SCALE_MODE_FILL) { 275975c49f182d754dfe1a38ba0457d6e603b125570John Hoford scale = Math.max(scale, content.height() / imageHeight); 276975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } else { 277975c49f182d754dfe1a38ba0457d6e603b125570John Hoford scale = Math.min(scale, content.height() / imageHeight); 278975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 279975c49f182d754dfe1a38ba0457d6e603b125570John Hoford matrix.postScale(scale, scale); 280975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 281975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // Center the content. 282975c49f182d754dfe1a38ba0457d6e603b125570John Hoford final float translateX = (content.width() 283975c49f182d754dfe1a38ba0457d6e603b125570John Hoford - imageWidth * scale) / 2; 284975c49f182d754dfe1a38ba0457d6e603b125570John Hoford final float translateY = (content.height() 285975c49f182d754dfe1a38ba0457d6e603b125570John Hoford - imageHeight * scale) / 2; 286975c49f182d754dfe1a38ba0457d6e603b125570John Hoford matrix.postTranslate(translateX, translateY); 287975c49f182d754dfe1a38ba0457d6e603b125570John Hoford return matrix; 288975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 289975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 290975c49f182d754dfe1a38ba0457d6e603b125570John Hoford /** 291b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Prints an image located at the Uri. Image types supported are those of 292b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * <code>BitmapFactory.decodeStream</code> (JPEG, GIF, PNG, BMP, WEBP) 293b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 294b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param jobName The print job name. 295b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param imageFile The <code>Uri</code> pointing to an image to print. 296b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov * @param callback Optional callback to observe when printing is finished. 297b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @throws FileNotFoundException if <code>Uri</code> is not pointing to a valid image. 298b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 299b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov public void printBitmap(final String jobName, final Uri imageFile, 300b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov final OnPrintFinishCallback callback) throws FileNotFoundException { 301975c49f182d754dfe1a38ba0457d6e603b125570John Hoford final int fittingMode = mScaleMode; 302975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 303975c49f182d754dfe1a38ba0457d6e603b125570John Hoford PrintDocumentAdapter printDocumentAdapter = new PrintDocumentAdapter() { 304975c49f182d754dfe1a38ba0457d6e603b125570John Hoford private PrintAttributes mAttributes; 305854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav AsyncTask<Uri, Boolean, Bitmap> mLoadBitmap; 306975c49f182d754dfe1a38ba0457d6e603b125570John Hoford Bitmap mBitmap = null; 307975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 308975c49f182d754dfe1a38ba0457d6e603b125570John Hoford @Override 309975c49f182d754dfe1a38ba0457d6e603b125570John Hoford public void onLayout(final PrintAttributes oldPrintAttributes, 310975c49f182d754dfe1a38ba0457d6e603b125570John Hoford final PrintAttributes newPrintAttributes, 311975c49f182d754dfe1a38ba0457d6e603b125570John Hoford final CancellationSignal cancellationSignal, 312975c49f182d754dfe1a38ba0457d6e603b125570John Hoford final LayoutResultCallback layoutResultCallback, 313975c49f182d754dfe1a38ba0457d6e603b125570John Hoford Bundle bundle) { 314854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav 315854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav mAttributes = newPrintAttributes; 316854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav 317975c49f182d754dfe1a38ba0457d6e603b125570John Hoford if (cancellationSignal.isCanceled()) { 318975c49f182d754dfe1a38ba0457d6e603b125570John Hoford layoutResultCallback.onLayoutCancelled(); 319975c49f182d754dfe1a38ba0457d6e603b125570John Hoford return; 320975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 321975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // we finished the load 322975c49f182d754dfe1a38ba0457d6e603b125570John Hoford if (mBitmap != null) { 323975c49f182d754dfe1a38ba0457d6e603b125570John Hoford PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName) 324975c49f182d754dfe1a38ba0457d6e603b125570John Hoford .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO) 325975c49f182d754dfe1a38ba0457d6e603b125570John Hoford .setPageCount(1) 326975c49f182d754dfe1a38ba0457d6e603b125570John Hoford .build(); 327975c49f182d754dfe1a38ba0457d6e603b125570John Hoford boolean changed = !newPrintAttributes.equals(oldPrintAttributes); 328975c49f182d754dfe1a38ba0457d6e603b125570John Hoford layoutResultCallback.onLayoutFinished(info, changed); 329975c49f182d754dfe1a38ba0457d6e603b125570John Hoford return; 330975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 331975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 332854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav mLoadBitmap = new AsyncTask<Uri, Boolean, Bitmap>() { 333975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 334975c49f182d754dfe1a38ba0457d6e603b125570John Hoford @Override 335975c49f182d754dfe1a38ba0457d6e603b125570John Hoford protected void onPreExecute() { 336975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // First register for cancellation requests. 337975c49f182d754dfe1a38ba0457d6e603b125570John Hoford cancellationSignal.setOnCancelListener( 338975c49f182d754dfe1a38ba0457d6e603b125570John Hoford new CancellationSignal.OnCancelListener() { 339975c49f182d754dfe1a38ba0457d6e603b125570John Hoford @Override 340975c49f182d754dfe1a38ba0457d6e603b125570John Hoford public void onCancel() { // on different thread 341975c49f182d754dfe1a38ba0457d6e603b125570John Hoford cancelLoad(); 342975c49f182d754dfe1a38ba0457d6e603b125570John Hoford cancel(false); 343975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 344975c49f182d754dfe1a38ba0457d6e603b125570John Hoford }); 345975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 346975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 347975c49f182d754dfe1a38ba0457d6e603b125570John Hoford @Override 348975c49f182d754dfe1a38ba0457d6e603b125570John Hoford protected Bitmap doInBackground(Uri... uris) { 349975c49f182d754dfe1a38ba0457d6e603b125570John Hoford try { 350975c49f182d754dfe1a38ba0457d6e603b125570John Hoford return loadConstrainedBitmap(imageFile, MAX_PRINT_SIZE); 351975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } catch (FileNotFoundException e) { 352975c49f182d754dfe1a38ba0457d6e603b125570John Hoford /* ignore */ 353975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 354975c49f182d754dfe1a38ba0457d6e603b125570John Hoford return null; 355975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 356975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 357975c49f182d754dfe1a38ba0457d6e603b125570John Hoford @Override 358975c49f182d754dfe1a38ba0457d6e603b125570John Hoford protected void onPostExecute(Bitmap bitmap) { 359975c49f182d754dfe1a38ba0457d6e603b125570John Hoford super.onPostExecute(bitmap); 360975c49f182d754dfe1a38ba0457d6e603b125570John Hoford mBitmap = bitmap; 361975c49f182d754dfe1a38ba0457d6e603b125570John Hoford if (bitmap != null) { 362975c49f182d754dfe1a38ba0457d6e603b125570John Hoford PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName) 363975c49f182d754dfe1a38ba0457d6e603b125570John Hoford .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO) 364975c49f182d754dfe1a38ba0457d6e603b125570John Hoford .setPageCount(1) 365975c49f182d754dfe1a38ba0457d6e603b125570John Hoford .build(); 366975c49f182d754dfe1a38ba0457d6e603b125570John Hoford boolean changed = !newPrintAttributes.equals(oldPrintAttributes); 367975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 368975c49f182d754dfe1a38ba0457d6e603b125570John Hoford layoutResultCallback.onLayoutFinished(info, changed); 369975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 370975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } else { 371975c49f182d754dfe1a38ba0457d6e603b125570John Hoford layoutResultCallback.onLayoutFailed(null); 372975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 373854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav mLoadBitmap = null; 374975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 375975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 376975c49f182d754dfe1a38ba0457d6e603b125570John Hoford @Override 377975c49f182d754dfe1a38ba0457d6e603b125570John Hoford protected void onCancelled(Bitmap result) { 378975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // Task was cancelled, report that. 379975c49f182d754dfe1a38ba0457d6e603b125570John Hoford layoutResultCallback.onLayoutCancelled(); 380854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav mLoadBitmap = null; 381975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 382854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav }.execute(); 383975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 384975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 385975c49f182d754dfe1a38ba0457d6e603b125570John Hoford private void cancelLoad() { 386975c49f182d754dfe1a38ba0457d6e603b125570John Hoford synchronized (mLock) { // prevent race with set null below 387975c49f182d754dfe1a38ba0457d6e603b125570John Hoford if (mDecodeOptions != null) { 388975c49f182d754dfe1a38ba0457d6e603b125570John Hoford mDecodeOptions.requestCancelDecode(); 389975c49f182d754dfe1a38ba0457d6e603b125570John Hoford mDecodeOptions = null; 390975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 391975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 392975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 393975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 394975c49f182d754dfe1a38ba0457d6e603b125570John Hoford @Override 395975c49f182d754dfe1a38ba0457d6e603b125570John Hoford public void onFinish() { 396975c49f182d754dfe1a38ba0457d6e603b125570John Hoford super.onFinish(); 397975c49f182d754dfe1a38ba0457d6e603b125570John Hoford cancelLoad(); 398854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav if (mLoadBitmap != null) { 399854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav mLoadBitmap.cancel(true); 400854aed9e83ca17ad558f3aec7fff49ef2153ceafSvetoslav } 401b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov if (callback != null) { 402b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov callback.onFinish(); 403b4eb9c984f1c6ac8007c74fab239437cf9f6b474Svet Ganov } 404975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 405975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 406975c49f182d754dfe1a38ba0457d6e603b125570John Hoford @Override 407975c49f182d754dfe1a38ba0457d6e603b125570John Hoford public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor fileDescriptor, 408975c49f182d754dfe1a38ba0457d6e603b125570John Hoford CancellationSignal cancellationSignal, 409975c49f182d754dfe1a38ba0457d6e603b125570John Hoford WriteResultCallback writeResultCallback) { 410975c49f182d754dfe1a38ba0457d6e603b125570John Hoford PrintedPdfDocument pdfDocument = new PrintedPdfDocument(mContext, 411975c49f182d754dfe1a38ba0457d6e603b125570John Hoford mAttributes); 412975c49f182d754dfe1a38ba0457d6e603b125570John Hoford try { 413975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 414975c49f182d754dfe1a38ba0457d6e603b125570John Hoford Page page = pdfDocument.startPage(1); 415975c49f182d754dfe1a38ba0457d6e603b125570John Hoford RectF content = new RectF(page.getInfo().getContentRect()); 416975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 417975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // Compute and apply scale to fill the page. 418975c49f182d754dfe1a38ba0457d6e603b125570John Hoford Matrix matrix = getMatrix(mBitmap.getWidth(), mBitmap.getHeight(), 419975c49f182d754dfe1a38ba0457d6e603b125570John Hoford content, fittingMode); 420975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 421975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // Draw the bitmap. 422975c49f182d754dfe1a38ba0457d6e603b125570John Hoford page.getCanvas().drawBitmap(mBitmap, matrix, null); 423975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 424975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // Finish the page. 425975c49f182d754dfe1a38ba0457d6e603b125570John Hoford pdfDocument.finishPage(page); 426975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 427975c49f182d754dfe1a38ba0457d6e603b125570John Hoford try { 428975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // Write the document. 429975c49f182d754dfe1a38ba0457d6e603b125570John Hoford pdfDocument.writeTo(new FileOutputStream( 430975c49f182d754dfe1a38ba0457d6e603b125570John Hoford fileDescriptor.getFileDescriptor())); 431975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // Done. 432975c49f182d754dfe1a38ba0457d6e603b125570John Hoford writeResultCallback.onWriteFinished( 433975c49f182d754dfe1a38ba0457d6e603b125570John Hoford new PageRange[]{PageRange.ALL_PAGES}); 434975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } catch (IOException ioe) { 435975c49f182d754dfe1a38ba0457d6e603b125570John Hoford // Failed. 436975c49f182d754dfe1a38ba0457d6e603b125570John Hoford Log.e(LOG_TAG, "Error writing printed content", ioe); 437975c49f182d754dfe1a38ba0457d6e603b125570John Hoford writeResultCallback.onWriteFailed(null); 438975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 439975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } finally { 440975c49f182d754dfe1a38ba0457d6e603b125570John Hoford if (pdfDocument != null) { 441975c49f182d754dfe1a38ba0457d6e603b125570John Hoford pdfDocument.close(); 442975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 443975c49f182d754dfe1a38ba0457d6e603b125570John Hoford if (fileDescriptor != null) { 444975c49f182d754dfe1a38ba0457d6e603b125570John Hoford try { 445975c49f182d754dfe1a38ba0457d6e603b125570John Hoford fileDescriptor.close(); 446975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } catch (IOException ioe) { 447975c49f182d754dfe1a38ba0457d6e603b125570John Hoford /* ignore */ 448975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 449975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 450975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 451975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 452975c49f182d754dfe1a38ba0457d6e603b125570John Hoford }; 453975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 454975c49f182d754dfe1a38ba0457d6e603b125570John Hoford PrintManager printManager = (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE); 455975c49f182d754dfe1a38ba0457d6e603b125570John Hoford PrintAttributes.Builder builder = new PrintAttributes.Builder(); 456975c49f182d754dfe1a38ba0457d6e603b125570John Hoford builder.setColorMode(mColorMode); 457975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 458975c49f182d754dfe1a38ba0457d6e603b125570John Hoford if (mOrientation == ORIENTATION_LANDSCAPE) { 459975c49f182d754dfe1a38ba0457d6e603b125570John Hoford builder.setMediaSize(PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE); 460975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } else if (mOrientation == ORIENTATION_PORTRAIT) { 461975c49f182d754dfe1a38ba0457d6e603b125570John Hoford builder.setMediaSize(PrintAttributes.MediaSize.UNKNOWN_PORTRAIT); 462975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 463975c49f182d754dfe1a38ba0457d6e603b125570John Hoford PrintAttributes attr = builder.build(); 464975c49f182d754dfe1a38ba0457d6e603b125570John Hoford 465975c49f182d754dfe1a38ba0457d6e603b125570John Hoford printManager.print(jobName, printDocumentAdapter, attr); 466b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 467b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 468b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 469b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Loads a bitmap while limiting its size 470b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * 471b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param uri location of a valid image 472b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @param maxSideLength the maximum length of a size 473b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @return the Bitmap 474b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * @throws FileNotFoundException if the Uri does not point to an image 475b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 476b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav private Bitmap loadConstrainedBitmap(Uri uri, int maxSideLength) throws FileNotFoundException { 477b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (maxSideLength <= 0 || uri == null || mContext == null) { 478b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav throw new IllegalArgumentException("bad argument to getScaledBitmap"); 479b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 480b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Get width and height of stored bitmap 481b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav BitmapFactory.Options opt = new BitmapFactory.Options(); 482b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav opt.inJustDecodeBounds = true; 483b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav loadBitmap(uri, opt); 484b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 485b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav int w = opt.outWidth; 486b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav int h = opt.outHeight; 487b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 488b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // If bitmap cannot be decoded, return null 489b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (w <= 0 || h <= 0) { 490b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return null; 491b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 492b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 493b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Find best downsampling size 494b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav int imageSide = Math.max(w, h); 495b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 496b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav int sampleSize = 1; 497b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav while (imageSide > maxSideLength) { 498b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav imageSide >>>= 1; 499b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav sampleSize <<= 1; 500b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 501b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 502b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav // Make sure sample size is reasonable 503b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (sampleSize <= 0 || 0 >= (int) (Math.min(w, h) / sampleSize)) { 504b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return null; 505b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 506975c49f182d754dfe1a38ba0457d6e603b125570John Hoford BitmapFactory.Options decodeOptions = null; 507975c49f182d754dfe1a38ba0457d6e603b125570John Hoford synchronized (mLock) { // prevent race with set null below 508975c49f182d754dfe1a38ba0457d6e603b125570John Hoford mDecodeOptions = new BitmapFactory.Options(); 509975c49f182d754dfe1a38ba0457d6e603b125570John Hoford mDecodeOptions.inMutable = true; 510975c49f182d754dfe1a38ba0457d6e603b125570John Hoford mDecodeOptions.inSampleSize = sampleSize; 511975c49f182d754dfe1a38ba0457d6e603b125570John Hoford decodeOptions = mDecodeOptions; 512975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 513975c49f182d754dfe1a38ba0457d6e603b125570John Hoford try { 514975c49f182d754dfe1a38ba0457d6e603b125570John Hoford return loadBitmap(uri, decodeOptions); 515975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } finally { 516975c49f182d754dfe1a38ba0457d6e603b125570John Hoford synchronized (mLock) { 517975c49f182d754dfe1a38ba0457d6e603b125570John Hoford mDecodeOptions = null; 518975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 519975c49f182d754dfe1a38ba0457d6e603b125570John Hoford } 520b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 521b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav 522b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav /** 523b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Returns the bitmap from the given uri loaded using the given options. 524b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav * Returns null on failure. 525b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav */ 526b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav private Bitmap loadBitmap(Uri uri, BitmapFactory.Options o) throws FileNotFoundException { 527b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav if (uri == null || mContext == null) { 528b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav throw new IllegalArgumentException("bad argument to loadBitmap"); 529b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 530b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav InputStream is = null; 531b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav try { 532b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav is = mContext.getContentResolver().openInputStream(uri); 533b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav return BitmapFactory.decodeStream(is, null, o); 534b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } finally { 535545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov if (is != null) { 536545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov try { 537545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov is.close(); 538545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov } catch (IOException t) { 539545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov Log.w(LOG_TAG, "close fail ", t); 540545f1bf8b47c12d2453143706a2fd76d9eef2368Svetoslav Ganov } 541b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 542b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 543b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav } 544b363776d911abae9d067b9ef77fccc1c3c56e652Svetoslav}