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 <iterator>
28 : #include "inc/GlyphFace.h"
29 : #include "inc/GlyphFaceCache.h"
30 : #include "inc/TtfUtil.h"
31 : #include "inc/Endian.h"
32 :
33 :
34 : using namespace graphite2;
35 :
36 : namespace
37 : {
38 : struct glyph_attr { uint16 id, value; };
39 :
40 : class glat_iterator : public std::iterator<std::input_iterator_tag, glyph_attr>
41 : {
42 : public:
43 0 : glat_iterator(const void * glat=0) : _p(reinterpret_cast<const byte *>(glat)), _n(0) {}
44 :
45 0 : glat_iterator & operator ++ () { ++_v.id; --_n; _p += sizeof(uint16); if (_n == -1) { _p -= 2; _v.id = *_p++; _n = *_p++; } return *this; }
46 : glat_iterator operator ++ (int) { glat_iterator tmp(*this); operator++(); return tmp; }
47 :
48 0 : bool operator == (const glat_iterator & rhs) { return _p >= rhs._p || _p + _n*sizeof(uint16) > rhs._p; }
49 0 : bool operator != (const glat_iterator & rhs) { return !operator==(rhs); }
50 :
51 0 : value_type operator * () const {
52 0 : if (_n==0) { _v.id = *_p++; _n = *_p++; }
53 0 : _v.value = be::peek<uint16>(_p);
54 0 : return _v;
55 : }
56 0 : const value_type * operator ->() const { operator * (); return &_v; }
57 :
58 : protected:
59 : mutable const byte * _p;
60 : mutable value_type _v;
61 : mutable int _n;
62 : };
63 :
64 : class glat2_iterator : public glat_iterator
65 : {
66 : public:
67 0 : glat2_iterator(const void * glat) : glat_iterator(glat) {}
68 :
69 0 : glat_iterator & operator ++ () { ++_v.id; --_n; _p += sizeof(uint16); if (_n == -1) { _p -= sizeof(uint16)*2; _v.id = be::read<uint16>(_p); _n = be::read<uint16>(_p); } return *this; }
70 : glat_iterator operator ++ (int) { glat_iterator tmp(*this); operator++(); return tmp; }
71 :
72 0 : value_type operator * () const {
73 0 : if (_n==0) { _v.id = be::read<uint16>(_p); _n = be::read<uint16>(_p); }
74 0 : _v.value = be::peek<uint16>(_p);
75 0 : return _v;
76 : }
77 0 : const value_type * operator ->() const { operator * (); return &_v; }
78 : };
79 : }
80 :
81 :
82 :
83 0 : GlyphFace::GlyphFace(const GlyphFaceCacheHeader& hdr, unsigned short glyphid)
84 : {
85 0 : if (glyphid < hdr.m_nGlyphsWithGraphics)
86 : {
87 : int nLsb, xMin, yMin, xMax, yMax;
88 : unsigned int nAdvWid;
89 0 : size_t locidx = TtfUtil::LocaLookup(glyphid, hdr.m_pLoca, hdr.m_lLoca, hdr.m_pHead);
90 0 : void *pGlyph = TtfUtil::GlyfLookup(hdr.m_pGlyf, locidx, hdr.m_lGlyf);
91 0 : if (TtfUtil::HorMetrics(glyphid, hdr.m_pHmtx, hdr.m_lHmtx, hdr.m_pHHea, nLsb, nAdvWid))
92 0 : m_advance = Position(static_cast<float>(nAdvWid), 0);
93 : else
94 0 : m_advance = Position();
95 0 : if (pGlyph && TtfUtil::GlyfBox(pGlyph, xMin, yMin, xMax, yMax))
96 : m_bbox = Rect(Position(static_cast<float>(xMin), static_cast<float>(yMin)),
97 0 : Position(static_cast<float>(xMax), static_cast<float>(yMax)));
98 : else
99 0 : m_bbox = Rect();
100 : }
101 : else
102 : {
103 0 : m_advance = Position();
104 0 : m_bbox = Rect();
105 : }
106 0 : if (glyphid < hdr.m_nGlyphsWithAttributes)
107 : {
108 : size_t glocs, gloce;
109 0 : const byte * gloc = hdr.m_pGloc;
110 :
111 0 : if (hdr.m_locFlagsUse32Bit)
112 : {
113 0 : be::skip<uint32>(gloc, glyphid);
114 0 : glocs = be::read<uint32>(gloc);
115 0 : gloce = be::read<uint32>(gloc);
116 : }
117 : else
118 : {
119 0 : be::skip<uint16>(gloc, glyphid);
120 0 : glocs = be::read<uint16>(gloc);
121 0 : gloce = be::read<uint16>(gloc);
122 : }
123 0 : if (glocs < hdr.m_lGlat && gloce <= hdr.m_lGlat)
124 : {
125 0 : if (hdr.m_fGlat < 0x00020000)
126 : {
127 0 : if (gloce - glocs < 2*sizeof(byte)+sizeof(uint16)
128 : || gloce - glocs > hdr.m_numAttrs*(2*sizeof(byte)+sizeof(uint16)))
129 0 : return;
130 :
131 0 : new (&m_attrs) sparse(glat_iterator(hdr.m_pGlat + glocs), glat_iterator(hdr.m_pGlat + gloce));
132 : }
133 : else
134 : {
135 0 : if (gloce - glocs < 3*sizeof(uint16)
136 : || gloce - glocs > hdr.m_numAttrs*3*sizeof(uint16))
137 0 : return;
138 :
139 0 : new (&m_attrs) sparse(glat2_iterator(hdr.m_pGlat + glocs), glat2_iterator(hdr.m_pGlat + gloce));
140 : }
141 :
142 0 : if (m_attrs.size() > hdr.m_numAttrs)
143 : {
144 0 : m_attrs.~sparse();
145 0 : new (&m_attrs) sparse();
146 : }
147 : }
148 : }
149 : }
150 :
151 :
152 :
153 0 : uint16 GlyphFace::getMetric(uint8 metric) const
154 : {
155 0 : switch (metrics(metric))
156 : {
157 0 : case kgmetLsb : return static_cast<uint16>(m_bbox.bl.x);
158 0 : case kgmetRsb : return static_cast<uint16>(m_advance.x - m_bbox.tr.x);
159 0 : case kgmetBbTop : return static_cast<uint16>(m_bbox.tr.y);
160 0 : case kgmetBbBottom : return static_cast<uint16>(m_bbox.bl.y);
161 0 : case kgmetBbLeft : return static_cast<uint16>(m_bbox.bl.x);
162 0 : case kgmetBbRight : return static_cast<uint16>(m_bbox.tr.x);
163 0 : case kgmetBbHeight: return static_cast<uint16>(m_bbox.tr.y - m_bbox.bl.y);
164 0 : case kgmetBbWidth : return static_cast<uint16>(m_bbox.tr.x - m_bbox.bl.x);
165 0 : case kgmetAdvWidth : return static_cast<uint16>(m_advance.x);
166 0 : case kgmetAdvHeight : return static_cast<uint16>(m_advance.y);
167 0 : default : return 0;
168 : }
169 : }
|