Line data Source code
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/Face.h"
31 : #include "inc/TtfTypes.h"
32 : #include "inc/TtfUtil.h"
33 :
34 :
35 : using namespace graphite2;
36 :
37 0 : const void * bmp_subtable(const Face::Table & cmap)
38 : {
39 : const void * stbl;
40 0 : if (!cmap.size()) return 0;
41 0 : if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()), cmap + cmap.size())
42 0 : || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()), cmap + cmap.size())
43 0 : || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()), cmap + cmap.size())
44 0 : || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()), cmap + cmap.size())
45 0 : || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()), cmap + cmap.size()))
46 0 : return stbl;
47 0 : return 0;
48 : }
49 :
50 0 : const void * smp_subtable(const Face::Table & cmap)
51 : {
52 : const void * stbl;
53 0 : if (!cmap.size()) return 0;
54 0 : if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()), cmap + cmap.size())
55 0 : || TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()), cmap + cmap.size()))
56 0 : return stbl;
57 0 : return 0;
58 : }
59 :
60 : template <unsigned int (*NextCodePoint)(const void *, unsigned int, int *),
61 : uint16 (*LookupCodePoint)(const void *, unsigned int, int)>
62 0 : bool cache_subtable(uint16 * blocks[], const void * cst, const unsigned int limit)
63 : {
64 0 : int rangeKey = 0;
65 0 : uint32 codePoint = NextCodePoint(cst, 0, &rangeKey),
66 0 : prevCodePoint = 0;
67 0 : while (codePoint < limit)
68 : {
69 0 : unsigned int block = codePoint >> 8;
70 0 : if (!blocks[block])
71 : {
72 0 : blocks[block] = grzeroalloc<uint16>(0x100);
73 0 : if (!blocks[block])
74 0 : return false;
75 : }
76 0 : blocks[block][codePoint & 0xFF] = LookupCodePoint(cst, codePoint, rangeKey);
77 : // prevent infinite loop
78 0 : if (codePoint <= prevCodePoint)
79 0 : codePoint = prevCodePoint + 1;
80 0 : prevCodePoint = codePoint;
81 0 : codePoint = NextCodePoint(cst, codePoint, &rangeKey);
82 : }
83 0 : return true;
84 : }
85 :
86 :
87 0 : CachedCmap::CachedCmap(const Face & face)
88 : : m_isBmpOnly(true),
89 0 : m_blocks(0)
90 : {
91 0 : const Face::Table cmap(face, Tag::cmap);
92 0 : if (!cmap) return;
93 :
94 0 : const void * bmp_cmap = bmp_subtable(cmap);
95 0 : const void * smp_cmap = smp_subtable(cmap);
96 0 : m_isBmpOnly = !smp_cmap;
97 :
98 0 : m_blocks = grzeroalloc<uint16 *>(m_isBmpOnly ? 0x100 : 0x1100);
99 0 : if (m_blocks && smp_cmap)
100 : {
101 0 : if (!cache_subtable<TtfUtil::CmapSubtable12NextCodepoint, TtfUtil::CmapSubtable12Lookup>(m_blocks, smp_cmap, 0x10FFFF))
102 0 : return;
103 : }
104 :
105 0 : if (m_blocks && bmp_cmap)
106 : {
107 0 : if (!cache_subtable<TtfUtil::CmapSubtable4NextCodepoint, TtfUtil::CmapSubtable4Lookup>(m_blocks, bmp_cmap, 0xFFFF))
108 0 : return;
109 : }
110 : }
111 :
112 0 : CachedCmap::~CachedCmap() throw()
113 : {
114 0 : if (!m_blocks) return;
115 0 : unsigned int numBlocks = (m_isBmpOnly)? 0x100 : 0x1100;
116 0 : for (unsigned int i = 0; i < numBlocks; i++)
117 0 : free(m_blocks[i]);
118 0 : free(m_blocks);
119 0 : }
120 :
121 0 : uint16 CachedCmap::operator [] (const uint32 usv) const throw()
122 : {
123 0 : if ((m_isBmpOnly && usv > 0xFFFF) || (usv > 0x10FFFF))
124 0 : return 0;
125 0 : const uint32 block = 0xFFFF & (usv >> 8);
126 0 : if (m_blocks[block])
127 0 : return m_blocks[block][usv & 0xFF];
128 0 : return 0;
129 : };
130 :
131 0 : CachedCmap::operator bool() const throw()
132 : {
133 0 : return m_blocks != 0;
134 : }
135 :
136 :
137 0 : DirectCmap::DirectCmap(const Face & face)
138 : : _cmap(face, Tag::cmap),
139 0 : _smp(smp_subtable(_cmap)),
140 0 : _bmp(bmp_subtable(_cmap))
141 : {
142 0 : }
143 :
144 0 : uint16 DirectCmap::operator [] (const uint32 usv) const throw()
145 : {
146 : return usv > 0xFFFF
147 0 : ? (_smp ? TtfUtil::CmapSubtable12Lookup(_smp, usv, 0) : 0)
148 0 : : TtfUtil::CmapSubtable4Lookup(_bmp, usv, 0);
149 : }
150 :
151 0 : DirectCmap::operator bool () const throw()
152 : {
153 0 : return _cmap && _bmp;
154 : }
155 :
|