root/printing/printing_context_android.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Round
  2. SetSizes
  3. GetPageRanges
  4. Create
  5. PdfWritingDone
  6. AskUserForSettings
  7. AskUserForSettingsReply
  8. UseDefaultSettings
  9. GetPdfPaperSizeDeviceUnits
  10. UpdatePrinterSettings
  11. InitWithSettings
  12. NewDocument
  13. NewPage
  14. PageDone
  15. DocumentDone
  16. Cancel
  17. ReleaseContext
  18. context
  19. RegisterPrintingContext

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "printing/printing_context_android.h"

#include <vector>

#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "jni/PrintingContext_jni.h"
#include "printing/metafile.h"
#include "printing/print_job_constants.h"
#include "printing/units.h"
#include "third_party/icu/source/i18n/unicode/ulocdata.h"

namespace {

// 1 inch in mils.
const int kInchToMil = 1000;

inline int Round(double x) {
  return static_cast<int>(x + 0.5);
}

// Sets the page sizes for a |PrintSettings| object.  |width| and |height|
// arguments should be in device units.
void SetSizes(
    printing::PrintSettings* settings, int dpi, int width, int height) {
  gfx::Size physical_size_device_units(width, height);
  // Assume full page is printable for now.
  gfx::Rect printable_area_device_units(0, 0, width, height);

  settings->set_dpi(dpi);
  settings->SetPrinterPrintableArea(physical_size_device_units,
                                    printable_area_device_units,
                                    false);
}

void GetPageRanges(JNIEnv* env,
                   jintArray int_arr,
                   printing::PageRanges& range_vector) {
  std::vector<int> pages;
  base::android::JavaIntArrayToIntVector(env, int_arr, &pages);
  for (std::vector<int>::const_iterator it = pages.begin();
      it != pages.end();
      ++it) {
    printing::PageRange range;
    range.from = *it;
    range.to = *it;
    range_vector.push_back(range);
  }
}

}  // namespace

