Add ICU message format support
[chromium-blink-merge.git] / printing / printing_context_android.cc
blobc524883bf36e12364350525aa0618f947ca86e37
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"
7 #include <vector>
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"
21 namespace {
23 // 1 inch in mils.
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.
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);
38 settings->set_dpi(dpi);
39 settings->SetPrinterPrintableArea(physical_size_device_units,
40 printable_area_device_units,
41 false);
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);
59 } // namespace
61 namespace printing {
63 // static
64 scoped_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) {
65 return make_scoped_ptr<PrintingContext>(new PrintingContextAndroid(delegate));
68 // static
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(
83 int max_pages,
84 bool has_selection,
85 bool is_scripted,
86 const PrintSettingsCallback& callback) {
87 // This method is always run in the UI thread.
88 callback_ = callback;
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)));
97 if (is_scripted) {
98 Java_PrintingContext_showPrintDialog(env, j_printing_context_.obj());
99 } else {
100 Java_PrintingContext_pageCountEstimationDone(env,
101 j_printing_context_.obj(),
102 max_pages);
106 void PrintingContextAndroid::AskUserForSettingsReply(JNIEnv* env,
107 jobject obj,
108 jboolean success) {
109 if (!success) {
110 // TODO(cimamoglu): Differentiate between FAILED And CANCEL.
111 callback_.Run(FAILED);
112 return;
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);
137 callback_.Run(OK);
140 void PrintingContextAndroid::ShowSystemDialogDone(JNIEnv* env,
141 jobject obj) {
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_);
149 ResetSettings();
150 settings_.set_dpi(kDefaultPdfDpi);
151 gfx::Size physical_size = GetPdfPaperSizeDeviceUnits();
152 SetSizes(&settings_, kDefaultPdfDpi, physical_size.width(),
153 physical_size.height());
154 return OK;
157 gfx::Size PrintingContextAndroid::GetPdfPaperSizeDeviceUnits() {
158 // NOTE: This implementation is the same as in PrintingContextNoSystemDialog.
159 int32_t width = 0;
160 int32_t height = 0;
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: "
167 << 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());
172 } else {
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;
177 width *= multiplier;
178 height *= multiplier;
180 return gfx::Size(width, height);
183 PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings(
184 bool external_preview,
185 bool show_system_dialog,
186 int page_count) {
187 DCHECK(!show_system_dialog);
188 DCHECK(!in_print_job_);
190 // Intentional No-op.
192 return OK;
195 PrintingContext::Result PrintingContextAndroid::InitWithSettings(
196 const PrintSettings& settings) {
197 DCHECK(!in_print_job_);
199 settings_ = settings;
201 return OK;
204 PrintingContext::Result PrintingContextAndroid::NewDocument(
205 const base::string16& document_name) {
206 DCHECK(!in_print_job_);
207 in_print_job_ = true;
209 return OK;
212 PrintingContext::Result PrintingContextAndroid::NewPage() {
213 if (abort_printing_)
214 return CANCEL;
215 DCHECK(in_print_job_);
217 // Intentional No-op.
219 return OK;
222 PrintingContext::Result PrintingContextAndroid::PageDone() {
223 if (abort_printing_)
224 return CANCEL;
225 DCHECK(in_print_job_);
227 // Intentional No-op.
229 return OK;
232 PrintingContext::Result PrintingContextAndroid::DocumentDone() {
233 if (abort_printing_)
234 return CANCEL;
235 DCHECK(in_print_job_);
237 ResetSettings();
238 return OK;
241 void PrintingContextAndroid::Cancel() {
242 abort_printing_ = true;
243 in_print_job_ = false;
246 void PrintingContextAndroid::ReleaseContext() {
247 // Intentional No-op.
250 gfx::NativeDrawingContext PrintingContextAndroid::context() const {
251 // Intentional No-op.
252 return NULL;
255 // static
256 bool PrintingContextAndroid::RegisterPrintingContext(JNIEnv* env) {
257 return RegisterNativesImpl(env);
260 } // namespace printing