printing_context_android.cc revision f2477e01787aa58f445919b809d89e252beef54f
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 21namespace { 22 23// 1 inch in mils. 24const int kInchToMil = 1000; 25 26inline 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. 32void 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 44void 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 61namespace printing { 62 63// static 64PrintingContext* PrintingContext::Create(const std::string& app_locale) { 65 return new PrintingContextAndroid(app_locale); 66} 67 68// static 69void PrintingContextAndroid::PdfWritingDone(int fd, bool success) { 70 JNIEnv* env = base::android::AttachCurrentThread(); 71 Java_PrintingContext_pdfWritingDone(env, fd, success); 72} 73 74PrintingContextAndroid::PrintingContextAndroid(const std::string& app_locale) 75 : PrintingContext(app_locale) { 76 // The constructor is run in the IO thread. 77} 78 79PrintingContextAndroid::~PrintingContextAndroid() { 80} 81 82void 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 102void 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 136PrintingContext::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 147gfx::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 172PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings( 173 bool external_preview) { 174 DCHECK(!in_print_job_); 175 176 // Intentional No-op. 177 178 return OK; 179} 180 181PrintingContext::Result PrintingContextAndroid::InitWithSettings( 182 const PrintSettings& settings) { 183 DCHECK(!in_print_job_); 184 185 settings_ = settings; 186 187 return OK; 188} 189 190PrintingContext::Result PrintingContextAndroid::NewDocument( 191 const string16& document_name) { 192 DCHECK(!in_print_job_); 193 in_print_job_ = true; 194 195 return OK; 196} 197 198PrintingContext::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 208PrintingContext::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 218PrintingContext::Result PrintingContextAndroid::DocumentDone() { 219 if (abort_printing_) 220 return CANCEL; 221 DCHECK(in_print_job_); 222 223 ResetSettings(); 224 return OK; 225} 226 227void PrintingContextAndroid::Cancel() { 228 abort_printing_ = true; 229 in_print_job_ = false; 230} 231 232void PrintingContextAndroid::ReleaseContext() { 233 // Intentional No-op. 234} 235 236gfx::NativeDrawingContext PrintingContextAndroid::context() const { 237 // Intentional No-op. 238 return NULL; 239} 240 241// static 242bool PrintingContextAndroid::RegisterPrintingContext(JNIEnv* env) { 243 return RegisterNativesImpl(env); 244} 245 246} // namespace printing 247