namespace printing {

// static
PrintingContext* PrintingContext::Create(const std::string& app_locale) {
  return new PrintingContextAndroid(app_locale);
}

// static
void PrintingContextAndroid::PdfWritingDone(int fd, bool success) {
  JNIEnv* env = base::android::AttachCurrentThread();
  Java_PrintingContext_pdfWritingDone(env, fd, success);
}

PrintingContextAndroid::PrintingContextAndroid(const std::string& app_locale)
    : PrintingContext(app_locale) {
  // The constructor is run in the IO thread.
}

PrintingContextAndroid::~PrintingContextAndroid() {
}

void PrintingContextAndroid::AskUserForSettings(
    gfx::NativeView parent_view,
    int max_pages,
    bool has_selection,
    const PrintSettingsCallback& callback) {
  // This method is always run in the UI thread.
  callback_ = callback;

  JNIEnv* env = base::android::AttachCurrentThread();
  if (j_printing_context_.is_null()) {
    j_printing_context_.Reset(Java_PrintingContext_create(
        env,
        reinterpret_cast<intptr_t>(this)));
  }

  Java_PrintingContext_pageCountEstimationDone(env,
                                               j_printing_context_.obj(),
                                               max_pages);
}

void PrintingContextAndroid::AskUserForSettingsReply(JNIEnv* env,
                                                     jobject obj,
                                                     jboolean success) {
  if (!success) {
    // TODO(cimamoglu): Differentiate between FAILED And CANCEL.
    callback_.Run(FAILED);
    return;
  }

  // We use device name variable to store the file descriptor.  This is hacky
  // but necessary. Since device name is not necessary for the upstream
  // printing code for Android, this is harmless.
  int fd = Java_PrintingContext_getFileDescriptor(env,
                                                  j_printing_context_.obj());
  settings_.set_device_name(base::IntToString16(fd));

  ScopedJavaLocalRef<jintArray> intArr =
      Java_PrintingContext_getPages(env, j_printing_context_.obj());
  if (intArr.obj() != NULL) {
    PageRanges range_vector;
    GetPageRanges(env, intArr.obj(), range_vector);
    settings_.set_ranges(range_vector);
  }

  int dpi = Java_PrintingContext_getDpi(env, j_printing_context_.obj());
  int width = Java_PrintingContext_getWidth(env, j_printing_context_.obj());
  int height = Java_PrintingContext_getHeight(env, j_printing_context_.obj());
  width = Round(ConvertUnitDouble(width, kInchToMil, 1.0) * dpi);
  height = Round(ConvertUnitDouble(height, kInchToMil, 1.0) * dpi);
  SetSizes(&settings_, dpi, width, height);

  callback_.Run(OK);
}

PrintingContext::Result PrintingContextAndroid::UseDefaultSettings() {
  DCHECK(!in_print_job_);

  ResetSettings();
  settings_.set_dpi(kDefaultPdfDpi);
  gfx::Size physical_size = GetPdfPaperSizeDeviceUnits();
  SetSizes(&settings_, kDefaultPdfDpi, physical_size.width(),
           physical_size.height());
  return OK;
}

gfx::Size PrintingContextAndroid::GetPdfPaperSizeDeviceUnits() {
  // NOTE: This implementation is the same as in PrintingContextNoSystemDialog.
  int32_t width = 0;
  int32_t height = 0;
  UErrorCode error = U_ZERO_ERROR;
  ulocdata_getPaperSize(app_locale_.c_str(), &height, &width, &error);
  if (error > U_ZERO_ERROR) {
    // If the call failed, assume a paper size of 8.5 x 11 inches.
    LOG(WARNING) << "ulocdata_getPaperSize failed, using 8.5 x 11, error: "
                 << error;
    width = static_cast<int>(
        kLetterWidthInch * settings_.device_units_per_inch());
    height = static_cast<int>(
        kLetterHeightInch  * settings_.device_units_per_inch());
  } else {
    // ulocdata_getPaperSize returns the width and height in mm.
    // Convert this to pixels based on the dpi.
    float multiplier = 100 * settings_.device_units_per_inch();
    multiplier /= kHundrethsMMPerInch;
    width *= multiplier;
    height *= multiplier;
  }
  return gfx::Size(width, height);
}

PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings(
    bool external_preview) {
  DCHECK(!in_print_job_);

  // Intentional No-op.

  return OK;
}

PrintingContext::Result PrintingContextAndroid::InitWithSettings(
    const PrintSettings& settings) {
  DCHECK(!in_print_job_);

  settings_ = settings;

  return OK;
}

PrintingContext::Result PrintingContextAndroid::NewDocument(
    const base::string16& document_name) {
  DCHECK(!in_print_job_);
  in_print_job_ = true;

  return OK;
}

PrintingContext::Result PrintingContextAndroid::NewPage() {
  if (abort_printing_)
    return CANCEL;
  DCHECK(in_print_job_);

  // Intentional No-op.

  return OK;
}

PrintingContext::Result PrintingContextAndroid::PageDone() {
  if (abort_printing_)
    return CANCEL;
  DCHECK(in_print_job_);

  // Intentional No-op.

  return OK;
}

PrintingContext::Result PrintingContextAndroid::DocumentDone() {
  if (abort_printing_)
    return CANCEL;
  DCHECK(in_print_job_);

  ResetSettings();
  return OK;
}

void PrintingContextAndroid::Cancel() {
  abort_printing_ = true;
  in_print_job_ = false;
}

void PrintingContextAndroid::ReleaseContext() {
  // Intentional No-op.
}

gfx::NativeDrawingContext PrintingContextAndroid::context() const {
  // Intentional No-op.
  return NULL;
}

// static
bool PrintingContextAndroid::RegisterPrintingContext(JNIEnv* env) {
   return RegisterNativesImpl(env);
}

}  // namespace printing

/* [<][>][^][v][top][bottom][index][help] */