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