1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/graphite2/src/CmapCache.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,155 @@ 1.4 +/* GRAPHITE2 LICENSING 1.5 + 1.6 + Copyright 2010, SIL International 1.7 + All rights reserved. 1.8 + 1.9 + This library is free software; you can redistribute it and/or modify 1.10 + it under the terms of the GNU Lesser General Public License as published 1.11 + by the Free Software Foundation; either version 2.1 of License, or 1.12 + (at your option) any later version. 1.13 + 1.14 + This program is distributed in the hope that it will be useful, 1.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.17 + Lesser General Public License for more details. 1.18 + 1.19 + You should also have received a copy of the GNU Lesser General Public 1.20 + License along with this library in the file named "LICENSE". 1.21 + If not, write to the Free Software Foundation, 51 Franklin Street, 1.22 + Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 1.23 + internet at http://www.fsf.org/licenses/lgpl.html. 1.24 + 1.25 +Alternatively, the contents of this file may be used under the terms of the 1.26 +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public 1.27 +License, as published by the Free Software Foundation, either version 2 1.28 +of the License or (at your option) any later version. 1.29 +*/ 1.30 + 1.31 +#include "inc/Main.h" 1.32 +#include "inc/CmapCache.h" 1.33 +#include "inc/Face.h" 1.34 +#include "inc/TtfTypes.h" 1.35 +#include "inc/TtfUtil.h" 1.36 + 1.37 + 1.38 +using namespace graphite2; 1.39 + 1.40 +const void * bmp_subtable(const Face::Table & cmap) 1.41 +{ 1.42 + const void * stbl; 1.43 + if (!cmap.size()) return 0; 1.44 + if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size())) 1.45 + || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size())) 1.46 + || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size())) 1.47 + || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size())) 1.48 + || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()))) 1.49 + return stbl; 1.50 + return 0; 1.51 +} 1.52 + 1.53 +const void * smp_subtable(const Face::Table & cmap) 1.54 +{ 1.55 + const void * stbl; 1.56 + if (!cmap.size()) return 0; 1.57 + if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size())) 1.58 + || TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()))) 1.59 + return stbl; 1.60 + return 0; 1.61 +} 1.62 + 1.63 +template <unsigned int (*NextCodePoint)(const void *, unsigned int, int *), 1.64 + uint16 (*LookupCodePoint)(const void *, unsigned int, int)> 1.65 +bool cache_subtable(uint16 * blocks[], const void * cst, const unsigned int limit) 1.66 +{ 1.67 + int rangeKey = 0; 1.68 + uint32 codePoint = NextCodePoint(cst, 0, &rangeKey), 1.69 + prevCodePoint = 0; 1.70 + while (codePoint != limit) 1.71 + { 1.72 + unsigned int block = codePoint >> 8; 1.73 + if (!blocks[block]) 1.74 + { 1.75 + blocks[block] = grzeroalloc<uint16>(0x100); 1.76 + if (!blocks[block]) 1.77 + return false; 1.78 + } 1.79 + blocks[block][codePoint & 0xFF] = LookupCodePoint(cst, codePoint, rangeKey); 1.80 + // prevent infinite loop 1.81 + if (codePoint <= prevCodePoint) 1.82 + codePoint = prevCodePoint + 1; 1.83 + prevCodePoint = codePoint; 1.84 + codePoint = NextCodePoint(cst, codePoint, &rangeKey); 1.85 + } 1.86 + return true; 1.87 +} 1.88 + 1.89 + 1.90 +CachedCmap::CachedCmap(const Face & face) 1.91 +: m_isBmpOnly(true), 1.92 + m_blocks(0) 1.93 +{ 1.94 + const Face::Table cmap(face, Tag::cmap); 1.95 + if (!cmap) return; 1.96 + 1.97 + const void * bmp_cmap = bmp_subtable(cmap); 1.98 + const void * smp_cmap = smp_subtable(cmap); 1.99 + m_isBmpOnly = !smp_cmap; 1.100 + 1.101 + m_blocks = grzeroalloc<uint16 *>(m_isBmpOnly ? 0x100 : 0x1100); 1.102 + if (m_blocks && smp_cmap) 1.103 + { 1.104 + if (!cache_subtable<TtfUtil::CmapSubtable12NextCodepoint, TtfUtil::CmapSubtable12Lookup>(m_blocks, smp_cmap, 0x10FFFF)) 1.105 + return; 1.106 + } 1.107 + 1.108 + if (m_blocks && bmp_cmap) 1.109 + { 1.110 + if (!cache_subtable<TtfUtil::CmapSubtable4NextCodepoint, TtfUtil::CmapSubtable4Lookup>(m_blocks, bmp_cmap, 0xFFFF)) 1.111 + return; 1.112 + } 1.113 +} 1.114 + 1.115 +CachedCmap::~CachedCmap() throw() 1.116 +{ 1.117 + if (!m_blocks) return; 1.118 + unsigned int numBlocks = (m_isBmpOnly)? 0x100 : 0x1100; 1.119 + for (unsigned int i = 0; i < numBlocks; i++) 1.120 + free(m_blocks[i]); 1.121 + free(m_blocks); 1.122 +} 1.123 + 1.124 +uint16 CachedCmap::operator [] (const uint32 usv) const throw() 1.125 +{ 1.126 + if ((m_isBmpOnly && usv > 0xFFFF) || (usv > 0x10FFFF)) 1.127 + return 0; 1.128 + const uint32 block = 0xFFFF & (usv >> 8); 1.129 + if (m_blocks[block]) 1.130 + return m_blocks[block][usv & 0xFF]; 1.131 + return 0; 1.132 +}; 1.133 + 1.134 +CachedCmap::operator bool() const throw() 1.135 +{ 1.136 + return m_blocks != 0; 1.137 +} 1.138 + 1.139 + 1.140 +DirectCmap::DirectCmap(const Face & face) 1.141 +: _cmap(face, Tag::cmap), 1.142 + _smp(smp_subtable(_cmap)), 1.143 + _bmp(bmp_subtable(_cmap)) 1.144 +{ 1.145 +} 1.146 + 1.147 +uint16 DirectCmap::operator [] (const uint32 usv) const throw() 1.148 +{ 1.149 + return usv > 0xFFFF 1.150 + ? (_smp ? TtfUtil::CmapSubtable12Lookup(_smp, usv, 0) : 0) 1.151 + : TtfUtil::CmapSubtable4Lookup(_bmp, usv, 0); 1.152 +} 1.153 + 1.154 +DirectCmap::operator bool () const throw() 1.155 +{ 1.156 + return _cmap && _bmp; 1.157 +} 1.158 +