blob: 44cb0f3788b57e46168d2211ff0242e0496f5302 [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;
50const int ONE_MB = 1024 * 1024;
[email protected]e6cddc572010-09-29 21:39:4551
initial.commit09911bf2008-07-26 23:55:2952} // namespace
53
54TEST(EmfTest, DC) {
initial.commit09911bf2008-07-26 23:55:2955 // Simplest use case.
thestig707a24b22015-09-14 18:16:3356 uint32_t size;
vitalybuka5d1290582014-09-12 09:19:5957 std::vector<char> data;
[email protected]481edc52011-03-22 06:36:5858 {
[email protected]d91db112011-10-18 20:58:5159 Emf emf;
[email protected]481edc52011-03-22 06:36:5860 EXPECT_TRUE(emf.Init());
thestig192677ec2016-06-09 07:43:1761 EXPECT_TRUE(emf.context());
[email protected]481edc52011-03-22 06:36:5862 // An empty EMF is invalid, so we put at least a rectangle in it.
63 ::Rectangle(emf.context(), 10, 10, 190, 190);
64 EXPECT_TRUE(emf.FinishDocument());
65 size = emf.GetDataSize();
66 EXPECT_GT(size, EMF_HEADER_SIZE);
[email protected]96fddd82011-03-24 23:37:4567 EXPECT_TRUE(emf.GetDataAsVector(&data));
[email protected]481edc52011-03-22 06:36:5868 EXPECT_EQ(data.size(), size);
69 }
initial.commit09911bf2008-07-26 23:55:2970
71 // Playback the data.
[email protected]d91db112011-10-18 20:58:5172 Emf emf;
[email protected]f2da4b02011-03-18 05:45:5173 EXPECT_TRUE(emf.InitFromData(&data.front(), size));
thestig5f683912016-09-30 22:42:1674 HDC hdc = CreateCompatibleDC(nullptr);
[email protected]481edc52011-03-22 06:36:5875 EXPECT_TRUE(hdc);
initial.commit09911bf2008-07-26 23:55:2976 RECT output_rect = {0, 0, 10, 10};
77 EXPECT_TRUE(emf.Playback(hdc, &output_rect));
78 EXPECT_TRUE(DeleteDC(hdc));
79}
80
initial.commit09911bf2008-07-26 23:55:2981// Disabled if no "UnitTest printer" exist. Useful to reproduce bug 1186598.
82TEST_F(EmfPrintingTest, Enumerate) {
83 if (IsTestCaseDisabled())
84 return;
85
[email protected]d91db112011-10-18 20:58:5186 PrintSettings settings;
initial.commit09911bf2008-07-26 23:55:2987
88 // My test case is a HP Color LaserJet 4550 PCL.
89 settings.set_device_name(L"UnitTest Printer");
90
91 // Initialize it.
thestig5f683912016-09-30 22:42:1692 PrintingContextWin context(this);
93 EXPECT_EQ(PrintingContext::OK, context.InitWithSettingsForTest(settings));
initial.commit09911bf2008-07-26 23:55:2994
[email protected]79f63882013-02-10 05:15:4595 base::FilePath emf_file;
[email protected]daee4972009-07-09 14:28:2496 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &emf_file));
97 emf_file = emf_file.Append(FILE_PATH_LITERAL("printing"))
98 .Append(FILE_PATH_LITERAL("test"))
99 .Append(FILE_PATH_LITERAL("data"))
100 .Append(FILE_PATH_LITERAL("test4.emf"));
initial.commit09911bf2008-07-26 23:55:29101 // Load any EMF with an image.
[email protected]d91db112011-10-18 20:58:51102 Emf emf;
initial.commit09911bf2008-07-26 23:55:29103 std::string emf_data;
[email protected]82f84b92013-08-30 18:23:50104 base::ReadFileToString(emf_file, &emf_data);
initial.commit09911bf2008-07-26 23:55:29105 ASSERT_TRUE(emf_data.size());
[email protected]89eff96a2011-03-17 23:22:06106 EXPECT_TRUE(emf.InitFromData(&emf_data[0], emf_data.size()));
initial.commit09911bf2008-07-26 23:55:29107
108 // This will print to file. The reason is that when running inside a
[email protected]d91db112011-10-18 20:58:51109 // unit_test, PrintingContext automatically dumps its files to the
initial.commit09911bf2008-07-26 23:55:29110 // current directory.
111 // TODO(maruel): Clean the .PRN file generated in current directory.
thestig5f683912016-09-30 22:42:16112 context.NewDocument(L"EmfTest.Enumerate");
113 context.NewPage();
initial.commit09911bf2008-07-26 23:55:29114 // Process one at a time.
[email protected]59149922014-07-04 22:08:04115 RECT page_bounds = emf.GetPageBounds(1).ToRECT();
thestig5f683912016-09-30 22:42:16116 Emf::Enumerator emf_enum(emf, context.context(), &page_bounds);
[email protected]d91db112011-10-18 20:58:51117 for (Emf::Enumerator::const_iterator itr = emf_enum.begin();
initial.commit09911bf2008-07-26 23:55:29118 itr != emf_enum.end();
119 ++itr) {
120 // 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;
[email protected]0064b392012-06-20 01:57:38125 EXPECT_TRUE(itr->SafePlayback(&emf_enum.context_)) <<
initial.commit09911bf2008-07-26 23:55:29126 " index: " << index << " type: " << itr->record()->iType;
127 }
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]60d77bd2012-08-22 00:10:07212TEST(EmfTest, RasterizeMetafile) {
213 Emf emf;
214 EXPECT_TRUE(emf.Init());
thestig192677ec2016-06-09 07:43:17215 EXPECT_TRUE(emf.context());
[email protected]60d77bd2012-08-22 00:10:07216 HBRUSH brush = static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
217 for (int i = 0; i < 4; ++i) {
218 RECT rect = { 5 + i, 5 + i, 5 + i + 1, 5 + i + 2};
219 FillRect(emf.context(), &rect, brush);
220 }
221 EXPECT_TRUE(emf.FinishDocument());
222
dchengc3df9ba2016-04-07 23:09:32223 std::unique_ptr<Emf> raster(emf.RasterizeMetafile(1));
[email protected]60d77bd2012-08-22 00:10:07224 // Just 1px bitmap but should be stretched to the same bounds.
225 EXPECT_EQ(emf.GetPageBounds(1), raster->GetPageBounds(1));
226
vitalybuka5d1290582014-09-12 09:19:59227 raster = emf.RasterizeMetafile(20);
[email protected]60d77bd2012-08-22 00:10:07228 EXPECT_EQ(emf.GetPageBounds(1), raster->GetPageBounds(1));
229
thestig707a24b22015-09-14 18:16:33230 raster = emf.RasterizeMetafile(16 * ONE_MB);
[email protected]60d77bd2012-08-22 00:10:07231 // Expected size about 64MB.
thestig707a24b22015-09-14 18:16:33232 EXPECT_LE(abs(static_cast<int>(raster->GetDataSize()) - 64 * ONE_MB), ONE_MB);
[email protected]60d77bd2012-08-22 00:10:07233 // Bounds should still be the same.
234 EXPECT_EQ(emf.GetPageBounds(1), raster->GetPageBounds(1));
235}
236
[email protected]5ad76172011-03-02 19:25:17237} // namespace printing