1 : /* GRAPHITE2 LICENSING
2 :
3 : Copyright 2010, SIL International
4 : All rights reserved.
5 :
6 : This library is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU Lesser General Public License as published
8 : by the Free Software Foundation; either version 2.1 of License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should also have received a copy of the GNU Lesser General Public
17 : License along with this library in the file named "LICENSE".
18 : If not, write to the Free Software Foundation, 51 Franklin Street,
19 : Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
20 : internet at http://www.fsf.org/licenses/lgpl.html.
21 :
22 : Alternatively, the contents of this file may be used under the terms of the
23 : Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
24 : License, as published by the Free Software Foundation, either version 2
25 : of the License or (at your option) any later version.
26 : */
27 :
28 : #include "inc/Main.h"
29 : #include "inc/CmapCache.h"
30 : #include "inc/TtfTypes.h"
31 : #include "inc/TtfUtil.h"
32 :
33 :
34 : using namespace graphite2;
35 :
36 0 : CmapCache::CmapCache(const void* cmapTable, size_t length)
37 : {
38 0 : const void * table31 = TtfUtil::FindCmapSubtable(cmapTable, 3, 1, length);
39 0 : const void * table310 = TtfUtil::FindCmapSubtable(cmapTable, 3, 10, length);
40 0 : m_isBmpOnly = (!table310);
41 0 : int rangeKey = 0;
42 0 : uint32 codePoint = 0,
43 0 : prevCodePoint = 0;
44 0 : if (table310 && TtfUtil::CheckCmap310Subtable(table310))
45 : {
46 0 : m_blocks = grzeroalloc<uint16*>(0x1100);
47 0 : if (!m_blocks) return;
48 0 : codePoint = TtfUtil::Cmap310NextCodepoint(table310, codePoint, &rangeKey);
49 0 : while (codePoint != 0x10FFFF)
50 : {
51 0 : unsigned int block = (codePoint & 0xFFFF00) >> 8;
52 0 : if (!m_blocks[block])
53 : {
54 0 : m_blocks[block] = grzeroalloc<uint16>(0x100);
55 0 : if (!m_blocks[block])
56 0 : return;
57 : }
58 0 : m_blocks[block][codePoint & 0xFF] = TtfUtil::Cmap310Lookup(table310, codePoint, rangeKey);
59 : // prevent infinite loop
60 0 : if (codePoint <= prevCodePoint)
61 0 : codePoint = prevCodePoint + 1;
62 0 : prevCodePoint = codePoint;
63 0 : codePoint = TtfUtil::Cmap310NextCodepoint(table310, codePoint, &rangeKey);
64 : }
65 : }
66 : else
67 : {
68 0 : m_blocks = grzeroalloc<uint16*>(0x100);
69 0 : if (!m_blocks) return;
70 : }
71 0 : if (table31 && TtfUtil::CheckCmap31Subtable(table31))
72 : {
73 0 : codePoint = 0;
74 0 : rangeKey = 0;
75 0 : codePoint = TtfUtil::Cmap31NextCodepoint(table31, codePoint, &rangeKey);
76 0 : while (codePoint != 0xFFFF)
77 : {
78 0 : unsigned int block = (codePoint & 0xFFFF00) >> 8;
79 0 : if (!m_blocks[block])
80 : {
81 0 : m_blocks[block] = grzeroalloc<uint16>(0x100);
82 0 : if (!m_blocks[block])
83 0 : return;
84 : }
85 0 : m_blocks[block][codePoint & 0xFF] = TtfUtil::Cmap31Lookup(table31, codePoint, rangeKey);
86 : // prevent infinite loop
87 0 : if (codePoint <= prevCodePoint)
88 0 : codePoint = prevCodePoint + 1;
89 0 : prevCodePoint = codePoint;
90 0 : codePoint = TtfUtil::Cmap31NextCodepoint(table31, codePoint, &rangeKey);
91 : }
92 : }
93 : }
94 :
95 0 : CmapCache::~CmapCache() throw()
96 : {
97 0 : unsigned int numBlocks = (m_isBmpOnly)? 0x100 : 0x1100;
98 0 : for (unsigned int i = 0; i < numBlocks; i++)
99 0 : free(m_blocks[i]);
100 0 : free(m_blocks);
101 0 : }
102 :
103 0 : uint16 CmapCache::operator [] (const uint32 usv) const throw()
104 : {
105 0 : if ((m_isBmpOnly && usv > 0xFFFF) || (usv > 0x10FFFF))
106 0 : return 0;
107 0 : const uint32 block = 0xFFFF & (usv >> 8);
108 0 : if (m_blocks[block])
109 0 : return m_blocks[block][usv & 0xFF];
110 0 : return 0;
111 : };
112 :
113 0 : CmapCache::operator bool() const throw()
114 : {
115 0 : return m_blocks;
116 : }
117 :
118 :
119 0 : DirectCmap::DirectCmap(const void* cmap, size_t length)
120 : {
121 0 : _ctable = TtfUtil::FindCmapSubtable(cmap, 3, 1, length);
122 0 : if (!_ctable || !TtfUtil::CheckCmap31Subtable(_ctable))
123 : {
124 0 : _ctable = 0;
125 0 : return;
126 : }
127 0 : _stable = TtfUtil::FindCmapSubtable(cmap, 3, 10, length);
128 0 : if (_stable && !TtfUtil::CheckCmap310Subtable(_stable))
129 0 : _stable = 0;
130 : }
131 :
132 0 : uint16 DirectCmap::operator [] (const uint32 usv) const throw()
133 : {
134 0 : return usv > 0xFFFF ? (_stable ? TtfUtil::Cmap310Lookup(_stable, usv) : 0) : TtfUtil::Cmap31Lookup(_ctable, usv);
135 : }
136 :
137 0 : DirectCmap::operator bool () const throw()
138 : {
139 0 : return _ctable;
140 : }
141 :
|