Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2350)

Unified Diff: chrome/common/gfx/emf.cc

Issue 149181: Move Emf class to the printing library. Also creates a platform agnostic Nat... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/common/gfx/emf.h ('k') | chrome/common/gfx/emf_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/common/gfx/emf.cc
===================================================================
--- chrome/common/gfx/emf.cc (revision 19913)
+++ chrome/common/gfx/emf.cc (working copy)
@@ -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
« no previous file with comments | « chrome/common/gfx/emf.h ('k') | chrome/common/gfx/emf_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698