1 //
2 // C++ Implementation: icushaper
3 //
4 // Description:
5 //
6 //
7 // Author: Pierre Marchand <pierremarc@oep-h.com>, (C) 2008
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12
13 #include <QDebug>
14 #include "icushaper.h"
15
16 #include <iostream>
17 using std::cerr;
18
19 QString OTF_tag_name ( unsigned int tag );
20 unsigned int OTF_name_tag ( QString s );
21
IcuShaper(FMOtf * o,QString s)22 IcuShaper::IcuShaper ( FMOtf * o, QString s )
23 :FMBaseShaper ( o,s )
24 {
25 fillTagToCode();
26 qDebug()<<"IcuShaper::IcuShaper("<< tagToCode.value ( script ) <<")";
27 LEErrorCode err(LE_NO_ERROR);
28 icuFont = new IcuFontImpl ( otf );
29 icuLE = LayoutEngine::layoutEngineFactory ( icuFont, tagToCode.value ( script ), -1 , err );
30 IcuError(err);
31 }
32
~IcuShaper()33 IcuShaper::~ IcuShaper()
34 {
35 icuLE->reset();
36 delete icuLE;
37 delete icuFont;
38 }
39
fillTagToCode()40 void IcuShaper::fillTagToCode()
41 {
42 if ( tagToCode.isEmpty() )
43 {
44 tagToCode["zyyy"] = zyyyScriptCode ;
45 tagToCode["qaai"] = qaaiScriptCode ;
46 tagToCode["arab"] = arabScriptCode ;
47 tagToCode["armn"] = armnScriptCode ;
48 tagToCode["beng"] = bengScriptCode ;
49 tagToCode["bopo"] = bopoScriptCode ;
50 tagToCode["cher"] = cherScriptCode ;
51 tagToCode["copt"] = coptScriptCode ;
52 tagToCode["cyrl"] = cyrlScriptCode ;
53 tagToCode["dsrt"] = dsrtScriptCode ;
54 tagToCode["deva"] = devaScriptCode ;
55 tagToCode["ethi"] = ethiScriptCode ;
56 tagToCode["geor"] = georScriptCode ;
57 tagToCode["goth"] = gothScriptCode ;
58 tagToCode["grek"] = grekScriptCode ;
59 tagToCode["gujr"] = gujrScriptCode ;
60 tagToCode["guru"] = guruScriptCode ;
61 tagToCode["hani"] = haniScriptCode ;
62 tagToCode["hang"] = hangScriptCode ;
63 tagToCode["hebr"] = hebrScriptCode ;
64 tagToCode["hira"] = hiraScriptCode ;
65 tagToCode["knda"] = kndaScriptCode ;
66 tagToCode["kana"] = kanaScriptCode ;
67 tagToCode["khmr"] = khmrScriptCode ;
68 tagToCode["lao "] = laooScriptCode ;
69 tagToCode["latn"] = latnScriptCode ;
70 tagToCode["mlym"] = mlymScriptCode ;
71 tagToCode["mong"] = mongScriptCode ;
72 tagToCode["mymr"] = mymrScriptCode ;
73 tagToCode["ogam"] = ogamScriptCode ;
74 tagToCode["ital"] = italScriptCode ;
75 tagToCode["orya"] = oryaScriptCode ;
76 tagToCode["runr"] = runrScriptCode ;
77 tagToCode["sinh"] = sinhScriptCode ;
78 tagToCode["syrc"] = syrcScriptCode ;
79 tagToCode["taml"] = tamlScriptCode ;
80 tagToCode["telu"] = teluScriptCode ;
81 tagToCode["thaa"] = thaaScriptCode ;
82 tagToCode["thai"] = thaiScriptCode ;
83 tagToCode["tibt"] = tibtScriptCode ;
84 tagToCode["cans"] = cansScriptCode ;
85 tagToCode["yi "] = yiiiScriptCode ;
86 tagToCode["tglg"] = tglgScriptCode ;
87 tagToCode["hano"] = hanoScriptCode ;
88 tagToCode["buhd"] = buhdScriptCode ;
89 tagToCode["tagb"] = tagbScriptCode ;
90 tagToCode["brai"] = braiScriptCode ;
91 tagToCode["cprt"] = cprtScriptCode ;
92 tagToCode["limb"] = limbScriptCode ;
93 tagToCode["linb"] = linbScriptCode ;
94 tagToCode["osma"] = osmaScriptCode ;
95 tagToCode["shaw"] = shawScriptCode ;
96 tagToCode["tale"] = taleScriptCode ;
97 tagToCode["ugar"] = ugarScriptCode ;
98 tagToCode["hrkt"] = hrktScriptCode ;
99 tagToCode["bugi"] = bugiScriptCode ;
100 tagToCode["glag"] = glagScriptCode ;
101 tagToCode["khar"] = kharScriptCode ;
102 tagToCode["sylo"] = syloScriptCode ;
103 tagToCode["talu"] = taluScriptCode ;
104 tagToCode["tfng"] = tfngScriptCode ;
105 tagToCode["xpeo"] = xpeoScriptCode ;
106 tagToCode["bali"] = baliScriptCode ;
107 tagToCode["batk"] = batkScriptCode ;
108 tagToCode["blis"] = blisScriptCode ;
109 tagToCode["brah"] = brahScriptCode ;
110 tagToCode["cham"] = chamScriptCode ;
111 tagToCode["cirt"] = cirtScriptCode ;
112 tagToCode["cyrs"] = cyrsScriptCode ;
113 tagToCode["egyd"] = egydScriptCode ;
114 tagToCode["egyh"] = egyhScriptCode ;
115 tagToCode["egyp"] = egypScriptCode ;
116 tagToCode["geok"] = geokScriptCode ;
117 tagToCode["hans"] = hansScriptCode ;
118 tagToCode["hant"] = hantScriptCode ;
119 tagToCode["hmng"] = hmngScriptCode ;
120 tagToCode["hung"] = hungScriptCode ;
121 tagToCode["inds"] = indsScriptCode ;
122 tagToCode["java"] = javaScriptCode ;
123 tagToCode["kali"] = kaliScriptCode ;
124 tagToCode["latf"] = latfScriptCode ;
125 tagToCode["latg"] = latgScriptCode ;
126 tagToCode["lepc"] = lepcScriptCode ;
127 tagToCode["lina"] = linaScriptCode ;
128 tagToCode["mand"] = mandScriptCode ;
129 tagToCode["maya"] = mayaScriptCode ;
130 tagToCode["mero"] = meroScriptCode ;
131 tagToCode["nko "] = nkooScriptCode ;
132 tagToCode["orkh"] = orkhScriptCode ;
133 tagToCode["perm"] = permScriptCode ;
134 tagToCode["phag"] = phagScriptCode ;
135 tagToCode["phnx"] = phnxScriptCode ;
136 tagToCode["plrd"] = plrdScriptCode ;
137 tagToCode["roro"] = roroScriptCode ;
138 tagToCode["sara"] = saraScriptCode ;
139 tagToCode["syre"] = syreScriptCode ;
140 tagToCode["syrj"] = syrjScriptCode ;
141 tagToCode["syrn"] = syrnScriptCode ;
142 tagToCode["teng"] = tengScriptCode ;
143 tagToCode["vai "] = vaiiScriptCode ;
144 tagToCode["visp"] = vispScriptCode ;
145 tagToCode["xsux"] = xsuxScriptCode ;
146 tagToCode["zxxx"] = zxxxScriptCode ;
147 tagToCode["zzzz"] = zzzzScriptCode ;
148 }
149 }
150
151
doShape(const QString & s)152 GlyphList IcuShaper::doShape ( const QString & s )
153 {
154 GlyphList ret;
155 int glAllocated ( 0 );
156
157 LEErrorCode err(LE_NO_ERROR);
158
159 LEUnicode16 *ts = new LEUnicode[s.count() ];
160 for ( int i ( 0 ); i< s.count();++i )
161 {
162 ts[i] = s[i].unicode();
163 // cerr << "["<< s[i].unicode() << "]";
164 }
165 // cerr<< std::endl;
166
167 icuLE->reset();
168 int sCount (s.count());
169 glAllocated = icuLE->layoutChars ( ts, 0,sCount , sCount, false, 0, 0, err ) ;
170 IcuError(err);
171
172 // cerr<<"provided "<<s.count()<< " got "<< glAllocated<< std::endl;
173
174 LEGlyphID *glyphs = new LEGlyphID[glAllocated];
175 le_int32 *indices = new le_int32[glAllocated];
176 float *positions = new float[ ( glAllocated * 2 ) + 2];
177 icuLE->getGlyphs ( glyphs, err );
178 icuLE->getCharIndices ( indices, err );
179 icuLE->getGlyphPositions ( positions, err );
180 float stackX ( 0.0 );
181
182 for ( int gIdx ( 0 ); gIdx < glAllocated ; ++gIdx )
183 {
184 if(glyphs[gIdx] != 0xFFFF)
185 {
186 RenderedGlyph rg;
187 rg.glyph = glyphs[gIdx];
188 rg.log = indices[gIdx];
189 rg.lChar = s[rg.log].unicode();
190 rg.xadvance = positions[ ( gIdx + 1 ) * 2] - stackX;
191 rg.yadvance = positions[ ( ( gIdx + 1 ) * 2 ) + 1];
192 rg.xoffset = rg.yoffset = 0;
193 stackX += rg.xadvance;
194
195 ret << rg;
196 }
197
198 // cerr<< "["<< indices[gIdx] <<"]";
199 // cerr<< "["<< glyphs[gIdx] <<"]";
200 // cerr<< std::endl;
201 }
202 icuLE->reset();
203
204 delete ts;
205 delete glyphs;
206 delete indices;
207 delete positions;
208
209 return ret;
210 }
211
212
IcuError(int err)213 void IcuShaper::IcuError(int err)
214 {
215 switch ( err )
216 {
217 case LE_NO_SUBFONT_WARNING : qDebug()<<"The font does not contain subfonts.";break;
218 // case LE_NO_ERROR : qDebug()<<"No error, no warning.";break;
219 case LE_ILLEGAL_ARGUMENT_ERROR : qDebug()<<"An illegal argument was detected.";break;
220 case LE_MEMORY_ALLOCATION_ERROR : qDebug()<<"Memory allocation error.";break;
221 case LE_INDEX_OUT_OF_BOUNDS_ERROR : qDebug()<<"Trying to access an index that is out of bounds.";break;
222 case LE_NO_LAYOUT_ERROR : qDebug()<<"You must call layoutChars() first.";break;
223 case LE_INTERNAL_ERROR : qDebug()<<"An internal error was encountered.";break;
224 case LE_FONT_FILE_NOT_FOUND_ERROR : qDebug()<<"The requested font file cannot be opened.";break;
225 case LE_MISSING_FONT_TABLE_ERROR : qDebug()<<"The requested font table does not exist.";break;
226 default:/*qDebug()<<"NoCode"*/;
227 }
228 }
229
230
231
232 /// Je suis furieux d’avoir à écrire ça - pm
233
234 IcuFontImpl *IcuFontImpl::instance = 0;
235
IcuFontImpl(FMOtf * o)236 IcuFontImpl::IcuFontImpl ( FMOtf * o )
237 :otf ( o )
238 {
239 instance = this;
240 }
241
~IcuFontImpl()242 IcuFontImpl::~ IcuFontImpl()
243 {
244 foreach(unsigned char* p, tables)
245 {
246 delete p;
247 }
248
249 }
250
getFontTable(LETag tableTag,size_t & length_sz) const251 const void * IcuFontImpl::getFontTable ( LETag tableTag, size_t &length_sz ) const
252 {
253 // qDebug()<< "IcuFontImpl::getFontTable" << OTF_tag_name( tableTag );
254 FT_Face face ( otf->face() );
255 FT_ULong length(0);
256 if ( !FT_Load_Sfnt_Table ( face, tableTag, 0, NULL, &length ) )
257 {
258 if ( length > 0 )
259 {
260 // qDebug()<<"Table len"<< length;
261 FT_Byte * bA = new FT_Byte[length];
262
263 FT_Load_Sfnt_Table ( face, tableTag, 0, bA, &length );
264
265 regTables( tableTag, bA );
266 return (const void*) tables.value(tableTag);
267 }
268
269 }
270 return 0;
271 }
272
getUnitsPerEM() const273 le_int32 IcuFontImpl::getUnitsPerEM() const
274 {
275 return otf->face()->units_per_EM;
276 }
277
mapCharToGlyph(LEUnicode32 ch) const278 LEGlyphID IcuFontImpl::mapCharToGlyph ( LEUnicode32 ch ) const
279 {
280 int gi(FT_Get_Char_Index ( otf->face(), ch ));
281 // cerr << "IcuFontImpl::mapCharToGlyph("<< ch <<") = "<<gi<<std::endl;
282 return gi;
283 }
284
getGlyphAdvance(LEGlyphID glyph,LEPoint & advance) const285 void IcuFontImpl::getGlyphAdvance ( LEGlyphID glyph, LEPoint & advance ) const
286 {
287 FT_Face face ( otf->face() );
288 if ( !FT_Load_Glyph ( face, glyph , FT_LOAD_NO_SCALE ) )
289 {
290 advance.fX = face->glyph->metrics.horiAdvance;
291 advance.fY = face->glyph->metrics.vertAdvance;
292 }
293 else
294 {
295 advance.fX = 0;
296 advance.fY = 0;
297 }
298 }
299
getGlyphPoint(LEGlyphID glyph,le_int32 pointNumber,LEPoint & point) const300 le_bool IcuFontImpl::getGlyphPoint ( LEGlyphID glyph, le_int32 pointNumber, LEPoint & point ) const
301 {
302 // cerr<< "IcuFontImpl::getGlyphPoint" <<std::endl;
303 return false;
304 }
305
getXPixelsPerEm() const306 float IcuFontImpl::getXPixelsPerEm() const
307 {
308 return getUnitsPerEM();
309 }
310
getYPixelsPerEm() const311 float IcuFontImpl::getYPixelsPerEm() const
312 {
313 return getUnitsPerEM();
314 }
315
getScaleFactorX() const316 float IcuFontImpl::getScaleFactorX() const
317 {
318 return 1.0;
319 }
320
getScaleFactorY() const321 float IcuFontImpl::getScaleFactorY() const
322 {
323 return 1.0;
324 }
325
getAscent() const326 le_int32 IcuFontImpl::getAscent() const
327 {
328 return otf->face()->ascender;
329 }
330
getDescent() const331 le_int32 IcuFontImpl::getDescent() const
332 {
333 return otf->face()->descender;
334 }
335
getLeading() const336 le_int32 IcuFontImpl::getLeading() const
337 {
338 return 0;
339 }
340
341