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