| 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 |