image_win.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/image.h"
6
7#include "base/win/scoped_gdi_object.h"
8#include "base/win/scoped_hdc.h"
9#include "base/win/scoped_select_object.h"
10#include "printing/metafile.h"
11#include "skia/ext/platform_device.h"
12#include "ui/gfx/gdi_util.h"  // EMF support
13#include "ui/gfx/rect.h"
14
15
16namespace {
17
18// A simple class which temporarily overrides system settings.
19// The bitmap image rendered via the PlayEnhMetaFile() function depends on
20// some system settings.
21// As a workaround for such dependency, this class saves the system settings
22// and changes them. This class also restore the saved settings in its
23// destructor.
24class DisableFontSmoothing {
25 public:
26  explicit DisableFontSmoothing() : enable_again_(false) {
27    BOOL enabled;
28    if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &enabled, 0) &&
29        enabled) {
30      if (SystemParametersInfo(SPI_SETFONTSMOOTHING, FALSE, NULL, 0))
31        enable_again_ = true;
32    }
33  }
34
35  ~DisableFontSmoothing() {
36    if (enable_again_) {
37      BOOL result = SystemParametersInfo(SPI_SETFONTSMOOTHING, TRUE, NULL, 0);
38      DCHECK(result);
39    }
40  }
41
42 private:
43  bool enable_again_;
44
45  DISALLOW_COPY_AND_ASSIGN(DisableFontSmoothing);
46};
47
48}  // namespace
49
50namespace printing {
51
52bool Image::LoadMetafile(const Metafile& metafile) {
53    gfx::Rect rect(metafile.GetPageBounds(1));
54  DisableFontSmoothing disable_in_this_scope;
55
56  // Create a temporary HDC and bitmap to retrieve the rendered data.
57  base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
58  BITMAPV4HEADER hdr;
59  DCHECK_EQ(rect.x(), 0);
60  DCHECK_EQ(rect.y(), 0);
61  DCHECK_GE(rect.width(), 0);  // Metafile could be empty.
62  DCHECK_GE(rect.height(), 0);
63
64  if (rect.width() < 1 || rect.height() < 1)
65    return false;
66
67  size_ = rect.size();
68  gfx::CreateBitmapV4Header(rect.width(), rect.height(), &hdr);
69  unsigned char* bits = NULL;
70  base::win::ScopedBitmap bitmap(
71      ::CreateDIBSection(hdc, reinterpret_cast<BITMAPINFO*>(&hdr), 0,
72                         reinterpret_cast<void**>(&bits), NULL, 0));
73  DCHECK(bitmap);
74  base::win::ScopedSelectObject select_object(hdc, bitmap);
75
76  skia::InitializeDC(hdc);
77
78  bool success = metafile.Playback(hdc, NULL);
79
80  row_length_ = size_.width() * sizeof(uint32);
81  size_t bytes = row_length_ * size_.height();
82  DCHECK(bytes);
83
84  data_.assign(bits, bits + bytes);
85
86  return success;
87}
88
89}  // namespace printing
90