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/table/font_data_table.h"
18 
19 #include "sfntly/data/font_output_stream.h"
20 
21 namespace sfntly {
22 
23 /******************************************************************************
24  * FontDataTable class
25  ******************************************************************************/
26 
FontDataTable(ReadableFontData * data)27 FontDataTable::FontDataTable(ReadableFontData* data) {
28   data_ = data;
29 }
30 
~FontDataTable()31 FontDataTable::~FontDataTable() {}
32 
ReadFontData()33 ReadableFontData* FontDataTable::ReadFontData() {
34   return data_;
35 }
36 
DataLength()37 int32_t FontDataTable::DataLength() {
38   return data_->Length();
39 }
40 
Serialize(OutputStream * os)41 int32_t FontDataTable::Serialize(OutputStream* os) {
42   return data_->CopyTo(os);
43 }
44 
Serialize(WritableFontData * data)45 int32_t FontDataTable::Serialize(WritableFontData* data) {
46   return data_->CopyTo(data);
47 }
48 
49 /******************************************************************************
50  * FontDataTable::Builder class
51  ******************************************************************************/
Data()52 CALLER_ATTACH WritableFontData* FontDataTable::Builder::Data() {
53   WritableFontDataPtr new_data;
54   if (model_changed_) {
55     if (!SubReadyToSerialize()) {
56 #if !defined (SFNTLY_NO_EXCEPTION)
57       throw IOException("Table not ready to build.");
58 #endif
59       return NULL;
60     }
61     int32_t size = SubDataSizeToSerialize();
62     new_data.Attach(WritableFontData::CreateWritableFontData(size));
63     SubSerialize(new_data);
64   } else {
65     ReadableFontDataPtr data = InternalReadData();
66     new_data.Attach(WritableFontData::CreateWritableFontData(
67                         data != NULL ? data->Length() : 0));
68     if (data != NULL) {
69       data->CopyTo(new_data);
70     }
71   }
72   return new_data.Detach();
73 }
74 
SetData(ReadableFontData * data)75 void FontDataTable::Builder::SetData(ReadableFontData* data) {
76   InternalSetData(data, true);
77 }
78 
79 
Build()80 CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() {
81   FontDataTablePtr table;  // NULL default table
82   ReadableFontDataPtr data = InternalReadData();
83   if (model_changed_) {
84     // Let subclass serialize from model.
85     if (!SubReadyToSerialize()) {
86 #if !defined (SFNTLY_NO_EXCEPTION)
87       throw IOException("Table not ready to build.");
88 #endif
89       return NULL;
90     }
91     int32_t size = SubDataSizeToSerialize();
92     WritableFontDataPtr new_data;
93     new_data.Attach(WritableFontData::CreateWritableFontData(size));
94     SubSerialize(new_data);
95     data = new_data;
96   }
97 
98   if (data != NULL) {
99     table = SubBuildTable(data);
100     NotifyPostTableBuild(table);
101   }
102 
103   r_data_.Release();
104   w_data_.Release();
105   return table;
106 }
107 
ReadyToBuild()108 bool FontDataTable::Builder::ReadyToBuild() {
109   return true;
110 }
111 
InternalReadData()112 ReadableFontData* FontDataTable::Builder::InternalReadData() {
113   return (r_data_ != NULL) ? r_data_.p_ :
114                              static_cast<ReadableFontData*>(w_data_.p_);
115 }
116 
InternalWriteData()117 WritableFontData* FontDataTable::Builder::InternalWriteData() {
118   if (w_data_ == NULL) {
119     WritableFontDataPtr new_data;
120     new_data.Attach(WritableFontData::CreateWritableFontData(
121                         r_data_ == NULL ? 0 : r_data_->Length()));
122 #if !defined (SFNTLY_NO_EXCEPTION)
123     try {
124 #endif
125       if (r_data_) {
126         r_data_->CopyTo(new_data);
127       }
128 #if !defined (SFNTLY_NO_EXCEPTION)
129     } catch (IOException& e) {
130       // TODO(stuartg): fix when IOExceptions are cleaned up
131     }
132 #endif
133     InternalSetData(new_data, false);
134   }
135   return w_data_.p_;
136 }
137 
Builder()138 FontDataTable::Builder::Builder()
139     : model_changed_(false),
140       contained_model_changed_(false),
141       data_changed_(false) {
142 }
143 
Builder(int32_t data_size)144 FontDataTable::Builder::Builder(int32_t data_size)
145     : model_changed_(false),
146       contained_model_changed_(false),
147       data_changed_(false) {
148   w_data_.Attach(WritableFontData::CreateWritableFontData(data_size));
149 }
150 
Builder(WritableFontData * data)151 FontDataTable::Builder::Builder(WritableFontData* data)
152     : model_changed_(false),
153       contained_model_changed_(false),
154       data_changed_(false) {
155   w_data_ = data;
156 }
157 
Builder(ReadableFontData * data)158 FontDataTable::Builder::Builder(ReadableFontData* data)
159     : model_changed_(false),
160       contained_model_changed_(false),
161       data_changed_(false) {
162   r_data_ = data;
163 }
164 
~Builder()165 FontDataTable::Builder::~Builder() {
166 }
167 
NotifyPostTableBuild(FontDataTable * table)168 void FontDataTable::Builder::NotifyPostTableBuild(FontDataTable* table) {
169   // Default: NOP.
170   UNREFERENCED_PARAMETER(table);
171 }
172 
InternalSetData(WritableFontData * data,bool data_changed)173 void FontDataTable::Builder::InternalSetData(WritableFontData* data,
174                                              bool data_changed) {
175   w_data_ = data;
176   r_data_ = NULL;
177   if (data_changed) {
178     data_changed_ = true;
179     SubDataSet();
180   }
181 }
182 
InternalSetData(ReadableFontData * data,bool data_changed)183 void FontDataTable::Builder::InternalSetData(ReadableFontData* data,
184                                              bool data_changed) {
185   w_data_ = NULL;
186   r_data_ = data;
187   if (data_changed) {
188     data_changed_ = true;
189     SubDataSet();
190   }
191 }
192 
193 }  // namespace sfntly
194