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/data/writable_font_data.h"
18 
19 #include <algorithm>
20 #include <limits>
21 
22 #include "sfntly/data/memory_byte_array.h"
23 #include "sfntly/data/growable_memory_byte_array.h"
24 
25 namespace sfntly {
26 
WritableFontData(ByteArray * ba)27 WritableFontData::WritableFontData(ByteArray* ba) : ReadableFontData(ba) {
28 }
29 
~WritableFontData()30 WritableFontData::~WritableFontData() {}
31 
32 // static
33 CALLER_ATTACH
CreateWritableFontData(int32_t length)34 WritableFontData* WritableFontData::CreateWritableFontData(int32_t length) {
35   ByteArrayPtr ba;
36   if (length > 0) {
37     ba = new MemoryByteArray(length);
38     ba->SetFilledLength(length);
39   } else {
40     ba = new GrowableMemoryByteArray();
41   }
42   WritableFontDataPtr wfd = new WritableFontData(ba);
43   return wfd.Detach();
44 }
45 
46 // TODO(arthurhsu): re-investigate the memory model of this function.  It's
47 //                  not too useful without copying, but it's not performance
48 //                  savvy to do copying.
49 CALLER_ATTACH
CreateWritableFontData(std::vector<uint8_t> * b)50 WritableFontData* WritableFontData::CreateWritableFontData(std::vector<uint8_t>* b) {
51   ByteArrayPtr ba = new GrowableMemoryByteArray();
52   ba->Put(0, b);
53   WritableFontDataPtr wfd = new WritableFontData(ba);
54   return wfd.Detach();
55 }
56 
WriteByte(int32_t index,uint8_t b)57 int32_t WritableFontData::WriteByte(int32_t index, uint8_t b) {
58   array_->Put(BoundOffset(index), b);
59   return 1;
60 }
61 
WriteBytes(int32_t index,uint8_t * b,int32_t offset,int32_t length)62 int32_t WritableFontData::WriteBytes(int32_t index,
63                                      uint8_t* b,
64                                      int32_t offset,
65                                      int32_t length) {
66   return array_->Put(BoundOffset(index),
67                      b,
68                      offset,
69                      BoundLength(index, length));
70 }
71 
WriteBytes(int32_t index,std::vector<uint8_t> * b)72 int32_t WritableFontData::WriteBytes(int32_t index, std::vector<uint8_t>* b) {
73   assert(b);
74   return WriteBytes(index, &((*b)[0]), 0, b->size());
75 }
76 
WriteBytesPad(int32_t index,std::vector<uint8_t> * b,int32_t offset,int32_t length,uint8_t pad)77 int32_t WritableFontData::WriteBytesPad(int32_t index,
78                                         std::vector<uint8_t>* b,
79                                         int32_t offset,
80                                         int32_t length,
81                                         uint8_t pad) {
82   int32_t written =
83       array_->Put(BoundOffset(index),
84                   &((*b)[0]),
85                   offset,
86                   BoundLength(index,
87                               std::min<int32_t>(length, b->size() - offset)));
88   written += WritePadding(written + index, length - written, pad);
89   return written;
90 }
91 
WritePadding(int32_t index,int32_t count)92 int32_t WritableFontData::WritePadding(int32_t index, int32_t count) {
93   return WritePadding(index, count, (uint8_t)0);
94 }
95 
WritePadding(int32_t index,int32_t count,uint8_t pad)96 int32_t WritableFontData::WritePadding(int32_t index, int32_t count,
97                                        uint8_t pad) {
98   for (int32_t i = 0; i < count; ++i) {
99     array_->Put(index + i, pad);
100   }
101   return count;
102 }
103 
WriteChar(int32_t index,uint8_t c)104 int32_t WritableFontData::WriteChar(int32_t index, uint8_t c) {
105   return WriteByte(index, c);
106 }
107 
WriteUShort(int32_t index,int32_t us)108 int32_t WritableFontData::WriteUShort(int32_t index, int32_t us) {
109   WriteByte(index, (uint8_t)((us >> 8) & 0xff));
110   WriteByte(index + 1, (uint8_t)(us & 0xff));
111   return 2;
112 }
113 
WriteUShortLE(int32_t index,int32_t us)114 int32_t WritableFontData::WriteUShortLE(int32_t index, int32_t us) {
115   WriteByte(index, (uint8_t)(us & 0xff));
116   WriteByte(index + 1, (uint8_t)((us >> 8) & 0xff));
117   return 2;
118 }
119 
WriteShort(int32_t index,int32_t s)120 int32_t WritableFontData::WriteShort(int32_t index, int32_t s) {
121   return WriteUShort(index, s);
122 }
123 
WriteUInt24(int32_t index,int32_t ui)124 int32_t WritableFontData::WriteUInt24(int32_t index, int32_t ui) {
125   WriteByte(index, (uint8_t)((ui >> 16) & 0xff));
126   WriteByte(index + 1, (uint8_t)((ui >> 8) & 0xff));
127   WriteByte(index + 2, (uint8_t)(ui & 0xff));
128   return 3;
129 }
130 
WriteULong(int32_t index,int64_t ul)131 int32_t WritableFontData::WriteULong(int32_t index, int64_t ul) {
132   WriteByte(index, (uint8_t)((ul >> 24) & 0xff));
133   WriteByte(index + 1, (uint8_t)((ul >> 16) & 0xff));
134   WriteByte(index + 2, (uint8_t)((ul >> 8) & 0xff));
135   WriteByte(index + 3, (uint8_t)(ul & 0xff));
136   return 4;
137 }
138 
WriteULongLE(int32_t index,int64_t ul)139 int32_t WritableFontData::WriteULongLE(int32_t index, int64_t ul) {
140   WriteByte(index, (uint8_t)(ul & 0xff));
141   WriteByte(index + 1, (uint8_t)((ul >> 8) & 0xff));
142   WriteByte(index + 2, (uint8_t)((ul >> 16) & 0xff));
143   WriteByte(index + 3, (uint8_t)((ul >> 24) & 0xff));
144   return 4;
145 }
146 
WriteLong(int32_t index,int64_t l)147 int32_t WritableFontData::WriteLong(int32_t index, int64_t l) {
148   return WriteULong(index, l);
149 }
150 
WriteFixed(int32_t index,int32_t f)151 int32_t WritableFontData::WriteFixed(int32_t index, int32_t f) {
152   return WriteLong(index, f);
153 }
154 
WriteDateTime(int32_t index,int64_t date)155 int32_t WritableFontData::WriteDateTime(int32_t index, int64_t date) {
156   WriteULong(index, (date >> 32) & 0xffffffff);
157   WriteULong(index + 4, date & 0xffffffff);
158   return 8;
159 }
160 
CopyFrom(InputStream * is,int32_t length)161 void WritableFontData::CopyFrom(InputStream* is, int32_t length) {
162   array_->CopyFrom(is, length);
163 }
164 
CopyFrom(InputStream * is)165 void WritableFontData::CopyFrom(InputStream* is) {
166   array_->CopyFrom(is);
167 }
168 
Slice(int32_t offset,int32_t length)169 CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset,
170                                                 int32_t length) {
171   if (offset < 0 || length < 0 ||
172       offset > std::numeric_limits<int32_t>::max() - length ||
173       offset + length > Size()) {
174 #if !defined (SFNTLY_NO_EXCEPTION)
175     throw IndexOutOfBoundsException(
176         "Attempt to bind data outside of its limits");
177 #endif
178     return NULL;
179   }
180   FontDataPtr slice = new WritableFontData(this, offset, length);
181   return slice.Detach();
182 }
183 
Slice(int32_t offset)184 CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset) {
185   if (offset < 0 || offset > Size()) {
186 #if !defined (SFNTLY_NO_EXCEPTION)
187     throw IndexOutOfBoundsException(
188         "Attempt to bind data outside of its limits");
189 #endif
190     return NULL;
191   }
192   FontDataPtr slice = new WritableFontData(this, offset);
193   return slice.Detach();
194 }
195 
WritableFontData(WritableFontData * data,int32_t offset)196 WritableFontData::WritableFontData(WritableFontData* data, int32_t offset)
197     : ReadableFontData(data, offset) {
198 }
199 
WritableFontData(WritableFontData * data,int32_t offset,int32_t length)200 WritableFontData::WritableFontData(WritableFontData* data,
201                                    int32_t offset,
202                                    int32_t length)
203     : ReadableFontData(data, offset, length) {
204 }
205 
206 }  // namespace sfntly
207