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 #ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_
18 #define SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_
19 
20 #include "sfntly/data/font_data.h"
21 #include "sfntly/port/lock.h"
22 
23 namespace sfntly {
24 
25 class WritableFontData;
26 class OutputStream;
27 
28 // Writable font data wrapper. Supports reading of data primitives in the
29 // TrueType / OpenType spec.
30 // The data types used are as listed:
31 // BYTE       8-bit unsigned integer.
32 // CHAR       8-bit signed integer.
33 // USHORT     16-bit unsigned integer.
34 // SHORT      16-bit signed integer.
35 // UINT24     24-bit unsigned integer.
36 // ULONG      32-bit unsigned integer.
37 // LONG       32-bit signed integer.
38 // Fixed      32-bit signed fixed-point number (16.16)
39 // FUNIT      Smallest measurable distance in the em space.
40 // FWORD      16-bit signed integer (SHORT) that describes a quantity in FUnits.
41 // UFWORD     16-bit unsigned integer (USHORT) that describes a quantity in
42 //            FUnits.
43 // F2DOT14    16-bit signed fixed number with the low 14 bits of fraction (2.14)
44 // LONGDATETIME  Date represented in number of seconds since 12:00 midnight,
45 //               January 1, 1904. The value is represented as a signed 64-bit
46 //               integer.
47 
48 class ReadableFontData : public FontData,
49                          public RefCounted<ReadableFontData> {
50  public:
51   explicit ReadableFontData(ByteArray* array);
52   virtual ~ReadableFontData();
53 
54   static CALLER_ATTACH ReadableFontData* CreateReadableFontData(ByteVector* b);
55 
56   // Gets a computed checksum for the data. This checksum uses the OpenType spec
57   // calculation. Every ULong value (32 bit unsigned) in the data is summed and
58   // the resulting value is truncated to 32 bits. If the data length in bytes is
59   // not an integral multiple of 4 then any remaining bytes are treated as the
60   // start of a 4 byte sequence whose remaining bytes are zero.
61   // @return the checksum
62   int64_t Checksum();
63 
64   // Sets the bounds to use for computing the checksum. These bounds are in
65   // begin and end pairs. If an odd number is given then the final range is
66   // assumed to extend to the end of the data. The lengths of each range must be
67   // a multiple of 4.
68   // @param ranges the range bounds to use for the checksum
69   void SetCheckSumRanges(const IntegerList& ranges);
70 
71   // Read the UBYTE at the given index.
72   // @param index index into the font data
73   // @return the UBYTE; -1 if outside the bounds of the font data
74   // @throws IndexOutOfBoundsException if index is outside the FontData's range
75   virtual int32_t ReadUByte(int32_t index);
76 
77   // Read the BYTE at the given index.
78   // @param index index into the font data
79   // @return the BYTE
80   // @throws IndexOutOfBoundsException if index is outside the FontData's range
81   virtual int32_t ReadByte(int32_t index);
82 
83   // Read the bytes at the given index into the array.
84   // @param index index into the font data
85   // @param b the destination for the bytes read
86   // @param offset offset in the byte array to place the bytes
87   // @param length the length of bytes to read
88   // @return the number of bytes actually read; -1 if the index is outside the
89   //         bounds of the font data
90   virtual int32_t ReadBytes(int32_t index,
91                             byte_t* b,
92                             int32_t offset,
93                             int32_t length);
94 
95   // Read the CHAR at the given index.
96   // @param index index into the font data
97   // @return the CHAR
98   // @throws IndexOutOfBoundsException if index is outside the FontData's range
99   virtual int32_t ReadChar(int32_t index);
100 
101   // Read the USHORT at the given index.
102   // @param index index into the font data
103   // @return the USHORT
104   // @throws IndexOutOfBoundsException if index is outside the FontData's range
105   virtual int32_t ReadUShort(int32_t index);
106 
107   // Read the SHORT at the given index.
108   // @param index index into the font data
109   // @return the SHORT
110   // @throws IndexOutOfBoundsException if index is outside the FontData's range
111   virtual int32_t ReadShort(int32_t index);
112 
113   // Read the UINT24 at the given index.
114   // @param index index into the font data
115   // @return the UINT24
116   // @throws IndexOutOfBoundsException if index is outside the FontData's range
117   virtual int32_t ReadUInt24(int32_t index);
118 
119   // Read the ULONG at the given index.
120   // @param index index into the font data
121   // @return the ULONG
122   // @throws IndexOutOfBoundsException if index is outside the FontData's range
123   virtual int64_t ReadULong(int32_t index);
124 
125   // Read the ULONG at the given index as int32_t.
126   // @param index index into the font data
127   // @return the ULONG
128   // @throws IndexOutOfBoundsException if index is outside the FontData's range
129   virtual int32_t ReadULongAsInt(int32_t index);
130 
131   // Read the ULONG at the given index, little-endian variant
132   // @param index index into the font data
133   // @return the ULONG
134   // @throws IndexOutOfBoundsException if index is outside the FontData's range
135   virtual int64_t ReadULongLE(int32_t index);
136 
137   // Read the LONG at the given index.
138   // @param index index into the font data
139   // @return the LONG
140   // @throws IndexOutOfBoundsException if index is outside the FontData's range
141   virtual int32_t ReadLong(int32_t index);
142 
143   // Read the Fixed at the given index.
144   // @param index index into the font data
145   // @return the Fixed
146   // @throws IndexOutOfBoundsException if index is outside the FontData's range
147   virtual int32_t ReadFixed(int32_t index);
148 
149   // Read the LONGDATETIME at the given index.
150   // @param index index into the font data
151   // @return the LONGDATETIME
152   // @throws IndexOutOfBoundsException if index is outside the FontData's range
153   virtual int64_t ReadDateTimeAsLong(int32_t index);
154 
155   // Read the FWORD at the given index.
156   // @param index index into the font data
157   // @return the FWORD
158   // @throws IndexOutOfBoundsException if index is outside the FontData's range
159   virtual int32_t ReadFWord(int32_t index);
160 
161   // Read the UFWORD at the given index.
162   // @param index index into the font data
163   // @return the UFWORD
164   // @throws IndexOutOfBoundsException if index is outside the FontData's range
165   virtual int32_t ReadFUFWord(int32_t index);
166 
167   // Note: Not ported because they just throw UnsupportedOperationException()
168   //       in Java.
169   /*
170   virtual int32_t ReadFUnit(int32_t index);
171   virtual int64_t ReadF2Dot14(int32_t index);
172   */
173 
174   // Copy the FontData to an OutputStream.
175   // @param os the destination
176   // @return number of bytes copied
177   // @throws IOException
178   virtual int32_t CopyTo(OutputStream* os);
179 
180   // Copy the FontData to a WritableFontData.
181   // @param wfd the destination
182   // @return number of bytes copied
183   // @throws IOException
184   virtual int32_t CopyTo(WritableFontData* wfd);
185 
186   // Make gcc -Woverloaded-virtual happy.
187   virtual int32_t CopyTo(ByteArray* ba);
188 
189   // Search for the key value in the range tables provided.
190   // The search looks through the start-end pairs looking for the key value. It
191   // is assumed that the start-end pairs are both represented by UShort values,
192   // ranges do not overlap, and are monotonically increasing.
193   // @param startIndex the position to read the first start value from
194   // @param startOffset the offset between subsequent start values
195   // @param endIndex the position to read the first end value from
196   // @param endOffset the offset between subsequent end values
197   // @param length the number of start-end pairs
198   // @param key the value to search for
199   // @return the index of the start-end pairs in which the key was found; -1
200   //         otherwise
201   int32_t SearchUShort(int32_t start_index,
202                        int32_t start_offset,
203                        int32_t end_index,
204                        int32_t end_offset,
205                        int32_t length,
206                        int32_t key);
207 
208   // Search for the key value in the table provided.
209   // The search looks through the values looking for the key value. It is
210   // assumed that the are represented by UShort values and are monotonically
211   // increasing.
212   // @param startIndex the position to read the first start value from
213   // @param startOffset the offset between subsequent start values
214   // @param length the number of start-end pairs
215   // @param key the value to search for
216   // @return the index of the start-end pairs in which the key was found; -1
217   //         otherwise
218   int32_t SearchUShort(int32_t start_index,
219                        int32_t start_offset,
220                        int32_t length,
221                        int32_t key);
222 
223   // Search for the key value in the range tables provided.
224   // The search looks through the start-end pairs looking for the key value. It
225   // is assumed that the start-end pairs are both represented by ULong values
226   // that can be represented within 31 bits, ranges do not overlap, and are
227   // monotonically increasing.
228   // @param startIndex the position to read the first start value from
229   // @param startOffset the offset between subsequent start values
230   // @param endIndex the position to read the first end value from
231   // @param endOffset the offset between subsequent end values
232   // @param length the number of start-end pairs
233   // @param key the value to search for
234   // @return the index of the start-end pairs in which the key was found; -1
235   //         otherwise
236   int32_t SearchULong(int32_t start_index,
237                       int32_t start_offset,
238                       int32_t end_index,
239                       int32_t end_offset,
240                       int32_t length,
241                       int32_t key);
242 
243 
244   // TODO(arthurhsu): IMPLEMENT
245   /*
246   virtual int32_t ReadFUnit(int32_t index);
247   virtual int64_t ReadF2Dot14(int32_t index);
248   virtual int64_t ReadLongDateTime(int32_t index);
249   */
250 
251   // Makes a slice of this FontData. The returned slice will share the data with
252   // the original FontData.
253   // @param offset the start of the slice
254   // @param length the number of bytes in the slice
255   // @return a slice of the original FontData
256   // Note: C++ polymorphism requires return type to be consistent
257   virtual CALLER_ATTACH FontData* Slice(int32_t offset, int32_t length);
258 
259   // Makes a bottom bound only slice of this array. The returned slice will
260   // share the data with the original FontData.
261   // @param offset the start of the slice
262   // @return a slice of the original FontData
263   // Note: C++ polymorphism requires return type to be consistent
264   virtual CALLER_ATTACH FontData* Slice(int32_t offset);
265 
266   // Not Ported: toString()
267 
268  protected:
269   // Constructor. Creates a bounded wrapper of another ReadableFontData from the
270   // given offset until the end of the original ReadableFontData.
271   // @param data data to wrap
272   // @param offset the start of this data's view of the original data
273   ReadableFontData(ReadableFontData* data, int32_t offset);
274 
275   // Constructor. Creates a bounded wrapper of another ReadableFontData from the
276   // given offset until the end of the original ReadableFontData.
277   // @param data data to wrap
278   // @param offset the start of this data's view of the original data
279   // @param length the length of the other FontData to use
280   ReadableFontData(ReadableFontData* data, int32_t offset, int32_t length);
281 
282  private:
283   // Compute the checksum for the font data using any ranges set for the
284   // calculation.
285   void ComputeChecksum();
286 
287   // Do the actual computation of the checksum for a range using the
288   // TrueType/OpenType checksum algorithm. The range used is from the low bound
289   // to the high bound in steps of four bytes. If any of the bytes within that 4
290   // byte segment are not readable then it will considered a zero for
291   // calculation.
292   // Only called from within a synchronized method so it does not need to be
293   // synchronized itself.
294   // @param lowBound first position to start a 4 byte segment on
295   // @param highBound last possible position to start a 4 byte segment on
296   // @return the checksum for the total range
297   int64_t ComputeCheckSum(int32_t low_bound, int32_t high_bound);
298 
299   Lock checksum_lock_;
300   bool checksum_set_;
301   int64_t checksum_;
302   IntegerList checksum_range_;
303 };
304 typedef Ptr<ReadableFontData> ReadableFontDataPtr;
305 
306 }  // namespace sfntly
307 
308 #endif  // SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_
309