blob: d7395f59bd62aae98bf855f9240cb96dba339466 [file] [log] [blame]
[email protected]0064b392012-06-20 01:57:381// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]0e0fca32009-07-06 15:25:505#include "printing/emf_win.h"
initial.commit09911bf2008-07-26 23:55:296
7// For quick access.
avi126e93c2015-12-21 21:48:168#include <stdint.h>
initial.commit09911bf2008-07-26 23:55:299#include <wingdi.h>
[email protected]2aa8e182010-07-12 16:25:0410#include <winspool.h>
initial.commit09911bf2008-07-26 23:55:2911
dchengc3df9ba2016-04-07 23:09:3212#include <memory>
[email protected]83deae22011-10-07 05:56:3213#include <string>
14
[email protected]57999812013-02-24 05:40:5215#include "base/files/file_path.h"
thestig22dfc4012014-09-05 08:29:4416#include "base/files/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2317#include "base/files/scoped_temp_dir.h"
initial.commit09911bf2008-07-26 23:55:2918#include "base/path_service.h"
[email protected]0142bd4f2010-12-31 01:02:4719#include "base/win/scoped_hdc.h"
[email protected]daee4972009-07-09 14:28:2420#include "printing/printing_context.h"
thestig5f683912016-09-30 22:42:1621#include "printing/printing_context_win.h"
initial.commit09911bf2008-07-26 23:55:2922#include "testing/gtest/include/gtest/gtest.h"
tfarina655f81d2014-12-23 02:38:5023#include "ui/gfx/geometry/point.h"
tfarinaebe974f02015-01-03 04:25:3224#include "ui/gfx/geometry/size.h"
initial.commit09911bf2008-07-26 23:55:2925
Vitaly Bukabd7c9812014-08-26 08:57:5426namespace printing {
27
initial.commit09911bf2008-07-26 23:55:2928namespace {
29
30// This test is automatically disabled if no printer named "UnitTest Printer" is
31// available.
Vitaly Bukabd7c9812014-08-26 08:57:5432class EmfPrintingTest : public testing::Test, public PrintingContext::Delegate {
initial.commit09911bf2008-07-26 23:55:2933 public:
34 typedef testing::Test Parent;
35 static bool IsTestCaseDisabled() {
36 // It is assumed this printer is a HP Color LaserJet 4550 PCL or 4700.
thestig5f683912016-09-30 22:42:1637 HDC hdc = CreateDC(L"WINSPOOL", L"UnitTest Printer", nullptr, nullptr);
initial.commit09911bf2008-07-26 23:55:2938 if (!hdc)
39 return true;
40 DeleteDC(hdc);
41 return false;
42 }
Vitaly Bukabd7c9812014-08-26 08:57:5443
44 // PrintingContext::Delegate methods.
thestig5f683912016-09-30 22:42:1645 gfx::NativeView GetParentView() override { return nullptr; }
nickbc761612015-04-27 23:30:4646 std::string GetAppLocale() override { return std::string(); }
initial.commit09911bf2008-07-26 23:55:2947};
48
thestig707a24b22015-09-14 18:16:3349const uint32_t EMF_HEADER_SIZE = 128;
[email protected]e6cddc572010-09-29 21:39:4550
initial.commit09911bf2008-07-26 23:55:2951} // namespace
52
53TEST(EmfTest, DC) {
initial.commit09911bf2008-07-26 23:55:2954 // Simplest use case.
thestig707a24b22015-09-14 18:16:3355 uint32_t size;
vitalybuka5d1290582014-09-12 09:19:5956 std::vector<char> data;
[email protected]481edc52011-03-22 06:36:5857 {
[email protected]d91db112011-10-18 20:58:5158 Emf emf;
[email protected]481edc52011-03-22 06:36:5859 EXPECT_TRUE(emf.Init());
thestig192677ec2016-06-09 07:43:1760 EXPECT_TRUE(emf.context());
[email protected]481edc52011-03-22 06:36:5861 // An empty EMF is invalid, so we put at least a rectangle in it.
62 ::Rectangle(emf.context(), 10, 10, 190, 190);
63 EXPECT_TRUE(emf.FinishDocument());
64 size = emf.GetDataSize();
65 EXPECT_GT(size, EMF_HEADER_SIZE);
[email protected]96fddd82011-03-24 23:37:4566 EXPECT_TRUE(emf.GetDataAsVector(&data));
[email protected]481edc52011-03-22 06:36:5867 EXPECT_EQ(data.size(), size);
68 }
initial.commit09911bf2008-07-26 23:55:2969
70 // Playback the data.
[email protected]d91db112011-10-18 20:58:5171 Emf emf;
[email protected]f2da4b02011-03-18 05:45:5172 EXPECT_TRUE(emf.InitFromData(&data.front(), size));
thestig5f683912016-09-30 22:42:1673 HDC hdc = CreateCompatibleDC(nullptr);
[email protected]481edc52011-03-22 06:36:5874 EXPECT_TRUE(hdc);
initial.commit09911bf2008-07-26 23:55:2975 RECT output_rect = {0, 0, 10, 10};
76 EXPECT_TRUE(emf.Playback(hdc, &output_rect));
77 EXPECT_TRUE(DeleteDC(hdc));
78}
79
initial.commit09911bf2008-07-26 23:55:2980// Disabled if no "UnitTest printer" exist. Useful to reproduce bug 1186598.
81TEST_F(EmfPrintingTest, Enumerate) {
82 if (IsTestCaseDisabled())
83 return;
84
[email protected]d91db112011-10-18 20:58:5185 PrintSettings settings;
initial.commit09911bf2008-07-26 23:55:2986
87 // My test case is a HP Color LaserJet 4550 PCL.
88 settings.set_device_name(L"UnitTest Printer");
89
90 // Initialize it.
thestig5f683912016-09-30 22:42:1691 PrintingContextWin context(this);
92 EXPECT_EQ(PrintingContext::OK, context.InitWithSettingsForTest(settings));
initial.commit09911bf2008-07-26 23:55:2993
[email protected]79f63882013-02-10 05:15:4594 base::FilePath emf_file;
Avi Drissmanea15ea02018-05-07 18:55:1295 EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &emf_file));
[email protected]daee4972009-07-09 14:28:2496 emf_file = emf_file.Append(FILE_PATH_LITERAL("printing"))
Lei Zhang01a1d3c02019-05-21 04:59:1097 .Append(FILE_PATH_LITERAL("test"))
98 .Append(FILE_PATH_LITERAL("data"))
99 .Append(FILE_PATH_LITERAL("test4.emf"));
thestig6b4461f2016-10-28 19:34:30100
initial.commit09911bf2008-07-26 23:55:29101 // Load any EMF with an image.
initial.commit09911bf2008-07-26 23:55:29102 std::string emf_data;
[email protected]82f84b92013-08-30 18:23:50103 base::ReadFileToString(emf_file, &emf_data);
initial.commit09911bf2008-07-26 23:55:29104 ASSERT_TRUE(emf_data.size());
thestig6b4461f2016-10-28 19:34:30105
106 Emf emf;
[email protected]89eff96a2011-03-17 23:22:06107 EXPECT_TRUE(emf.InitFromData(&emf_data[0], emf_data.size()));
initial.commit09911bf2008-07-26 23:55:29108
109 // This will print to file. The reason is that when running inside a
[email protected]d91db112011-10-18 20:58:51110 // unit_test, PrintingContext automatically dumps its files to the
initial.commit09911bf2008-07-26 23:55:29111 // current directory.
112 // TODO(maruel): Clean the .PRN file generated in current directory.
thestig5f683912016-09-30 22:42:16113 context.NewDocument(L"EmfTest.Enumerate");
114 context.NewPage();
initial.commit09911bf2008-07-26 23:55:29115 // Process one at a time.
[email protected]59149922014-07-04 22:08:04116 RECT page_bounds = emf.GetPageBounds(1).ToRECT();
thestig5f683912016-09-30 22:42:16117 Emf::Enumerator emf_enum(emf, context.context(), &page_bounds);
[email protected]d91db112011-10-18 20:58:51118 for (Emf::Enumerator::const_iterator itr = emf_enum.begin();
Lei Zhang01a1d3c02019-05-21 04:59:10119 itr != emf_enum.end(); ++itr) {
initial.commit09911bf2008-07-26 23:55:29120 // To help debugging.
121 ptrdiff_t index = itr - emf_enum.begin();
122 // If you get this assert, you need to lookup iType in wingdi.h. It starts
123 // with EMR_HEADER.
124 EMR_HEADER;
Lei Zhang01a1d3c02019-05-21 04:59:10125 EXPECT_TRUE(itr->SafePlayback(&emf_enum.context_))
126 << " index: " << index << " type: " << itr->record()->iType;
initial.commit09911bf2008-07-26 23:55:29127 }
thestig5f683912016-09-30 22:42:16128 context.PageDone();
129 context.DocumentDone();
initial.commit09911bf2008-07-26 23:55:29130}
[email protected]daee4972009-07-09 14:28:24131
[email protected]2aa8e182010-07-12 16:25:04132// Disabled if no "UnitTest printer" exists.
133TEST_F(EmfPrintingTest, PageBreak) {
[email protected]83deae22011-10-07 05:56:32134 base::win::ScopedCreateDC dc(
thestig5f683912016-09-30 22:42:16135 CreateDC(L"WINSPOOL", L"UnitTest Printer", nullptr, nullptr));
[email protected]6f0db2b2012-02-14 03:56:18136 if (!dc.Get())
[email protected]2aa8e182010-07-12 16:25:04137 return;
thestig707a24b22015-09-14 18:16:33138 uint32_t size;
vitalybuka5d1290582014-09-12 09:19:59139 std::vector<char> data;
[email protected]481edc52011-03-22 06:36:58140 {
[email protected]d91db112011-10-18 20:58:51141 Emf emf;
[email protected]481edc52011-03-22 06:36:58142 EXPECT_TRUE(emf.Init());
thestig192677ec2016-06-09 07:43:17143 EXPECT_TRUE(emf.context());
[email protected]481edc52011-03-22 06:36:58144 int pages = 3;
145 while (pages) {
thestig192677ec2016-06-09 07:43:17146 emf.StartPage(gfx::Size(), gfx::Rect(), 1);
[email protected]481edc52011-03-22 06:36:58147 ::Rectangle(emf.context(), 10, 10, 190, 190);
148 EXPECT_TRUE(emf.FinishPage());
149 --pages;
150 }
[email protected]830cf742011-04-01 16:06:25151 EXPECT_EQ(3U, emf.GetPageCount());
[email protected]481edc52011-03-22 06:36:58152 EXPECT_TRUE(emf.FinishDocument());
153 size = emf.GetDataSize();
[email protected]96fddd82011-03-24 23:37:45154 EXPECT_TRUE(emf.GetDataAsVector(&data));
[email protected]481edc52011-03-22 06:36:58155 EXPECT_EQ(data.size(), size);
156 }
[email protected]2aa8e182010-07-12 16:25:04157
158 // Playback the data.
159 DOCINFO di = {0};
160 di.cbSize = sizeof(DOCINFO);
161 di.lpszDocName = L"Test Job";
[email protected]6f0db2b2012-02-14 03:56:18162 int job_id = ::StartDoc(dc.Get(), &di);
[email protected]d91db112011-10-18 20:58:51163 Emf emf;
[email protected]89eff96a2011-03-17 23:22:06164 EXPECT_TRUE(emf.InitFromData(&data.front(), size));
[email protected]6f0db2b2012-02-14 03:56:18165 EXPECT_TRUE(emf.SafePlayback(dc.Get()));
166 ::EndDoc(dc.Get());
[email protected]2aa8e182010-07-12 16:25:04167 // Since presumably the printer is not real, let us just delete the job from
168 // the queue.
thestig5f683912016-09-30 22:42:16169 HANDLE printer = nullptr;
170 if (::OpenPrinter(const_cast<LPTSTR>(L"UnitTest Printer"), &printer,
171 nullptr)) {
172 ::SetJob(printer, job_id, 0, nullptr, JOB_CONTROL_DELETE);
[email protected]2aa8e182010-07-12 16:25:04173 ClosePrinter(printer);
174 }
175}
176
[email protected]481edc52011-03-22 06:36:58177TEST(EmfTest, FileBackedEmf) {
[email protected]e6cddc572010-09-29 21:39:45178 // Simplest use case.
[email protected]ea1a3f62012-11-16 20:34:23179 base::ScopedTempDir scratch_metafile_dir;
[email protected]f21104d2010-10-08 20:57:57180 ASSERT_TRUE(scratch_metafile_dir.CreateUniqueTempDir());
[email protected]79f63882013-02-10 05:15:45181 base::FilePath metafile_path;
vabr16e5f602016-09-15 18:14:00182 EXPECT_TRUE(base::CreateTemporaryFileInDir(scratch_metafile_dir.GetPath(),
[email protected]03d9afc02013-12-03 17:55:52183 &metafile_path));
thestig707a24b22015-09-14 18:16:33184 uint32_t size;
vitalybuka5d1290582014-09-12 09:19:59185 std::vector<char> data;
[email protected]481edc52011-03-22 06:36:58186 {
[email protected]d91db112011-10-18 20:58:51187 Emf emf;
[email protected]481edc52011-03-22 06:36:58188 EXPECT_TRUE(emf.InitToFile(metafile_path));
thestig192677ec2016-06-09 07:43:17189 EXPECT_TRUE(emf.context());
[email protected]481edc52011-03-22 06:36:58190 // An empty EMF is invalid, so we put at least a rectangle in it.
191 ::Rectangle(emf.context(), 10, 10, 190, 190);
192 EXPECT_TRUE(emf.FinishDocument());
193 size = emf.GetDataSize();
194 EXPECT_GT(size, EMF_HEADER_SIZE);
[email protected]96fddd82011-03-24 23:37:45195 EXPECT_TRUE(emf.GetDataAsVector(&data));
[email protected]481edc52011-03-22 06:36:58196 EXPECT_EQ(data.size(), size);
197 }
thestig707a24b22015-09-14 18:16:33198 int64_t file_size = 0;
[email protected]56285702013-12-04 18:22:49199 base::GetFileSize(metafile_path, &file_size);
[email protected]e6cddc572010-09-29 21:39:45200 EXPECT_EQ(size, file_size);
[email protected]e6cddc572010-09-29 21:39:45201
202 // Playback the data.
thestig5f683912016-09-30 22:42:16203 HDC hdc = CreateCompatibleDC(nullptr);
[email protected]e6cddc572010-09-29 21:39:45204 EXPECT_TRUE(hdc);
[email protected]d91db112011-10-18 20:58:51205 Emf emf;
[email protected]481edc52011-03-22 06:36:58206 EXPECT_TRUE(emf.InitFromFile(metafile_path));
[email protected]e6cddc572010-09-29 21:39:45207 RECT output_rect = {0, 0, 10, 10};
208 EXPECT_TRUE(emf.Playback(hdc, &output_rect));
209 EXPECT_TRUE(DeleteDC(hdc));
210}
211
[email protected]5ad76172011-03-02 19:25:17212} // namespace printing