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.
5 #include "printing/printing_context_android.h"
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"
24 const int kInchToMil
= 1000;
26 inline int Round(double x
) {
27 return static_cast<int>(x
+ 0.5);
30 // Sets the page sizes for a |PrintSettings| object. |width| and |height|
31 // arguments should be in device units.
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
);
38 settings
->set_dpi(dpi
);
39 settings
->SetPrinterPrintableArea(physical_size_device_units
,
40 printable_area_device_units
,
44 void GetPageRanges(JNIEnv
* env
,
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();
52 printing::PageRange range
;
55 range_vector
.push_back(range
);
64 scoped_ptr
<PrintingContext
> PrintingContext::Create(Delegate
* delegate
) {
65 return make_scoped_ptr
<PrintingContext
>(new PrintingContextAndroid(delegate
));
69 void PrintingContextAndroid::PdfWritingDone(int fd
, bool success
) {
70 JNIEnv
* env
= base::android::AttachCurrentThread();
71 Java_PrintingContext_pdfWritingDone(env
, fd
, success
);
74 PrintingContextAndroid::PrintingContextAndroid(Delegate
* delegate
)
75 : PrintingContext(delegate
) {
76 // The constructor is run in the IO thread.
79 PrintingContextAndroid::~PrintingContextAndroid() {
82 void PrintingContextAndroid::AskUserForSettings(
86 const PrintSettingsCallback
& callback
) {
87 // This method is always run in the UI thread.
90 JNIEnv
* env
= base::android::AttachCurrentThread();
91 if (j_printing_context_
.is_null()) {
92 j_printing_context_
.Reset(Java_PrintingContext_create(
94 reinterpret_cast<intptr_t>(this)));
98 Java_PrintingContext_showPrintDialog(env
, j_printing_context_
.obj());
100 Java_PrintingContext_pageCountEstimationDone(env
,
101 j_printing_context_
.obj(),
106 void PrintingContextAndroid::AskUserForSettingsReply(JNIEnv
* env
,
110 // TODO(cimamoglu): Differentiate between FAILED And CANCEL.
111 callback_
.Run(FAILED
);
115 // We use device name variable to store the file descriptor. This is hacky
116 // but necessary. Since device name is not necessary for the upstream
117 // printing code for Android, this is harmless.
118 int fd
= Java_PrintingContext_getFileDescriptor(env
,
119 j_printing_context_
.obj());
120 settings_
.set_device_name(base::IntToString16(fd
));
122 ScopedJavaLocalRef
<jintArray
> intArr
=
123 Java_PrintingContext_getPages(env
, j_printing_context_
.obj());
124 if (intArr
.obj() != NULL
) {
125 PageRanges range_vector
;
126 GetPageRanges(env
, intArr
.obj(), range_vector
);
127 settings_
.set_ranges(range_vector
);
130 int dpi
= Java_PrintingContext_getDpi(env
, j_printing_context_
.obj());
131 int width
= Java_PrintingContext_getWidth(env
, j_printing_context_
.obj());
132 int height
= Java_PrintingContext_getHeight(env
, j_printing_context_
.obj());
133 width
= Round(ConvertUnitDouble(width
, kInchToMil
, 1.0) * dpi
);
134 height
= Round(ConvertUnitDouble(height
, kInchToMil
, 1.0) * dpi
);
135 SetSizes(&settings_
, dpi
, width
, height
);
140 void PrintingContextAndroid::ShowSystemDialogDone(JNIEnv
* env
,
142 // Settings are not updated, callback is called only to unblock javascript.
143 callback_
.Run(CANCEL
);
146 PrintingContext::Result
PrintingContextAndroid::UseDefaultSettings() {
147 DCHECK(!in_print_job_
);
150 settings_
.set_dpi(kDefaultPdfDpi
);
151 gfx::Size physical_size
= GetPdfPaperSizeDeviceUnits();
152 SetSizes(&settings_
, kDefaultPdfDpi
, physical_size
.width(),
153 physical_size
.height());
157 gfx::Size
PrintingContextAndroid::GetPdfPaperSizeDeviceUnits() {
158 // NOTE: This implementation is the same as in PrintingContextNoSystemDialog.
161 UErrorCode error
= U_ZERO_ERROR
;
162 ulocdata_getPaperSize(
163 delegate_
->GetAppLocale().c_str(), &height
, &width
, &error
);
164 if (error
> U_ZERO_ERROR
) {
165 // If the call failed, assume a paper size of 8.5 x 11 inches.
166 LOG(WARNING
) << "ulocdata_getPaperSize failed, using 8.5 x 11, error: "
168 width
= static_cast<int>(
169 kLetterWidthInch
* settings_
.device_units_per_inch());
170 height
= static_cast<int>(
171 kLetterHeightInch
* settings_
.device_units_per_inch());
173 // ulocdata_getPaperSize returns the width and height in mm.
174 // Convert this to pixels based on the dpi.
175 float multiplier
= 100 * settings_
.device_units_per_inch();
176 multiplier
/= kHundrethsMMPerInch
;
178 height
*= multiplier
;
180 return gfx::Size(width
, height
);
183 PrintingContext::Result
PrintingContextAndroid::UpdatePrinterSettings(
184 bool external_preview
,
185 bool show_system_dialog
) {
186 DCHECK(!show_system_dialog
);
187 DCHECK(!in_print_job_
);
189 // Intentional No-op.
194 PrintingContext::Result
PrintingContextAndroid::InitWithSettings(
195 const PrintSettings
& settings
) {
196 DCHECK(!in_print_job_
);
198 settings_
= settings
;
203 PrintingContext::Result
PrintingContextAndroid::NewDocument(
204 const base::string16
& document_name
) {
205 DCHECK(!in_print_job_
);
206 in_print_job_
= true;
211 PrintingContext::Result
PrintingContextAndroid::NewPage() {
214 DCHECK(in_print_job_
);
216 // Intentional No-op.
221 PrintingContext::Result
PrintingContextAndroid::PageDone() {
224 DCHECK(in_print_job_
);
226 // Intentional No-op.
231 PrintingContext::Result
PrintingContextAndroid::DocumentDone() {
234 DCHECK(in_print_job_
);
240 void PrintingContextAndroid::Cancel() {
241 abort_printing_
= true;
242 in_print_job_
= false;
245 void PrintingContextAndroid::ReleaseContext() {
246 // Intentional No-op.
249 gfx::NativeDrawingContext
PrintingContextAndroid::context() const {
250 // Intentional No-op.
255 bool PrintingContextAndroid::RegisterPrintingContext(JNIEnv
* env
) {
256 return RegisterNativesImpl(env
);
259 } // namespace printing