summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/mock_printer_driver_win.cc
blob: 4232019c5fa916d37fd95b6ac0face94e8219b43 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright (c) 2009 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 "chrome/renderer/mock_printer_driver_win.h"

#include "base/gfx/gdi_util.h"
#include "base/logging.h"
#include "chrome/common/gfx/emf.h"
#include "chrome/renderer/mock_printer.h"
#include "skia/ext/platform_device.h"

namespace {

// A simple class which temporarily overrides system settings.
// The bitmap image rendered via the PlayEnhMetaFile() function depends on
// some system settings.
// As a workaround for such dependency, this class saves the system settings
// and changes them. This class also restore the saved settings in its
// destructor.
class SystemSettingsOverride {
 public:
  SystemSettingsOverride() : font_smoothing_(0) {
  }

  ~SystemSettingsOverride() {
    SystemParametersInfo(SPI_SETFONTSMOOTHING, font_smoothing_, NULL, 0);
  }

  BOOL Init(BOOL font_smoothing) {
    if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &font_smoothing_, 0))
      return FALSE;
    return SystemParametersInfo(SPI_SETFONTSMOOTHING, font_smoothing, NULL, 0);
  }

 private:
  BOOL font_smoothing_;
};

// A class which renders an EMF data and returns a raw bitmap data.
// The bitmap data returned from Create() is deleted in the destructor of this
// class. So, we need to create a copy of this bitmap data if it is used after
// this object is deleted,
class EmfRenderer {
 public:
  EmfRenderer() : dc_(NULL), bitmap_(NULL) {
  }

  ~EmfRenderer() {
    if (bitmap_) {
      DeleteObject(bitmap_);
      bitmap_ = NULL;
    }
    if (dc_) {
      DeleteDC(dc_);
      dc_ = NULL;
    }
  }

  const void* Create(int width, int height, const gfx::Emf* emf) {
    CHECK(!dc_ && !bitmap_);

    BITMAPV4HEADER header;
    gfx::CreateBitmapV4Header(width, height, &header);

    dc_ = CreateCompatibleDC(NULL);
    if (!dc_)
      return NULL;

    void* bits;
    bitmap_ = CreateDIBSection(dc_, reinterpret_cast<BITMAPINFO*>(&header), 0,
                               &bits, NULL, 0);
    if (!bitmap_ || !bits)
      return NULL;

    SelectObject(dc_, bitmap_);

    skia::PlatformDeviceWin::InitializeDC(dc_);
    emf->Playback(dc_, NULL);

    return reinterpret_cast<uint8*>(bits);
  }

 private:
  HDC dc_;
  HBITMAP bitmap_;
};

}  // namespace

MockPrinterDriverWin::MockPrinterDriverWin() {
}

MockPrinterDriverWin::~MockPrinterDriverWin() {
}

MockPrinterPage* MockPrinterDriverWin::LoadSource(const void* source_data,
                                                  size_t source_size) {
  // This code is mostly copied from the Image::LoadEMF() function in
  // "src/chrome/browser/printing/printing_layout_uitest.cc".
  gfx::Emf emf;
  emf.CreateFromData(source_data, source_size);
  gfx::Rect rect(emf.GetBounds());

  // Create a temporary DC and bitmap to retrieve the renderered data.
  if (rect.width() <= 0 || rect.height() <= 0)
    return NULL;

  // Disable the font-smoothing feature of Windows.
  SystemSettingsOverride system_settings;
  system_settings.Init(FALSE);

  // Render the EMF data and create a bitmap.
  EmfRenderer renderer;
  const void* bitmap_data = renderer.Create(rect.width(), rect.height(), &emf);
  if (!bitmap_data)
    return NULL;

  // Create a new MockPrinterPage instance and return it.
  size_t row_byte_width = rect.width() * 4;
  size_t bitmap_size = row_byte_width * rect.height();
  return new MockPrinterPage(rect.width(), rect.height(),
                             source_data, source_size,
                             bitmap_data, bitmap_size);
}