// Copyright (c) 2011 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/printed_document.h"

#include "base/check_op.h"
#include "base/strings/utf_string_conversions.h"
#include "printing/metafile_skia.h"
#include "printing/page_number.h"
#include "printing/printed_page_win.h"
#include "printing/printing_context_win.h"
#include "printing/units.h"
#include "skia/ext/skia_utils_win.h"

namespace {

void SimpleModifyWorldTransform(HDC context,
                                int offset_x,
                                int offset_y,
                                float shrink_factor) {
  XFORM xform = {0};
  xform.eDx = static_cast<float>(offset_x);
  xform.eDy = static_cast<float>(offset_y);
  xform.eM11 = xform.eM22 = 1.f / shrink_factor;
  BOOL res = ModifyWorldTransform(context, &xform, MWT_LEFTMULTIPLY);
  DCHECK_NE(res, 0);
}

}  // namespace

namespace printing {

void PrintedDocument::RenderPrintedPage(
    const PrintedPage& page,
    printing::NativeDrawingContext context) const {
#ifndef NDEBUG
  {
    // Make sure the page is from our list.
    base::AutoLock lock(lock_);
    DCHECK(&page == mutable_.pages_.find(page.page_number() - 1)->second.get());
  }
#endif

  DCHECK(context);

  const PageSetup& page_setup = immutable_.settings_->page_setup_device_units();
  gfx::Rect content_area = GetCenteredPageContentRect(
      page_setup.physical_size(), page.page_size(), page.page_content_rect());

  // Save the state to make sure the context this function call does not modify
  // the device context.
  int saved_state = SaveDC(context);
  DCHECK_NE(saved_state, 0);
  skia::InitializeDC(context);
  {
    // Save the state (again) to apply the necessary world transformation.
    int saved_state_inner = SaveDC(context);
    DCHECK_NE(saved_state_inner, 0);

    // Setup the matrix to translate and scale to the right place. Take in
    // account the actual shrinking factor.
    // Note that the printing output is relative to printable area of the page.
    // That is 0,0 is offset by PHYSICALOFFSETX/Y from the page.
    SimpleModifyWorldTransform(
        context, content_area.x() - page_setup.printable_area().x(),
        content_area.y() - page_setup.printable_area().y(),
        page.shrink_factor());

    ::StartPage(context);
    bool played_back = page.metafile()->SafePlayback(context);
    DCHECK(played_back);
    ::EndPage(context);

    BOOL res = RestoreDC(context, saved_state_inner);
    DCHECK_NE(res, 0);
  }

  BOOL res = RestoreDC(context, saved_state);
  DCHECK_NE(res, 0);
}

bool PrintedDocument::RenderPrintedDocument(PrintingContext* context) {
  if (context->NewPage() != PrintingContext::OK)
    return false;

  std::wstring device_name =
      base::UTF16ToWide(immutable_.settings_->device_name());
  {
    base::AutoLock lock(lock_);
    const MetafilePlayer* metafile = GetMetafile();
    static_cast<PrintingContextWin*>(context)->PrintDocument(
        device_name, *(static_cast<const MetafileSkia*>(metafile)));
  }
  return context->PageDone() == PrintingContext::OK;
}

}  // namespace printing
