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

Unified Diff: content/common/font_warmup_win_unittest.cc

Issue 1327673002: Added GDI font emulation support for Flash. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@warmup_direct_write
Patch Set: Changed comment and used common check Created 5 years, 3 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
Index: content/common/font_warmup_win_unittest.cc
diff --git a/content/common/font_warmup_win_unittest.cc b/content/common/font_warmup_win_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fd8bf5eb060705a8f04afcd4208242eb71213bc6
--- /dev/null
+++ b/content/common/font_warmup_win_unittest.cc
@@ -0,0 +1,426 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
scottmg 2015/09/17 23:24:25 no (c)
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/font_warmup_win.h"
+
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/win/windows_version.h"
+#include "skia/ext/refptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkString.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+#include "third_party/skia/include/ports/SkFontMgr.h"
+
+class TestSkTypeface : public SkTypeface {
scottmg 2015/09/17 23:24:25 all in namespace content {
forshaw 2015/09/18 00:00:28 Acknowledged.
+ public:
+ TestSkTypeface(const SkFontStyle& style,
+ const char* familyName,
+ SkFontTableTag tag,
+ const char* data,
+ size_t dataLength)
+ : SkTypeface(style, 0),
+ familyName_(familyName),
+ tag_(tag),
+ data_(data, data + dataLength) {}
+
+ protected:
+ SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+ void onFilterRec(SkScalerContextRec*) const override { ADD_FAILURE(); }
+ SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
+ PerGlyphInfo,
+ const uint32_t* glyphIDs,
+ uint32_t glyphIDsCount) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ SkStreamAsset* onOpenStream(int* ttcIndex) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ SkFontData* onCreateFontData() const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const override {
+ ADD_FAILURE();
+ }
+
+ int onCharsToGlyphs(const void* chars,
+ Encoding,
+ uint16_t glyphs[],
+ int glyphCount) const override {
+ ADD_FAILURE();
+ return 0;
+ }
+
+ int onCountGlyphs() const override {
+ ADD_FAILURE();
+ return 0;
+ }
+
+ int onGetUPEM() const override {
+ ADD_FAILURE();
+ return 0;
+ }
+ bool onGetKerningPairAdjustments(const uint16_t glyphs[],
+ int count,
+ int32_t adjustments[]) const override {
+ ADD_FAILURE();
+ return false;
+ }
+
+ /** Returns the family name of the typeface as known by its font manager.
scottmg 2015/09/17 23:24:25 no /** or /* comments unless in .c files.
forshaw 2015/09/18 00:00:28 Okay, this was just C&P from the skia headers, wil
+ * This name may or may not be produced by the family name iterator.
+ */
+ void onGetFamilyName(SkString* familyName) const override {
+ *familyName = familyName_;
+ }
+
+ /** Returns an iterator over the family names in the font. */
+ LocalizedStrings* onCreateFamilyNameIterator() const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ int onGetTableTags(SkFontTableTag tags[]) const override {
+ ADD_FAILURE();
+ return 0;
+ }
+
+ size_t onGetTableData(SkFontTableTag tag,
+ size_t offset,
+ size_t length,
+ void* data) const override {
+ size_t retsize = 0;
+ if (tag == tag_) {
+ retsize = length > data_.size() ? data_.size() : length;
+ if (data)
+ memcpy(data, &data_[0], retsize);
+ }
+ return retsize;
+ }
+
+ bool onComputeBounds(SkRect*) const override {
+ ADD_FAILURE();
+ return false;
+ }
+
+ private:
+ SkString familyName_;
+ SkFontTableTag tag_;
+ std::vector<char> data_;
+};
+
+const char* kTestFontFamily = "GDITest";
+const wchar_t* kTestFontFamilyW = L"GDITest";
+const SkFontTableTag kTestFontTableTag = 0x11223344;
+const char* kTestFontData = "GDITestGDITest";
+const wchar_t* kTestFontFamilyInvalid = L"InvalidFont";
+
+static inline DWORD SwapEndian(DWORD dwTable) {
scottmg 2015/09/17 23:24:25 replace with base/sys_byteorder.h
forshaw 2015/09/18 00:00:28 Acknowledged.
+ return ((dwTable & 0xFF) << 24) | ((dwTable & 0xFF00) << 8) |
+ ((dwTable & 0xFF0000) >> 8) | (dwTable >> 24);
+}
+
+class TestSkFontMgr : public SkFontMgr {
+ public:
+ TestSkFontMgr() { content::SetPreSandboxWarmupFontMgr(this); }
+
+ ~TestSkFontMgr() { content::SetPreSandboxWarmupFontMgr(nullptr); }
+
+ protected:
+ // Implement the virtual methods
+ int onCountFamilies() const override { return 1; }
+
+ void onGetFamilyName(int index, SkString* familyName) const override {
+ if (index == 0)
+ *familyName = kTestFontFamily;
+ }
+
+ SkFontStyleSet* onCreateStyleSet(int index) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ /** May return nullptr if the name is not found. */
+ SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ SkTypeface* onMatchFamilyStyle(const char familyName[],
+ const SkFontStyle&) const override {
+ if (strcmp(familyName, kTestFontFamily) == 0) {
+ return createTypeface();
+ }
+ return nullptr;
+ }
+
+ SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
+ const SkFontStyle&,
+ const char* bcp47[],
+ int bcp47Count,
+ SkUnichar character) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ SkTypeface* onMatchFaceStyle(const SkTypeface*,
+ const SkFontStyle&) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ SkTypeface* onCreateFromData(SkData*, int ttcIndex) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ SkTypeface* onCreateFromStream(SkStreamAsset*, int ttcIndex) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ SkTypeface* onCreateFromFontData(SkFontData*) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ SkTypeface* onLegacyCreateTypeface(const char familyName[],
+ unsigned styleBits) const override {
+ ADD_FAILURE();
+ return nullptr;
+ }
+
+ private:
+ SkTypeface* createTypeface() const {
+ SkFontStyle style(400, 100, SkFontStyle::kUpright_Slant);
+
+ return new TestSkTypeface(style, kTestFontFamily,
+ SwapEndian(kTestFontTableTag), kTestFontData,
+ strlen(kTestFontData));
+ }
+};
+
+static void InitLogFont(LOGFONTW* logfont, const wchar_t* fontname) {
+ memcpy(logfont->lfFaceName, fontname,
scottmg 2015/09/17 23:24:25 probably better to use the (small) target buffer s
forshaw 2015/09/18 00:00:28 Acknowledged.
+ (wcslen(fontname) + 1) * sizeof(wchar_t));
+}
+
+static content::GdiFontPatchData* SetupTest() {
+ HMODULE module_handle;
+ if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ reinterpret_cast<LPCWSTR>(SetupTest),
+ &module_handle)) {
+ WCHAR module_path[MAX_PATH];
+
+ if (GetModuleFileNameW(module_handle, module_path, MAX_PATH) > 0) {
+ base::FilePath path(module_path);
+ return content::PatchGdiFontEnumeration(path);
+ }
+ }
+ return nullptr;
+}
+
+static int CALLBACK EnumFontCallbackTest(const LOGFONT* lpelfe,
+ const TEXTMETRIC* lpntme,
+ DWORD FontType,
+ LPARAM lParam) {
+ const NEWTEXTMETRICEX* m = reinterpret_cast<const NEWTEXTMETRICEX*>(lpntme);
+
+ return !(FontType & TRUETYPE_FONTTYPE) &&
+ !(m->ntmTm.ntmFlags & NTM_PS_OPENTYPE);
+}
+
+TEST(GDIFontEmulationTest, CreateDeleteDCSuccess) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+
+ HDC hdc = CreateCompatibleDC(0);
+ EXPECT_TRUE(hdc != nullptr);
scottmg 2015/09/17 23:24:25 EXPECT_NE(nullptr, hdc) and similar below
forshaw 2015/09/18 00:00:28 Acknowledged.
+ EXPECT_TRUE(DeleteDC(hdc));
+}
+
+TEST(GDIFontEmulationTest, CreateUniqueDCSuccess) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
scottmg 2015/09/17 23:24:25 does EXPECT_TRUE() not compile?
forshaw 2015/09/18 00:00:28 Acknowledged.
+
+ HDC hdc1 = CreateCompatibleDC(0);
+ EXPECT_TRUE(hdc1 != nullptr);
+ HDC hdc2 = CreateCompatibleDC(0);
+ EXPECT_TRUE(hdc2 != nullptr);
+ EXPECT_NE(hdc1, hdc2);
+ EXPECT_TRUE(DeleteDC(hdc2));
+ EXPECT_TRUE(DeleteDC(hdc1));
+}
+
+TEST(GDIFontEmulationTest, CreateFontSuccess) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+ LOGFONTW logfont = {0};
+ InitLogFont(&logfont, kTestFontFamilyW);
+ HFONT font = CreateFontIndirectW(&logfont);
+ EXPECT_TRUE(font != nullptr);
+ EXPECT_TRUE(DeleteObject(font));
+}
+
+TEST(GDIFontEmulationTest, CreateFontFailure) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+ LOGFONTW logfont = {0};
+ InitLogFont(&logfont, kTestFontFamilyInvalid);
+ HFONT font = CreateFontIndirectW(&logfont);
+ EXPECT_TRUE(font == nullptr);
+}
+
+TEST(GDIFontEmulationTest, EnumFontFamilySuccess) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+ HDC hdc = CreateCompatibleDC(0);
+ EXPECT_TRUE(hdc != nullptr);
+ LOGFONTW logfont = {0};
+ InitLogFont(&logfont, kTestFontFamilyW);
+ int res = EnumFontFamiliesExW(hdc, &logfont, EnumFontCallbackTest, 0, 0);
+ EXPECT_FALSE(res);
+ EXPECT_TRUE(DeleteDC(hdc));
+}
+
+TEST(GDIFontEmulationTest, EnumFontFamilyFailure) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+ HDC hdc = CreateCompatibleDC(0);
+ EXPECT_TRUE(hdc != nullptr);
+ LOGFONTW logfont = {0};
+ InitLogFont(&logfont, kTestFontFamilyInvalid);
+ int res = EnumFontFamiliesExW(hdc, &logfont, EnumFontCallbackTest, 0, 0);
+ EXPECT_TRUE(res);
+ EXPECT_TRUE(DeleteDC(hdc));
+}
+
+TEST(GDIFontEmulationTest, DeleteDCFailure) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+ HDC hdc = reinterpret_cast<HDC>(0x11223344);
scottmg 2015/09/17 23:24:25 maybe use something other than 11223344 unless you
forshaw 2015/09/18 00:00:28 Acknowledged.
+ EXPECT_FALSE(DeleteDC(hdc));
+}
+
+TEST(GDIFontEmulationTest, DeleteObjectFailure) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+ HFONT font = reinterpret_cast<HFONT>(0x11223344);
+ EXPECT_FALSE(DeleteObject(font));
+}
+
+TEST(GDIFontEmulationTest, GetFontDataSizeSuccess) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+ HDC hdc = CreateCompatibleDC(0);
+ EXPECT_TRUE(hdc != nullptr);
+ LOGFONTW logfont = {0};
+ InitLogFont(&logfont, kTestFontFamilyW);
+ HFONT font = CreateFontIndirectW(&logfont);
+ EXPECT_TRUE(font != nullptr);
+ EXPECT_TRUE(SelectObject(hdc, font) == nullptr);
+ DWORD size = GetFontData(hdc, kTestFontTableTag, 0, nullptr, 0);
+ DWORD data_size = static_cast<DWORD>(strlen(kTestFontData));
+ EXPECT_EQ(size, data_size);
+ EXPECT_TRUE(DeleteObject(font));
+ EXPECT_TRUE(DeleteDC(hdc));
+}
+
+TEST(GDIFontEmulationTest, GetFontDataInvalidTagSuccess) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+ HDC hdc = CreateCompatibleDC(0);
+ EXPECT_TRUE(hdc != nullptr);
+ LOGFONTW logfont = {0};
+ InitLogFont(&logfont, kTestFontFamilyW);
+ HFONT font = CreateFontIndirectW(&logfont);
+ EXPECT_TRUE(font != nullptr);
+ EXPECT_TRUE(SelectObject(hdc, font) == nullptr);
+ DWORD size = GetFontData(hdc, kTestFontTableTag + 1, 0, nullptr, 0);
+ EXPECT_EQ(size, GDI_ERROR);
+ EXPECT_TRUE(DeleteObject(font));
+ EXPECT_TRUE(DeleteDC(hdc));
+}
+
+TEST(GDIFontEmulationTest, GetFontDataInvalidFontSuccess) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+ HDC hdc = CreateCompatibleDC(0);
+ EXPECT_TRUE(hdc != nullptr);
+ DWORD size = GetFontData(hdc, kTestFontTableTag, 0, nullptr, 0);
+ EXPECT_EQ(size, GDI_ERROR);
+ EXPECT_TRUE(DeleteDC(hdc));
+}
+
+TEST(GDIFontEmulationTest, GetFontDataDataSuccess) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+ TestSkFontMgr fontmgr;
+ scoped_ptr<content::GdiFontPatchData> patch_data(SetupTest());
+ EXPECT_FALSE(!patch_data);
+ HDC hdc = CreateCompatibleDC(0);
+ EXPECT_TRUE(hdc != nullptr);
+ LOGFONTW logfont = {0};
+ InitLogFont(&logfont, kTestFontFamilyW);
+ HFONT font = CreateFontIndirectW(&logfont);
+ EXPECT_TRUE(font != nullptr);
+ EXPECT_TRUE(SelectObject(hdc, font) == nullptr);
+ DWORD data_size = static_cast<DWORD>(strlen(kTestFontData));
+ std::vector<char> data(data_size);
+ DWORD size = GetFontData(hdc, kTestFontTableTag, 0, &data[0], data.size());
+ EXPECT_EQ(size, data_size);
+ EXPECT_EQ(memcmp(&data[0], kTestFontData, data.size()), 0);
+ EXPECT_TRUE(DeleteObject(font));
+ EXPECT_TRUE(DeleteDC(hdc));
scottmg 2015/09/17 23:24:25 is it worth verifying the globals are empty in som
forshaw 2015/09/18 00:00:28 As in the global state of handles? Yeah probably,
+}

Powered by Google App Engine
This is Rietveld 408576698