OLD | NEW |
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "printing/image.h" | 5 #include "printing/image.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/gfx/png_decoder.h" | 8 #include "base/gfx/png_decoder.h" |
9 #include "base/gfx/png_encoder.h" | 9 #include "base/gfx/png_encoder.h" |
10 #include "base/gfx/rect.h" | 10 #include "base/gfx/rect.h" |
| 11 #include "base/md5.h" |
11 #include "base/string_util.h" | 12 #include "base/string_util.h" |
12 #include "printing/native_metafile.h" | |
13 #include "skia/ext/platform_device.h" | 13 #include "skia/ext/platform_device.h" |
14 | 14 |
15 #if defined(OS_WIN) | 15 #if defined(OS_WIN) |
16 #include "base/gfx/gdi_util.h" // EMF support | 16 #include "base/gfx/gdi_util.h" // EMF support |
17 #endif | 17 #endif |
18 | 18 |
19 printing::Image::Image(const std::wstring& filename) : ignore_alpha_(true) { | 19 namespace { |
| 20 |
| 21 // A simple class which temporarily overrides system settings. |
| 22 // The bitmap image rendered via the PlayEnhMetaFile() function depends on |
| 23 // some system settings. |
| 24 // As a workaround for such dependency, this class saves the system settings |
| 25 // and changes them. This class also restore the saved settings in its |
| 26 // destructor. |
| 27 class DisableFontSmoothing { |
| 28 public: |
| 29 explicit DisableFontSmoothing(bool disable) : enable_again_(false) { |
| 30 if (disable) { |
| 31 #if defined(OS_WIN) |
| 32 BOOL enabled; |
| 33 if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &enabled, 0) && |
| 34 enabled) { |
| 35 if (SystemParametersInfo(SPI_SETFONTSMOOTHING, FALSE, NULL, 0)) |
| 36 enable_again_ = true; |
| 37 } |
| 38 #endif |
| 39 } |
| 40 } |
| 41 |
| 42 ~DisableFontSmoothing() { |
| 43 if (enable_again_) { |
| 44 #if defined(OS_WIN) |
| 45 BOOL result = SystemParametersInfo(SPI_SETFONTSMOOTHING, TRUE, NULL, 0); |
| 46 DCHECK(result); |
| 47 #endif |
| 48 } |
| 49 } |
| 50 |
| 51 private: |
| 52 bool enable_again_; |
| 53 |
| 54 DISALLOW_EVIL_CONSTRUCTORS(DisableFontSmoothing); |
| 55 }; |
| 56 |
| 57 } // namespace |
| 58 |
| 59 namespace printing { |
| 60 |
| 61 Image::Image(const std::wstring& filename) |
| 62 : row_length_(0), |
| 63 ignore_alpha_(true) { |
20 std::string data; | 64 std::string data; |
21 file_util::ReadFileToString(filename, &data); | 65 file_util::ReadFileToString(filename, &data); |
22 std::wstring ext = file_util::GetFileExtensionFromPath(filename); | 66 std::wstring ext = file_util::GetFileExtensionFromPath(filename); |
23 bool success = false; | 67 bool success = false; |
24 if (LowerCaseEqualsASCII(ext, "png")) { | 68 if (LowerCaseEqualsASCII(ext, "png")) { |
25 success = LoadPng(data); | 69 success = LoadPng(data); |
26 } else if (LowerCaseEqualsASCII(ext, "emf")) { | 70 } else if (LowerCaseEqualsASCII(ext, "emf")) { |
27 success = LoadMetafile(data); | 71 success = LoadMetafile(data); |
28 } else { | 72 } else { |
29 DCHECK(false); | 73 DCHECK(false); |
30 } | 74 } |
31 if (!success) { | 75 if (!success) { |
32 size_.SetSize(0, 0); | 76 size_.SetSize(0, 0); |
33 row_length_ = 0; | 77 row_length_ = 0; |
34 data_.clear(); | 78 data_.clear(); |
35 } | 79 } |
36 } | 80 } |
37 | 81 |
38 bool printing::Image::SaveToPng(const std::wstring& filename) { | 82 Image::Image(const NativeMetafile& metafile) |
| 83 : row_length_(0), |
| 84 ignore_alpha_(true) { |
| 85 LoadMetafile(metafile); |
| 86 } |
| 87 |
| 88 Image::Image(const Image& image) |
| 89 : size_(image.size_), |
| 90 row_length_(image.row_length_), |
| 91 data_(image.data_), |
| 92 ignore_alpha_(image.ignore_alpha_) { |
| 93 } |
| 94 |
| 95 std::string Image::checksum() const { |
| 96 MD5Digest digest; |
| 97 MD5Sum(&data_[0], data_.size(), &digest); |
| 98 return HexEncode(&digest, sizeof(digest)); |
| 99 } |
| 100 |
| 101 bool Image::SaveToPng(const std::wstring& filename) const { |
39 DCHECK(!data_.empty()); | 102 DCHECK(!data_.empty()); |
40 std::vector<unsigned char> compressed; | 103 std::vector<unsigned char> compressed; |
41 bool success = PNGEncoder::Encode(&*data_.begin(), | 104 bool success = PNGEncoder::Encode(&*data_.begin(), |
42 PNGEncoder::FORMAT_BGRA, | 105 PNGEncoder::FORMAT_BGRA, |
43 size_.width(), | 106 size_.width(), |
44 size_.height(), | 107 size_.height(), |
45 row_length_, | 108 row_length_, |
46 true, | 109 true, |
47 &compressed); | 110 &compressed); |
48 DCHECK(success && compressed.size()); | 111 DCHECK(success && compressed.size()); |
49 if (success) { | 112 if (success) { |
50 int write_bytes = file_util::WriteFile( | 113 int write_bytes = file_util::WriteFile( |
51 filename, | 114 filename, |
52 reinterpret_cast<char*>(&*compressed.begin()), compressed.size()); | 115 reinterpret_cast<char*>(&*compressed.begin()), compressed.size()); |
53 success = (write_bytes == static_cast<int>(compressed.size())); | 116 success = (write_bytes == static_cast<int>(compressed.size())); |
54 DCHECK(success); | 117 DCHECK(success); |
55 } | 118 } |
56 return success; | 119 return success; |
57 } | 120 } |
58 | 121 |
59 double printing::Image::PercentageDifferent(const Image& rhs) const { | 122 double Image::PercentageDifferent(const Image& rhs) const { |
60 if (size_.width() == 0 || size_.height() == 0 || | 123 if (size_.width() == 0 || size_.height() == 0 || |
61 rhs.size_.width() == 0 || rhs.size_.height() == 0) | 124 rhs.size_.width() == 0 || rhs.size_.height() == 0) |
62 return 100.; | 125 return 100.; |
63 | 126 |
64 int width = std::min(size_.width(), rhs.size_.width()); | 127 int width = std::min(size_.width(), rhs.size_.width()); |
65 int height = std::min(size_.height(), rhs.size_.height()); | 128 int height = std::min(size_.height(), rhs.size_.height()); |
66 // Compute pixels different in the overlap | 129 // Compute pixels different in the overlap |
67 int pixels_different = 0; | 130 int pixels_different = 0; |
68 for (int y = 0; y < height; ++y) { | 131 for (int y = 0; y < height; ++y) { |
69 for (int x = 0; x < width; ++x) { | 132 for (int x = 0; x < width; ++x) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 } | 169 } |
107 } | 170 } |
108 | 171 |
109 // Like the WebKit ImageDiff tool, we define percentage different in terms | 172 // Like the WebKit ImageDiff tool, we define percentage different in terms |
110 // of the size of the 'actual' bitmap. | 173 // of the size of the 'actual' bitmap. |
111 double total_pixels = static_cast<double>(size_.width()) * | 174 double total_pixels = static_cast<double>(size_.width()) * |
112 static_cast<double>(height); | 175 static_cast<double>(height); |
113 return static_cast<double>(pixels_different) / total_pixels * 100.; | 176 return static_cast<double>(pixels_different) / total_pixels * 100.; |
114 } | 177 } |
115 | 178 |
116 bool printing::Image::LoadPng(const std::string& compressed) { | 179 bool Image::LoadPng(const std::string& compressed) { |
117 int w; | 180 int w; |
118 int h; | 181 int h; |
119 bool success = PNGDecoder::Decode( | 182 bool success = PNGDecoder::Decode( |
120 reinterpret_cast<const unsigned char*>(compressed.c_str()), | 183 reinterpret_cast<const unsigned char*>(compressed.c_str()), |
121 compressed.size(), PNGDecoder::FORMAT_BGRA, &data_, &w, &h); | 184 compressed.size(), PNGDecoder::FORMAT_BGRA, &data_, &w, &h); |
122 size_.SetSize(w, h); | 185 size_.SetSize(w, h); |
123 row_length_ = size_.width() * sizeof(uint32); | 186 row_length_ = size_.width() * sizeof(uint32); |
124 return success; | 187 return success; |
125 } | 188 } |
126 | 189 |
127 bool printing::Image::LoadMetafile(const std::string& data) { | 190 bool Image::LoadMetafile(const std::string& data) { |
128 DCHECK(!data.empty()); | 191 DCHECK(!data.empty()); |
129 #if defined(OS_WIN) | 192 #if defined(OS_WIN) |
130 printing::NativeMetafile metafile; | 193 NativeMetafile metafile; |
131 metafile.CreateFromData(data.data(), data.size()); | 194 metafile.CreateFromData(data.data(), data.size()); |
| 195 return LoadMetafile(metafile); |
| 196 #else |
| 197 NOTIMPLEMENTED(); |
| 198 return false; |
| 199 #endif |
| 200 } |
| 201 |
| 202 bool Image::LoadMetafile(const NativeMetafile& metafile) { |
| 203 #if defined(OS_WIN) |
132 gfx::Rect rect(metafile.GetBounds()); | 204 gfx::Rect rect(metafile.GetBounds()); |
| 205 DisableFontSmoothing disable_in_this_scope(true); |
133 // Create a temporary HDC and bitmap to retrieve the rendered data. | 206 // Create a temporary HDC and bitmap to retrieve the rendered data. |
134 HDC hdc = CreateCompatibleDC(NULL); | 207 HDC hdc = CreateCompatibleDC(NULL); |
135 BITMAPV4HEADER hdr; | 208 BITMAPV4HEADER hdr; |
136 DCHECK_EQ(rect.x(), 0); | 209 DCHECK_EQ(rect.x(), 0); |
137 DCHECK_EQ(rect.y(), 0); | 210 DCHECK_EQ(rect.y(), 0); |
138 DCHECK_GT(rect.width(), 0); | 211 DCHECK_GE(rect.width(), 0); // Metafile could be empty. |
139 DCHECK_GT(rect.height(), 0); | 212 DCHECK_GE(rect.height(), 0); |
140 size_ = rect.size(); | 213 if (rect.width() > 0 && rect.height() > 0) { |
141 gfx::CreateBitmapV4Header(rect.width(), rect.height(), &hdr); | 214 size_ = rect.size(); |
142 void* bits; | 215 gfx::CreateBitmapV4Header(rect.width(), rect.height(), &hdr); |
143 HBITMAP bitmap = CreateDIBSection(hdc, | 216 void* bits; |
144 reinterpret_cast<BITMAPINFO*>(&hdr), 0, | 217 HBITMAP bitmap = CreateDIBSection(hdc, |
145 &bits, NULL, 0); | 218 reinterpret_cast<BITMAPINFO*>(&hdr), 0, |
146 DCHECK(bitmap); | 219 &bits, NULL, 0); |
147 DCHECK(SelectObject(hdc, bitmap)); | 220 DCHECK(bitmap); |
148 skia::PlatformDevice::InitializeDC(hdc); | 221 DCHECK(SelectObject(hdc, bitmap)); |
149 bool success = metafile.Playback(hdc, NULL); | 222 skia::PlatformDevice::InitializeDC(hdc); |
150 row_length_ = size_.width() * sizeof(uint32); | 223 bool success = metafile.Playback(hdc, NULL); |
151 size_t bytes = row_length_ * size_.height(); | 224 row_length_ = size_.width() * sizeof(uint32); |
152 DCHECK(bytes); | 225 size_t bytes = row_length_ * size_.height(); |
153 data_.resize(bytes); | 226 DCHECK(bytes); |
154 memcpy(&*data_.begin(), bits, bytes); | 227 data_.resize(bytes); |
155 DeleteDC(hdc); | 228 memcpy(&*data_.begin(), bits, bytes); |
156 DeleteObject(bitmap); | 229 DeleteDC(hdc); |
157 return success; | 230 DeleteObject(bitmap); |
| 231 return success; |
| 232 } |
158 #else | 233 #else |
159 NOTIMPLEMENTED(); | 234 NOTIMPLEMENTED(); |
| 235 #endif |
| 236 |
160 return false; | 237 return false; |
161 #endif | |
162 } | 238 } |
| 239 |
| 240 } // namespace printing |
OLD | NEW |