summaryrefslogtreecommitdiffstats
path: root/printing
diff options
context:
space:
mode:
Diffstat (limited to 'printing')
-rw-r--r--printing/image.cc134
-rw-r--r--printing/image.h24
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