130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/*
230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Copyright 2011 Google Inc. All Rights Reserved.
330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Licensed under the Apache License, Version 2.0 (the "License");
530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * you may not use this file except in compliance with the License.
630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * You may obtain a copy of the License at
730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *      http://www.apache.org/licenses/LICENSE-2.0
930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
1030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Unless required by applicable law or agreed to in writing, software
1130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * distributed under the License is distributed on an "AS IS" BASIS,
1230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * See the License for the specific language governing permissions and
1430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * limitations under the License.
1530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun */
1630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
1730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/font_factory.h"
1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <string.h>
2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/tag.h"
2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace sfntly {
2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFontFactory::~FontFactory() {
2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH FontFactory* FontFactory::GetInstance() {
2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontFactoryPtr instance = new FontFactory();
3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return instance.Detach();
3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::FingerprintFont(bool fingerprint) {
3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fingerprint_ = fingerprint;
3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool FontFactory::FingerprintFont() {
3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return fingerprint_;
3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::LoadFonts(InputStream* is, FontArray* output) {
4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(output);
4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  PushbackInputStream* pbis = down_cast<PushbackInputStream*>(is);
4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (IsCollection(pbis)) {
4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    LoadCollection(pbis, output);
4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return;
4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontPtr font;
4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  font.Attach(LoadSingleOTF(pbis));
5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (font) {
5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    output->push_back(font);
5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::LoadFonts(ByteVector* b, FontArray* output) {
5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  WritableFontDataPtr wfd;
5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  wfd.Attach(WritableFontData::CreateWritableFontData(b));
5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (IsCollection(wfd)) {
5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    LoadCollection(wfd, output);
6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return;
6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontPtr font;
6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  font.Attach(LoadSingleOTF(wfd));
6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (font) {
6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    output->push_back(font);
6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::LoadFontsForBuilding(InputStream* is,
7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       FontBuilderArray* output) {
7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  PushbackInputStream* pbis = down_cast<PushbackInputStream*>(is);
7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (IsCollection(pbis)) {
7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    LoadCollectionForBuilding(pbis, output);
7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return;
7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontBuilderPtr builder;
7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder.Attach(LoadSingleOTFForBuilding(pbis));
7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (builder) {
7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    output->push_back(builder);
8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::LoadFontsForBuilding(ByteVector* b,
8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       FontBuilderArray* output) {
8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  WritableFontDataPtr wfd;
8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  wfd.Attach(WritableFontData::CreateWritableFontData(b));
8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (IsCollection(wfd)) {
8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    LoadCollectionForBuilding(wfd, output);
8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return;
9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontBuilderPtr builder;
9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder.Attach(LoadSingleOTFForBuilding(wfd, 0));
9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (builder) {
9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    output->push_back(builder);
9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::SerializeFont(Font* font, OutputStream* os) {
9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  font->Serialize(os, &table_ordering_);
10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::SetSerializationTableOrdering(
10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    const IntegerList& table_ordering) {
10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  table_ordering_ = table_ordering;
10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH Font::Builder* FontFactory::NewFontBuilder() {
10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Font::Builder::GetOTFBuilder(this);
10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH Font* FontFactory::LoadSingleOTF(InputStream* is) {
11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontBuilderPtr builder;
11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder.Attach(LoadSingleOTFForBuilding(is));
11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder->Build();
11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH Font* FontFactory::LoadSingleOTF(WritableFontData* wfd) {
11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontBuilderPtr builder;
11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder.Attach(LoadSingleOTFForBuilding(wfd, 0));
12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder->Build();
12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::LoadCollection(InputStream* is, FontArray* output) {
12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontBuilderArray ba;
12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  LoadCollectionForBuilding(is, &ba);
12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  output->reserve(ba.size());
12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (FontBuilderArray::iterator builder = ba.begin(), builders_end = ba.end();
12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  builder != builders_end; ++builder) {
12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      FontPtr font;
13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      font.Attach((*builder)->Build());
13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      output->push_back(font);
13230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
13330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
13430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
13530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::LoadCollection(WritableFontData* wfd, FontArray* output) {
13630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontBuilderArray builders;
13730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  LoadCollectionForBuilding(wfd, &builders);
13830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  output->reserve(builders.size());
13930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (FontBuilderArray::iterator builder = builders.begin(),
14030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  builders_end = builders.end();
14130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  builder != builders_end; ++builder) {
14230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FontPtr font;
14330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    font.Attach((*builder)->Build());
14430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    output->push_back(font);
14530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
14630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
14730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
14830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH
14930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFont::Builder* FontFactory::LoadSingleOTFForBuilding(InputStream* is) {
15030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream
15130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Font::Builder* builder = Font::Builder::GetOTFBuilder(this, is);
15230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // UNIMPLEMENTED: setDigest
15330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder;
15430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
15530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
15630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH Font::Builder*
15730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FontFactory::LoadSingleOTFForBuilding(WritableFontData* wfd,
15830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                          int32_t offset_to_offset_table) {
15930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream
16030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Font::Builder* builder =
16130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      Font::Builder::GetOTFBuilder(this, wfd, offset_to_offset_table);
16230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // UNIMPLEMENTED: setDigest
16330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder;
16430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
16530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
16630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::LoadCollectionForBuilding(InputStream* is,
16730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                            FontBuilderArray* builders) {
16830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(is);
16930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(builders);
17030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  WritableFontDataPtr wfd;
17130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  wfd.Attach(WritableFontData::CreateWritableFontData(is->Available()));
17230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  wfd->CopyFrom(is);
17330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  LoadCollectionForBuilding(wfd, builders);
17430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
17530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
17630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontFactory::LoadCollectionForBuilding(WritableFontData* wfd,
17730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                            FontBuilderArray* builders) {
17830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t ttc_tag = wfd->ReadULongAsInt(Offset::kTTCTag);
17930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(ttc_tag);
18030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t version = wfd->ReadFixed(Offset::kVersion);
18130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(version);
18230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t num_fonts = wfd->ReadULongAsInt(Offset::kNumFonts);
18330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
18430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builders->reserve(num_fonts);
18530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t offset_table_offset = Offset::kOffsetTable;
18630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t font_number = 0;
18730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun               font_number < num_fonts;
18830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun               font_number++, offset_table_offset += DataSize::kULONG) {
18930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t offset = wfd->ReadULongAsInt(offset_table_offset);
19030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FontBuilderPtr builder;
19130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    builder.Attach(LoadSingleOTFForBuilding(wfd, offset));
19230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    builders->push_back(builder);
19330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
19430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
19530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
19630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool FontFactory::IsCollection(PushbackInputStream* pbis) {
19730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ByteVector tag(4);
19830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  pbis->Read(&tag);
19930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  pbis->Unread(&tag);
20030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Tag::ttcf == GenerateTag(tag[0], tag[1], tag[2], tag[3]);
20130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
20230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
20330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool FontFactory::IsCollection(ReadableFontData* rfd) {
20430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ByteVector tag(4);
20530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  rfd->ReadBytes(0, &(tag[0]), 0, tag.size());
20630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Tag::ttcf ==
20730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun         GenerateTag(tag[0], tag[1], tag[2], tag[3]);
20830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
20930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
21030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFontFactory::FontFactory()
21130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : fingerprint_(false) {
21230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
21330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
21430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}  // namespace sfntly
215