[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 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 | |
avi | 126e93c | 2015-12-21 21:48:16 | [diff] [blame] | 7 | #include <stdint.h> |
| 8 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 9 | #include <vector> |
| 10 | |
| 11 | #include "base/android/jni_android.h" |
| 12 | #include "base/android/jni_array.h" |
| 13 | #include "base/android/jni_string.h" |
| 14 | #include "base/logging.h" |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 15 | #include "base/memory/ptr_util.h" |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 16 | #include "base/strings/string_number_conversions.h" |
| 17 | #include "base/values.h" |
| 18 | #include "jni/PrintingContext_jni.h" |
| 19 | #include "printing/metafile.h" |
| 20 | #include "printing/print_job_constants.h" |
| 21 | #include "printing/units.h" |
| 22 | #include "third_party/icu/source/i18n/unicode/ulocdata.h" |
| 23 | |
torne | 8656011 | 2016-08-04 15:59:04 | [diff] [blame] | 24 | using base::android::JavaParamRef; |
| 25 | using base::android::ScopedJavaLocalRef; |
| 26 | |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 27 | namespace printing { |
| 28 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 29 | namespace { |
| 30 | |
| 31 | // 1 inch in mils. |
| 32 | const int kInchToMil = 1000; |
| 33 | |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 34 | int Round(double x) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 35 | return static_cast<int>(x + 0.5); |
| 36 | } |
| 37 | |
| 38 | // Sets the page sizes for a |PrintSettings| object. |width| and |height| |
| 39 | // arguments should be in device units. |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 40 | void SetSizes(PrintSettings* settings, int dpi, int width, int height) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 41 | gfx::Size physical_size_device_units(width, height); |
| 42 | // Assume full page is printable for now. |
| 43 | gfx::Rect printable_area_device_units(0, 0, width, height); |
| 44 | |
| 45 | settings->set_dpi(dpi); |
| 46 | settings->SetPrinterPrintableArea(physical_size_device_units, |
| 47 | printable_area_device_units, |
| 48 | false); |
| 49 | } |
| 50 | |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 51 | void GetPageRanges(JNIEnv* env, jintArray int_arr, PageRanges* range_vector) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 52 | std::vector<int> pages; |
| 53 | base::android::JavaIntArrayToIntVector(env, int_arr, &pages); |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 54 | for (int page : pages) { |
| 55 | PageRange range; |
| 56 | range.from = page; |
| 57 | range.to = page; |
| 58 | range_vector->push_back(range); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 59 | } |
| 60 | } |
| 61 | |
| 62 | } // namespace |
| 63 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 64 | // static |
dcheng | c3df9ba | 2016-04-07 23:09:32 | [diff] [blame] | 65 | std::unique_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) { |
| 66 | return base::WrapUnique(new PrintingContextAndroid(delegate)); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | // static |
| 70 | void PrintingContextAndroid::PdfWritingDone(int fd, bool success) { |
| 71 | JNIEnv* env = base::android::AttachCurrentThread(); |
| 72 | Java_PrintingContext_pdfWritingDone(env, fd, success); |
| 73 | } |
| 74 | |
Vitaly Buka | bd7c981 | 2014-08-26 08:57:54 | [diff] [blame] | 75 | PrintingContextAndroid::PrintingContextAndroid(Delegate* delegate) |
| 76 | : PrintingContext(delegate) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 77 | // The constructor is run in the IO thread. |
| 78 | } |
| 79 | |
| 80 | PrintingContextAndroid::~PrintingContextAndroid() { |
| 81 | } |
| 82 | |
| 83 | void PrintingContextAndroid::AskUserForSettings( |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 84 | int max_pages, |
| 85 | bool has_selection, |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 86 | bool is_scripted, |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 87 | const PrintSettingsCallback& callback) { |
| 88 | // This method is always run in the UI thread. |
| 89 | callback_ = callback; |
| 90 | |
| 91 | JNIEnv* env = base::android::AttachCurrentThread(); |
| 92 | if (j_printing_context_.is_null()) { |
| 93 | j_printing_context_.Reset(Java_PrintingContext_create( |
| 94 | env, |
[email protected] | 879517bd | 2013-11-22 20:36:31 | [diff] [blame] | 95 | reinterpret_cast<intptr_t>(this))); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 96 | } |
| 97 | |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 98 | if (is_scripted) { |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 99 | Java_PrintingContext_showPrintDialog(env, j_printing_context_); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 100 | } else { |
Shimi Zhang | 3089982 | 2017-06-16 01:49:55 | [diff] [blame^] | 101 | Java_PrintingContext_askUserForSettings(env, j_printing_context_, |
| 102 | max_pages); |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 103 | } |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 104 | } |
| 105 | |
torne | 6f3f097 | 2015-11-25 18:04:30 | [diff] [blame] | 106 | void PrintingContextAndroid::AskUserForSettingsReply( |
| 107 | JNIEnv* env, |
| 108 | const JavaParamRef<jobject>& obj, |
| 109 | jboolean success) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 110 | if (!success) { |
| 111 | // TODO(cimamoglu): Differentiate between FAILED And CANCEL. |
| 112 | callback_.Run(FAILED); |
| 113 | return; |
| 114 | } |
| 115 | |
| 116 | // We use device name variable to store the file descriptor. This is hacky |
| 117 | // but necessary. Since device name is not necessary for the upstream |
| 118 | // printing code for Android, this is harmless. |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 119 | int fd = Java_PrintingContext_getFileDescriptor(env, j_printing_context_); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 120 | settings_.set_device_name(base::IntToString16(fd)); |
| 121 | |
| 122 | ScopedJavaLocalRef<jintArray> intArr = |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 123 | Java_PrintingContext_getPages(env, j_printing_context_); |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 124 | if (intArr.obj()) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 125 | PageRanges range_vector; |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 126 | GetPageRanges(env, intArr.obj(), &range_vector); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 127 | settings_.set_ranges(range_vector); |
| 128 | } |
| 129 | |
torne | 948f366 | 2016-08-16 15:10:44 | [diff] [blame] | 130 | int dpi = Java_PrintingContext_getDpi(env, j_printing_context_); |
| 131 | int width = Java_PrintingContext_getWidth(env, j_printing_context_); |
| 132 | int height = Java_PrintingContext_getHeight(env, j_printing_context_); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 133 | width = Round(ConvertUnitDouble(width, kInchToMil, 1.0) * dpi); |
| 134 | height = Round(ConvertUnitDouble(height, kInchToMil, 1.0) * dpi); |
| 135 | SetSizes(&settings_, dpi, width, height); |
| 136 | |
| 137 | callback_.Run(OK); |
| 138 | } |
| 139 | |
torne | 6f3f097 | 2015-11-25 18:04:30 | [diff] [blame] | 140 | void PrintingContextAndroid::ShowSystemDialogDone( |
| 141 | JNIEnv* env, |
| 142 | const JavaParamRef<jobject>& obj) { |
dgn | 4c172eea | 2014-12-15 21:11:23 | [diff] [blame] | 143 | // Settings are not updated, callback is called only to unblock javascript. |
| 144 | callback_.Run(CANCEL); |
| 145 | } |
| 146 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 147 | PrintingContext::Result PrintingContextAndroid::UseDefaultSettings() { |
| 148 | DCHECK(!in_print_job_); |
| 149 | |
| 150 | ResetSettings(); |
[email protected] | c19b6a6 | 2013-11-18 21:53:11 | [diff] [blame] | 151 | settings_.set_dpi(kDefaultPdfDpi); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 152 | gfx::Size physical_size = GetPdfPaperSizeDeviceUnits(); |
| 153 | SetSizes(&settings_, kDefaultPdfDpi, physical_size.width(), |
| 154 | physical_size.height()); |
| 155 | return OK; |
| 156 | } |
| 157 | |
| 158 | gfx::Size PrintingContextAndroid::GetPdfPaperSizeDeviceUnits() { |
| 159 | // NOTE: This implementation is the same as in PrintingContextNoSystemDialog. |
| 160 | int32_t width = 0; |
| 161 | int32_t height = 0; |
| 162 | UErrorCode error = U_ZERO_ERROR; |
Vitaly Buka | bd7c981 | 2014-08-26 08:57:54 | [diff] [blame] | 163 | ulocdata_getPaperSize( |
| 164 | delegate_->GetAppLocale().c_str(), &height, &width, &error); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 165 | if (error > U_ZERO_ERROR) { |
| 166 | // If the call failed, assume a paper size of 8.5 x 11 inches. |
| 167 | LOG(WARNING) << "ulocdata_getPaperSize failed, using 8.5 x 11, error: " |
| 168 | << error; |
| 169 | width = static_cast<int>( |
| 170 | kLetterWidthInch * settings_.device_units_per_inch()); |
| 171 | height = static_cast<int>( |
| 172 | kLetterHeightInch * settings_.device_units_per_inch()); |
| 173 | } else { |
| 174 | // ulocdata_getPaperSize returns the width and height in mm. |
| 175 | // Convert this to pixels based on the dpi. |
| 176 | float multiplier = 100 * settings_.device_units_per_inch(); |
| 177 | multiplier /= kHundrethsMMPerInch; |
| 178 | width *= multiplier; |
| 179 | height *= multiplier; |
| 180 | } |
| 181 | return gfx::Size(width, height); |
| 182 | } |
| 183 | |
| 184 | PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings( |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 185 | bool external_preview, |
vitalybuka | 95fa3c9 | 2015-05-05 03:03:32 | [diff] [blame] | 186 | bool show_system_dialog, |
| 187 | int page_count) { |
vitalybuka | 92ab8ce | 2014-08-26 23:41:45 | [diff] [blame] | 188 | DCHECK(!show_system_dialog); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 189 | DCHECK(!in_print_job_); |
| 190 | |
| 191 | // Intentional No-op. |
| 192 | |
| 193 | return OK; |
| 194 | } |
| 195 | |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 196 | PrintingContext::Result PrintingContextAndroid::NewDocument( |
[email protected] | 90007a5 | 2013-12-19 23:28:07 | [diff] [blame] | 197 | const base::string16& document_name) { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 198 | DCHECK(!in_print_job_); |
| 199 | in_print_job_ = true; |
| 200 | |
| 201 | return OK; |
| 202 | } |
| 203 | |
| 204 | PrintingContext::Result PrintingContextAndroid::NewPage() { |
| 205 | if (abort_printing_) |
| 206 | return CANCEL; |
| 207 | DCHECK(in_print_job_); |
| 208 | |
| 209 | // Intentional No-op. |
| 210 | |
| 211 | return OK; |
| 212 | } |
| 213 | |
| 214 | PrintingContext::Result PrintingContextAndroid::PageDone() { |
| 215 | if (abort_printing_) |
| 216 | return CANCEL; |
| 217 | DCHECK(in_print_job_); |
| 218 | |
| 219 | // Intentional No-op. |
| 220 | |
| 221 | return OK; |
| 222 | } |
| 223 | |
| 224 | PrintingContext::Result PrintingContextAndroid::DocumentDone() { |
| 225 | if (abort_printing_) |
| 226 | return CANCEL; |
| 227 | DCHECK(in_print_job_); |
| 228 | |
| 229 | ResetSettings(); |
| 230 | return OK; |
| 231 | } |
| 232 | |
| 233 | void PrintingContextAndroid::Cancel() { |
| 234 | abort_printing_ = true; |
| 235 | in_print_job_ = false; |
| 236 | } |
| 237 | |
| 238 | void PrintingContextAndroid::ReleaseContext() { |
| 239 | // Intentional No-op. |
| 240 | } |
| 241 | |
tfarina | 876d1e0 | 2016-10-11 23:12:53 | [diff] [blame] | 242 | skia::NativeDrawingContext PrintingContextAndroid::context() const { |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 243 | // Intentional No-op. |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 244 | return nullptr; |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 245 | } |
| 246 | |
| 247 | // static |
| 248 | bool PrintingContextAndroid::RegisterPrintingContext(JNIEnv* env) { |
thestig | 5f68391 | 2016-09-30 22:42:16 | [diff] [blame] | 249 | return RegisterNativesImpl(env); |
[email protected] | b6f76a1 | 2013-11-14 17:29:24 | [diff] [blame] | 250 | } |
| 251 | |
| 252 | } // namespace printing |