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 
23 namespace sfntly {
24 
~FontFactory()25 FontFactory::~FontFactory() {
26 }
27 
GetInstance()28 CALLER_ATTACH FontFactory* FontFactory::GetInstance() {
29   FontFactoryPtr instance = new FontFactory();
30   return instance.Detach();
31 }
32 
FingerprintFont(bool fingerprint)33 void FontFactory::FingerprintFont(bool fingerprint) {
34   fingerprint_ = fingerprint;
35 }
36 
FingerprintFont()37 bool FontFactory::FingerprintFont() {
38   return fingerprint_;
39 }
40 
LoadFonts(InputStream * is,FontArray * output)41 void 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 
LoadFonts(ByteVector * b,FontArray * output)55 void 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 
LoadFontsForBuilding(InputStream * is,FontBuilderArray * output)69 void 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 
LoadFontsForBuilding(ByteVector * b,FontBuilderArray * output)83 void 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 
SerializeFont(Font * font,OutputStream * os)98 void FontFactory::SerializeFont(Font* font, OutputStream* os) {
99   font->Serialize(os, &table_ordering_);
100 }
101 
SetSerializationTableOrdering(const IntegerList & table_ordering)102 void FontFactory::SetSerializationTableOrdering(
103     const IntegerList& table_ordering) {
104   table_ordering_ = table_ordering;
105 }
106 
NewFontBuilder()107 CALLER_ATTACH Font::Builder* FontFactory::NewFontBuilder() {
108   return Font::Builder::GetOTFBuilder(this);
109 }
110 
LoadSingleOTF(InputStream * is)111 CALLER_ATTACH Font* FontFactory::LoadSingleOTF(InputStream* is) {
112   FontBuilderPtr builder;
113   builder.Attach(LoadSingleOTFForBuilding(is));
114   return builder->Build();
115 }
116 
LoadSingleOTF(WritableFontData * wfd)117 CALLER_ATTACH Font* FontFactory::LoadSingleOTF(WritableFontData* wfd) {
118   FontBuilderPtr builder;
119   builder.Attach(LoadSingleOTFForBuilding(wfd, 0));
120   return builder->Build();
121 }
122 
LoadCollection(InputStream * is,FontArray * output)123 void 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 
LoadCollection(WritableFontData * wfd,FontArray * output)135 void 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 
148 CALLER_ATTACH
LoadSingleOTFForBuilding(InputStream * is)149 Font::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 
156 CALLER_ATTACH Font::Builder*
LoadSingleOTFForBuilding(WritableFontData * wfd,int32_t offset_to_offset_table)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 
LoadCollectionForBuilding(InputStream * is,FontBuilderArray * builders)166 void 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 
LoadCollectionForBuilding(WritableFontData * wfd,FontBuilderArray * builders)176 void 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 
IsCollection(PushbackInputStream * pbis)196 bool 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 
IsCollection(ReadableFontData * rfd)203 bool 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 
FontFactory()210 FontFactory::FontFactory()
211     : fingerprint_(false) {
212 }
213 
214 }  // namespace sfntly
215