1// Copyright (c) 2011 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/printed_document.h"
6
7#include "base/logging.h"
8#include "printing/page_number.h"
9#include "printing/printed_pages_source.h"
10#include "printing/printed_page.h"
11#include "printing/units.h"
12#include "skia/ext/platform_device.h"
13
14namespace {
15
16void SimpleModifyWorldTransform(HDC context,
17                                int offset_x,
18                                int offset_y,
19                                double shrink_factor) {
20  XFORM xform = { 0 };
21  xform.eDx = static_cast<float>(offset_x);
22  xform.eDy = static_cast<float>(offset_y);
23  xform.eM11 = xform.eM22 = static_cast<float>(1. / shrink_factor);
24  BOOL res = ModifyWorldTransform(context, &xform, MWT_LEFTMULTIPLY);
25  DCHECK_NE(res, 0);
26}
27
28void DrawRect(HDC context, gfx::Rect rect) {
29  Rectangle(context, rect.x(), rect.y(), rect.right(), rect.bottom());
30}
31
32}  // namespace
33
34namespace printing {
35
36void PrintedDocument::RenderPrintedPage(
37    const PrintedPage& page, gfx::NativeDrawingContext context) const {
38#ifndef NDEBUG
39  {
40    // Make sure the page is from our list.
41    base::AutoLock lock(lock_);
42    DCHECK(&page == mutable_.pages_.find(page.page_number() - 1)->second.get());
43  }
44#endif
45
46  DCHECK(context);
47
48  const PageSetup& page_setup(immutable_.settings_.page_setup_device_units());
49  gfx::Rect content_area;
50  page.GetCenteredPageContentRect(page_setup.physical_size(), &content_area);
51
52  // Save the state to make sure the context this function call does not modify
53  // the device context.
54  int saved_state = SaveDC(context);
55  DCHECK_NE(saved_state, 0);
56  skia::InitializeDC(context);
57  {
58    // Save the state (again) to apply the necessary world transformation.
59    int saved_state = SaveDC(context);
60    DCHECK_NE(saved_state, 0);
61
62    // Setup the matrix to translate and scale to the right place. Take in
63    // account the actual shrinking factor.
64    // Note that the printing output is relative to printable area of the page.
65    // That is 0,0 is offset by PHYSICALOFFSETX/Y from the page.
66    SimpleModifyWorldTransform(
67        context,
68        content_area.x() - page_setup.printable_area().x(),
69        content_area.y() - page_setup.printable_area().y(),
70        page.shrink_factor());
71
72    ::StartPage(context);
73    if (!page.metafile()->SafePlayback(context)) {
74      NOTREACHED();
75    }
76    ::EndPage(context);
77
78    BOOL res = RestoreDC(context, saved_state);
79    DCHECK_NE(res, 0);
80  }
81
82  int res = RestoreDC(context, saved_state);
83  DCHECK_NE(res, 0);
84}
85
86}  // namespace printing
87