diff options
author | sverrir@chromium.org <sverrir@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-16 17:23:58 +0000 |
---|---|---|
committer | sverrir@chromium.org <sverrir@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-16 17:23:58 +0000 |
commit | aa82249f5670f88c545039f7ae997643c97fd639 (patch) | |
tree | 11ea4e90843eb246e77813ddac68b30bf4d907b0 | |
parent | 538173f8209bd078cb82627e32b06ae522766072 (diff) | |
download | chromium_src-aa82249f5670f88c545039f7ae997643c97fd639.zip chromium_src-aa82249f5670f88c545039f7ae997643c97fd639.tar.gz chromium_src-aa82249f5670f88c545039f7ae997643c97fd639.tar.bz2 |
Print only the focused frame. This makes more sense than trying to print all frames since most of the time you end up with ugly clipping and scroll bars on the printed page.
This also fixes printing issue with print selection since we don't pick up the currently selected text if's not in the main frame.
Also did some refactoring of the printing test in render_view_unittest. Mainly to reuse the new Image class.
BUG=http://crbug.com/15250
TEST=Print pages with frames. Print selection when using multiple frames (one example in bug).
Review URL: http://codereview.chromium.org/149644
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20876 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/chrome.gyp | 2 | ||||
-rw-r--r-- | chrome/renderer/mock_printer.cc | 57 | ||||
-rw-r--r-- | chrome/renderer/mock_printer.h | 56 | ||||
-rw-r--r-- | chrome/renderer/mock_printer_driver_win.cc | 125 | ||||
-rw-r--r-- | chrome/renderer/mock_printer_driver_win.h | 25 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 16 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 1 | ||||
-rw-r--r-- | chrome/renderer/render_view_unittest.cc | 50 | ||||
-rw-r--r-- | printing/image.cc | 134 | ||||
-rw-r--r-- | printing/image.h | 24 |
10 files changed, 216 insertions, 274 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index e78c383..e76e2f3 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -3221,8 +3221,6 @@ 'renderer/mock_keyboard_driver_win.h', 'renderer/mock_printer.cc', 'renderer/mock_printer.h', - 'renderer/mock_printer_driver_win.cc', - 'renderer/mock_printer_driver_win.h', 'renderer/mock_render_process.h', 'renderer/mock_render_thread.cc', 'renderer/mock_render_thread.h', diff --git a/chrome/renderer/mock_printer.cc b/chrome/renderer/mock_printer.cc index 2454a0c..4462ce7 100644 --- a/chrome/renderer/mock_printer.cc +++ b/chrome/renderer/mock_printer.cc @@ -5,9 +5,7 @@ #include "chrome/renderer/mock_printer.h" #include "base/file_util.h" -#include "base/gfx/png_encoder.h" #include "base/logging.h" -#include "base/md5.h" #include "base/shared_memory.h" #include "chrome/common/ipc_message_utils.h" #include "chrome/common/render_messages.h" @@ -116,8 +114,12 @@ void MockPrinter::PrintPage(const ViewHostMsg_DidPrintPage_Params& params) { base::SharedMemory emf_data(params.metafile_data_handle, true, GetCurrentProcess()); emf_data.Map(params.data_size); - MockPrinterPage* page_data = driver_.LoadSource(emf_data.memory(), - params.data_size); + printing::NativeMetafile metafile; + metafile.CreateFromData(emf_data.memory(), params.data_size); + printing::Image image(metafile); + MockPrinterPage* page_data = new MockPrinterPage(emf_data.memory(), + params.data_size, + image); if (!page_data) { printer_status_ = PRINTER_ERROR; return; @@ -140,6 +142,13 @@ int MockPrinter::GetPrintedPages() const { return page_number_; } +const MockPrinterPage* MockPrinter::GetPrintedPage(size_t pageno) const { + if (pages_.size() > pageno) + return pages_[pageno]; + else + return NULL; +} + int MockPrinter::GetWidth(size_t page) const { if (printer_status_ != PRINTER_READY || page >= pages_.size()) return -1; @@ -152,27 +161,10 @@ int MockPrinter::GetHeight(size_t page) const { return pages_[page]->height(); } -bool MockPrinter::GetSourceChecksum(size_t page, std::string* checksum) const { - if (printer_status_ != PRINTER_READY || page >= pages_.size()) - return false; - return GetChecksum(pages_[page]->source_data(), pages_[page]->source_size(), - checksum); -} - bool MockPrinter::GetBitmapChecksum(size_t page, std::string* checksum) const { if (printer_status_ != PRINTER_READY || page >= pages_.size()) return false; - return GetChecksum(pages_[page]->bitmap_data(), pages_[page]->bitmap_size(), - checksum); -} - -bool MockPrinter::GetBitmap(size_t page, - const void** data, - size_t* size) const { - if (printer_status_ != PRINTER_READY || page >= pages_.size()) - return false; - *data = pages_[page]->bitmap_data(); - *size = pages_[page]->bitmap_size(); + *checksum = pages_[page]->image().checksum(); return true; } @@ -191,17 +183,8 @@ bool MockPrinter::SaveBitmap(size_t page, const std::wstring& filename) const { if (printer_status_ != PRINTER_READY || page >= pages_.size()) return false; - int width = pages_[page]->width(); - int height = pages_[page]->height(); - int row_byte_width = width * 4; - const uint8* bitmap_data = pages_[page]->bitmap_data(); - std::vector<unsigned char> compressed; - PNGEncoder::Encode(bitmap_data, - PNGEncoder::FORMAT_BGRA, width, height, - row_byte_width, true, &compressed); - file_util::WriteFile(filename, - reinterpret_cast<char*>(&*compressed.begin()), - compressed.size()); + + pages_[page]->image().SaveToPng(filename); return true; } @@ -209,11 +192,3 @@ int MockPrinter::CreateDocumentCookie() { return ++current_document_cookie_; } -bool MockPrinter::GetChecksum(const void* data, - size_t size, - std::string* checksum) const { - MD5Digest digest; - MD5Sum(data, size, &digest); - checksum->assign(HexEncode(&digest, sizeof(digest))); - return true; -} diff --git a/chrome/renderer/mock_printer.h b/chrome/renderer/mock_printer.h index 16577cb..ba3f0de 100644 --- a/chrome/renderer/mock_printer.h +++ b/chrome/renderer/mock_printer.h @@ -11,10 +11,7 @@ #include "base/basictypes.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" - -#if defined(OS_WIN) -#include "chrome/renderer/mock_printer_driver_win.h" -#endif +#include "printing/image.h" struct ViewMsg_Print_Params; struct ViewMsg_PrintPages_Params; @@ -26,49 +23,30 @@ struct ViewHostMsg_DidPrintPage_Params; // a smart pointer of this object (i.e. scoped_refptr<>). class MockPrinterPage : public base::RefCounted<MockPrinterPage> { public: - MockPrinterPage() - : width_(0), - height_(0), - source_size_(0), - bitmap_size_(0) { - } - - MockPrinterPage(int width, - int height, - const void* source_data, + MockPrinterPage(const void* source_data, size_t source_size, - const void* bitmap_data, - size_t bitmap_size) - : width_(width), - height_(height), - source_size_(source_size), - bitmap_size_(bitmap_size) { - // Create copies of the source data and the bitmap data. + const printing::Image& image) + : source_size_(source_size), + image_(image) { + // Create copies of the source data source_data_.reset(new uint8[source_size]); if (source_data_.get()) memcpy(source_data_.get(), source_data, source_size); - bitmap_data_.reset(new uint8[bitmap_size]); - if (bitmap_data_.get()) - memcpy(bitmap_data_.get(), bitmap_data, bitmap_size); } ~MockPrinterPage() { } - int width() { return width_; } - int height() { return height_; } - const uint8* source_data() { return source_data_.get(); } - const size_t source_size() { return source_size_; } - const uint8* bitmap_data() { return bitmap_data_.get(); } - const size_t bitmap_size() { return bitmap_size_; } + int width() const { return image_.size().width(); } + int height() const { return image_.size().height(); } + const uint8* source_data() const { return source_data_.get(); } + const size_t source_size() const { return source_size_; } + const printing::Image& image() const { return image_; } private: - int width_; - int height_; size_t source_size_; scoped_array<uint8> source_data_; - size_t bitmap_size_; - scoped_array<uint8> bitmap_data_; + printing::Image image_; DISALLOW_COPY_AND_ASSIGN(MockPrinterPage); }; @@ -108,9 +86,13 @@ class MockPrinter { // Functions that retrieve the output pages. Status GetPrinterStatus() const { return printer_status_; } int GetPrintedPages() const; + + // Get a pointer to the printed page, returns NULL if pageno has not been + // printed. The pointer is for read only view and should not be deleted. + const MockPrinterPage* GetPrintedPage(size_t pageno) const; + int GetWidth(size_t page) const; int GetHeight(size_t page) const; - bool GetSourceChecksum(size_t page, std::string* checksum) const; bool GetBitmapChecksum(size_t page, std::string* checksum) const; bool GetSource(size_t page, const void** data, size_t* size) const; bool GetBitmap(size_t page, const void** data, size_t* size) const; @@ -149,10 +131,6 @@ class MockPrinter { int page_number_; std::vector<scoped_refptr<MockPrinterPage> > pages_; -#if defined(OS_WIN) - MockPrinterDriverWin driver_; -#endif - DISALLOW_COPY_AND_ASSIGN(MockPrinter); }; diff --git a/chrome/renderer/mock_printer_driver_win.cc b/chrome/renderer/mock_printer_driver_win.cc deleted file mode 100644 index 8fefd8e..0000000 --- a/chrome/renderer/mock_printer_driver_win.cc +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/renderer/mock_printer_driver_win.h" - -#include "base/gfx/gdi_util.h" -#include "base/logging.h" -#include "printing/emf_win.h" -#include "chrome/renderer/mock_printer.h" -#include "skia/ext/platform_device.h" - -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 SystemSettingsOverride { - public: - SystemSettingsOverride() : font_smoothing_(0) { - } - - ~SystemSettingsOverride() { - SystemParametersInfo(SPI_SETFONTSMOOTHING, font_smoothing_, NULL, 0); - } - - BOOL Init(BOOL font_smoothing) { - if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &font_smoothing_, 0)) - return FALSE; - return SystemParametersInfo(SPI_SETFONTSMOOTHING, font_smoothing, NULL, 0); - } - - private: - BOOL font_smoothing_; -}; - -// A class which renders an EMF data and returns a raw bitmap data. -// The bitmap data returned from Create() is deleted in the destructor of this -// class. So, we need to create a copy of this bitmap data if it is used after -// this object is deleted, -class EmfRenderer { - public: - EmfRenderer() : dc_(NULL), bitmap_(NULL) { - } - - ~EmfRenderer() { - if (bitmap_) { - DeleteObject(bitmap_); - bitmap_ = NULL; - } - if (dc_) { - DeleteDC(dc_); - dc_ = NULL; - } - } - - const void* Create(int width, int height, const printing::Emf* emf) { - CHECK(!dc_ && !bitmap_); - - BITMAPV4HEADER header; - gfx::CreateBitmapV4Header(width, height, &header); - - dc_ = CreateCompatibleDC(NULL); - if (!dc_) - return NULL; - - void* bits; - bitmap_ = CreateDIBSection(dc_, reinterpret_cast<BITMAPINFO*>(&header), 0, - &bits, NULL, 0); - if (!bitmap_ || !bits) - return NULL; - - SelectObject(dc_, bitmap_); - - skia::PlatformDevice::InitializeDC(dc_); - emf->Playback(dc_, NULL); - - return reinterpret_cast<uint8*>(bits); - } - - private: - HDC dc_; - HBITMAP bitmap_; -}; - -} // namespace - -MockPrinterDriverWin::MockPrinterDriverWin() { -} - -MockPrinterDriverWin::~MockPrinterDriverWin() { -} - -MockPrinterPage* MockPrinterDriverWin::LoadSource(const void* source_data, - size_t source_size) { - // This code is mostly copied from the Image::LoadEMF() function in - // "src/chrome/browser/printing/printing_layout_uitest.cc". - printing::Emf emf; - emf.CreateFromData(source_data, source_size); - gfx::Rect rect(emf.GetBounds()); - - // Create a temporary DC and bitmap to retrieve the renderered data. - if (rect.width() <= 0 || rect.height() <= 0) - return NULL; - - // Disable the font-smoothing feature of Windows. - SystemSettingsOverride system_settings; - system_settings.Init(FALSE); - - // Render the EMF data and create a bitmap. - EmfRenderer renderer; - const void* bitmap_data = renderer.Create(rect.width(), rect.height(), &emf); - if (!bitmap_data) - return NULL; - - // Create a new MockPrinterPage instance and return it. - size_t row_byte_width = rect.width() * 4; - size_t bitmap_size = row_byte_width * rect.height(); - return new MockPrinterPage(rect.width(), rect.height(), - source_data, source_size, - bitmap_data, bitmap_size); -} diff --git a/chrome/renderer/mock_printer_driver_win.h b/chrome/renderer/mock_printer_driver_win.h deleted file mode 100644 index 117aa16..0000000 --- a/chrome/renderer/mock_printer_driver_win.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_RENDERER_MOCK_PRINTER_DRIVER_WIN_H_ -#define CHROME_RENDERER_MOCK_PRINTER_DRIVER_WIN_H_ - -#include "base/basictypes.h" - -class MockPrinterPage; - -// Implements the platform-dependent part of a pseudo printer object. -// This class renders a platform-dependent input and creates a MockPrinterPage -// instance. -class MockPrinterDriverWin { - public: - MockPrinterDriverWin(); - ~MockPrinterDriverWin(); - - MockPrinterPage* LoadSource(const void* data, size_t size); - - DISALLOW_COPY_AND_ASSIGN(MockPrinterDriverWin); -}; - -#endif // CHROME_RENDERER_MOCK_PRINTER_DRIVER_WIN_H_ diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 96cf524a..9967ca9 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -451,8 +451,14 @@ void RenderView::SendThumbnail() { void RenderView::OnPrintPages() { DCHECK(webview()); - if (webview()) - Print(webview()->GetMainFrame(), false); + if (webview()) { + // If the user has selected text in the currently focused frame we print + // only that frame (this makes print selection work for multiple frames). + if (webview()->GetFocusedFrame()->HasSelection()) + Print(webview()->GetFocusedFrame(), false); + else + Print(webview()->GetMainFrame(), false); + } } void RenderView::OnPrintingDone(int document_cookie, bool success) { @@ -2309,7 +2315,11 @@ void RenderView::SetInputMethodState(bool enabled) { } void RenderView::ScriptedPrint(WebFrame* frame) { - Print(frame, true); + DCHECK(webview()); + if (webview()) { + // Print the full page - not just the frame the javascript is running from. + Print(webview()->GetMainFrame(), true); + } } void RenderView::UserMetricsRecordAction(const std::wstring& action) { diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index c8afcd2..4310d47 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -390,6 +390,7 @@ class RenderView : public RenderWidget, FRIEND_TEST(RenderViewTest, ImeComposition); FRIEND_TEST(RenderViewTest, OnSetTextDirection); FRIEND_TEST(RenderViewTest, OnPrintPages); + FRIEND_TEST(RenderViewTest, PrintWithIframe); FRIEND_TEST(RenderViewTest, PrintLayoutTest); FRIEND_TEST(RenderViewTest, OnHandleKeyboardEvent); FRIEND_TEST(RenderViewTest, InsertCharacters); diff --git a/chrome/renderer/render_view_unittest.cc b/chrome/renderer/render_view_unittest.cc index 4b4ed60..135c78d 100644 --- a/chrome/renderer/render_view_unittest.cc +++ b/chrome/renderer/render_view_unittest.cc @@ -3,10 +3,13 @@ // found in the LICENSE file. #include "base/file_util.h" +#include "base/shared_memory.h" #include "chrome/common/native_web_keyboard_event.h" #include "chrome/common/render_messages.h" #include "chrome/test/render_view_test.h" #include "net/base/net_errors.h" +#include "printing/image.h" +#include "printing/native_metafile.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/api/public/WebURLError.h" @@ -363,6 +366,45 @@ TEST_F(RenderViewTest, PrintWithJavascript) { #endif } +TEST_F(RenderViewTest, PrintWithIframe) { +#if defined(OS_WIN) + // Document that populates an iframe.. + const char html[] = + "<html><body>Lorem Ipsum:" + "<iframe name=\"sub1\" id=\"sub1\"></iframe><script>" + " document.write(frames['sub1'].name);" + " frames['sub1'].document.write(" + " '<p>Cras tempus ante eu felis semper luctus!</p>');" + "</script></body></html>"; + + LoadHTML(html); + + // Find the frame and set it as the focused one. This should mean that that + // the printout should only contain the contents of that frame. + WebFrame* sub1_frame = view_->webview()->GetFrameWithName(L"sub1"); + ASSERT_TRUE(sub1_frame); + view_->webview()->SetFocusedFrame(sub1_frame); + ASSERT_NE(view_->webview()->GetFocusedFrame(), + view_->webview()->GetMainFrame()); + + // Initiate printing. + view_->OnPrintPages(); + + // Verify output through MockPrinter. + const MockPrinter* printer(render_thread_.printer()); + ASSERT_EQ(1, printer->GetPrintedPages()); + const printing::Image& image1(printer->GetPrintedPage(0)->image()); + + // TODO(sverrir): Figure out a way to improve this test to actually print + // only the content of the iframe. Currently image1 will contain the full + // page. + EXPECT_NE(0, image1.size().width()); + EXPECT_NE(0, image1.size().height()); +#else + NOTIMPLEMENTED(); +#endif +} + // Tests if we can print a page and verify its results. // This test prints HTML pages into a pseudo printer and check their outputs, // i.e. a simplified version of the PrintingLayoutTextTest UI test. @@ -431,14 +473,6 @@ TEST_F(RenderViewTest, PrintLayoutTest) { if (kTestPages[i].checksum) EXPECT_EQ(kTestPages[i].checksum, bitmap_actual); - // Retrieve the bitmap data from the pseudo printer. - // TODO(hbono): implement a function which retrieves an expected result - // from a file and compares it with this bitmap data. - const void* bitmap_data; - size_t bitmap_size; - EXPECT_TRUE(render_thread_.printer()->GetBitmap(0, &bitmap_data, - &bitmap_size)); - if (baseline) { // Save the source data and the bitmap data into temporary files to // create base-line results. 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 |