1/*
2 * Copyright 2011 Google Inc. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "sfntly/font_factory.h"
18
19#include <string.h>
20
21#include "sfntly/tag.h"
22
23namespace sfntly {
24
25FontFactory::~FontFactory() {
26}
27
28CALLER_ATTACH FontFactory* FontFactory::GetInstance() {
29  FontFactoryPtr instance = new FontFactory();
30  return instance.Detach();
31}
32
33void FontFactory::FingerprintFont(bool fingerprint) {
34  fingerprint_ = fingerprint;
35}
36
37bool FontFactory::FingerprintFont() {
38  return fingerprint_;
39}
40
41void FontFactory::LoadFonts(InputStream* is, FontArray* output) {
42  assert(output);
43  PushbackInputStream* pbis = down_cast<PushbackInputStream*>(is);
44  if (IsCollection(pbis)) {
45    LoadCollection(pbis, output);
46    return;
47  }
48  FontPtr font;
49  font.Attach(LoadSingleOTF(pbis));
50  if (font) {
51    output->push_back(font);
52  }
53}
54
55void FontFactory::LoadFonts(ByteVector* b, FontArray* output) {
56  WritableFontDataPtr wfd;
57  wfd.Attach(WritableFontData::CreateWritableFontData(b));
58  if (IsCollection(wfd)) {
59    LoadCollection(wfd, output);
60    return;
61  }
62  FontPtr font;
63  font.Attach(LoadSingleOTF(wfd));
64  if (font) {
65    output->push_back(font);
66  }
67}
68
69void FontFactory::LoadFontsForBuilding(InputStream* is,
70                                       FontBuilderArray* output) {
71  PushbackInputStream* pbis = down_cast<PushbackInputStream*>(is);
72  if (IsCollection(pbis)) {
73    LoadCollectionForBuilding(pbis, output);
74    return;
75  }
76  FontBuilderPtr builder;
77  builder.Attach(LoadSingleOTFForBuilding(pbis));
78  if (builder) {
79    output->push_back(builder);
80  }
81}
82
83void FontFactory::LoadFontsForBuilding(ByteVector* b,
84                                       FontBuilderArray* output) {
85  WritableFontDataPtr wfd;
86  wfd.Attach(WritableFontData::CreateWritableFontData(b));
87  if (IsCollection(wfd)) {
88    LoadCollectionForBuilding(wfd, output);
89    return;
90  }
91  FontBuilderPtr builder;
92  builder.Attach(LoadSingleOTFForBuilding(wfd, 0));
93  if (builder) {
94    output->push_back(builder);
95  }
96}
97
98void FontFactory::SerializeFont(Font* font, OutputStream* os) {
99  font->Serialize(os, &table_ordering_);
100}
101
102void FontFactory::SetSerializationTableOrdering(
103    const IntegerList& table_ordering) {
104  table_ordering_ = table_ordering;
105}
106
107CALLER_ATTACH Font::Builder* FontFactory::NewFontBuilder() {
108  return Font::Builder::GetOTFBuilder(this);
109}
110
111CALLER_ATTACH Font* FontFactory::LoadSingleOTF(InputStream* is) {
112  FontBuilderPtr builder;
113  builder.Attach(LoadSingleOTFForBuilding(is));
114  return builder->Build();
115}
116
117CALLER_ATTACH Font* FontFactory::LoadSingleOTF(WritableFontData* wfd) {
118  FontBuilderPtr builder;
119  builder.Attach(LoadSingleOTFForBuilding(wfd, 0));
120  return builder->Build();
121}
122
123void FontFactory::LoadCollection(InputStream* is, FontArray* output) {
124  FontBuilderArray ba;
125  LoadCollectionForBuilding(is, &ba);
126  output->reserve(ba.size());
127  for (FontBuilderArray::iterator builder = ba.begin(), builders_end = ba.end();
128                                  builder != builders_end; ++builder) {
129      FontPtr font;
130      font.Attach((*builder)->Build());
131      output->push_back(font);
132  }
133}
134
135void FontFactory::LoadCollection(WritableFontData* wfd, FontArray* output) {
136  FontBuilderArray builders;
137  LoadCollectionForBuilding(wfd, &builders);
138  output->reserve(builders.size());
139  for (FontBuilderArray::iterator builder = builders.begin(),
140                                  builders_end = builders.end();
141                                  builder != builders_end; ++builder) {
142    FontPtr font;
143    font.Attach((*builder)->Build());
144    output->push_back(font);
145  }
146}
147
148CALLER_ATTACH
149Font::Builder* FontFactory::LoadSingleOTFForBuilding(InputStream* is) {
150  // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream
151  Font::Builder* builder = Font::Builder::GetOTFBuilder(this, is);
152  // UNIMPLEMENTED: setDigest
153  return builder;
154}
155
156CALLER_ATTACH Font::Builder*
157    FontFactory::LoadSingleOTFForBuilding(WritableFontData* wfd,
158                                          int32_t offset_to_offset_table) {
159  // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream
160  Font::Builder* builder =
161      Font::Builder::GetOTFBuilder(this, wfd, offset_to_offset_table);
162  // UNIMPLEMENTED: setDigest
163  return builder;
164}
165
166void FontFactory::LoadCollectionForBuilding(InputStream* is,
167                                            FontBuilderArray* builders) {
168  assert(is);
169  assert(builders);
170  WritableFontDataPtr wfd;
171  wfd.Attach(WritableFontData::CreateWritableFontData(is->Available()));
172  wfd->CopyFrom(is);
173  LoadCollectionForBuilding(wfd, builders);
174}
175
176void FontFactory::LoadCollectionForBuilding(WritableFontData* wfd,
177                                            FontBuilderArray* builders) {
178  int32_t ttc_tag = wfd->ReadULongAsInt(Offset::kTTCTag);
179  UNREFERENCED_PARAMETER(ttc_tag);
180  int32_t version = wfd->ReadFixed(Offset::kVersion);
181  UNREFERENCED_PARAMETER(version);
182  int32_t num_fonts = wfd->ReadULongAsInt(Offset::kNumFonts);
183
184  builders->reserve(num_fonts);
185  int32_t offset_table_offset = Offset::kOffsetTable;
186  for (int32_t font_number = 0;
187               font_number < num_fonts;
188               font_number++, offset_table_offset += DataSize::kULONG) {
189    int32_t offset = wfd->ReadULongAsInt(offset_table_offset);
190    FontBuilderPtr builder;
191    builder.Attach(LoadSingleOTFForBuilding(wfd, offset));
192    builders->push_back(builder);
193  }
194}
195
196bool FontFactory::IsCollection(PushbackInputStream* pbis) {
197  ByteVector tag(4);
198  pbis->Read(&tag);
199  pbis->Unread(&tag);
200  return Tag::ttcf == GenerateTag(tag[0], tag[1], tag[2], tag[3]);
201}
202
203bool FontFactory::IsCollection(ReadableFontData* rfd) {
204  ByteVector tag(4);
205  rfd->ReadBytes(0, &(tag[0]), 0, tag.size());
206  return Tag::ttcf ==
207         GenerateTag(tag[0], tag[1], tag[2], tag[3]);
208}
209
210FontFactory::FontFactory()
211    : fingerprint_(false) {
212}
213
214}  // namespace sfntly
215