Path: blob/master/thirdparty/graphite/src/CmapCache.cpp
9903 views
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later1// Copyright 2010, SIL International, All rights reserved.234#include "inc/Main.h"5#include "inc/CmapCache.h"6#include "inc/Face.h"7#include "inc/TtfTypes.h"8#include "inc/TtfUtil.h"91011using namespace graphite2;1213const void * bmp_subtable(const Face::Table & cmap)14{15const void * stbl;16if (!cmap.size()) return 0;17if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()), cmap + cmap.size())18|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()), cmap + cmap.size())19|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()), cmap + cmap.size())20|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()), cmap + cmap.size())21|| TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()), cmap + cmap.size()))22return stbl;23return 0;24}2526const void * smp_subtable(const Face::Table & cmap)27{28const void * stbl;29if (!cmap.size()) return 0;30if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()), cmap + cmap.size())31|| TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()), cmap + cmap.size()))32return stbl;33return 0;34}3536template <unsigned int (*NextCodePoint)(const void *, unsigned int, int *),37uint16 (*LookupCodePoint)(const void *, unsigned int, int)>38bool cache_subtable(uint16 * blocks[], const void * cst, const unsigned int limit)39{40int rangeKey = 0;41uint32 codePoint = NextCodePoint(cst, 0, &rangeKey),42prevCodePoint = 0;43while (codePoint < limit)44{45unsigned int block = codePoint >> 8;46if (!blocks[block])47{48blocks[block] = grzeroalloc<uint16>(0x100);49if (!blocks[block])50return false;51}52blocks[block][codePoint & 0xFF] = LookupCodePoint(cst, codePoint, rangeKey);53// prevent infinite loop54if (codePoint <= prevCodePoint)55codePoint = prevCodePoint + 1;56prevCodePoint = codePoint;57codePoint = NextCodePoint(cst, codePoint, &rangeKey);58}59return true;60}616263CachedCmap::CachedCmap(const Face & face)64: m_isBmpOnly(true),65m_blocks(0)66{67const Face::Table cmap(face, Tag::cmap);68if (!cmap) return;6970const void * bmp_cmap = bmp_subtable(cmap);71const void * smp_cmap = smp_subtable(cmap);72m_isBmpOnly = !smp_cmap;7374m_blocks = grzeroalloc<uint16 *>(m_isBmpOnly ? 0x100 : 0x1100);75if (m_blocks && smp_cmap)76{77if (!cache_subtable<TtfUtil::CmapSubtable12NextCodepoint, TtfUtil::CmapSubtable12Lookup>(m_blocks, smp_cmap, 0x10FFFF))78return;79}8081if (m_blocks && bmp_cmap)82{83if (!cache_subtable<TtfUtil::CmapSubtable4NextCodepoint, TtfUtil::CmapSubtable4Lookup>(m_blocks, bmp_cmap, 0xFFFF))84return;85}86}8788CachedCmap::~CachedCmap() throw()89{90if (!m_blocks) return;91unsigned int numBlocks = (m_isBmpOnly)? 0x100 : 0x1100;92for (unsigned int i = 0; i < numBlocks; i++)93free(m_blocks[i]);94free(m_blocks);95}9697uint16 CachedCmap::operator [] (const uint32 usv) const throw()98{99if ((m_isBmpOnly && usv > 0xFFFF) || (usv > 0x10FFFF))100return 0;101const uint32 block = 0xFFFF & (usv >> 8);102if (m_blocks[block])103return m_blocks[block][usv & 0xFF];104return 0;105};106107CachedCmap::operator bool() const throw()108{109return m_blocks != 0;110}111112113DirectCmap::DirectCmap(const Face & face)114: _cmap(face, Tag::cmap),115_smp(smp_subtable(_cmap)),116_bmp(bmp_subtable(_cmap))117{118}119120uint16 DirectCmap::operator [] (const uint32 usv) const throw()121{122return usv > 0xFFFF123? (_smp ? TtfUtil::CmapSubtable12Lookup(_smp, usv, 0) : 0)124: TtfUtil::CmapSubtable4Lookup(_bmp, usv, 0);125}126127DirectCmap::operator bool () const throw()128{129return _cmap && _bmp;130}131132133134