blob: 9372af13d27768deb67e1bfb86d62591513931bc [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"))
97 .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();
initial.commit09911bf2008-07-26 23:55:29119 itr != emf_enum.end();
120 ++itr) {
121 // To help debugging.
122 ptrdiff_t index = itr - emf_enum.begin();
123 // If you get this assert, you need to lookup iType in wingdi.h. It starts
124 // with EMR_HEADER.
125 EMR_HEADER;
[email protected]0064b392012-06-20 01:57:38126 EXPECT_TRUE(itr->SafePlayback(&emf_enum.context_)) <<
initial.commit09911bf2008-07-26 23:55:29127 " index: " << index << " type: " << itr->record()->iType;
128 }
thestig5f683912016-09-30 22:42:16129 context.PageDone();
130 context.DocumentDone();
initial.commit09911bf2008-07-26 23:55:29131}
[email protected]daee4972009-07-09 14:28:24132
[email protected]2aa8e182010-07-12 16:25:04133// Disabled if no "UnitTest printer" exists.
134TEST_F(EmfPrintingTest, PageBreak) {
[email protected]83deae22011-10-07 05:56:32135 base::win::ScopedCreateDC dc(
thestig5f683912016-09-30 22:42:16136 CreateDC(L"WINSPOOL", L"UnitTest Printer", nullptr, nullptr));
[email protected]6f0db2b2012-02-14 03:56:18137 if (!dc.Get())
[email protected]2aa8e182010-07-12 16:25:04138 return;
thestig707a24b22015-09-14 18:16:33139 uint32_t size;
vitalybuka5d1290582014-09-12 09:19:59140 std::vector<char> data;
[email protected]481edc52011-03-22 06:36:58141 {
[email protected]d91db112011-10-18 20:58:51142 Emf emf;
[email protected]481edc52011-03-22 06:36:58143 EXPECT_TRUE(emf.Init());
thestig192677ec2016-06-09 07:43:17144 EXPECT_TRUE(emf.context());
[email protected]481edc52011-03-22 06:36:58145 int pages = 3;
146 while (pages) {
thestig192677ec2016-06-09 07:43:17147 emf.StartPage(gfx::Size(), gfx::Rect(), 1);
[email protected]481edc52011-03-22 06:36:58148 ::Rectangle(emf.context(), 10, 10, 190, 190);
149 EXPECT_TRUE(emf.FinishPage());
150 --pages;
151 }
[email protected]830cf742011-04-01 16:06:25152 EXPECT_EQ(3U, emf.GetPageCount());
[email protected]481edc52011-03-22 06:36:58153 EXPECT_TRUE(emf.FinishDocument());
154 size = emf.GetDataSize();
[email protected]96fddd82011-03-24 23:37:45155 EXPECT_TRUE(emf.GetDataAsVector(&data));
[email protected]481edc52011-03-22 06:36:58156 EXPECT_EQ(data.size(), size);
157 }
[email protected]2aa8e182010-07-12 16:25:04158
159 // Playback the data.
160 DOCINFO di = {0};
161 di.cbSize = sizeof(DOCINFO);
162 di.lpszDocName = L"Test Job";
[email protected]6f0db2b2012-02-14 03:56:18163 int job_id = ::StartDoc(dc.Get(), &di);
[email protected]d91db112011-10-18 20:58:51164 Emf emf;
[email protected]89eff96a2011-03-17 23:22:06165 EXPECT_TRUE(emf.InitFromData(&data.front(), size));
[email protected]6f0db2b2012-02-14 03:56:18166 EXPECT_TRUE(emf.SafePlayback(dc.Get()));
167 ::EndDoc(dc.Get());
[email protected]2aa8e182010-07-12 16:25:04168 // Since presumably the printer is not real, let us just delete the job from
169 // the queue.
thestig5f683912016-09-30 22:42:16170 HANDLE printer = nullptr;
171 if (::OpenPrinter(const_cast<LPTSTR>(L"UnitTest Printer"), &printer,
172 nullptr)) {
173 ::SetJob(printer, job_id, 0, nullptr, JOB_CONTROL_DELETE);
[email protected]2aa8e182010-07-12 16:25:04174 ClosePrinter(printer);
175 }
176}
177
[email protected]481edc52011-03-22 06:36:58178TEST(EmfTest, FileBackedEmf) {
[email protected]e6cddc572010-09-29 21:39:45179 // Simplest use case.
[email protected]ea1a3f62012-11-16 20:34:23180 base::ScopedTempDir scratch_metafile_dir;
[email protected]f21104d2010-10-08 20:57:57181 ASSERT_TRUE(scratch_metafile_dir.CreateUniqueTempDir());
[email protected]79f63882013-02-10 05:15:45182 base::FilePath metafile_path;
vabr16e5f602016-09-15 18:14:00183 EXPECT_TRUE(base::CreateTemporaryFileInDir(scratch_metafile_dir.GetPath(),
[email protected]03d9afc02013-12-03 17:55:52184 &metafile_path));
thestig707a24b22015-09-14 18:16:33185 uint32_t size;
vitalybuka5d1290582014-09-12 09:19:59186 std::vector<char> data;
[email protected]481edc52011-03-22 06:36:58187 {
[email protected]d91db112011-10-18 20:58:51188 Emf emf;
[email protected]481edc52011-03-22 06:36:58189 EXPECT_TRUE(emf.InitToFile(metafile_path));
thestig192677ec2016-06-09 07:43:17190 EXPECT_TRUE(emf.context());
[email protected]481edc52011-03-22 06:36:58191 // An empty EMF is invalid, so we put at least a rectangle in it.
192 ::Rectangle(emf.context(), 10, 10, 190, 190);
193 EXPECT_TRUE(emf.FinishDocument());
194 size = emf.GetDataSize();
195 EXPECT_GT(size, EMF_HEADER_SIZE);
[email protected]96fddd82011-03-24 23:37:45196 EXPECT_TRUE(emf.GetDataAsVector(&data));
[email protected]481edc52011-03-22 06:36:58197 EXPECT_EQ(data.size(), size);
198 }
thestig707a24b22015-09-14 18:16:33199 int64_t file_size = 0;
[email protected]56285702013-12-04 18:22:49200 base::GetFileSize(metafile_path, &file_size);
[email protected]e6cddc572010-09-29 21:39:45201 EXPECT_EQ(size, file_size);
[email protected]e6cddc572010-09-29 21:39:45202
203 // Playback the data.
thestig5f683912016-09-30 22:42:16204 HDC hdc = CreateCompatibleDC(nullptr);
[email protected]e6cddc572010-09-29 21:39:45205 EXPECT_TRUE(hdc);
[email protected]d91db112011-10-18 20:58:51206 Emf emf;
[email protected]481edc52011-03-22 06:36:58207 EXPECT_TRUE(emf.InitFromFile(metafile_path));
[email protected]e6cddc572010-09-29 21:39:45208 RECT output_rect = {0, 0, 10, 10};
209 EXPECT_TRUE(emf.Playback(hdc, &output_rect));
210 EXPECT_TRUE(DeleteDC(hdc));
211}
212
[email protected]5ad76172011-03-02 19:25:17213} // namespace printing