1464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/* 2464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Copyright 2011 Google Inc. All Rights Reserved. 3464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * 4464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Licensed under the Apache License, Version 2.0 (the "License"); 5464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * you may not use this file except in compliance with the License. 6464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * You may obtain a copy of the License at 7464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * 8464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * http://www.apache.org/licenses/LICENSE-2.0 9464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * 10464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Unless required by applicable law or agreed to in writing, software 11464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * distributed under the License is distributed on an "AS IS" BASIS, 12464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * See the License for the specific language governing permissions and 14464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * limitations under the License. 15464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com */ 16464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 17246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com#include "sfntly/font_factory.h" 18246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 19464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include <string.h> 20464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 21464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/tag.h" 22464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 23464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comnamespace sfntly { 24464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 25464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comFontFactory::~FontFactory() { 26464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 27464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 28246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH FontFactory* FontFactory::GetInstance() { 29464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontFactoryPtr instance = new FontFactory(); 30246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return instance.Detach(); 31464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 32464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 33246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FontFactory::FingerprintFont(bool fingerprint) { 34464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com fingerprint_ = fingerprint; 35464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 36464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 37246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool FontFactory::FingerprintFont() { 38464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return fingerprint_; 39464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 40464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 41246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FontFactory::LoadFonts(InputStream* is, FontArray* output) { 42464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com assert(output); 43464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com PushbackInputStream* pbis = down_cast<PushbackInputStream*>(is); 44246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com if (IsCollection(pbis)) { 45246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com LoadCollection(pbis, output); 46246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return; 47246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com } 487b78f49e6ea3a141a398dd56c99069ca8404ca47dfilimon@google.com FontPtr font; 49943fc3bbbc953ac73890e8e7783a87acb397b227dfilimon@google.com font.Attach(LoadSingleOTF(pbis)); 50246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com if (font) { 51246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com output->push_back(font); 52246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com } 53246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 54246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 55b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comvoid FontFactory::LoadFonts(ByteVector* b, FontArray* output) { 56b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com WritableFontDataPtr wfd; 57b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com wfd.Attach(WritableFontData::CreateWritableFontData(b)); 58b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com if (IsCollection(wfd)) { 59b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com LoadCollection(wfd, output); 60464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return; 61464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 62246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com FontPtr font; 63b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com font.Attach(LoadSingleOTF(wfd)); 64464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (font) { 65464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com output->push_back(font); 66464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 67464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 68464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 69246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FontFactory::LoadFontsForBuilding(InputStream* is, 70464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontBuilderArray* output) { 71464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com PushbackInputStream* pbis = down_cast<PushbackInputStream*>(is); 72246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com if (IsCollection(pbis)) { 73246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com LoadCollectionForBuilding(pbis, output); 74464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return; 75464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 76464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontBuilderPtr builder; 77246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com builder.Attach(LoadSingleOTFForBuilding(pbis)); 78464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (builder) { 79464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com output->push_back(builder); 80464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 81464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 82464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 83b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comvoid FontFactory::LoadFontsForBuilding(ByteVector* b, 84246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com FontBuilderArray* output) { 85b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com WritableFontDataPtr wfd; 86b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com wfd.Attach(WritableFontData::CreateWritableFontData(b)); 87b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com if (IsCollection(wfd)) { 88b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com LoadCollectionForBuilding(wfd, output); 89246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return; 90246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com } 91464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontBuilderPtr builder; 92b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com builder.Attach(LoadSingleOTFForBuilding(wfd, 0)); 93246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com if (builder) { 94246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com output->push_back(builder); 95246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com } 96464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 97464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 98246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FontFactory::SerializeFont(Font* font, OutputStream* os) { 99246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com font->Serialize(os, &table_ordering_); 100246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 101246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 102246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FontFactory::SetSerializationTableOrdering( 103246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com const IntegerList& table_ordering) { 104246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com table_ordering_ = table_ordering; 105246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 106246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 107246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH Font::Builder* FontFactory::NewFontBuilder() { 108246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return Font::Builder::GetOTFBuilder(this); 109246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 110246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 111246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH Font* FontFactory::LoadSingleOTF(InputStream* is) { 112464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontBuilderPtr builder; 113246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com builder.Attach(LoadSingleOTFForBuilding(is)); 114246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return builder->Build(); 115464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 116464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 117b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCALLER_ATTACH Font* FontFactory::LoadSingleOTF(WritableFontData* wfd) { 118464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontBuilderPtr builder; 119b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com builder.Attach(LoadSingleOTFForBuilding(wfd, 0)); 120246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return builder->Build(); 121246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 122246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 123246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FontFactory::LoadCollection(InputStream* is, FontArray* output) { 124246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com FontBuilderArray ba; 125246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com LoadCollectionForBuilding(is, &ba); 126246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com output->reserve(ba.size()); 127246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com for (FontBuilderArray::iterator builder = ba.begin(), builders_end = ba.end(); 128246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com builder != builders_end; ++builder) { 129246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com FontPtr font; 130246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com font.Attach((*builder)->Build()); 131246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com output->push_back(font); 132246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com } 133464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 134464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 135b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comvoid FontFactory::LoadCollection(WritableFontData* wfd, FontArray* output) { 136464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontBuilderArray builders; 137b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com LoadCollectionForBuilding(wfd, &builders); 138b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com output->reserve(builders.size()); 139b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com for (FontBuilderArray::iterator builder = builders.begin(), 140b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com builders_end = builders.end(); 141b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com builder != builders_end; ++builder) { 142464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontPtr font; 143246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com font.Attach((*builder)->Build()); 144464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com output->push_back(font); 145464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 146464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 147464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 148b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCALLER_ATTACH 149b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comFont::Builder* FontFactory::LoadSingleOTFForBuilding(InputStream* is) { 150246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream 151246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com Font::Builder* builder = Font::Builder::GetOTFBuilder(this, is); 152246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com // UNIMPLEMENTED: setDigest 153246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return builder; 154246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 155246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 156246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH Font::Builder* 157b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com FontFactory::LoadSingleOTFForBuilding(WritableFontData* wfd, 158246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com int32_t offset_to_offset_table) { 159464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream 160464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com Font::Builder* builder = 161b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com Font::Builder::GetOTFBuilder(this, wfd, offset_to_offset_table); 162464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com // UNIMPLEMENTED: setDigest 163464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return builder; 164464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 165464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 166246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FontFactory::LoadCollectionForBuilding(InputStream* is, 167246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com FontBuilderArray* builders) { 168b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com assert(is); 169b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com assert(builders); 170b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com WritableFontDataPtr wfd; 171b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com wfd.Attach(WritableFontData::CreateWritableFontData(is->Available())); 172b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com wfd->CopyFrom(is); 173b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com LoadCollectionForBuilding(wfd, builders); 174246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com} 175246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 176b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comvoid FontFactory::LoadCollectionForBuilding(WritableFontData* wfd, 177464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontBuilderArray* builders) { 178b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com int32_t ttc_tag = wfd->ReadULongAsInt(Offset::kTTCTag); 179464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com UNREFERENCED_PARAMETER(ttc_tag); 180b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com int32_t version = wfd->ReadFixed(Offset::kVersion); 181464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com UNREFERENCED_PARAMETER(version); 182b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com int32_t num_fonts = wfd->ReadULongAsInt(Offset::kNumFonts); 183464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 184464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com builders->reserve(num_fonts); 185464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com int32_t offset_table_offset = Offset::kOffsetTable; 186b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com for (int32_t font_number = 0; 187b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com font_number < num_fonts; 188b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com font_number++, offset_table_offset += DataSize::kULONG) { 189b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com int32_t offset = wfd->ReadULongAsInt(offset_table_offset); 190464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com FontBuilderPtr builder; 191b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com builder.Attach(LoadSingleOTFForBuilding(wfd, offset)); 192464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com builders->push_back(builder); 193464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 194464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 195464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 196246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool FontFactory::IsCollection(PushbackInputStream* pbis) { 197246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ByteVector tag(4); 198246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com pbis->Read(&tag); 199246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com pbis->Unread(&tag); 200246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return Tag::ttcf == GenerateTag(tag[0], tag[1], tag[2], tag[3]); 201464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 202464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 203b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.combool FontFactory::IsCollection(ReadableFontData* rfd) { 204b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com ByteVector tag(4); 205b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com rfd->ReadBytes(0, &(tag[0]), 0, tag.size()); 206246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com return Tag::ttcf == 207b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com GenerateTag(tag[0], tag[1], tag[2], tag[3]); 208464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 209464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 210246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comFontFactory::FontFactory() 211246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com : fingerprint_(false) { 212464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} 213464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 214464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} // namespace sfntly 215