diff options
author | sverrir@google.com <sverrir@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-06 15:25:50 +0000 |
---|---|---|
committer | sverrir@google.com <sverrir@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-06 15:25:50 +0000 |
commit | 0e0fca32b226a29a774728b642848bfdd732f791 (patch) | |
tree | 70547f886163e2a364ed47a8d5c85765d48f0e12 /chrome | |
parent | d09e2889c21d0a420b70680291906e4a17fb8503 (diff) | |
download | chromium_src-0e0fca32b226a29a774728b642848bfdd732f791.zip chromium_src-0e0fca32b226a29a774728b642848bfdd732f791.tar.gz chromium_src-0e0fca32b226a29a774728b642848bfdd732f791.tar.bz2 |
Move Emf class to the printing library. Also creates a platform agnostic NativeMetafile definition to ease platform porting.
BUG=none
TEST=none (No functional change)
Review URL: http://codereview.chromium.org/149181
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19943 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/printing/print_job_manager.cc | 1 | ||||
-rw-r--r-- | chrome/browser/printing/print_job_worker.cc | 1 | ||||
-rw-r--r-- | chrome/browser/printing/print_view_manager.cc | 18 | ||||
-rw-r--r-- | chrome/browser/printing/printed_document.cc | 15 | ||||
-rw-r--r-- | chrome/browser/printing/printed_document.h | 8 | ||||
-rw-r--r-- | chrome/browser/printing/printed_page.cc | 10 | ||||
-rw-r--r-- | chrome/browser/printing/printed_page.h | 11 | ||||
-rw-r--r-- | chrome/browser/printing/printing_layout_uitest.cc | 16 | ||||
-rw-r--r-- | chrome/chrome.gyp | 6 | ||||
-rw-r--r-- | chrome/common/gfx/emf.cc | 317 | ||||
-rw-r--r-- | chrome/common/gfx/emf.h | 179 | ||||
-rw-r--r-- | chrome/common/gfx/emf_unittest.cc | 114 | ||||
-rw-r--r-- | chrome/common/render_messages.h | 8 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.cc | 17 | ||||
-rw-r--r-- | chrome/renderer/mock_printer.cc | 2 | ||||
-rw-r--r-- | chrome/renderer/mock_printer_driver_win.cc | 6 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper.cc | 38 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.cc | 11 |
18 files changed, 77 insertions, 701 deletions
diff --git a/chrome/browser/printing/print_job_manager.cc b/chrome/browser/printing/print_job_manager.cc index c6f4ac3..320aa21 100644 --- a/chrome/browser/printing/print_job_manager.cc +++ b/chrome/browser/printing/print_job_manager.cc @@ -8,7 +8,6 @@ #include "chrome/browser/printing/printer_query.h" #include "chrome/browser/printing/printed_document.h" #include "chrome/browser/printing/printed_page.h" -#include "chrome/common/gfx/emf.h" #include "chrome/common/notification_service.h" namespace printing { diff --git a/chrome/browser/printing/print_job_worker.cc b/chrome/browser/printing/print_job_worker.cc index af32da0..728ff3d 100644 --- a/chrome/browser/printing/print_job_worker.cc +++ b/chrome/browser/printing/print_job_worker.cc @@ -8,7 +8,6 @@ #include "chrome/browser/printing/print_job.h" #include "chrome/browser/printing/printed_document.h" #include "chrome/browser/printing/printed_page.h" -#include "chrome/common/gfx/emf.h" #include "chrome/common/notification_service.h" namespace printing { diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc index d775ff5..1c56d00d 100644 --- a/chrome/browser/printing/print_view_manager.cc +++ b/chrome/browser/printing/print_view_manager.cc @@ -5,6 +5,7 @@ #include "chrome/browser/printing/print_view_manager.h" #include "app/l10n_util.h" +#include "base/scoped_ptr.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/printing/print_job.h" #include "chrome/browser/printing/print_job_manager.h" @@ -13,10 +14,10 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/common/gfx/emf.h" #include "chrome/common/notification_service.h" #include "chrome/common/render_messages.h" #include "grit/generated_resources.h" +#include "printing/native_metafile.h" using base::TimeDelta; @@ -95,23 +96,24 @@ void PrintViewManager::DidPrintPage( return; } - base::SharedMemory shared_buf(params.emf_data_handle, true); + base::SharedMemory shared_buf(params.metafile_data_handle, true); if (!shared_buf.Map(params.data_size)) { NOTREACHED() << "couldn't map"; owner_.Stop(); return; } - gfx::Emf* emf = new gfx::Emf; - if (!emf->CreateFromData(shared_buf.memory(), params.data_size)) { - NOTREACHED() << "Invalid EMF header"; - delete emf; + scoped_ptr<NativeMetafile> metafile(new NativeMetafile()); + if (!metafile->CreateFromData(shared_buf.memory(), params.data_size)) { + NOTREACHED() << "Invalid metafile header"; owner_.Stop(); return; } // Update the rendered document. It will send notifications to the listener. - document->SetPage(params.page_number, emf, params.actual_shrink); + document->SetPage(params.page_number, + metafile.release(), + params.actual_shrink); ShouldQuitFromInnerMessageLoop(); } @@ -301,7 +303,7 @@ void PrintViewManager::TerminatePrintJob(bool cancel) { return; if (cancel) { - // We don't need the EMF data anymore because the printing is canceled. + // We don't need the metafile data anymore because the printing is canceled. print_job_->Cancel(); waiting_to_print_ = false; inside_inner_message_loop_ = false; diff --git a/chrome/browser/printing/printed_document.cc b/chrome/browser/printing/printed_document.cc index a366a95..ac26581 100644 --- a/chrome/browser/printing/printed_document.cc +++ b/chrome/browser/printing/printed_document.cc @@ -18,7 +18,6 @@ #include "chrome/browser/printing/page_overlays.h" #include "chrome/browser/printing/printed_pages_source.h" #include "chrome/browser/printing/printed_page.h" -#include "chrome/common/gfx/emf.h" #include "printing/units.h" #include "skia/ext/platform_device.h" @@ -60,12 +59,14 @@ PrintedDocument::PrintedDocument(const PrintSettings& settings, PrintedDocument::~PrintedDocument() { } -void PrintedDocument::SetPage(int page_number, gfx::Emf* emf, double shrink) { +void PrintedDocument::SetPage(int page_number, + NativeMetafile* metafile, + double shrink) { // Notice the page_number + 1, the reason is that this is the value that will // be shown. Users dislike 0-based counting. scoped_refptr<PrintedPage> page( new PrintedPage(page_number + 1, - emf, immutable_.settings_.page_setup_pixels().physical_size())); + metafile, immutable_.settings_.page_setup_pixels().physical_size())); { AutoLock lock(lock_); mutable_.pages_[page_number] = page; @@ -123,7 +124,7 @@ void PrintedDocument::RenderPrintedPage(const PrintedPage& page, BOOL res = ModifyWorldTransform(context, &xform, MWT_LEFTMULTIPLY); DCHECK_NE(res, 0); - if (!page.emf()->SafePlayback(context)) { + if (!page.native_metafile()->SafePlayback(context)) { NOTREACHED(); } @@ -176,7 +177,7 @@ bool PrintedDocument::IsComplete() const { for (; page != PageNumber::npos(); ++page) { PrintedPages::const_iterator itr = mutable_.pages_.find(page.ToInt()); if (itr == mutable_.pages_.end() || !itr->second.get() || - !itr->second->emf()) + !itr->second->native_metafile()) return false; } return true; @@ -202,7 +203,7 @@ size_t PrintedDocument::MemoryUsage() const { } size_t total = 0; for (size_t i = 0; i < pages_copy.size(); ++i) { - total += pages_copy[i]->emf()->GetDataSize(); + total += pages_copy[i]->native_metafile()->GetDataSize(); } return total; } @@ -321,7 +322,7 @@ void PrintedDocument::DebugDump(const PrintedPage& page) file_util::ReplaceIllegalCharacters(&filename, '_'); std::wstring path(g_debug_dump_info->debug_dump_path); file_util::AppendToPath(&path, filename); - page.emf()->SaveTo(path); + page.native_metafile()->SaveTo(path); } void PrintedDocument::set_debug_dump_path(const std::wstring& debug_dump_path) { diff --git a/chrome/browser/printing/printed_document.h b/chrome/browser/printing/printed_document.h index 5efc415..0d1480d 100644 --- a/chrome/browser/printing/printed_document.h +++ b/chrome/browser/printing/printed_document.h @@ -11,12 +11,12 @@ #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "chrome/browser/printing/print_settings.h" +#include "printing/native_metafile.h" #include "googleurl/src/gurl.h" class MessageLoop; namespace gfx { -class Emf; class Font; } @@ -40,9 +40,9 @@ class PrintedDocument : public base::RefCountedThreadSafe<PrintedDocument> { int cookie); ~PrintedDocument(); - // Sets a page's data. 0-based. Takes emf ownership. + // Sets a page's data. 0-based. Takes metafile ownership. // Note: locks for a short amount of time. - void SetPage(int page_number, gfx::Emf* emf, double shrink); + void SetPage(int page_number, NativeMetafile* metafile, double shrink); // Retrieves a page. If the page is not available right now, it // requests to have this page be rendered and returns false. @@ -103,7 +103,7 @@ class PrintedDocument : public base::RefCountedThreadSafe<PrintedDocument> { static const std::wstring& debug_dump_path(); private: - // Array of EMF data for each print previewed page. + // Array of data for each print previewed page. typedef std::map<int, scoped_refptr<PrintedPage>> PrintedPages; // Contains all the mutable stuff. All this stuff MUST be accessed with the diff --git a/chrome/browser/printing/printed_page.cc b/chrome/browser/printing/printed_page.cc index 1cb5c0d..4c44acc 100644 --- a/chrome/browser/printing/printed_page.cc +++ b/chrome/browser/printing/printed_page.cc @@ -4,23 +4,21 @@ #include "chrome/browser/printing/printed_page.h" -#include "chrome/common/gfx/emf.h" - namespace printing { PrintedPage::PrintedPage(int page_number, - gfx::Emf* emf, + NativeMetafile* native_metafile, const gfx::Size& page_size) : page_number_(page_number), - emf_(emf), + native_metafile_(native_metafile), page_size_(page_size) { } PrintedPage::~PrintedPage() { } -const gfx::Emf* PrintedPage::emf() const { - return emf_.get(); +const NativeMetafile* PrintedPage::native_metafile() const { + return native_metafile_.get(); } } // namespace printing diff --git a/chrome/browser/printing/printed_page.h b/chrome/browser/printing/printed_page.h index 9058d72..b60c93d 100644 --- a/chrome/browser/printing/printed_page.h +++ b/chrome/browser/printing/printed_page.h @@ -9,10 +9,7 @@ #include "base/gfx/size.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" - -namespace gfx { -class Emf; -} +#include "printing/native_metafile.h" namespace printing { @@ -25,13 +22,13 @@ namespace printing { class PrintedPage : public base::RefCountedThreadSafe<PrintedPage> { public: PrintedPage(int page_number, - gfx::Emf* emf, + NativeMetafile* native_metafile, const gfx::Size& page_size); ~PrintedPage(); // Getters int page_number() const { return page_number_; } - const gfx::Emf* emf() const; + const NativeMetafile* native_metafile() const; const gfx::Size& page_size() const { return page_size_; } private: @@ -39,7 +36,7 @@ class PrintedPage : public base::RefCountedThreadSafe<PrintedPage> { const int page_number_; // Actual paint data. - const scoped_ptr<gfx::Emf> emf_; + const scoped_ptr<NativeMetafile> native_metafile_; // The physical page size. To support multiple page formats inside on print // job. diff --git a/chrome/browser/printing/printing_layout_uitest.cc b/chrome/browser/printing/printing_layout_uitest.cc index a651a0a..e9f6c27 100644 --- a/chrome/browser/printing/printing_layout_uitest.cc +++ b/chrome/browser/printing/printing_layout_uitest.cc @@ -11,13 +11,13 @@ #include "base/simple_thread.h" #include "base/win_util.h" #include "chrome/common/chrome_paths.h" -#include "chrome/common/gfx/emf.h" #include "chrome/test/automation/browser_proxy.h" #include "chrome/test/automation/tab_proxy.h" #include "chrome/test/automation/window_proxy.h" #include "chrome/test/ui/ui_test.h" #include "chrome/browser/printing/printing_test.h" #include "net/url_request/url_request_unittest.h" +#include "printing/native_metafile.h" namespace { @@ -37,7 +37,7 @@ class Image { if (LowerCaseEqualsASCII(ext, "png")) { LoadPng(data); } else if (LowerCaseEqualsASCII(ext, "emf")) { - LoadEmf(data); + LoadMetafile(data); } else { EXPECT_TRUE(false); } @@ -149,11 +149,11 @@ class Image { row_length_ = size_.width() * sizeof(uint32); } - void LoadEmf(const std::string& data) { + void LoadMetafile(const std::string& data) { ASSERT_FALSE(data.empty()); - gfx::Emf emf; - emf.CreateFromData(data.data(), data.size()); - gfx::Rect rect(emf.GetBounds()); + printing::NativeMetafile metafile; + metafile.CreateFromData(data.data(), data.size()); + gfx::Rect rect(metafile.GetBounds()); // Create a temporary HDC and bitmap to retrieve the renderered data. HDC hdc = CreateCompatibleDC(NULL); BITMAPV4HEADER hdr; @@ -170,7 +170,7 @@ class Image { EXPECT_TRUE(bitmap); EXPECT_TRUE(SelectObject(hdc, bitmap)); skia::PlatformDevice::InitializeDC(hdc); - EXPECT_TRUE(emf.Playback(hdc, NULL)); + EXPECT_TRUE(metafile.Playback(hdc, NULL)); row_length_ = size_.width() * sizeof(uint32); size_t bytes = row_length_ * size_.height(); ASSERT_TRUE(bytes); @@ -200,7 +200,7 @@ class PrintingLayoutTest : public PrintingTest<UITest> { public: PrintingLayoutTest() { emf_path_ = browser_directory_.ToWStringHack(); - file_util::AppendToPath(&emf_path_, L"emf_dumps"); + file_util::AppendToPath(&emf_path_, L"metafile_dumps"); launch_arguments_.AppendSwitchWithValue(L"debug-print", L'"' + emf_path_ + L'"'); show_window_ = true; diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 4251678..9893313 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -302,8 +302,6 @@ 'common/extensions/url_pattern.h', 'common/extensions/user_script.cc', 'common/extensions/user_script.h', - 'common/gfx/emf.cc', - 'common/gfx/emf.h', 'common/gfx/utils.h', 'common/net/cookie_monster_sqlite.cc', 'common/net/cookie_monster_sqlite.h', @@ -525,7 +523,6 @@ ], }, { # else: OS != "win" 'sources!': [ - 'common/gfx/emf.cc', 'common/classfactory.cc', ], }], @@ -3575,7 +3572,6 @@ 'common/extensions/url_pattern_unittest.cc', 'common/extensions/user_script_unittest.cc', 'common/file_descriptor_set_unittest.cc', - 'common/gfx/emf_unittest.cc', 'common/important_file_writer_unittest.cc', 'common/ipc_message_unittest.cc', 'common/ipc_sync_channel_unittest.cc', @@ -3758,7 +3754,6 @@ 'browser/views/find_bar_win_unittest.cc', 'browser/views/keyword_editor_view_unittest.cc', 'common/chrome_plugin_unittest.cc', - 'common/gfx/emf_unittest.cc', 'common/net/url_util_unittest.cc', 'test/browser_with_test_window_test.cc', 'test/browser_with_test_window_test.h', @@ -4232,6 +4227,7 @@ 'installer/installer.gyp:installer_util_strings', 'theme_dll', 'worker', + '../printing/printing.gyp:printing', '../net/net.gyp:net_resources', '../build/util/support/support.gyp:*', '../third_party/cld/cld.gyp:cld', diff --git a/chrome/common/gfx/emf.cc b/chrome/common/gfx/emf.cc deleted file mode 100644 index 17ffae9..0000000 --- a/chrome/common/gfx/emf.cc +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (c) 2006-2008 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/common/gfx/emf.h" - -#include "base/gfx/rect.h" -#include "base/logging.h" - -namespace gfx { - -Emf::Emf() : emf_(NULL), hdc_(NULL) { -} - -Emf::~Emf() { - CloseEmf(); - DCHECK(!emf_ && !hdc_); -} - -bool Emf::CreateDc(HDC sibling, const RECT* rect) { - DCHECK(!emf_ && !hdc_); - hdc_ = CreateEnhMetaFile(sibling, NULL, rect, NULL); - DCHECK(hdc_); - return hdc_ != NULL; -} - -bool Emf::CreateFromData(const void* buffer, size_t size) { - DCHECK(!emf_ && !hdc_); - emf_ = SetEnhMetaFileBits(static_cast<unsigned>(size), - reinterpret_cast<const BYTE*>(buffer)); - DCHECK(emf_); - return emf_ != NULL; -} - -bool Emf::CloseDc() { - DCHECK(!emf_ && hdc_); - emf_ = CloseEnhMetaFile(hdc_); - DCHECK(emf_); - hdc_ = NULL; - return emf_ != NULL; -} - -void Emf::CloseEmf() { - DCHECK(!hdc_); - if (emf_) { - DeleteEnhMetaFile(emf_); - emf_ = NULL; - } -} - -bool Emf::Playback(HDC hdc, const RECT* rect) const { - DCHECK(emf_ && !hdc_); - RECT bounds; - if (!rect) { - // Get the natural bounds of the EMF buffer. - bounds = GetBounds().ToRECT(); - rect = &bounds; - } - return PlayEnhMetaFile(hdc, emf_, rect) != 0; -} - -bool Emf::SafePlayback(HDC context) const { - DCHECK(emf_ && !hdc_); - XFORM base_matrix; - if (!GetWorldTransform(context, &base_matrix)) { - NOTREACHED(); - return false; - } - - return EnumEnhMetaFile(context, - emf_, - &Emf::SafePlaybackProc, - reinterpret_cast<void*>(&base_matrix), - &GetBounds().ToRECT()) != 0; -} - -gfx::Rect Emf::GetBounds() const { - DCHECK(emf_ && !hdc_); - ENHMETAHEADER header; - if (GetEnhMetaFileHeader(emf_, sizeof(header), &header) != sizeof(header)) { - NOTREACHED(); - return gfx::Rect(); - } - if (header.rclBounds.left == 0 && - header.rclBounds.top == 0 && - header.rclBounds.right == -1 && - header.rclBounds.bottom == -1) { - // A freshly created EMF buffer that has no drawing operation has invalid - // bounds. Instead of having an (0,0) size, it has a (-1,-1) size. Detect - // this special case and returns an empty Rect instead of an invalid one. - return gfx::Rect(); - } - return gfx::Rect(header.rclBounds.left, - header.rclBounds.top, - header.rclBounds.right - header.rclBounds.left, - header.rclBounds.bottom - header.rclBounds.top); -} - -unsigned Emf::GetDataSize() const { - DCHECK(emf_ && !hdc_); - return GetEnhMetaFileBits(emf_, 0, NULL); -} - -bool Emf::GetData(void* buffer, size_t size) const { - DCHECK(emf_ && !hdc_); - DCHECK(buffer && size); - unsigned size2 = GetEnhMetaFileBits(emf_, static_cast<unsigned>(size), - reinterpret_cast<BYTE*>(buffer)); - DCHECK(size2 == size); - return size2 == size && size2 != 0; -} - -bool Emf::GetData(std::vector<uint8>* buffer) const { - unsigned size = GetDataSize(); - if (!size) - return false; - - buffer->resize(size); - if (!GetData(&buffer->front(), size)) - return false; - return true; -} - -bool Emf::SaveTo(const std::wstring& filename) const { - HANDLE file = CreateFile(filename.c_str(), GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - CREATE_ALWAYS, 0, NULL); - if (file == INVALID_HANDLE_VALUE) - return false; - - bool success = false; - std::vector<uint8> buffer; - if (GetData(&buffer)) { - DWORD written = 0; - if (WriteFile(file, &*buffer.begin(), static_cast<DWORD>(buffer.size()), - &written, NULL) && - written == buffer.size()) { - success = true; - } - } - CloseHandle(file); - return success; -} - -int CALLBACK Emf::SafePlaybackProc(HDC hdc, - HANDLETABLE* handle_table, - const ENHMETARECORD* record, - int objects_count, - LPARAM param) { - const XFORM* base_matrix = reinterpret_cast<const XFORM*>(param); - EnumerationContext context; - context.handle_table = handle_table; - context.objects_count = objects_count; - context.hdc = hdc; - Record record_instance(&context, record); - bool success = record_instance.SafePlayback(base_matrix); - DCHECK(success); - return 1; -} - -Emf::Record::Record() { -} - -Emf::Record::Record(const EnumerationContext* context, - const ENHMETARECORD* record) - : record_(record), - context_(context) { - DCHECK(record_); -} - -bool Emf::Record::Play() const { - return 0 != PlayEnhMetaFileRecord(context_->hdc, - context_->handle_table, - record_, - context_->objects_count); -} - -bool Emf::Record::SafePlayback(const XFORM* base_matrix) const { - // For EMF field description, see [MS-EMF] Enhanced Metafile Format - // Specification. - // - // This is the second major EMF breakage I get; the first one being - // SetDCBrushColor/SetDCPenColor/DC_PEN/DC_BRUSH being silently ignored. - // - // This function is the guts of the fix for bug 1186598. Some printer drivers - // somehow choke on certain EMF records, but calling the corresponding - // function directly on the printer HDC is fine. Still, playing the EMF record - // fails. Go figure. - // - // The main issue is that SetLayout is totally unsupported on these printers - // (HP 4500/4700). I used to call SetLayout and I stopped. I found out this is - // not sufficient because GDI32!PlayEnhMetaFile internally calls SetLayout(!) - // Damn. - // - // So I resorted to manually parse the EMF records and play them one by one. - // The issue with this method compared to using PlayEnhMetaFile to play back - // an EMF buffer is that the later silently fixes the matrix to take in - // account the matrix currently loaded at the time of the call. - // The matrix magic is done transparently when using PlayEnhMetaFile but since - // I'm processing one field at a time, I need to do the fixup myself. Note - // that PlayEnhMetaFileRecord doesn't fix the matrix correctly even when - // called inside an EnumEnhMetaFile loop. Go figure (bis). - // - // So when I see a EMR_SETWORLDTRANSFORM and EMR_MODIFYWORLDTRANSFORM, I need - // to fix the matrix according to the matrix previously loaded before playing - // back the buffer. Otherwise, the previously loaded matrix would be ignored - // and the EMF buffer would always be played back at its native resolution. - // Duh. - // - // I also use this opportunity to skip over eventual EMR_SETLAYOUT record that - // could remain. - // - // Note: I should probably care about view ports and clipping, eventually. - bool res; - switch (record()->iType) { - case EMR_SETWORLDTRANSFORM: { - DCHECK_EQ(record()->nSize, sizeof(DWORD) * 2 + sizeof(XFORM)); - const XFORM* xform = reinterpret_cast<const XFORM*>(record()->dParm); - HDC hdc = context_->hdc; - if (base_matrix) { - res = 0 != SetWorldTransform(hdc, base_matrix) && - ModifyWorldTransform(hdc, xform, MWT_LEFTMULTIPLY); - } else { - res = 0 != SetWorldTransform(hdc, xform); - } - break; - } - case EMR_MODIFYWORLDTRANSFORM: { - DCHECK_EQ(record()->nSize, - sizeof(DWORD) * 2 + sizeof(XFORM) + sizeof(DWORD)); - const XFORM* xform = reinterpret_cast<const XFORM*>(record()->dParm); - const DWORD* option = reinterpret_cast<const DWORD*>(xform + 1); - HDC hdc = context_->hdc; - switch (*option) { - case MWT_IDENTITY: - if (base_matrix) { - res = 0 != SetWorldTransform(hdc, base_matrix); - } else { - res = 0 != ModifyWorldTransform(hdc, xform, MWT_IDENTITY); - } - break; - case MWT_LEFTMULTIPLY: - case MWT_RIGHTMULTIPLY: - res = 0 != ModifyWorldTransform(hdc, xform, *option); - break; - case 4: // MWT_SET - if (base_matrix) { - res = 0 != SetWorldTransform(hdc, base_matrix) && - ModifyWorldTransform(hdc, xform, MWT_LEFTMULTIPLY); - } else { - res = 0 != SetWorldTransform(hdc, xform); - } - break; - default: - res = false; - break; - } - break; - } - case EMR_SETLAYOUT: - // Ignore it. - res = true; - break; - default: { - res = Play(); - break; - } - } - return res; -} - -Emf::Enumerator::Enumerator(const Emf& emf, HDC context, const RECT* rect) { - context_.handle_table = NULL; - context_.objects_count = 0; - context_.hdc = NULL; - items_.clear(); - if (!EnumEnhMetaFile(context, - emf.emf(), - &Emf::Enumerator::EnhMetaFileProc, - reinterpret_cast<void*>(this), - rect)) { - NOTREACHED(); - items_.clear(); - } - DCHECK_EQ(context_.hdc, context); -} - -Emf::Enumerator::const_iterator Emf::Enumerator::begin() const { - return items_.begin(); -} - -Emf::Enumerator::const_iterator Emf::Enumerator::end() const { - return items_.end(); -} - -int CALLBACK Emf::Enumerator::EnhMetaFileProc(HDC hdc, - HANDLETABLE* handle_table, - const ENHMETARECORD* record, - int objects_count, - LPARAM param) { - Enumerator& emf = *reinterpret_cast<Enumerator*>(param); - if (!emf.context_.handle_table) { - DCHECK(!emf.context_.handle_table); - DCHECK(!emf.context_.objects_count); - emf.context_.handle_table = handle_table; - emf.context_.objects_count = objects_count; - emf.context_.hdc = hdc; - } else { - DCHECK_EQ(emf.context_.handle_table, handle_table); - DCHECK_EQ(emf.context_.objects_count, objects_count); - DCHECK_EQ(emf.context_.hdc, hdc); - } - emf.items_.push_back(Record(&emf.context_, record)); - return 1; -} - -} // namespace gfx diff --git a/chrome/common/gfx/emf.h b/chrome/common/gfx/emf.h deleted file mode 100644 index 973f1e45..0000000 --- a/chrome/common/gfx/emf.h +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2006-2008 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_COMMON_GFX_EMF_H__ -#define CHROME_COMMON_GFX_EMF_H__ - -#include <windows.h> -#include <vector> - -#include "base/basictypes.h" - -namespace gfx { - -class Rect; - -// Simple wrapper class that manage an EMF data stream and its virtual HDC. -class Emf { - public: - class Record; - class Enumerator; - struct EnumerationContext; - - Emf(); - ~Emf(); - - // Generates a virtual HDC that will record every GDI commands and compile it - // in a EMF data stream. - // hdc is used to setup the default DPI and color settings. hdc is optional. - // rect specifies the dimensions (in .01-millimeter units) of the EMF. rect is - // optional. - bool CreateDc(HDC sibling, const RECT* rect); - - // Load a EMF data stream. buffer contains EMF data. - bool CreateFromData(const void* buffer, size_t size); - - // TODO(maruel): CreateFromFile(). If ever used. Maybe users would like to - // have the ability to save web pages to an EMF file? Afterward, it is easy to - // convert to PDF or PS. - - // Closes the HDC created by CreateDc() and generates the compiled EMF - // data. - bool CloseDc(); - - // Closes the EMF data handle when it is not needed anymore. - void CloseEmf(); - - // "Plays" the EMF buffer in a HDC. It is the same effect as calling the - // original GDI function that were called when recording the EMF. |rect| is in - // "logical units" and is optional. If |rect| is NULL, the natural EMF bounds - // are used. - // Note: Windows has been known to have stack buffer overflow in its GDI - // functions, whether used directly or indirectly through precompiled EMF - // data. We have to accept the risk here. Since it is used only for printing, - // it requires user intervention. - bool Playback(HDC hdc, const RECT* rect) const; - - // The slow version of Playback(). It enumerates all the records and play them - // back in the HDC. The trick is that it skip over the records known to have - // issue with some printers. See Emf::Record::SafePlayback implementation for - // details. - bool SafePlayback(HDC hdc) const; - - // Retrieves the bounds of the painted area by this EMF buffer. This value - // should be passed to Playback to keep the exact same size. - gfx::Rect GetBounds() const; - - // Retrieves the EMF stream size. - unsigned GetDataSize() const; - - // Retrieves the EMF stream. - bool GetData(void* buffer, size_t size) const; - - // Retrieves the EMF stream. It is an helper function. - bool GetData(std::vector<uint8>* buffer) const; - - HENHMETAFILE emf() const { - return emf_; - } - - HDC hdc() const { - return hdc_; - } - - // Saves the EMF data to a file as-is. It is recommended to use the .emf file - // extension but it is not enforced. This function synchronously writes to the - // file. For testing only. - bool SaveTo(const std::wstring& filename) const; - - private: - // Playbacks safely one EMF record. - static int CALLBACK SafePlaybackProc(HDC hdc, - HANDLETABLE* handle_table, - const ENHMETARECORD* record, - int objects_count, - LPARAM param); - - // Compiled EMF data handle. - HENHMETAFILE emf_; - - // Valid when generating EMF data through a virtual HDC. - HDC hdc_; - - DISALLOW_EVIL_CONSTRUCTORS(Emf); -}; - -struct Emf::EnumerationContext { - HANDLETABLE* handle_table; - int objects_count; - HDC hdc; -}; - -// One EMF record. It keeps pointers to the EMF buffer held by Emf::emf_. -// The entries become invalid once Emf::CloseEmf() is called. -class Emf::Record { - public: - Record(); - - // Plays the record. - bool Play() const; - - // Plays the record working around quirks with SetLayout, - // SetWorldTransform and ModifyWorldTransform. See implementation for details. - bool SafePlayback(const XFORM* base_matrix) const; - - // Access the underlying EMF record. - const ENHMETARECORD* record() const { return record_; } - - protected: - Record(const EnumerationContext* context, - const ENHMETARECORD* record); - - private: - friend class Emf; - friend class Enumerator; - const ENHMETARECORD* record_; - const EnumerationContext* context_; -}; - -// Retrieves individual records out of a Emf buffer. The main use is to skip -// over records that are unsupported on a specific printer or to play back -// only a part of an EMF buffer. -class Emf::Enumerator { - public: - // Iterator type used for iterating the records. - typedef std::vector<Record>::const_iterator const_iterator; - - // Enumerates the records at construction time. |hdc| and |rect| are - // both optional at the same time or must both be valid. - // Warning: |emf| must be kept valid for the time this object is alive. - Enumerator(const Emf& emf, HDC hdc, const RECT* rect); - - // Retrieves the first Record. - const_iterator begin() const; - - // Retrieves the end of the array. - const_iterator end() const; - - private: - // Processes one EMF record and saves it in the items_ array. - static int CALLBACK EnhMetaFileProc(HDC hdc, - HANDLETABLE* handle_table, - const ENHMETARECORD* record, - int objects_count, - LPARAM param); - - // The collection of every EMF records in the currently loaded EMF buffer. - // Initialized by Enumerate(). It keeps pointers to the EMF buffer held by - // Emf::emf_. The entries become invalid once Emf::CloseEmf() is called. - std::vector<Record> items_; - - EnumerationContext context_; - - DISALLOW_EVIL_CONSTRUCTORS(Enumerator); -}; - -} // namespace gfx - -#endif // CHROME_COMMON_GFX_EMF_H__ diff --git a/chrome/common/gfx/emf_unittest.cc b/chrome/common/gfx/emf_unittest.cc deleted file mode 100644 index 4a78e9a..0000000 --- a/chrome/common/gfx/emf_unittest.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2006-2008 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/common/gfx/emf.h" - -// For quick access. -#include <wingdi.h> - -#include "base/basictypes.h" -#include "base/file_util.h" -#include "base/path_service.h" -#include "chrome/browser/printing/win_printing_context.h" -#include "chrome/common/chrome_paths.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -// This test is automatically disabled if no printer named "UnitTest Printer" is -// available. -class EmfPrintingTest : public testing::Test { - public: - typedef testing::Test Parent; - static bool IsTestCaseDisabled() { - // It is assumed this printer is a HP Color LaserJet 4550 PCL or 4700. - HDC hdc = CreateDC(L"WINSPOOL", L"UnitTest Printer", NULL, NULL); - if (!hdc) - return true; - DeleteDC(hdc); - return false; - } -}; - -} // namespace - -TEST(EmfTest, DC) { - static const int EMF_HEADER_SIZE = 128; - - // Simplest use case. - gfx::Emf emf; - RECT rect = {100, 100, 200, 200}; - HDC hdc = CreateCompatibleDC(NULL); - EXPECT_TRUE(hdc != NULL); - EXPECT_TRUE(emf.CreateDc(hdc, &rect)); - EXPECT_TRUE(emf.hdc() != NULL); - // In theory, you'd use the HDC with GDI functions here. - EXPECT_TRUE(emf.CloseDc()); - unsigned size = emf.GetDataSize(); - EXPECT_EQ(size, EMF_HEADER_SIZE); - std::vector<BYTE> data; - EXPECT_TRUE(emf.GetData(&data)); - EXPECT_EQ(data.size(), size); - emf.CloseEmf(); - EXPECT_TRUE(DeleteDC(hdc)); - - // Playback the data. - hdc = CreateCompatibleDC(NULL); - EXPECT_TRUE(hdc); - EXPECT_TRUE(emf.CreateFromData(&data.front(), size)); - RECT output_rect = {0, 0, 10, 10}; - EXPECT_TRUE(emf.Playback(hdc, &output_rect)); - EXPECT_TRUE(DeleteDC(hdc)); -} - - -// Disabled if no "UnitTest printer" exist. Useful to reproduce bug 1186598. -TEST_F(EmfPrintingTest, Enumerate) { - if (IsTestCaseDisabled()) - return; - - printing::PrintSettings settings; - - // My test case is a HP Color LaserJet 4550 PCL. - settings.set_device_name(L"UnitTest Printer"); - - // Initialize it. - printing::PrintingContext context; - EXPECT_EQ(context.InitWithSettings(settings), printing::PrintingContext::OK); - - std::wstring test_file; - PathService::Get(chrome::DIR_TEST_DATA, &test_file); - - // Load any EMF with an image. - gfx::Emf emf; - file_util::AppendToPath(&test_file, L"printing"); - file_util::AppendToPath(&test_file, L"test4.emf"); - std::string emf_data; - file_util::ReadFileToString(test_file, &emf_data); - ASSERT_TRUE(emf_data.size()); - EXPECT_TRUE(emf.CreateFromData(&emf_data[0], emf_data.size())); - - // This will print to file. The reason is that when running inside a - // unit_test, printing::PrintingContext automatically dumps its files to the - // current directory. - // TODO(maruel): Clean the .PRN file generated in current directory. - context.NewDocument(L"EmfTest.Enumerate"); - context.NewPage(); - // Process one at a time. - gfx::Emf::Enumerator emf_enum(emf, context.context(), - &emf.GetBounds().ToRECT()); - for (gfx::Emf::Enumerator::const_iterator itr = emf_enum.begin(); - itr != emf_enum.end(); - ++itr) { - // To help debugging. - ptrdiff_t index = itr - emf_enum.begin(); - // If you get this assert, you need to lookup iType in wingdi.h. It starts - // with EMR_HEADER. - EMR_HEADER; - EXPECT_TRUE(itr->SafePlayback(NULL)) << - " index: " << index << " type: " << itr->record()->iType; - } - context.PageDone(); - context.DocumentDone(); -} diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index cd62ed1..8cd4280 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -335,9 +335,9 @@ struct ViewMsg_PrintPages_Params { struct ViewHostMsg_DidPrintPage_Params { // A shared memory handle to the EMF data. This data can be quite large so a // memory map needs to be used. - base::SharedMemoryHandle emf_data_handle; + base::SharedMemoryHandle metafile_data_handle; - // Size of the EMF data. + // Size of the metafile data. unsigned data_size; // Cookie for the document to ensure correctness. @@ -1490,14 +1490,14 @@ template <> struct ParamTraits<ViewHostMsg_DidPrintPage_Params> { typedef ViewHostMsg_DidPrintPage_Params param_type; static void Write(Message* m, const param_type& p) { - WriteParam(m, p.emf_data_handle); + WriteParam(m, p.metafile_data_handle); WriteParam(m, p.data_size); WriteParam(m, p.document_cookie); WriteParam(m, p.page_number); WriteParam(m, p.actual_shrink); } static bool Read(const Message* m, void** iter, param_type* p) { - return ReadParam(m, iter, &p->emf_data_handle) && + return ReadParam(m, iter, &p->metafile_data_handle) && ReadParam(m, iter, &p->data_size) && ReadParam(m, iter, &p->document_cookie) && ReadParam(m, iter, &p->page_number) && diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index 8cc3273..e607667 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -13,16 +13,13 @@ #include "chrome/plugin/plugin_channel.h" #include "chrome/plugin/plugin_thread.h" #include "chrome/plugin/webplugin_proxy.h" +#include "printing/native_metafile.h" #include "third_party/npapi/bindings/npapi.h" #include "third_party/npapi/bindings/npruntime.h" #include "skia/ext/platform_device.h" #include "webkit/glue/webcursor.h" #include "webkit/glue/webplugin_delegate.h" -#if defined(OS_WIN) -#include "chrome/common/gfx/emf.h" -#endif - class FinishDestructionTask : public Task { public: FinishDestructionTask(WebPluginDelegate* delegate, WebPlugin* webplugin) @@ -230,26 +227,26 @@ void WebPluginDelegateStub::OnDidPaint() { void WebPluginDelegateStub::OnPrint(base::SharedMemoryHandle* shared_memory, size_t* size) { #if defined(OS_WIN) - gfx::Emf emf; - if (!emf.CreateDc(NULL, NULL)) { + printing::NativeMetafile metafile; + if (!metafile.CreateDc(NULL, NULL)) { NOTREACHED(); return; } - HDC hdc = emf.hdc(); + HDC hdc = metafile.hdc(); skia::PlatformDevice::InitializeDC(hdc); delegate_->Print(hdc); - if (!emf.CloseDc()) { + if (!metafile.CloseDc()) { NOTREACHED(); return; } - *size = emf.GetDataSize(); + *size = metafile.GetDataSize(); DCHECK(*size); base::SharedMemory shared_buf; CreateSharedBuffer(*size, &shared_buf, shared_memory); // Retrieve a copy of the data. - bool success = emf.GetData(shared_buf.memory(), *size); + bool success = metafile.GetData(shared_buf.memory(), *size); DCHECK(success); #else // TODO(port): plugin printing. diff --git a/chrome/renderer/mock_printer.cc b/chrome/renderer/mock_printer.cc index 1b0dcc5..2454a0c 100644 --- a/chrome/renderer/mock_printer.cc +++ b/chrome/renderer/mock_printer.cc @@ -113,7 +113,7 @@ void MockPrinter::PrintPage(const ViewHostMsg_DidPrintPage_Params& params) { // We duplicate the given file handle when creating a base::SharedMemory // instance so that its destructor closes the copy. EXPECT_GT(params.data_size, 0U); - base::SharedMemory emf_data(params.emf_data_handle, true, + base::SharedMemory emf_data(params.metafile_data_handle, true, GetCurrentProcess()); emf_data.Map(params.data_size); MockPrinterPage* page_data = driver_.LoadSource(emf_data.memory(), diff --git a/chrome/renderer/mock_printer_driver_win.cc b/chrome/renderer/mock_printer_driver_win.cc index 051838b..8fefd8e 100644 --- a/chrome/renderer/mock_printer_driver_win.cc +++ b/chrome/renderer/mock_printer_driver_win.cc @@ -6,7 +6,7 @@ #include "base/gfx/gdi_util.h" #include "base/logging.h" -#include "chrome/common/gfx/emf.h" +#include "printing/emf_win.h" #include "chrome/renderer/mock_printer.h" #include "skia/ext/platform_device.h" @@ -57,7 +57,7 @@ class EmfRenderer { } } - const void* Create(int width, int height, const gfx::Emf* emf) { + const void* Create(int width, int height, const printing::Emf* emf) { CHECK(!dc_ && !bitmap_); BITMAPV4HEADER header; @@ -98,7 +98,7 @@ 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". - gfx::Emf emf; + printing::Emf emf; emf.CreateFromData(source_data, source_size); gfx::Rect rect(emf.GetBounds()); diff --git a/chrome/renderer/print_web_view_helper.cc b/chrome/renderer/print_web_view_helper.cc index d5389af..f53709e 100644 --- a/chrome/renderer/print_web_view_helper.cc +++ b/chrome/renderer/print_web_view_helper.cc @@ -10,6 +10,7 @@ #include "chrome/common/render_messages.h" #include "chrome/renderer/render_view.h" #include "grit/generated_resources.h" +#include "printing/native_metafile.h" #include "printing/units.h" #include "webkit/api/public/WebConsoleMessage.h" #include "webkit/api/public/WebScreenInfo.h" @@ -19,7 +20,6 @@ #include "webkit/glue/webframe.h" #if defined(OS_WIN) -#include "chrome/common/gfx/emf.h" #include "skia/ext/vector_canvas.h" #endif @@ -283,12 +283,11 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, const gfx::Size& canvas_size, WebFrame* frame) { #if defined(OS_WIN) - // Generate a memory-based EMF file. The EMF will use the current screen's - // DPI. - gfx::Emf emf; + // Generate a memory-based metafile. It will use the current screen's DPI. + printing::NativeMetafile metafile; - emf.CreateDc(NULL, NULL); - HDC hdc = emf.hdc(); + metafile.CreateDc(NULL, NULL); + HDC hdc = metafile.hdc(); DCHECK(hdc); skia::PlatformDevice::InitializeDC(hdc); // Since WebKit extends the page width depending on the magical shrink @@ -344,17 +343,17 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, } #endif - // Done printing. Close the device context to retrieve the compiled EMF. - if (!emf.CloseDc()) { - NOTREACHED() << "EMF failed"; + // Done printing. Close the device context to retrieve the compiled metafile. + if (!metafile.CloseDc()) { + NOTREACHED() << "metafile failed"; } - // Get the size of the compiled EMF. - unsigned buf_size = emf.GetDataSize(); + // Get the size of the compiled metafile. + unsigned buf_size = metafile.GetDataSize(); DCHECK_GT(buf_size, 128u); ViewHostMsg_DidPrintPage_Params page_params; page_params.data_size = 0; - page_params.emf_data_handle = NULL; + page_params.metafile_data_handle = NULL; page_params.page_number = params.page_number; page_params.document_cookie = params.params.document_cookie; page_params.actual_shrink = shrink; @@ -364,12 +363,12 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, // Windows 2000/XP: When a page in a spooled file exceeds approximately 350 // MB, it can fail to print and not send an error message. if (buf_size < 350*1024*1024) { - // Allocate a shared memory buffer to hold the generated EMF data. + // Allocate a shared memory buffer to hold the generated metafile data. if (shared_buf.Create(L"", false, false, buf_size) && shared_buf.Map(buf_size)) { // Copy the bits into shared memory. - if (emf.GetData(shared_buf.memory(), buf_size)) { - page_params.emf_data_handle = shared_buf.handle(); + if (metafile.GetData(shared_buf.memory(), buf_size)) { + page_params.metafile_data_handle = shared_buf.handle(); page_params.data_size = buf_size; } else { NOTREACHED() << "GetData() failed"; @@ -381,10 +380,11 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, } else { NOTREACHED() << "Buffer too large: " << buf_size; } - emf.CloseEmf(); - if (Send(new ViewHostMsg_DuplicateSection(routing_id(), - page_params.emf_data_handle, - &page_params.emf_data_handle))) { + metafile.CloseEmf(); + if (Send(new ViewHostMsg_DuplicateSection( + routing_id(), + page_params.metafile_data_handle, + &page_params.metafile_data_handle))) { Send(new ViewHostMsg_DidPrintPage(routing_id(), page_params)); } #else // defined(OS_WIN) diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 8117acf..b98b728 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -29,6 +29,7 @@ #include "googleurl/src/gurl.h" #include "grit/generated_resources.h" #include "net/base/mime_util.h" +#include "printing/native_metafile.h" #include "webkit/api/public/WebDragData.h" #include "webkit/api/public/WebString.h" #include "webkit/api/public/WebVector.h" @@ -37,10 +38,6 @@ #include "webkit/glue/webplugin.h" #include "webkit/glue/webview.h" -#if defined(OS_WIN) -#include "chrome/common/gfx/emf.h" -#endif - #if defined(OS_POSIX) #include "chrome/common/ipc_channel_posix.h" #endif @@ -579,13 +576,13 @@ void WebPluginDelegateProxy::Print(gfx::NativeDrawingContext context) { } #if defined(OS_WIN) - gfx::Emf emf; - if (!emf.CreateFromData(memory.memory(), size)) { + printing::NativeMetafile metafile; + if (!metafile.CreateFromData(memory.memory(), size)) { NOTREACHED(); return; } // Playback the buffer. - emf.Playback(context, NULL); + metafile.Playback(context, NULL); #else // TODO(port): plugin printing. NOTIMPLEMENTED(); |