Home | History | Annotate | Download | only in sfntly
      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 
     25 FontFactory::~FontFactory() {
     26 }
     27 
     28 CALLER_ATTACH FontFactory* FontFactory::GetInstance() {
     29   FontFactoryPtr instance = new FontFactory();
     30   return instance.Detach();
     31 }
     32 
     33 void FontFactory::FingerprintFont(bool fingerprint) {
     34   fingerprint_ = fingerprint;
     35 }
     36 
     37 bool FontFactory::FingerprintFont() {
     38   return fingerprint_;
     39 }
     40 
     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 
     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 
     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 
     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 
     98 void FontFactory::SerializeFont(Font* font, OutputStream* os) {
     99   font->Serialize(os, &table_ordering_);
    100 }
    101 
    102 void FontFactory::SetSerializationTableOrdering(
    103     const IntegerList& table_ordering) {
    104   table_ordering_ = table_ordering;
    105 }
    106 
    107 CALLER_ATTACH Font::Builder* FontFactory::NewFontBuilder() {
    108   return Font::Builder::GetOTFBuilder(this);
    109 }
    110 
    111 CALLER_ATTACH Font* FontFactory::LoadSingleOTF(InputStream* is) {
    112   FontBuilderPtr builder;
    113   builder.Attach(LoadSingleOTFForBuilding(is));
    114   return builder->Build();
    115 }
    116 
    117 CALLER_ATTACH Font* FontFactory::LoadSingleOTF(WritableFontData* wfd) {
    118   FontBuilderPtr builder;
    119   builder.Attach(LoadSingleOTFForBuilding(wfd, 0));
    120   return builder->Build();
    121 }
    122 
    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 
    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
    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*
    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 
    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 
    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 
    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 
    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 
    210 FontFactory::FontFactory()
    211     : fingerprint_(false) {
    212 }
    213 
    214 }  // namespace sfntly
    215