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 : #include "inc/GlyphFaceCache.h"
28 : #include "graphite2/Font.h"
29 : #include "inc/Face.h" //for the tags
30 : #include "inc/Endian.h"
31 :
32 : using namespace graphite2;
33 :
34 0 : /*virtual*/ bool GlyphFaceCacheHeader::initialize(const Face & face, const bool dumb_font) //return result indicates success. Do not use if failed.
35 : {
36 0 : if ((m_pLoca = face.getTable(Tag::loca, &m_lLoca)) == NULL) return false;
37 0 : if ((m_pHead = face.getTable(Tag::head)) == NULL) return false;
38 0 : if ((m_pGlyf = face.getTable(Tag::glyf, &m_lGlyf)) == NULL) return false;
39 0 : if ((m_pHmtx = face.getTable(Tag::hmtx, &m_lHmtx)) == NULL) return false;
40 0 : if ((m_pHHea = face.getTable(Tag::hhea)) == NULL) return false;
41 :
42 0 : const void* pMaxp = face.getTable(Tag::maxp);
43 0 : if (pMaxp == NULL) return false;
44 0 : m_nGlyphs = m_nGlyphsWithGraphics = (unsigned short)TtfUtil::GlyphCount(pMaxp);
45 :
46 0 : if (!dumb_font)
47 : {
48 0 : if ((m_pGlat = face.getTable(Tag::Glat, &m_lGlat)) == NULL) return false;
49 0 : m_fGlat = be::peek<uint32>(m_pGlat);
50 : size_t lGloc;
51 0 : if ((m_pGloc = face.getTable(Tag::Gloc, &lGloc)) == NULL) return false;
52 0 : if (lGloc < 6) return false;
53 0 : int version = be::read<uint32>(m_pGloc);
54 0 : if (version != 0x00010000) return false;
55 :
56 0 : const uint16 locFlags = be::read<uint16>(m_pGloc);
57 0 : m_numAttrs = be::read<uint16>(m_pGloc);
58 0 : if (m_numAttrs > 0x1000) return false; // is this hard limit appropriate?
59 :
60 0 : if (locFlags & 1)
61 : {
62 0 : m_locFlagsUse32Bit = true;
63 0 : m_nGlyphsWithAttributes = (unsigned short)((lGloc - 12) / 4);
64 : }
65 : else
66 : {
67 0 : m_locFlagsUse32Bit = false;
68 0 : m_nGlyphsWithAttributes = (unsigned short)((lGloc - 10) / 2);
69 : }
70 :
71 0 : if (m_nGlyphsWithAttributes > m_nGlyphs)
72 0 : m_nGlyphs = m_nGlyphsWithAttributes;
73 : }
74 :
75 0 : return true;
76 : }
77 :
78 0 : GlyphFaceCache* GlyphFaceCache::makeCache(const GlyphFaceCacheHeader& hdr)
79 : {
80 0 : return new (hdr) GlyphFaceCache(hdr);
81 : }
82 :
83 0 : GlyphFaceCache::GlyphFaceCache(const GlyphFaceCacheHeader& hdr)
84 0 : : GlyphFaceCacheHeader(hdr)
85 : {
86 0 : unsigned int nGlyphs = numGlyphs();
87 :
88 0 : for (unsigned int i = 0; i < nGlyphs; i++)
89 : {
90 0 : *glyphPtrDirect(i) = NULL;
91 : }
92 0 : }
93 :
94 0 : GlyphFaceCache::~GlyphFaceCache()
95 : {
96 0 : unsigned int nGlyphs = numGlyphs();
97 0 : int deltaPointers = (*glyphPtrDirect(nGlyphs-1u) - *glyphPtrDirect(0u));
98 0 : if ((nGlyphs > 0u) && (deltaPointers == static_cast<int>(nGlyphs - 1)))
99 : {
100 0 : for (unsigned int i=0 ; i<nGlyphs; ++i)
101 : {
102 0 : GlyphFace *p = *glyphPtrDirect(i);
103 0 : assert (p);
104 0 : p->~GlyphFace();
105 : }
106 0 : free (*glyphPtrDirect(0));
107 : }
108 : else
109 : {
110 0 : for (unsigned int i=0 ; i<nGlyphs; ++i)
111 : {
112 0 : GlyphFace *p = *glyphPtrDirect(i);
113 0 : if (p)
114 : {
115 0 : p->~GlyphFace();
116 0 : free(p);
117 : }
118 : }
119 : }
120 0 : }
121 :
122 0 : void GlyphFaceCache::loadAllGlyphs()
123 : {
124 0 : unsigned int nGlyphs = numGlyphs();
125 : // size_t sparse_size = 0;
126 0 : GlyphFace * glyphs = gralloc<GlyphFace>(nGlyphs);
127 0 : for (unsigned short glyphid = 0; glyphid < nGlyphs; glyphid++)
128 : {
129 0 : GlyphFace **p = glyphPtrDirect(glyphid);
130 0 : *p = &(glyphs[glyphid]);
131 0 : new(*p) GlyphFace(*this, glyphid);
132 : // sparse_size += (*p)->m_attrs._sizeof();
133 : }
134 : // const size_t flat_size = nGlyphs*(sizeof(uint16*) + sizeof(uint16)*numAttrs());
135 : // assert(sparse_size <= flat_size);
136 0 : }
137 :
138 0 : /*virtual*/ const GlyphFace *GlyphFaceCache::glyph(unsigned short glyphid) const //result may be changed by subsequent call with a different glyphid
139 : {
140 0 : GlyphFace **p = glyphPtrDirect(glyphid);
141 0 : if (*p)
142 0 : return *p;
143 :
144 0 : *p = (GlyphFace*)malloc(sizeof(GlyphFace));
145 0 : new(*p) GlyphFace(*this, glyphid);
146 0 : return *p;
147 : }
|