diff options
Diffstat (limited to 'printing')
-rw-r--r-- | printing/image.cc | 134 | ||||
-rw-r--r-- | printing/image.h | 24 |
2 files changed, 127 insertions, 31 deletions
diff --git a/printing/image.cc b/printing/image.cc index 8f397d8..667adae 100644 --- a/printing/image.cc +++ b/printing/image.cc @@ -8,15 +8,59 @@ #include "base/gfx/png_decoder.h" #include "base/gfx/png_encoder.h" #include "base/gfx/rect.h" +#include "base/md5.h" #include "base/string_util.h" -#include "printing/native_metafile.h" #include "skia/ext/platform_device.h" #if defined(OS_WIN) #include "base/gfx/gdi_util.h" // EMF support #endif -printing::Image::Image(const std::wstring& filename) : ignore_alpha_(true) { +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 DisableFontSmoothing { + public: + explicit DisableFontSmoothing(bool disable) : enable_again_(false) { + if (disable) { +#if defined(OS_WIN) + BOOL enabled; + if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &enabled, 0) && + enabled) { + if (SystemParametersInfo(SPI_SETFONTSMOOTHING, FALSE, NULL, 0)) + enable_again_ = true; + } +#endif + } + } + + ~DisableFontSmoothing() { + if (enable_again_) { +#if defined(OS_WIN) + BOOL result = SystemParametersInfo(SPI_SETFONTSMOOTHING, TRUE, NULL, 0); + DCHECK(result); +#endif + } + } + + private: + bool enable_again_; + + DISALLOW_EVIL_CONSTRUCTORS(DisableFontSmoothing); +}; + +} // namespace + +namespace printing { + +Image::Image(const std::wstring& filename) + : row_length_(0), + ignore_alpha_(true) { std::string data; file_util::ReadFileToString(filename, &data); std::wstring ext = file_util::GetFileExtensionFromPath(filename); @@ -35,7 +79,26 @@ printing::Image::Image(const std::wstring& filename) : ignore_alpha_(true) { } } -bool printing::Image::SaveToPng(const std::wstring& filename) { +Image::Image(const NativeMetafile& metafile) + : row_length_(0), + ignore_alpha_(true) { + LoadMetafile(metafile); +} + +Image::Image(const Image& image) + : size_(image.size_), + row_length_(image.row_length_), + data_(image.data_), + ignore_alpha_(image.ignore_alpha_) { +} + +std::string Image::checksum() const { + MD5Digest digest; + MD5Sum(&data_[0], data_.size(), &digest); + return HexEncode(&digest, sizeof(digest)); +} + +bool Image::SaveToPng(const std::wstring& filename) const { DCHECK(!data_.empty()); std::vector<unsigned char> compressed; bool success = PNGEncoder::Encode(&*data_.begin(), @@ -56,7 +119,7 @@ bool printing::Image::SaveToPng(const std::wstring& filename) { return success; } -double printing::Image::PercentageDifferent(const Image& rhs) const { +double Image::PercentageDifferent(const Image& rhs) const { if (size_.width() == 0 || size_.height() == 0 || rhs.size_.width() == 0 || rhs.size_.height() == 0) return 100.; @@ -113,7 +176,7 @@ double printing::Image::PercentageDifferent(const Image& rhs) const { return static_cast<double>(pixels_different) / total_pixels * 100.; } -bool printing::Image::LoadPng(const std::string& compressed) { +bool Image::LoadPng(const std::string& compressed) { int w; int h; bool success = PNGDecoder::Decode( @@ -124,39 +187,54 @@ bool printing::Image::LoadPng(const std::string& compressed) { return success; } -bool printing::Image::LoadMetafile(const std::string& data) { +bool Image::LoadMetafile(const std::string& data) { DCHECK(!data.empty()); #if defined(OS_WIN) - printing::NativeMetafile metafile; + NativeMetafile metafile; metafile.CreateFromData(data.data(), data.size()); + return LoadMetafile(metafile); +#else + NOTIMPLEMENTED(); + return false; +#endif +} + +bool Image::LoadMetafile(const NativeMetafile& metafile) { +#if defined(OS_WIN) gfx::Rect rect(metafile.GetBounds()); + DisableFontSmoothing disable_in_this_scope(true); // Create a temporary HDC and bitmap to retrieve the rendered data. HDC hdc = CreateCompatibleDC(NULL); BITMAPV4HEADER hdr; DCHECK_EQ(rect.x(), 0); DCHECK_EQ(rect.y(), 0); - DCHECK_GT(rect.width(), 0); - DCHECK_GT(rect.height(), 0); - size_ = rect.size(); - gfx::CreateBitmapV4Header(rect.width(), rect.height(), &hdr); - void* bits; - HBITMAP bitmap = CreateDIBSection(hdc, - reinterpret_cast<BITMAPINFO*>(&hdr), 0, - &bits, NULL, 0); - DCHECK(bitmap); - DCHECK(SelectObject(hdc, bitmap)); - skia::PlatformDevice::InitializeDC(hdc); - bool success = metafile.Playback(hdc, NULL); - row_length_ = size_.width() * sizeof(uint32); - size_t bytes = row_length_ * size_.height(); - DCHECK(bytes); - data_.resize(bytes); - memcpy(&*data_.begin(), bits, bytes); - DeleteDC(hdc); - DeleteObject(bitmap); - return success; + DCHECK_GE(rect.width(), 0); // Metafile could be empty. + DCHECK_GE(rect.height(), 0); + if (rect.width() > 0 && rect.height() > 0) { + size_ = rect.size(); + gfx::CreateBitmapV4Header(rect.width(), rect.height(), &hdr); + void* bits; + HBITMAP bitmap = CreateDIBSection(hdc, + reinterpret_cast<BITMAPINFO*>(&hdr), 0, + &bits, NULL, 0); + DCHECK(bitmap); + DCHECK(SelectObject(hdc, bitmap)); + skia::PlatformDevice::InitializeDC(hdc); + bool success = metafile.Playback(hdc, NULL); + row_length_ = size_.width() * sizeof(uint32); + size_t bytes = row_length_ * size_.height(); + DCHECK(bytes); + data_.resize(bytes); + memcpy(&*data_.begin(), bits, bytes); + DeleteDC(hdc); + DeleteObject(bitmap); + return success; + } #else NOTIMPLEMENTED(); - return false; #endif + + return false; } + +} // namespace printing diff --git a/printing/image.h b/printing/image.h index 8ef1007..a927549 100644 --- a/printing/image.h +++ b/printing/image.h @@ -11,10 +11,11 @@ #include "base/basictypes.h" #include "base/gfx/size.h" #include "base/logging.h" +#include "printing/native_metafile.h" namespace printing { -// Lightweight raw-bitmap management. The image, once initialized, is immuable. +// Lightweight raw-bitmap management. The image, once initialized, is immutable. // The main purpose is testing image contents. class Image { public: @@ -23,12 +24,22 @@ class Image { // If image loading fails size().IsEmpty() will be true. explicit Image(const std::wstring& filename); + // Creates the image from the metafile. Deduces bounds based on bounds in + // metafile. If loading fails size().IsEmpty() will be true. + explicit Image(const NativeMetafile& metafile); + + // Copy constructor. + explicit Image(const Image& image); + const gfx::Size& size() const { return size_; } + // Return a checksum of the image (MD5 over the internal data structure). + std::string checksum() const; + // Save image as PNG. - bool SaveToPng(const std::wstring& filename); + bool SaveToPng(const std::wstring& filename) const; // Returns % of pixels different double PercentageDifferent(const Image& rhs) const; @@ -50,10 +61,16 @@ class Image { } private: + // Construct from metafile. This is kept internal since it's ambiguous what + // kind of data is used (png, bmp, metafile etc). + Image(const void* data, size_t size); + bool LoadPng(const std::string& compressed); bool LoadMetafile(const std::string& data); + bool LoadMetafile(const NativeMetafile& metafile); + // Pixel dimensions of the image. gfx::Size size_; @@ -67,7 +84,8 @@ class Image { // Flag to signal if the comparison functions should ignore the alpha channel. const bool ignore_alpha_; // Currently always true. - DISALLOW_EVIL_CONSTRUCTORS(Image); + // Prevent operator= (this function has no implementation) + Image& operator=(const Image& image); }; } // namespace printing |