• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "printing/printing_context_android.h"
6 
7 #include <vector>
8 
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_array.h"
11 #include "base/android/jni_string.h"
12 #include "base/logging.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/values.h"
15 #include "jni/PrintingContext_jni.h"
16 #include "printing/metafile.h"
17 #include "printing/print_job_constants.h"
18 #include "printing/units.h"
19 #include "third_party/icu/source/i18n/unicode/ulocdata.h"
20 
21 namespace {
22 
23 // 1 inch in mils.
24 const int kInchToMil = 1000;
25 
Round(double x)26 inline int Round(double x) {
27   return static_cast<int>(x + 0.5);
28 }
29 
30 // Sets the page sizes for a |PrintSettings| object.  |width| and |height|
31 // arguments should be in device units.
SetSizes(printing::PrintSettings * settings,int dpi,int width,int height)32 void SetSizes(
33     printing::PrintSettings* settings, int dpi, int width, int height) {
34   gfx::Size physical_size_device_units(width, height);
35   // Assume full page is printable for now.
36   gfx::Rect printable_area_device_units(0, 0, width, height);
37 
38   settings->set_dpi(dpi);
39   settings->SetPrinterPrintableArea(physical_size_device_units,
40                                     printable_area_device_units,
41                                     false);
42 }
43 
GetPageRanges(JNIEnv * env,jintArray int_arr,printing::PageRanges & range_vector)44 void GetPageRanges(JNIEnv* env,
45                    jintArray int_arr,
46                    printing::PageRanges& range_vector) {
47   std::vector<int> pages;
48   base::android::JavaIntArrayToIntVector(env, int_arr, &pages);
49   for (std::vector<int>::const_iterator it = pages.begin();
50       it != pages.end();
51       ++it) {
52     printing::PageRange range;
53     range.from = *it;
54     range.to = *it;
55     range_vector.push_back(range);
56   }
57 }
58 
59 }  // namespace
60 
61 namespace printing {
62 
63 // static
Create(const std::string & app_locale)64 PrintingContext* PrintingContext::Create(const std::string& app_locale) {
65   return new PrintingContextAndroid(app_locale);
66 }
67 
68 // static
PdfWritingDone(int fd,bool success)69 void PrintingContextAndroid::PdfWritingDone(int fd, bool success) {
70   JNIEnv* env = base::android::AttachCurrentThread();
71   Java_PrintingContext_pdfWritingDone(env, fd, success);
72 }
73 
PrintingContextAndroid(const std::string & app_locale)74 PrintingContextAndroid::PrintingContextAndroid(const std::string& app_locale)
75     : PrintingContext(app_locale) {
76   // The constructor is run in the IO thread.
77 }
78 
~PrintingContextAndroid()79 PrintingContextAndroid::~PrintingContextAndroid() {
80 }
81 
AskUserForSettings(gfx::NativeView parent_view,int max_pages,bool has_selection,const PrintSettingsCallback & callback)82 void PrintingContextAndroid::AskUserForSettings(
83     gfx::NativeView parent_view,
84     int max_pages,
85     bool has_selection,
86     const PrintSettingsCallback& callback) {
87   // This method is always run in the UI thread.
88   callback_ = callback;
89 
90   JNIEnv* env = base::android::AttachCurrentThread();
91   if (j_printing_context_.is_null()) {
92     j_printing_context_.Reset(Java_PrintingContext_create(
93         env,
94         reinterpret_cast<intptr_t>(this)));
95   }
96 
97   Java_PrintingContext_pageCountEstimationDone(env,
98                                                j_printing_context_.obj(),
99                                                max_pages);
100 }
101 
AskUserForSettingsReply(JNIEnv * env,jobject obj,jboolean success)102 void PrintingContextAndroid::AskUserForSettingsReply(JNIEnv* env,
103                                                      jobject obj,
104                                                      jboolean success) {
105   if (!success) {
106     // TODO(cimamoglu): Differentiate between FAILED And CANCEL.
107     callback_.Run(FAILED);
108     return;
109   }
110 
111   // We use device name variable to store the file descriptor.  This is hacky
112   // but necessary. Since device name is not necessary for the upstream
113   // printing code for Android, this is harmless.
114   int fd = Java_PrintingContext_getFileDescriptor(env,
115                                                   j_printing_context_.obj());
116   settings_.set_device_name(base::IntToString16(fd));
117 
118   ScopedJavaLocalRef<jintArray> intArr =
119       Java_PrintingContext_getPages(env, j_printing_context_.obj());
120   if (intArr.obj() != NULL) {
121     PageRanges range_vector;
122     GetPageRanges(env, intArr.obj(), range_vector);
123     settings_.set_ranges(range_vector);
124   }
125 
126   int dpi = Java_PrintingContext_getDpi(env, j_printing_context_.obj());
127   int width = Java_PrintingContext_getWidth(env, j_printing_context_.obj());
128   int height = Java_PrintingContext_getHeight(env, j_printing_context_.obj());
129   width = Round(ConvertUnitDouble(width, kInchToMil, 1.0) * dpi);
130   height = Round(ConvertUnitDouble(height, kInchToMil, 1.0) * dpi);
131   SetSizes(&settings_, dpi, width, height);
132 
133   callback_.Run(OK);
134 }
135 
UseDefaultSettings()136 PrintingContext::Result PrintingContextAndroid::UseDefaultSettings() {
137   DCHECK(!in_print_job_);
138 
139   ResetSettings();
140   settings_.set_dpi(kDefaultPdfDpi);
141   gfx::Size physical_size = GetPdfPaperSizeDeviceUnits();
142   SetSizes(&settings_, kDefaultPdfDpi, physical_size.width(),
143            physical_size.height());
144   return OK;
145 }
146 
GetPdfPaperSizeDeviceUnits()147 gfx::Size PrintingContextAndroid::GetPdfPaperSizeDeviceUnits() {
148   // NOTE: This implementation is the same as in PrintingContextNoSystemDialog.
149   int32_t width = 0;
150   int32_t height = 0;
151   UErrorCode error = U_ZERO_ERROR;
152   ulocdata_getPaperSize(app_locale_.c_str(), &height, &width, &error);
153   if (error > U_ZERO_ERROR) {
154     // If the call failed, assume a paper size of 8.5 x 11 inches.
155     LOG(WARNING) << "ulocdata_getPaperSize failed, using 8.5 x 11, error: "
156                  << error;
157     width = static_cast<int>(
158         kLetterWidthInch * settings_.device_units_per_inch());
159     height = static_cast<int>(
160         kLetterHeightInch  * settings_.device_units_per_inch());
161   } else {
162     // ulocdata_getPaperSize returns the width and height in mm.
163     // Convert this to pixels based on the dpi.
164     float multiplier = 100 * settings_.device_units_per_inch();
165     multiplier /= kHundrethsMMPerInch;
166     width *= multiplier;
167     height *= multiplier;
168   }
169   return gfx::Size(width, height);
170 }
171 
UpdatePrinterSettings(bool external_preview)172 PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings(
173     bool external_preview) {
174   DCHECK(!in_print_job_);
175 
176   // Intentional No-op.
177 
178   return OK;
179 }
180 
InitWithSettings(const PrintSettings & settings)181 PrintingContext::Result PrintingContextAndroid::InitWithSettings(
182     const PrintSettings& settings) {
183   DCHECK(!in_print_job_);
184 
185   settings_ = settings;
186 
187   return OK;
188 }
189 
NewDocument(const base::string16 & document_name)190 PrintingContext::Result PrintingContextAndroid::NewDocument(
191     const base::string16& document_name) {
192   DCHECK(!in_print_job_);
193   in_print_job_ = true;
194 
195   return OK;
196 }
197 
NewPage()198 PrintingContext::Result PrintingContextAndroid::NewPage() {
199   if (abort_printing_)
200     return CANCEL;
201   DCHECK(in_print_job_);
202 
203   // Intentional No-op.
204 
205   return OK;
206 }
207 
PageDone()208 PrintingContext::Result PrintingContextAndroid::PageDone() {
209   if (abort_printing_)
210     return CANCEL;
211   DCHECK(in_print_job_);
212 
213   // Intentional No-op.
214 
215   return OK;
216 }
217 
DocumentDone()218 PrintingContext::Result PrintingContextAndroid::DocumentDone() {
219   if (abort_printing_)
220     return CANCEL;
221   DCHECK(in_print_job_);
222 
223   ResetSettings();
224   return OK;
225 }
226 
Cancel()227 void PrintingContextAndroid::Cancel() {
228   abort_printing_ = true;
229   in_print_job_ = false;
230 }
231 
ReleaseContext()232 void PrintingContextAndroid::ReleaseContext() {
233   // Intentional No-op.
234 }
235 
context() const236 gfx::NativeDrawingContext PrintingContextAndroid::context() const {
237   // Intentional No-op.
238   return NULL;
239 }
240 
241 // static
RegisterPrintingContext(JNIEnv * env)242 bool PrintingContextAndroid::RegisterPrintingContext(JNIEnv* env) {
243    return RegisterNativesImpl(env);
244 }
245 
246 }  // namespace printing
247