1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Tests PPB_TrueTypeFont interface. 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/tests/test_truetype_font.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string.h> 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <algorithm> 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <limits> 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ppapi/c/private/ppb_testing_private.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/cpp/completion_callback.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/cpp/dev/truetype_font_dev.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/cpp/instance.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/cpp/var.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/tests/test_utils.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/tests/testing_instance.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)REGISTER_TEST_CASE(TrueTypeFont); 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define MAKE_TABLE_TAG(a, b, c, d) ((a) << 24) + ((b) << 16) + ((c) << 8) + (d) 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const PP_Resource kInvalidResource = 0; 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const PP_Instance kInvalidInstance = 0; 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TrueType font header and table entry structs. See 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// https://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct FontHeader { 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int32_t font_type; 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint16_t num_tables; 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint16_t search_range; 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint16_t entry_selector; 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint16_t range_shift; 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct FontDirectoryEntry { 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32_t tag; 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32_t checksum; 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32_t offset; 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32_t logical_length; 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint32_t ReadBigEndian32(const void* ptr) { 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const uint8_t* data = reinterpret_cast<const uint8_t*>(ptr); 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return (data[3] << 0) | (data[2] << 8) | (data[1] << 16) | (data[0] << 24); 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint16_t ReadBigEndian16(const void* ptr) { 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const uint8_t* data = reinterpret_cast<const uint8_t*>(ptr); 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return (data[1] << 0) | (data[0] << 8); 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TestTrueTypeFont::TestTrueTypeFont(TestingInstance* instance) 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : TestCase(instance), 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ppb_truetype_font_interface_(NULL), 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ppb_core_interface_(NULL), 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ppb_var_interface_(NULL) { 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool TestTrueTypeFont::Init() { 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ppb_truetype_font_interface_ = static_cast<const PPB_TrueTypeFont_Dev*>( 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::Module::Get()->GetBrowserInterface(PPB_TRUETYPEFONT_DEV_INTERFACE)); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!ppb_truetype_font_interface_) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->AppendError("PPB_TrueTypeFont_Dev interface not available"); 71a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 72a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ppb_core_interface_ = static_cast<const PPB_Core*>( 73a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!ppb_core_interface_) 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->AppendError("PPB_Core interface not available"); 76a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 77a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ppb_var_interface_ = static_cast<const PPB_Var*>( 78a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE)); 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!ppb_var_interface_) 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->AppendError("PPB_Var interface not available"); 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 82a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return 83a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ppb_truetype_font_interface_ && 84a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ppb_core_interface_ && 85a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ppb_var_interface_; 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TestTrueTypeFont::~TestTrueTypeFont() { 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void TestTrueTypeFont::RunTests(const std::string& filter) { 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RUN_TEST(GetFontFamilies, filter); 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RUN_TEST(GetFontsInFamily, filter); 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RUN_TEST(Create, filter); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RUN_TEST(Describe, filter); 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RUN_TEST(GetTableTags, filter); 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RUN_TEST(GetTable, filter); 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string TestTrueTypeFont::TestGetFontFamilies() { 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // A valid instance should be able to enumerate fonts. 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<pp::Var> > cc( 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult(pp::TrueTypeFont_Dev::GetFontFamilies(instance_, 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback())); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::vector<pp::Var> font_families = cc.output(); 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We should get some font families on any platform. 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(0, font_families.size()); 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(static_cast<int32_t>(font_families.size()), cc.result()); 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Make sure at least one family is a non-empty string. 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(0, font_families[0].AsString().size()); 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Using an invalid instance should fail. 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<pp::Var> > cc( 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult( 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ppb_truetype_font_interface_->GetFontFamilies( 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kInvalidInstance, 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback().output(), 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback().pp_completion_callback())); 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(cc.result() == PP_ERROR_FAILED || 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.result() == PP_ERROR_BADARGUMENT); 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, cc.output().size()); 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PASS(); 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string TestTrueTypeFont::TestGetFontsInFamily() { 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Get the list of all font families. 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<pp::Var> > cc( 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult(pp::TrueTypeFont_Dev::GetFontFamilies(instance_, 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback())); 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Try to use a common family that is likely to have multiple variations. 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::vector<pp::Var> families = cc.output(); 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::Var family("Arial"); 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (std::find(families.begin(), families.end(), family) == families.end()) { 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) family = pp::Var("Times"); 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (std::find(families.begin(), families.end(), family) == families.end()) 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) family = families[0]; // Just use the first family. 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // GetFontsInFamily: A valid instance should be able to enumerate fonts 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // in a given family. 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<pp::TrueTypeFontDesc_Dev> > 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc2(instance_->pp_instance(), false); 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc2.WaitForResult(pp::TrueTypeFont_Dev::GetFontsInFamily( 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_, 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) family, 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc2.GetCallback())); 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector<pp::TrueTypeFontDesc_Dev> fonts_in_family = cc2.output(); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(0, fonts_in_family.size()); 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(static_cast<int32_t>(fonts_in_family.size()), cc2.result()); 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We should be able to create any of the returned fonts without fallback. 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < fonts_in_family.size(); ++i) { 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::TrueTypeFontDesc_Dev& font_in_family = fonts_in_family[i]; 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::TrueTypeFont_Dev font(instance_, font_in_family); 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput<pp::TrueTypeFontDesc_Dev> cc( 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult(font.Describe(cc.GetCallback())); 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const pp::TrueTypeFontDesc_Dev desc = cc.output(); 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(family, desc.family()); 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(font_in_family.style(), desc.style()); 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(font_in_family.weight(), desc.weight()); 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Using an invalid instance should fail. 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<pp::TrueTypeFontDesc_Dev> > 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc(instance_->pp_instance(), false); 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::Var family("Times"); 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult( 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ppb_truetype_font_interface_->GetFontsInFamily( 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kInvalidInstance, 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) family.pp_var(), 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback().output(), 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback().pp_completion_callback())); 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(cc.result() == PP_ERROR_FAILED || 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.result() == PP_ERROR_BADARGUMENT); 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, cc.output().size()); 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PASS(); 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string TestTrueTypeFont::TestCreate() { 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_Resource font; 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_TrueTypeFontDesc_Dev desc = { 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_MakeUndefined(), 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_TRUETYPEFONTFAMILY_SERIF, 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_TRUETYPEFONTSTYLE_NORMAL, 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_TRUETYPEFONTWEIGHT_NORMAL, 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_TRUETYPEFONTWIDTH_NORMAL, 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_TRUETYPEFONTCHARSET_DEFAULT 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Creating a font from an invalid instance returns an invalid resource. 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) font = ppb_truetype_font_interface_->Create(kInvalidInstance, &desc); 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(kInvalidResource, font); 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(PP_TRUE, ppb_truetype_font_interface_->IsTrueTypeFont(font)); 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Creating a font from a valid instance returns a font resource. 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) font = ppb_truetype_font_interface_->Create(instance_->pp_instance(), &desc); 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(kInvalidResource, font); 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_TRUE, ppb_truetype_font_interface_->IsTrueTypeFont(font)); 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ppb_core_interface_->ReleaseResource(font); 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Once released, the resource shouldn't be a font. 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(PP_TRUE, ppb_truetype_font_interface_->IsTrueTypeFont(font)); 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PASS(); 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string TestTrueTypeFont::TestDescribe() { 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::TrueTypeFontDesc_Dev create_desc; 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) create_desc.set_generic_family(PP_TRUETYPEFONTFAMILY_SERIF); 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) create_desc.set_style(PP_TRUETYPEFONTSTYLE_NORMAL); 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) create_desc.set_weight(PP_TRUETYPEFONTWEIGHT_NORMAL); 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::TrueTypeFont_Dev font(instance_, create_desc); 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Describe: See what font-matching did with a generic font. We should always 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // be able to Create a generic Serif font. 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput<pp::TrueTypeFontDesc_Dev> cc( 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult(font.Describe(cc.GetCallback())); 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const pp::TrueTypeFontDesc_Dev desc = cc.output(); 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(0, desc.family().AsString().size()); 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_TRUETYPEFONTFAMILY_SERIF, desc.generic_family()); 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_TRUETYPEFONTSTYLE_NORMAL, desc.style()); 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_TRUETYPEFONTWEIGHT_NORMAL, desc.weight()); 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Describe an invalid resource should fail. 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_TrueTypeFontDesc_Dev fail_desc; 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memset(&fail_desc, 0, sizeof(fail_desc)); 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fail_desc.family = PP_MakeUndefined(); 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Create a shallow copy to check that no data is changed. 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_TrueTypeFontDesc_Dev fail_desc_copy; 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(&fail_desc_copy, &fail_desc, sizeof(fail_desc)); 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult( 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ppb_truetype_font_interface_->Describe( 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kInvalidResource, 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &fail_desc, 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback().pp_completion_callback())); 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_ERROR_BADRESOURCE, cc.result()); 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_VARTYPE_UNDEFINED, fail_desc.family.type); 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, memcmp(&fail_desc, &fail_desc_copy, sizeof(fail_desc))); 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PASS(); 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string TestTrueTypeFont::TestGetTableTags() { 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::TrueTypeFontDesc_Dev desc; 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::TrueTypeFont_Dev font(instance_, desc); 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<uint32_t> > cc( 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult(font.GetTableTags(cc.GetCallback())); 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector<uint32_t> tags = cc.output(); 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(0, tags.size()); 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(static_cast<int32_t>(tags.size()), cc.result()); 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Tags will vary depending on the actual font that the host platform 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // chooses. Check that all required TrueType tags are present. 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int required_tag_count = 9; 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32_t required_tags[required_tag_count] = { 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Note: these must be sorted for std::includes below. 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('c', 'm', 'a', 'p'), 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('g', 'l', 'y', 'f'), 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('h', 'e', 'a', 'd'), 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('h', 'h', 'e', 'a'), 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('h', 'm', 't', 'x'), 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('l', 'o', 'c', 'a'), 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('m', 'a', 'x', 'p'), 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('n', 'a', 'm', 'e'), 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('p', 'o', 's', 't') 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::sort(tags.begin(), tags.end()); 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(std::includes(tags.begin(), 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tags.end(), 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) required_tags, 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) required_tags + required_tag_count)); 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Invalid resource should fail and write no data. 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<uint32_t> > cc( 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult( 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ppb_truetype_font_interface_->GetTableTags( 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kInvalidResource, 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback().output(), 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback().pp_completion_callback())); 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_ERROR_BADRESOURCE, cc.result()); 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, cc.output().size()); 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PASS(); 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string TestTrueTypeFont::TestGetTable() { 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::TrueTypeFontDesc_Dev desc; 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::TrueTypeFont_Dev font(instance_, desc); 306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Getting a required table from a valid font should succeed. 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<char> > cc1( 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc1.WaitForResult(font.GetTable(MAKE_TABLE_TAG('c', 'm', 'a', 'p'), 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, std::numeric_limits<int32_t>::max(), 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc1.GetCallback())); 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::vector<char> cmap_data = cc1.output(); 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(0, cmap_data.size()); 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(static_cast<int32_t>(cmap_data.size()), cc1.result()); 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Passing 0 for the table tag should return the entire font. 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<char> > cc2( 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc2.WaitForResult(font.GetTable(0 /* table_tag */, 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, std::numeric_limits<int32_t>::max(), 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc2.GetCallback())); 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::vector<char> entire_font = cc2.output(); 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(0, entire_font.size()); 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(static_cast<int32_t>(entire_font.size()), cc2.result()); 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Verify that the CMAP table is in entire_font, and that it's identical 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // to the one we retrieved above. Note that since the font header and table 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // directory are in file (big-endian) order, we need to byte swap tags and 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // numbers. 332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const size_t kHeaderSize = sizeof(FontHeader); 333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const size_t kEntrySize = sizeof(FontDirectoryEntry); 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(kHeaderSize < entire_font.size()); 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FontHeader header; 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(&header, &entire_font[0], kHeaderSize); 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint16_t num_tables = ReadBigEndian16(&header.num_tables); 338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector<FontDirectoryEntry> directory(num_tables); 339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t directory_size = kEntrySize * num_tables; 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(kHeaderSize + directory_size < entire_font.size()); 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(&directory[0], &entire_font[kHeaderSize], directory_size); 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const FontDirectoryEntry* cmap_entry = NULL; 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (uint16_t i = 0; i < num_tables; i++) { 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (ReadBigEndian32(&directory[i].tag) == 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('c', 'm', 'a', 'p')) { 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmap_entry = &directory[i]; 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NE(NULL, cmap_entry); 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32_t logical_length = ReadBigEndian32(&cmap_entry->logical_length); 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32_t table_offset = ReadBigEndian32(&cmap_entry->offset); 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(static_cast<size_t>(logical_length), cmap_data.size()); 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(static_cast<size_t>(table_offset + logical_length) < 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) entire_font.size()); 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* cmap_table = &entire_font[0] + table_offset; 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, memcmp(cmap_table, &cmap_data[0], cmap_data.size())); 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Use offset and max_data_length to restrict the data. Read a part of 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the 'CMAP' table. 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<char> > cc3( 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int32_t kOffset = 4; 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int32_t partial_cmap_size = static_cast<int32_t>(cmap_data.size() - 64); 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc3.WaitForResult(font.GetTable(MAKE_TABLE_TAG('c', 'm', 'a', 'p'), 367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kOffset, 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) partial_cmap_size, 369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc3.GetCallback())); 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::vector<char> partial_cmap_data = cc3.output(); 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(partial_cmap_data.size(), static_cast<size_t>(cc3.result())); 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(partial_cmap_data.size(), static_cast<size_t>(partial_cmap_size)); 373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, memcmp(cmap_table + kOffset, &partial_cmap_data[0], 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) partial_cmap_size)); 375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Getting an invalid table should fail ('zzzz' should be safely invalid). 378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<char> > cc( 379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult(font.GetTable(MAKE_TABLE_TAG('z', 'z', 'z', 'z'), 381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, std::numeric_limits<int32_t>::max(), 382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback())); 383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, cc.output().size()); 384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_ERROR_FAILED, cc.result()); 385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // GetTable on an invalid resource should fail with a bad resource error 388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // and write no data. 389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<char> > cc( 390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult( 392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ppb_truetype_font_interface_->GetTable( 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kInvalidResource, 394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MAKE_TABLE_TAG('c', 'm', 'a', 'p'), 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, std::numeric_limits<int32_t>::max(), 396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback().output(), 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback().pp_completion_callback())); 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_ERROR_BADRESOURCE, cc.result()); 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, cc.output().size()); 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Negative offset should fail with a bad argument error and write no data. 403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<char> > cc( 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult(font.GetTable(MAKE_TABLE_TAG('c', 'm', 'a', 'p'), 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) -100, 0, 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback())); 408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_ERROR_BADARGUMENT, cc.result()); 409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, cc.output().size()); 410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Offset larger than file size succeeds but returns no data. 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<char> > cc( 414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult(font.GetTable(MAKE_TABLE_TAG('c', 'm', 'a', 'p'), 416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1 << 28, 0, 417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback())); 418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_OK, cc.result()); 419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, cc.output().size()); 420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Negative max_data_length should fail with a bad argument error and write 423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // no data. 424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TestCompletionCallbackWithOutput< std::vector<char> > cc( 425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance_->pp_instance(), false); 426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.WaitForResult(font.GetTable(MAKE_TABLE_TAG('c', 'm', 'a', 'p'), 427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, -100, 428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cc.GetCallback())); 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(PP_ERROR_BADARGUMENT, cc.result()); 430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_EQ(0, cc.output().size()); 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PASS(); 434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 435