1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v4.print;
18
19import android.content.Context;
20import android.graphics.Bitmap;
21import android.os.Build;
22
23import android.net.Uri;
24
25import java.io.FileNotFoundException;
26
27/**
28 * Helper for printing bitmaps.
29 */
30public final class PrintHelper {
31    /**
32     * image will be scaled but leave white space
33     */
34    public static final int SCALE_MODE_FIT = 1;
35
36    /**
37     * image will fill the paper and be cropped (default)
38     */
39    public static final int SCALE_MODE_FILL = 2;
40
41    /**
42     * this is a black and white image
43     */
44    public static final int COLOR_MODE_MONOCHROME = 1;
45
46    /**
47     * this is a color image (default)
48     */
49    public static final int COLOR_MODE_COLOR = 2;
50
51    /**
52     * Print the image in landscape orientation (default).
53     */
54    public static final int ORIENTATION_LANDSCAPE = 1;
55
56    /**
57     * Print the image in  portrait orientation.
58     */
59    public static final int ORIENTATION_PORTRAIT = 2;
60
61    /**
62     * Callback for observing when a print operation is completed.
63     * When print is finished either the system acquired the
64     * document to print or printing was cancelled.
65     */
66    public interface OnPrintFinishCallback {
67
68        /**
69         * Called when a print operation is finished.
70         */
71        public void onFinish();
72    }
73
74    PrintHelperVersionImpl mImpl;
75
76    /**
77     * Gets whether the system supports printing.
78     *
79     * @return True if printing is supported.
80     */
81    public static boolean systemSupportsPrint() {
82        if (Build.VERSION.SDK_INT >= 19) {
83            // Supported on Android 4.4 or later.
84            return true;
85        }
86        return false;
87    }
88
89    /**
90     * Interface implemented by classes that support printing
91     */
92    static interface PrintHelperVersionImpl {
93
94        public void setScaleMode(int scaleMode);
95
96        public int getScaleMode();
97
98        public void setColorMode(int colorMode);
99
100        public int getColorMode();
101
102        public void setOrientation(int orientation);
103
104        public int getOrientation();
105
106        public void printBitmap(String jobName, Bitmap bitmap, OnPrintFinishCallback callback);
107
108        public void printBitmap(String jobName, Uri imageFile, OnPrintFinishCallback callback)
109                throws FileNotFoundException;
110    }
111
112    /**
113     * Implementation used when we do not support printing
114     */
115    private static final class PrintHelperStubImpl implements PrintHelperVersionImpl {
116        int mScaleMode = SCALE_MODE_FILL;
117        int mColorMode = COLOR_MODE_COLOR;
118        int mOrientation = ORIENTATION_LANDSCAPE;
119        @Override
120        public void setScaleMode(int scaleMode) {
121            mScaleMode = scaleMode;
122        }
123
124        @Override
125        public int getColorMode() {
126            return mColorMode;
127        }
128
129        @Override
130        public void setColorMode(int colorMode) {
131            mColorMode = colorMode;
132        }
133
134        @Override
135        public void setOrientation(int orientation) { mOrientation = orientation; }
136
137        @Override
138        public int getOrientation() { return mOrientation; }
139
140        @Override
141        public int getScaleMode() {
142            return mScaleMode;
143        }
144
145        @Override
146        public void printBitmap(String jobName, Bitmap bitmap, OnPrintFinishCallback callback) {
147        }
148
149        @Override
150        public void printBitmap(String jobName, Uri imageFile, OnPrintFinishCallback callback) {
151        }
152    }
153
154    /**
155     * Generic implementation for KitKat to Api24
156     */
157    private static class PrintHelperImpl<RealHelper extends PrintHelperKitkat>
158            implements PrintHelperVersionImpl {
159        private final RealHelper mPrintHelper;
160
161        protected PrintHelperImpl(RealHelper helper) {
162            mPrintHelper = helper;
163        }
164
165        @Override
166        public void setScaleMode(int scaleMode) {
167            mPrintHelper.setScaleMode(scaleMode);
168        }
169
170        @Override
171        public int getScaleMode() {
172            return mPrintHelper.getScaleMode();
173        }
174
175        @Override
176        public void setColorMode(int colorMode) {
177            mPrintHelper.setColorMode(colorMode);
178        }
179
180        @Override
181        public int getColorMode() {
182            return mPrintHelper.getColorMode();
183        }
184
185        @Override
186        public void setOrientation(int orientation) {
187            mPrintHelper.setOrientation(orientation);
188        }
189
190        @Override
191        public int getOrientation() {
192            return mPrintHelper.getOrientation();
193        }
194
195        @Override
196        public void printBitmap(String jobName, Bitmap bitmap,
197                final OnPrintFinishCallback callback) {
198            RealHelper.OnPrintFinishCallback delegateCallback = null;
199            if (callback != null) {
200                delegateCallback = new RealHelper.OnPrintFinishCallback() {
201                    @Override
202                    public void onFinish() {
203                        callback.onFinish();
204                    }
205                };
206            }
207            mPrintHelper.printBitmap(jobName, bitmap, delegateCallback);
208        }
209
210        @Override
211        public void printBitmap(String jobName, Uri imageFile,
212                final OnPrintFinishCallback callback) throws FileNotFoundException {
213            RealHelper.OnPrintFinishCallback delegateCallback = null;
214            if (callback != null) {
215                delegateCallback = new RealHelper.OnPrintFinishCallback() {
216                    @Override
217                    public void onFinish() {
218                        callback.onFinish();
219                    }
220                };
221            }
222            mPrintHelper.printBitmap(jobName, imageFile, delegateCallback);
223        }
224    }
225
226    /**
227     * Implementation used on KitKat
228     */
229    private static final class PrintHelperKitkatImpl extends PrintHelperImpl<PrintHelperKitkat> {
230        PrintHelperKitkatImpl(Context context) {
231            super(new PrintHelperKitkat(context));
232        }
233    }
234
235    /**
236     * Implementation used on Api20 to Api22
237     */
238    private static final class PrintHelperApi20Impl extends PrintHelperImpl<PrintHelperApi20> {
239        PrintHelperApi20Impl(Context context) {
240            super(new PrintHelperApi20(context));
241        }
242    }
243
244    /**
245     * Implementation used on Api23
246     */
247    private static final class PrintHelperApi23Impl extends PrintHelperImpl<PrintHelperApi23> {
248        PrintHelperApi23Impl(Context context) {
249            super(new PrintHelperApi23(context));
250        }
251    }
252
253
254    /**
255     * Implementation used on Api24 and above
256     */
257    private static final class PrintHelperApi24Impl extends PrintHelperImpl<PrintHelperApi24> {
258        PrintHelperApi24Impl(Context context) {
259            super(new PrintHelperApi24(context));
260        }
261    }
262
263    /**
264     * Returns the PrintHelper that can be used to print images.
265     *
266     * @param context A context for accessing system resources.
267     * @return the <code>PrintHelper</code> to support printing images.
268     */
269    public PrintHelper(Context context) {
270        if (systemSupportsPrint()) {
271            if (Build.VERSION.SDK_INT >= 24) {
272                mImpl = new PrintHelperApi24Impl(context);
273            } else if (Build.VERSION.SDK_INT >= 23) {
274                mImpl = new PrintHelperApi23Impl(context);
275            } else if (Build.VERSION.SDK_INT >= 20) {
276                mImpl = new PrintHelperApi20Impl(context);
277            } else {
278                mImpl = new PrintHelperKitkatImpl(context);
279            }
280        } else {
281            mImpl = new PrintHelperStubImpl();
282        }
283    }
284
285    /**
286     * Selects whether the image will fill the paper and be cropped
287     * {@link #SCALE_MODE_FIT}
288     * or whether the image will be scaled but leave white space
289     * {@link #SCALE_MODE_FILL}.
290     *
291     * @param scaleMode {@link #SCALE_MODE_FIT} or
292     *                  {@link #SCALE_MODE_FILL}
293     */
294    public void setScaleMode(int scaleMode) {
295        mImpl.setScaleMode(scaleMode);
296    }
297
298    /**
299     * Returns the scale mode with which the image will fill the paper.
300     *
301     * @return The scale Mode: {@link #SCALE_MODE_FIT} or
302     * {@link #SCALE_MODE_FILL}
303     */
304    public int getScaleMode() {
305        return mImpl.getScaleMode();
306    }
307
308    /**
309     * Sets whether the image will be printed in color (default)
310     * {@link #COLOR_MODE_COLOR} or in back and white
311     * {@link #COLOR_MODE_MONOCHROME}.
312     *
313     * @param colorMode The color mode which is one of
314     * {@link #COLOR_MODE_COLOR} and {@link #COLOR_MODE_MONOCHROME}.
315     */
316    public void setColorMode(int colorMode) {
317        mImpl.setColorMode(colorMode);
318    }
319
320    /**
321     * Gets the color mode with which the image will be printed.
322     *
323     * @return The color mode which is one of {@link #COLOR_MODE_COLOR}
324     * and {@link #COLOR_MODE_MONOCHROME}.
325     */
326    public int getColorMode() {
327        return mImpl.getColorMode();
328    }
329
330    /**
331     * Sets whether the image will be printed in landscape {@link #ORIENTATION_LANDSCAPE} (default)
332     * or portrait {@link #ORIENTATION_PORTRAIT}.
333     *
334     * @param orientation The page orientation which is one of
335     *                    {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}.
336     */
337    public void setOrientation(int orientation) {
338        mImpl.setOrientation(orientation);
339    }
340
341    /**
342     * Gets whether the image will be printed in landscape or portrait.
343     *
344     * @return The page orientation which is one of
345     * {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}.
346     */
347    public int getOrientation() {
348        return mImpl.getOrientation();
349    }
350
351
352    /**
353     * Prints a bitmap.
354     *
355     * @param jobName The print job name.
356     * @param bitmap  The bitmap to print.
357     */
358    public void printBitmap(String jobName, Bitmap bitmap) {
359        mImpl.printBitmap(jobName, bitmap, null);
360    }
361
362    /**
363     * Prints a bitmap.
364     *
365     * @param jobName The print job name.
366     * @param bitmap  The bitmap to print.
367     * @param callback Optional callback to observe when printing is finished.
368     */
369    public void printBitmap(String jobName, Bitmap bitmap, OnPrintFinishCallback callback) {
370        mImpl.printBitmap(jobName, bitmap, callback);
371    }
372
373    /**
374     * Prints an image located at the Uri. Image types supported are those of
375     * {@link android.graphics.BitmapFactory#decodeStream(java.io.InputStream)
376     * android.graphics.BitmapFactory.decodeStream(java.io.InputStream)}
377     *
378     * @param jobName   The print job name.
379     * @param imageFile The <code>Uri</code> pointing to an image to print.
380     * @throws FileNotFoundException if <code>Uri</code> is not pointing to a valid image.
381     */
382    public void printBitmap(String jobName, Uri imageFile) throws FileNotFoundException {
383        mImpl.printBitmap(jobName, imageFile, null);
384    }
385
386    /**
387     * Prints an image located at the Uri. Image types supported are those of
388     * {@link android.graphics.BitmapFactory#decodeStream(java.io.InputStream)
389     * android.graphics.BitmapFactory.decodeStream(java.io.InputStream)}
390     *
391     * @param jobName   The print job name.
392     * @param imageFile The <code>Uri</code> pointing to an image to print.
393     * @throws FileNotFoundException if <code>Uri</code> is not pointing to a valid image.
394     * @param callback Optional callback to observe when printing is finished.
395     */
396    public void printBitmap(String jobName, Uri imageFile, OnPrintFinishCallback callback)
397            throws FileNotFoundException {
398        mImpl.printBitmap(jobName, imageFile, callback);
399    }
400}
401