1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "printing/emf_win.h"
15 #include "base/files/file_path.h"
16 #include "base/files/file_util.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/path_service.h"
19 #include "base/win/scoped_hdc.h"
20 #include "printing/printing_context.h"
21 #include "printing/printing_context_win.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/gfx/geometry/point.h"
24 #include "ui/gfx/geometry/size.h"
30 // This test is automatically disabled if no printer named "UnitTest Printer" is
32 class EmfPrintingTest : public testing::Test, public PrintingContext::Delegate {
34 typedef testing::Test Parent;
35 static bool IsTestCaseDisabled() {
36 // It is assumed this printer is a HP Color LaserJet 4550 PCL or 4700.
37 HDC hdc = CreateDC(L"WINSPOOL", L"UnitTest Printer", nullptr, nullptr);
44 // PrintingContext::Delegate methods.
45 gfx::NativeView GetParentView() override { return nullptr; }
46 std::string GetAppLocale() override { return std::string(); }
49 const uint32_t EMF_HEADER_SIZE = 128;
56 std::vector<char> data;
59 EXPECT_TRUE(emf.Init());
60 EXPECT_TRUE(emf.context());
61 // 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);
66 EXPECT_TRUE(emf.GetDataAsVector(&data));
67 EXPECT_EQ(data.size(), size);
72 EXPECT_TRUE(emf.InitFromData(&data.front(), size));
73 HDC hdc = CreateCompatibleDC(nullptr);
75 RECT output_rect = {0, 0, 10, 10};
76 EXPECT_TRUE(emf.Playback(hdc, &output_rect));
77 EXPECT_TRUE(DeleteDC(hdc));
80 // Disabled if no "UnitTest printer" exist. Useful to reproduce bug 1186598.
81 TEST_F(EmfPrintingTest, Enumerate) {
82 if (IsTestCaseDisabled())
85 PrintSettings settings;
87 // My test case is a HP Color LaserJet 4550 PCL.
88 settings.set_device_name(L"UnitTest Printer");
91 PrintingContextWin context(this);
92 EXPECT_EQ(PrintingContext::OK, context.InitWithSettingsForTest(settings));
94 base::FilePath emf_file;
95 EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &emf_file));
96 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"));
101 // Load any EMF with an image.
102 std::string emf_data;
103 base::ReadFileToString(emf_file, &emf_data);
104 ASSERT_TRUE(emf_data.size());
107 EXPECT_TRUE(emf.InitFromData(&emf_data[0], emf_data.size()));
109 // This will print to file. The reason is that when running inside a
110 // unit_test, PrintingContext automatically dumps its files to the
111 // current directory.
112 // TODO(maruel): Clean the .PRN file generated in current directory.
113 context.NewDocument(L"EmfTest.Enumerate");
115 // Process one at a time.
116 RECT page_bounds = emf.GetPageBounds(1).ToRECT();
117 Emf::Enumerator emf_enum(emf, context.context(), &page_bounds);
118 for (Emf::Enumerator::const_iterator itr = emf_enum.begin();
119 itr != emf_enum.end();
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
126 EXPECT_TRUE(itr->SafePlayback(&emf_enum.context_)) <<
127 " index: " << index << " type: " << itr->record()->iType;
130 context.DocumentDone();
133 // Disabled if no "UnitTest printer" exists.
134 TEST_F(EmfPrintingTest, PageBreak) {
135 base::win::ScopedCreateDC dc(
136 CreateDC(L"WINSPOOL", L"UnitTest Printer", nullptr, nullptr));
140 std::vector<char> data;
143 EXPECT_TRUE(emf.Init());
144 EXPECT_TRUE(emf.context());
147 emf.StartPage(gfx::Size(), gfx::Rect(), 1);
148 ::Rectangle(emf.context(), 10, 10, 190, 190);
149 EXPECT_TRUE(emf.FinishPage());
152 EXPECT_EQ(3U, emf.GetPageCount());
153 EXPECT_TRUE(emf.FinishDocument());
154 size = emf.GetDataSize();
155 EXPECT_TRUE(emf.GetDataAsVector(&data));
156 EXPECT_EQ(data.size(), size);
159 // Playback the data.
161 di.cbSize = sizeof(DOCINFO);
162 di.lpszDocName = L"Test Job";
163 int job_id = ::StartDoc(dc.Get(), &di);
165 EXPECT_TRUE(emf.InitFromData(&data.front(), size));
166 EXPECT_TRUE(emf.SafePlayback(dc.Get()));
168 // Since presumably the printer is not real, let us just delete the job from
170 HANDLE printer = nullptr;
171 if (::OpenPrinter(const_cast<LPTSTR>(L"UnitTest Printer"), &printer,
173 ::SetJob(printer, job_id, 0, nullptr, JOB_CONTROL_DELETE);
174 ClosePrinter(printer);
178 TEST(EmfTest, FileBackedEmf) {
179 // Simplest use case.
180 base::ScopedTempDir scratch_metafile_dir;
181 ASSERT_TRUE(scratch_metafile_dir.CreateUniqueTempDir());
182 base::FilePath metafile_path;
183 EXPECT_TRUE(base::CreateTemporaryFileInDir(scratch_metafile_dir.GetPath(),
186 std::vector<char> data;
189 EXPECT_TRUE(emf.InitToFile(metafile_path));
190 EXPECT_TRUE(emf.context());
191 // 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);
196 EXPECT_TRUE(emf.GetDataAsVector(&data));
197 EXPECT_EQ(data.size(), size);
199 int64_t file_size = 0;
200 base::GetFileSize(metafile_path, &file_size);
201 EXPECT_EQ(size, file_size);
203 // Playback the data.
204 HDC hdc = CreateCompatibleDC(nullptr);
207 EXPECT_TRUE(emf.InitFromFile(metafile_path));
208 RECT output_rect = {0, 0, 10, 10};
209 EXPECT_TRUE(emf.Playback(hdc, &output_rect));
210 EXPECT_TRUE(DeleteDC(hdc));
213 } // namespace printing