ttfmain.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042
  1. /* Copyright (C) 2003 Aladdin Enterprises. All rights reserved.
  2. This software is provided AS-IS with no warranty, either express or
  3. implied.
  4. This software is distributed under license and may not be copied,
  5. modified or distributed except as expressly authorized under the terms
  6. of the license contained in the file LICENSE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostscript.com/licensing/. For information on
  9. commercial licensing, go to http://www.artifex.com/licensing/ or
  10. contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  12. */
  13. /* $Id: ttfmain.c,v 1.34 2005/08/02 11:12:32 igor Exp $ */
  14. /* A Free Type interface adapter. */
  15. /* Uses code fragments from the FreeType project. */
  16. #include "ttmisc.h"
  17. #include "ttfoutl.h"
  18. #include "ttfmemd.h"
  19. #include "ttfinp.h"
  20. #include "ttfsfnt.h"
  21. #include "ttobjs.h"
  22. #include "ttinterp.h"
  23. #include "ttcalc.h"
  24. private const bool skip_instructions = 0; /* Debug purpose only. */
  25. typedef struct {
  26. Fixed a, b, c, d, tx, ty;
  27. } FixMatrix;
  28. struct ttfSubGlyphUsage_s {
  29. FixMatrix m;
  30. int index;
  31. int flags;
  32. short arg1, arg2;
  33. };
  34. /*------------------------------------------------------------------- */
  35. private Fixed AVE(F26Dot6 a, F26Dot6 b)
  36. { return (a + b) / 2;
  37. }
  38. private F26Dot6 shortToF26Dot6(short a)
  39. { return (F26Dot6)a << 6;
  40. }
  41. private F26Dot6 floatToF26Dot6(float a)
  42. { return (F26Dot6)(a * (1 << 6) + 0.5);
  43. }
  44. private Fixed floatToF16Dot16(float a)
  45. { return (F26Dot6)(a * (1 << 16) + 0.5);
  46. }
  47. private void TransformF26Dot6PointFix(F26Dot6Point *pt, F26Dot6 dx, F26Dot6 dy, FixMatrix *m)
  48. { pt->x = MulDiv(dx, m->a, 65536) + MulDiv(dy, m->c, 65536) + (m->tx >> 10);
  49. pt->y = MulDiv(dx, m->b, 65536) + MulDiv(dy, m->d, 65536) + (m->ty >> 10);
  50. }
  51. private void TransformF26Dot6PointFloat(FloatPoint *pt, F26Dot6 dx, F26Dot6 dy, FloatMatrix *m)
  52. { pt->x = dx * m->a / 64 + dy * m->c / 64 + m->tx;
  53. pt->y = dx * m->b / 64 + dy * m->d / 64 + m->ty;
  54. }
  55. /*-------------------------------------------------------------------*/
  56. private ttfPtrElem *ttfFont__get_table_ptr(ttfFont *f, char *id)
  57. {
  58. if (!memcmp(id, "cvt ", 4))
  59. return &f->t_cvt_;
  60. if (!memcmp(id, "fpgm", 4))
  61. return &f->t_fpgm;
  62. if (!memcmp(id, "glyf", 4))
  63. return &f->t_glyf;
  64. if (!memcmp(id, "head", 4))
  65. return &f->t_head;
  66. if (!memcmp(id, "hhea", 4))
  67. return &f->t_hhea;
  68. if (!memcmp(id, "hmtx", 4))
  69. return &f->t_hmtx;
  70. if (!memcmp(id, "vhea", 4))
  71. return &f->t_vhea;
  72. if (!memcmp(id, "vmtx", 4))
  73. return &f->t_vmtx;
  74. if (!memcmp(id, "loca", 4))
  75. return &f->t_loca;
  76. if (!memcmp(id, "maxp", 4))
  77. return &f->t_maxp;
  78. if (!memcmp(id, "prep", 4))
  79. return &f->t_prep;
  80. if (!memcmp(id, "cmap", 4))
  81. return &f->t_cmap;
  82. return 0;
  83. }
  84. /*-------------------------------------------------------------------*/
  85. TT_Error TT_Set_Instance_CharSizes(TT_Instance instance,
  86. TT_F26Dot6 charWidth,
  87. TT_F26Dot6 charHeight)
  88. {
  89. PInstance ins = instance.z;
  90. if ( !ins )
  91. return TT_Err_Invalid_Instance_Handle;
  92. if (charWidth < 1*64)
  93. charWidth = 1*64;
  94. if (charHeight < 1*64)
  95. charHeight = 1*64;
  96. ins->metrics.x_scale1 = charWidth;
  97. ins->metrics.y_scale1 = charHeight;
  98. ins->metrics.x_scale2 = ins->face->font->nUnitsPerEm;
  99. ins->metrics.y_scale2 = ins->face->font->nUnitsPerEm;
  100. if (ins->face->font->nFlags & 8) {
  101. ins->metrics.x_scale1 = (ins->metrics.x_scale1+32) & -64;
  102. ins->metrics.y_scale1 = (ins->metrics.y_scale1+32) & -64;
  103. }
  104. ins->metrics.x_ppem = ins->metrics.x_scale1 / 64;
  105. ins->metrics.y_ppem = ins->metrics.y_scale1 / 64;
  106. if (charWidth > charHeight)
  107. ins->metrics.pointSize = charWidth;
  108. else
  109. ins->metrics.pointSize = charHeight;
  110. ins->valid = FALSE;
  111. return Instance_Reset(ins, FALSE);
  112. }
  113. /*-------------------------------------------------------------------*/
  114. int ttfInterpreter__obtain(ttfMemory *mem, ttfInterpreter **ptti)
  115. {
  116. ttfInterpreter *tti;
  117. if (*ptti) {
  118. (*ptti)->lock++;
  119. return 0;
  120. }
  121. tti = mem->alloc_struct(mem, (const ttfMemoryDescriptor *)&st_ttfInterpreter, "ttfInterpreter__obtain");
  122. if (!tti)
  123. return fMemoryError;
  124. tti->usage = 0;
  125. tti->usage_size = 0;
  126. tti->ttf_memory = mem;
  127. tti->lock = 1;
  128. tti->exec = mem->alloc_struct(mem, (const ttfMemoryDescriptor *)&st_TExecution_Context, "ttfInterpreter__obtain");
  129. if (!tti->exec) {
  130. mem->free(mem, tti, "ttfInterpreter__obtain");
  131. return fMemoryError;
  132. }
  133. memset(tti->exec, 0, sizeof(*tti->exec));
  134. *ptti = tti;
  135. return 0;
  136. }
  137. void ttfInterpreter__release(ttfInterpreter **ptti)
  138. {
  139. ttfInterpreter *tti = *ptti;
  140. ttfMemory *mem = tti->ttf_memory;
  141. if(--tti->lock)
  142. return;
  143. mem->free(mem, tti->usage, "ttfInterpreter__release");
  144. mem->free(mem, tti->exec, "ttfInterpreter__release");
  145. mem->free(mem, *ptti, "ttfInterpreter__release");
  146. mem->free(mem, mem, "ttfInterpreter__release");
  147. *ptti = 0;
  148. }
  149. /*-------------------------------------------------------------------*/
  150. void ttfFont__init(ttfFont *this, ttfMemory *mem,
  151. void (*DebugRepaint)(ttfFont *),
  152. int (*DebugPrint)(ttfFont *, const char *s, ...))
  153. {
  154. memset(this, 0, sizeof(*this));
  155. this->DebugRepaint = DebugRepaint;
  156. this->DebugPrint = DebugPrint;
  157. }
  158. void ttfFont__finit(ttfFont *this)
  159. { ttfMemory *mem = this->tti->ttf_memory;
  160. if (this->exec)
  161. Context_Destroy(this->exec);
  162. this->exec = NULL;
  163. if (this->inst)
  164. Instance_Destroy(this->inst);
  165. mem->free(mem, this->inst, "ttfFont__finit");
  166. this->inst = NULL;
  167. if (this->face)
  168. Face_Destroy(this->face);
  169. mem->free(mem, this->face, "ttfFont__finit");
  170. this->face = NULL;
  171. }
  172. #define MAX_SUBGLYPH_NESTING 3 /* Arbitrary. We need this because we don't want
  173. a ttfOutliner__BuildGlyphOutline recursion
  174. while a glyph is loaded in ttfReader. */
  175. FontError ttfFont__Open(ttfInterpreter *tti, ttfFont *this, ttfReader *r,
  176. unsigned int nTTC, float w, float h,
  177. bool design_grid)
  178. { char sVersion[4], sVersion0[4] = {0, 1, 0, 0};
  179. unsigned int nNumTables, i;
  180. TT_Error code;
  181. int k;
  182. TT_Instance I;
  183. ttfMemory *mem = tti->ttf_memory;
  184. F26Dot6 ww, hh;
  185. this->tti = tti;
  186. this->design_grid = design_grid;
  187. r->Read(r, sVersion, 4);
  188. if(!memcmp(sVersion, "ttcf", 4)) {
  189. unsigned int nFonts;
  190. unsigned int nPos = 0xbaadf00d; /* Quiet compiler. */
  191. r->Read(r, sVersion, 4);
  192. if(memcmp(sVersion, sVersion0, 4))
  193. return fUnimplemented;
  194. nFonts = ttfReader__UInt(r);
  195. if (nFonts == 0)
  196. return fBadFontData;
  197. if(nTTC >= nFonts)
  198. return fTableNotFound;
  199. for(i = 0; i <= nTTC; i++)
  200. nPos = ttfReader__UInt(r);
  201. r->Seek(r, nPos);
  202. r->Read(r, sVersion, 4);
  203. }
  204. if(memcmp(sVersion, sVersion0, 4) && memcmp(sVersion, "true", 4))
  205. return fUnimplemented;
  206. nNumTables = ttfReader__UShort(r);
  207. ttfReader__UShort(r); /* nSearchRange */
  208. ttfReader__UShort(r); /* nEntrySelector */
  209. ttfReader__UShort(r); /* nRangeShift */
  210. for (i = 0; i < nNumTables; i++) {
  211. char sTag[5];
  212. unsigned int nOffset, nLength;
  213. ttfPtrElem *e;
  214. sTag[4] = 0;
  215. r->Read(r, sTag, 4);
  216. ttfReader__UInt(r); /* nCheckSum */
  217. nOffset = ttfReader__UInt(r);
  218. nLength = ttfReader__UInt(r);
  219. e = ttfFont__get_table_ptr(this, sTag);
  220. if (e != NULL) {
  221. e->nPos = nOffset;
  222. e->nLen = nLength;
  223. }
  224. }
  225. r->Seek(r, this->t_head.nPos + offset_of(sfnt_FontHeader, flags));
  226. this->nFlags = ttfReader__UShort(r);
  227. r->Seek(r, this->t_head.nPos + offset_of(sfnt_FontHeader, unitsPerEm));
  228. this->nUnitsPerEm = ttfReader__UShort(r);
  229. r->Seek(r, this->t_head.nPos + offset_of(sfnt_FontHeader, indexToLocFormat));
  230. this->nIndexToLocFormat = ttfReader__UShort(r);
  231. r->Seek(r, this->t_maxp.nPos + offset_of(sfnt_maxProfileTable, numGlyphs));
  232. this->nNumGlyphs = ttfReader__UShort(r);
  233. r->Seek(r, this->t_maxp.nPos + offset_of(sfnt_maxProfileTable, maxComponentElements));
  234. this->nMaxComponents = ttfReader__UShort(r);
  235. if(this->nMaxComponents < 10)
  236. this->nMaxComponents = 10; /* work around DynaLab bug in lgoth.ttf */
  237. r->Seek(r, this->t_hhea.nPos + offset_of(sfnt_MetricsHeader, numberLongMetrics));
  238. this->nLongMetricsHorz = ttfReader__UShort(r);
  239. if (this->t_vhea.nPos != 0) {
  240. r->Seek(r, this->t_vhea.nPos + offset_of(sfnt_MetricsHeader, numberLongMetrics));
  241. this->nLongMetricsVert = ttfReader__UShort(r);
  242. } else
  243. this->nLongMetricsVert = 0;
  244. if (tti->usage_size < this->nMaxComponents * MAX_SUBGLYPH_NESTING) {
  245. tti->ttf_memory->free(tti->ttf_memory, tti->usage, "ttfFont__Open");
  246. tti->usage_size = 0;
  247. tti->usage = mem->alloc_bytes(mem,
  248. sizeof(ttfSubGlyphUsage) * this->nMaxComponents * MAX_SUBGLYPH_NESTING,
  249. "ttfFont__Open");
  250. if (tti->usage == NULL)
  251. return fMemoryError;
  252. tti->usage_size = this->nMaxComponents * MAX_SUBGLYPH_NESTING;
  253. }
  254. this->face = mem->alloc_struct(mem, (const ttfMemoryDescriptor *)&st_TFace, "ttfFont__Open");
  255. if (this->face == NULL)
  256. return fMemoryError;
  257. memset(this->face, 0, sizeof(*this->face));
  258. this->face->r = r;
  259. this->face->font = this;
  260. this->exec = tti->exec;
  261. code = Face_Create(this->face);
  262. if (code)
  263. return fMemoryError;
  264. code = r->Error(r);
  265. if (code < 0)
  266. return fBadFontData;
  267. this->inst = mem->alloc_struct(mem, (const ttfMemoryDescriptor *)&st_TInstance, "ttfFont__Open");
  268. if (this->inst == NULL)
  269. return fMemoryError;
  270. memset(this->inst, 0, sizeof(*this->inst));
  271. code = Context_Create(this->exec, this->face); /* See comment in the implementation of Context_Create. */
  272. if (code == TT_Err_Out_Of_Memory)
  273. return fMemoryError;
  274. code = Instance_Create(this->inst, this->face);
  275. if (code == TT_Err_Out_Of_Memory)
  276. return fMemoryError;
  277. if (code)
  278. return fBadFontData;
  279. for(k = 0; k < this->face->cvtSize; k++)
  280. this->inst->cvt[k] = shortToF26Dot6(this->face->cvt[k]);
  281. code = Instance_Init(this->inst);
  282. if (code == TT_Err_Out_Of_Memory)
  283. return fMemoryError;
  284. if (code >= TT_Err_Invalid_Opcode && code <= TT_Err_Invalid_Displacement)
  285. return fBadInstruction;
  286. if (code)
  287. return fBadFontData;
  288. I.z = this->inst;
  289. if (design_grid)
  290. ww = hh = shortToF26Dot6(this->nUnitsPerEm);
  291. else {
  292. /* Round towards zero for a better view of mirrored characters : */
  293. ww = floatToF26Dot6(w);
  294. hh = floatToF26Dot6(h);
  295. }
  296. code = TT_Set_Instance_CharSizes(I, ww, hh);
  297. this->inst->metrics = this->exec->metrics;
  298. if (code == TT_Err_Invalid_Engine)
  299. return fPatented;
  300. if (code == TT_Err_Out_Of_Memory)
  301. return fMemoryError;
  302. if (code >= TT_Err_Invalid_Opcode && code <= TT_Err_Invalid_Displacement)
  303. return fBadInstruction;
  304. if (code)
  305. return fBadFontData;
  306. return code;
  307. }
  308. private void ttfFont__StartGlyph(ttfFont *this)
  309. { Context_Load( this->exec, this->inst );
  310. if ( this->inst->GS.instruct_control & 2 )
  311. this->exec->GS = Default_GraphicsState;
  312. else
  313. this->exec->GS = this->inst->GS;
  314. this->tti->usage_top = 0;
  315. }
  316. private void ttfFont__StopGlyph(ttfFont *this)
  317. {
  318. Context_Save(this->exec, this->inst);
  319. }
  320. /*-------------------------------------------------------------------*/
  321. private void mount_zone( PGlyph_Zone source,
  322. PGlyph_Zone target )
  323. {
  324. Int np, nc;
  325. np = source->n_points;
  326. nc = source->n_contours;
  327. target->org_x = source->org_x + np;
  328. target->org_y = source->org_y + np;
  329. target->cur_x = source->cur_x + np;
  330. target->cur_y = source->cur_y + np;
  331. target->touch = source->touch + np;
  332. target->contours = source->contours + nc;
  333. target->n_points = 0;
  334. target->n_contours = 0;
  335. }
  336. private void Init_Glyph_Component( PSubglyph_Record element,
  337. PSubglyph_Record original,
  338. PExecution_Context exec )
  339. {
  340. element->index = -1;
  341. element->is_scaled = FALSE;
  342. element->is_hinted = FALSE;
  343. if (original)
  344. mount_zone( &original->zone, &element->zone );
  345. else
  346. element->zone = exec->pts;
  347. element->zone.n_contours = 0;
  348. element->zone.n_points = 0;
  349. element->arg1 = 0;
  350. element->arg2 = 0;
  351. element->element_flag = 0;
  352. element->preserve_pps = FALSE;
  353. element->transform.xx = 1 << 16;
  354. element->transform.xy = 0;
  355. element->transform.yx = 0;
  356. element->transform.yy = 1 << 16;
  357. element->transform.ox = 0;
  358. element->transform.oy = 0;
  359. element->leftBearing = 0;
  360. element->advanceWidth = 0;
  361. }
  362. private void cur_to_org( Int n, PGlyph_Zone zone )
  363. {
  364. Int k;
  365. for ( k = 0; k < n; k++ )
  366. zone->org_x[k] = zone->cur_x[k];
  367. for ( k = 0; k < n; k++ )
  368. zone->org_y[k] = zone->cur_y[k];
  369. }
  370. private void org_to_cur( Int n, PGlyph_Zone zone )
  371. {
  372. Int k;
  373. for ( k = 0; k < n; k++ )
  374. zone->cur_x[k] = zone->org_x[k];
  375. for ( k = 0; k < n; k++ )
  376. zone->cur_y[k] = zone->org_y[k];
  377. }
  378. /*-------------------------------------------------------------------*/
  379. void ttfOutliner__init(ttfOutliner *this, ttfFont *f, ttfReader *r, ttfExport *exp,
  380. bool bOutline, bool bFirst, bool bVertical)
  381. {
  382. this->r = r;
  383. this->bOutline = bOutline;
  384. this->bFirst = bFirst;
  385. this->pFont = f;
  386. this->bVertical = bVertical;
  387. this->exp = exp;
  388. }
  389. private void MoveGlyphOutline(TGlyph_Zone *pts, int nOffset, ttfGlyphOutline *out, FixMatrix *m)
  390. { F26Dot6* x = pts->org_x + nOffset;
  391. F26Dot6* y = pts->org_y + nOffset;
  392. short count = out->pointCount;
  393. F26Dot6Point p;
  394. if (m->a == 65536 && m->b == 0 &&
  395. m->c == 0 && m->d == 65536 &&
  396. m->tx == 0 && m->ty == 0)
  397. return;
  398. for (; count != 0; --count) {
  399. TransformF26Dot6PointFix(&p, *x, *y, m);
  400. *x++ = p.x;
  401. *y++ = p.y;
  402. }
  403. }
  404. private FontError ttfOutliner__BuildGlyphOutlineAux(ttfOutliner *this, int glyphIndex,
  405. FixMatrix *m_orig, ttfGlyphOutline* gOutline)
  406. { ttfFont *pFont = this->pFont;
  407. ttfReader *r = this->r;
  408. ttfInterpreter *tti = pFont->tti;
  409. short sideBearing;
  410. FontError error = fNoError;
  411. short arg1, arg2;
  412. short count;
  413. unsigned int nMtxPos, nMtxGlyph = glyphIndex, nLongMetrics, i;
  414. unsigned short nAdvance;
  415. unsigned int nNextGlyphPtr = 0;
  416. unsigned int nPosBeg;
  417. TExecution_Context *exec = pFont->exec;
  418. TGlyph_Zone *pts = &exec->pts;
  419. TSubglyph_Record subglyph;
  420. ttfSubGlyphUsage *usage = tti->usage + tti->usage_top;
  421. const byte *glyph = NULL;
  422. int glyph_size;
  423. if(this->bVertical && pFont->t_vhea.nPos && pFont->t_vmtx.nPos) {
  424. nLongMetrics = pFont->nLongMetricsVert;
  425. nMtxPos = pFont->t_vmtx.nPos;
  426. } else {
  427. nLongMetrics = pFont->nLongMetricsHorz;
  428. nMtxPos = pFont->t_hmtx.nPos;
  429. }
  430. if (this->bVertical && (!pFont->t_vhea.nPos || pFont->t_vmtx.nPos) && nMtxGlyph < nLongMetrics) {
  431. /* A bad font fix. */
  432. nMtxGlyph = nLongMetrics;
  433. if(nMtxGlyph >= pFont->nNumGlyphs)
  434. nMtxGlyph = pFont->nNumGlyphs - 1;
  435. }
  436. if (nMtxGlyph < nLongMetrics) {
  437. r->Seek(r, nMtxPos + 4 * nMtxGlyph);
  438. nAdvance = ttfReader__Short(r);
  439. sideBearing = ttfReader__Short(r);
  440. } else {
  441. r->Seek(r, nMtxPos + 4 * (nLongMetrics - 1));
  442. nAdvance = ttfReader__Short(r);
  443. r->Seek(r, nMtxPos + 4 * nLongMetrics + 2 * (nMtxGlyph - nLongMetrics));
  444. sideBearing = ttfReader__Short(r);
  445. }
  446. if (r->Error(r))
  447. goto errex;
  448. gOutline->sideBearing = shortToF26Dot6(sideBearing);
  449. gOutline->advance.x = shortToF26Dot6(nAdvance);
  450. gOutline->advance.y = 0;
  451. this->bFirst = FALSE;
  452. if (!this->bOutline)
  453. return fNoError;
  454. if (!r->LoadGlyph(r, glyphIndex, &glyph, &glyph_size))
  455. return fGlyphNotFound;
  456. if (r->Eof(r)) {
  457. r->ReleaseGlyph(r, glyphIndex);
  458. gOutline->xMinB = gOutline->yMinB = 0;
  459. gOutline->xMaxB = gOutline->yMaxB = 0;
  460. return fNoError;
  461. }
  462. if (r->Error(r))
  463. goto errex;
  464. nPosBeg = r->Tell(r);
  465. gOutline->contourCount = ttfReader__Short(r);
  466. subglyph.bbox.xMin = ttfReader__Short(r);
  467. subglyph.bbox.yMin = ttfReader__Short(r);
  468. subglyph.bbox.xMax = ttfReader__Short(r);
  469. subglyph.bbox.yMax = ttfReader__Short(r);
  470. gOutline->xMinB = subglyph.bbox.xMin;
  471. gOutline->yMinB = subglyph.bbox.yMin;
  472. gOutline->xMaxB = subglyph.bbox.xMax;
  473. gOutline->yMaxB = subglyph.bbox.yMax;
  474. /* FreeType stuff beg */
  475. Init_Glyph_Component(&subglyph, NULL, pFont->exec);
  476. subglyph.leftBearing = sideBearing;
  477. subglyph.advanceWidth = nAdvance;
  478. subglyph.pp1.x = subglyph.bbox.xMin - sideBearing;
  479. subglyph.pp1.y = 0;
  480. subglyph.pp2.x = subglyph.pp1.x + nAdvance;
  481. subglyph.pp2.y = 0;
  482. /* FreeType stuff end */
  483. if (gOutline->contourCount == 0)
  484. gOutline->pointCount = 0;
  485. else if (gOutline->contourCount == -1) {
  486. unsigned short flags, index, bHaveInstructions = 0;
  487. unsigned int nUsage = 0;
  488. unsigned int nPos;
  489. unsigned int n_ins;
  490. gOutline->bCompound = TRUE;
  491. if (tti->usage_top + pFont->nMaxComponents > tti->usage_size)
  492. return fBadFontData;
  493. gOutline->contourCount = gOutline->pointCount = 0;
  494. do {
  495. FixMatrix m;
  496. ttfSubGlyphUsage *e;
  497. if (nUsage >= pFont->nMaxComponents) {
  498. error = fMemoryError; goto ex;
  499. }
  500. flags = ttfReader__UShort(r);
  501. index = ttfReader__UShort(r);
  502. bHaveInstructions |= (flags & WE_HAVE_INSTRUCTIONS);
  503. if (flags & ARG_1_AND_2_ARE_WORDS) {
  504. arg1 = ttfReader__Short(r);
  505. arg2 = ttfReader__Short(r);
  506. } else {
  507. if (flags & ARGS_ARE_XY_VALUES) {
  508. /* offsets are signed */
  509. arg1 = ttfReader__SignedByte(r);
  510. arg2 = ttfReader__SignedByte(r);
  511. } else { /* anchor points are unsigned */
  512. arg1 = ttfReader__Byte(r);
  513. arg2 = ttfReader__Byte(r);
  514. }
  515. }
  516. m.b = m.c = m.tx = m.ty = 0;
  517. if (flags & WE_HAVE_A_SCALE)
  518. m.a = m.d = (Fixed)ttfReader__Short(r) << 2;
  519. else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
  520. m.a = (Fixed)ttfReader__Short(r) << 2;
  521. m.d = (Fixed)ttfReader__Short(r) << 2;
  522. } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
  523. m.a = (Fixed)ttfReader__Short(r)<<2;
  524. m.b = (Fixed)ttfReader__Short(r)<<2;
  525. m.c = (Fixed)ttfReader__Short(r)<<2;
  526. m.d = (Fixed)ttfReader__Short(r)<<2;
  527. } else
  528. m.a = m.d = 65536;
  529. e = &usage[nUsage];
  530. e->m = m;
  531. e->index = index;
  532. e->arg1 = arg1;
  533. e->arg2 = arg2;
  534. e->flags = flags;
  535. nUsage++;
  536. } while (flags & MORE_COMPONENTS);
  537. /* Some fonts have bad WE_HAVE_INSTRUCTIONS, so use nNextGlyphPtr : */
  538. if (r->Error(r))
  539. goto errex;
  540. nPos = r->Tell(r);
  541. n_ins = ((!r->Eof(r) && (bHaveInstructions || nPos < nNextGlyphPtr)) ? ttfReader__UShort(r) : 0);
  542. nPos = r->Tell(r);
  543. r->ReleaseGlyph(r, glyphIndex);
  544. glyph = NULL;
  545. for (i = 0; i < nUsage; i++) {
  546. ttfGlyphOutline out;
  547. ttfSubGlyphUsage *e = &usage[i];
  548. int j;
  549. TT_Error code;
  550. int nPointsStored = this->nPointsTotal, nContoursStored = this->nContoursTotal;
  551. out.contourCount = 0;
  552. out.pointCount = 0;
  553. out.bCompound = FALSE;
  554. pts->org_x += nPointsStored;
  555. pts->org_y += nPointsStored;
  556. pts->cur_x += nPointsStored;
  557. pts->cur_y += nPointsStored;
  558. pts->touch += nPointsStored;
  559. pts->contours += nContoursStored;
  560. tti->usage_top += nUsage;
  561. code = ttfOutliner__BuildGlyphOutlineAux(this, e->index, m_orig, &out);
  562. pts->org_x -= nPointsStored;
  563. pts->org_y -= nPointsStored;
  564. pts->cur_x -= nPointsStored;
  565. pts->cur_y -= nPointsStored;
  566. pts->touch -= nPointsStored;
  567. tti->usage_top -= nUsage;
  568. pts->contours -= nContoursStored;
  569. if (code == fPatented)
  570. error = code;
  571. else if (code != fNoError) {
  572. error = code;
  573. goto ex;
  574. }
  575. if (flags & ARGS_ARE_XY_VALUES) {
  576. e->m.tx = Scale_X( &exec->metrics, e->arg1 ) << 10;
  577. e->m.ty = Scale_Y( &exec->metrics, e->arg2 ) << 10;
  578. } else {
  579. e->m.tx = (pts->org_x[e->arg1] - pts->org_x[gOutline->pointCount + e->arg2]) << 10;
  580. e->m.ty = (pts->org_y[e->arg1] - pts->org_y[gOutline->pointCount + e->arg2]) << 10;
  581. }
  582. MoveGlyphOutline(pts, nPointsStored, &out, &e->m);
  583. for (j = nContoursStored; j < out.contourCount + nContoursStored; j++)
  584. pts->contours[j] += nPointsStored;
  585. gOutline->contourCount += out.contourCount;
  586. gOutline->pointCount += out.pointCount;
  587. if(e->flags & USE_MY_METRICS) {
  588. gOutline->advance.x = out.advance.x;
  589. gOutline->sideBearing = out.sideBearing;
  590. }
  591. }
  592. if (!skip_instructions && n_ins &&
  593. !(pFont->inst->GS.instruct_control & 1)) {
  594. TT_Error code;
  595. r->LoadGlyph(r, glyphIndex, &glyph, &glyph_size);
  596. if (r->Error(r))
  597. goto errex;
  598. if (nPos + n_ins > glyph_size)
  599. goto errex;
  600. code = Set_CodeRange(exec, TT_CodeRange_Glyph, (byte *)glyph + nPos, n_ins);
  601. if (!code) {
  602. int nPoints = gOutline->pointCount + 2;
  603. int k;
  604. F26Dot6 x;
  605. exec->pts = subglyph.zone;
  606. pts->n_points = nPoints;
  607. pts->n_contours = gOutline->contourCount;
  608. /* add phantom points : */
  609. pts->org_x[nPoints - 2] = Scale_X(&exec->metrics, subglyph.pp1.x);
  610. pts->org_y[nPoints - 2] = Scale_Y(&exec->metrics, subglyph.pp1.y);
  611. pts->org_x[nPoints - 1] = Scale_X(&exec->metrics, subglyph.pp2.x);
  612. pts->org_y[nPoints - 1] = Scale_Y(&exec->metrics, subglyph.pp2.y);
  613. pts->touch[nPoints - 1] = 0;
  614. pts->touch[nPoints - 2] = 0;
  615. /* if hinting, round the phantom points (not sure) : */
  616. x = pts->org_x[nPoints - 2];
  617. x = ((x + 32) & -64) - x;
  618. if (x)
  619. for (k = 0; k < nPoints; k++)
  620. pts->org_x[k] += x;
  621. pts->cur_x[nPoints - 1] = (pts->cur_x[nPoints - 1] + 32) & -64;
  622. for (k = 0; k < nPoints; k++)
  623. pts->touch[k] = pts->touch[k] & TT_Flag_On_Curve;
  624. org_to_cur(nPoints, pts);
  625. exec->is_composite = TRUE;
  626. if (pFont->patented)
  627. code = TT_Err_Invalid_Engine;
  628. else
  629. code = Context_Run(exec, FALSE);
  630. if (!code)
  631. cur_to_org(nPoints, pts);
  632. else if (code == TT_Err_Invalid_Engine)
  633. error = fPatented;
  634. else
  635. error = fBadFontData;
  636. }
  637. Unset_CodeRange(exec);
  638. Clear_CodeRange(exec, TT_CodeRange_Glyph);
  639. }
  640. } else if (gOutline->contourCount > 0) {
  641. uint16 i;
  642. int nPoints;
  643. bool bInsOK;
  644. byte *onCurve, *stop, flag;
  645. short *endPoints;
  646. unsigned int nPos;
  647. unsigned int n_ins;
  648. if (this->nContoursTotal + gOutline->contourCount > exec->n_contours) {
  649. error = fBadFontData; goto ex;
  650. }
  651. endPoints = pts->contours;
  652. for (i = 0; i < gOutline->contourCount; i++)
  653. endPoints[i] = ttfReader__Short(r);
  654. for (i = 1; i < gOutline->contourCount; i++)
  655. if (endPoints[i - 1] >= endPoints[i]) {
  656. error = fBadFontData; goto ex;
  657. }
  658. nPoints = gOutline->pointCount = endPoints[gOutline->contourCount - 1] + 1;
  659. if (this->nPointsTotal + nPoints + 2 > exec->n_points) {
  660. error = fBadFontData; goto ex;
  661. }
  662. n_ins = ttfReader__Short(r);
  663. nPos = r->Tell(r);
  664. r->Seek(r, nPos + n_ins);
  665. if (r->Error(r))
  666. goto errex;
  667. bInsOK = !Set_CodeRange(exec, TT_CodeRange_Glyph, (byte *)glyph + nPos, n_ins);
  668. onCurve = pts->touch;
  669. stop = onCurve + gOutline->pointCount;
  670. while (onCurve < stop) {
  671. *onCurve++ = flag = ttfReader__Byte(r);
  672. if (flag & REPEAT_FLAGS) {
  673. count = ttfReader__Byte(r);
  674. for (--count; count >= 0; --count)
  675. *onCurve++ = flag;
  676. }
  677. }
  678. /* Lets do X */
  679. { short coord = (this->bVertical ? 0 : sideBearing - subglyph.bbox.xMin);
  680. F26Dot6* x = pts->org_x;
  681. onCurve = pts->touch;
  682. while (onCurve < stop) {
  683. if ((flag = *onCurve++) & XSHORT) {
  684. if (flag & SHORT_X_IS_POS)
  685. coord += ttfReader__Byte(r);
  686. else
  687. coord -= ttfReader__Byte(r);
  688. } else if (!(flag & NEXT_X_IS_ZERO))
  689. coord += ttfReader__Short(r);
  690. *x++ = Scale_X(&exec->metrics, coord);
  691. }
  692. }
  693. /* Lets do Y */
  694. { short coord = 0;
  695. F26Dot6* y = pts->org_y;
  696. onCurve = pts->touch;
  697. while (onCurve < stop) {
  698. if((flag = *onCurve) & YSHORT)
  699. if ( flag & SHORT_Y_IS_POS )
  700. coord += ttfReader__Byte(r);
  701. else
  702. coord -= ttfReader__Byte(r);
  703. else if(!(flag & NEXT_Y_IS_ZERO))
  704. coord += ttfReader__Short(r);
  705. *y++ = Scale_Y( &exec->metrics, coord );
  706. /* Filter off the extra bits */
  707. *onCurve++ = flag & ONCURVE;
  708. }
  709. }
  710. MoveGlyphOutline(pts, 0, gOutline, m_orig);
  711. this->nContoursTotal += gOutline->contourCount;
  712. this->nPointsTotal += nPoints;
  713. if (!skip_instructions &&
  714. !r->Error(r) && n_ins && bInsOK && !(pFont->inst->GS.instruct_control & 1)) {
  715. TGlyph_Zone *pts = &exec->pts;
  716. int k;
  717. F26Dot6 x;
  718. TT_Error code;
  719. exec->is_composite = FALSE;
  720. /* add phantom points : */
  721. pts->org_x[nPoints ] = Scale_X(&exec->metrics, subglyph.pp1.x);
  722. pts->org_y[nPoints ] = Scale_Y(&exec->metrics, subglyph.pp1.y);
  723. pts->org_x[nPoints + 1] = Scale_X(&exec->metrics, subglyph.pp2.x);
  724. pts->org_y[nPoints + 1] = Scale_Y(&exec->metrics, subglyph.pp2.y);
  725. pts->touch[nPoints ] = 0;
  726. pts->touch[nPoints + 1] = 0;
  727. pts->n_points = nPoints + 2;
  728. pts->n_contours = gOutline->contourCount;
  729. /* if hinting, round the phantom points (not sure) : */
  730. x = pts->org_x[nPoints];
  731. x = ((x + 32) & -64) - x;
  732. if (x)
  733. for (k = 0; k < nPoints + 2; k++)
  734. pts->org_x[k] += x;
  735. pts->cur_x[nPoints + 1] = (pts->cur_x[nPoints + 1] + 32) & -64;
  736. org_to_cur(nPoints + 2, pts);
  737. exec->is_composite = FALSE;
  738. for (k = 0; k < nPoints + 2; k++)
  739. pts->touch[k] &= TT_Flag_On_Curve;
  740. if (pFont->patented)
  741. code = TT_Err_Invalid_Engine;
  742. else
  743. code = Context_Run(exec, FALSE );
  744. if (!code)
  745. cur_to_org(nPoints + 2, pts);
  746. else if (code == TT_Err_Invalid_Engine)
  747. error = fPatented;
  748. else
  749. error = fBadInstruction;
  750. gOutline->sideBearing = subglyph.bbox.xMin - subglyph.pp1.x;
  751. gOutline->advance.x = subglyph.pp2.x - subglyph.pp1.x;
  752. }
  753. Unset_CodeRange(exec);
  754. Clear_CodeRange(exec, TT_CodeRange_Glyph);
  755. } else
  756. error = fBadFontData;
  757. goto ex;
  758. errex:;
  759. error = fBadFontData;
  760. ex:;
  761. r->ReleaseGlyph(r, glyphIndex);
  762. return error;
  763. }
  764. private FontError ttfOutliner__BuildGlyphOutline(ttfOutliner *this, int glyphIndex,
  765. float orig_x, float orig_y, ttfGlyphOutline* gOutline)
  766. {
  767. FixMatrix m_orig = {1 << 16, 0, 0, 1 << 16, 0, 0};
  768. /* Round towards zero like old character coordinate conversions do. */
  769. m_orig.tx = floatToF16Dot16(orig_x);
  770. m_orig.ty = floatToF16Dot16(orig_y);
  771. return ttfOutliner__BuildGlyphOutlineAux(this, glyphIndex, &m_orig, gOutline);
  772. }
  773. #define AVECTOR_BUG 1 /* Work around a bug in AVector fonts. */
  774. void ttfOutliner__DrawGlyphOutline(ttfOutliner *this)
  775. { ttfGlyphOutline* out = &this->out;
  776. FloatMatrix *m = &this->post_transform;
  777. ttfFont *pFont = this->pFont;
  778. ttfExport *exp = this->exp;
  779. TExecution_Context *exec = pFont->exec;
  780. TGlyph_Zone *pts = &exec->pts;
  781. short* endP = pts->contours;
  782. byte* onCurve = pts->touch;
  783. F26Dot6* x = pts->org_x;
  784. F26Dot6* y = pts->org_y;
  785. F26Dot6 px, py;
  786. short sp, ctr;
  787. FloatPoint p0, p1, p2, p3;
  788. # if AVECTOR_BUG
  789. short xMinB = out->xMinB >> 6, xMaxB=out->xMaxB >> 6;
  790. short yMinB = out->yMinB >> 6, yMaxB=out->yMaxB >> 6;
  791. short expand=pFont->nUnitsPerEm*2;
  792. F26Dot6 xMin, xMax, yMin, yMax;
  793. xMinB -= expand;
  794. yMinB -= expand;
  795. xMaxB += expand;
  796. yMaxB += expand;
  797. xMin = Scale_X(&exec->metrics, xMinB);
  798. xMax = Scale_X(&exec->metrics, xMaxB);
  799. yMin = Scale_X(&exec->metrics, yMinB);
  800. yMax = Scale_X(&exec->metrics, yMaxB);
  801. # endif
  802. TransformF26Dot6PointFloat(&p1, out->advance.x, out->advance.y, m);
  803. p1.x -= this->post_transform.tx;
  804. p1.y -= this->post_transform.ty;
  805. exp->SetWidth(exp, &p1);
  806. sp = -1;
  807. for (ctr = out->contourCount; ctr != 0; --ctr) {
  808. short pt, pts = *endP - sp;
  809. short ep = pts - 1;
  810. if (pts < 3) {
  811. x += pts;
  812. y += pts;
  813. onCurve += pts;
  814. sp = *endP++;
  815. continue; /* skip 1 and 2 point contours */
  816. }
  817. if (exp->bPoints) {
  818. for (pt = 0; pt <= ep; pt++) {
  819. px = x[pt], py = y[pt];
  820. # if AVECTOR_BUG
  821. if (x[pt] < xMin || xMax < x[pt] || y[pt] < yMin || yMax < y[pt]) {
  822. short prevIndex = pt == 0 ? ep : pt - 1;
  823. short nextIndex = pt == ep ? 0 : pt + 1;
  824. if (nextIndex > ep)
  825. nextIndex = 0;
  826. px=AVE(x[prevIndex], x[nextIndex]);
  827. py=AVE(y[prevIndex], y[nextIndex]);
  828. }
  829. # endif
  830. TransformF26Dot6PointFloat(&p0, px, py, m);
  831. exp->Point(exp, &p0, onCurve[pt], !pt);
  832. }
  833. }
  834. if (exp->bOutline) {
  835. pt = 0;
  836. if(onCurve[ep] & 1) {
  837. px = x[ep];
  838. py = y[ep];
  839. } else if (onCurve[0] & 1) {
  840. px = x[0];
  841. py = y[0];
  842. pt = 1;
  843. } else {
  844. px = AVE(x[0], x[ep]);
  845. py = AVE(y[0], y[ep]);
  846. }
  847. this->ppx = px; this->ppy = py;
  848. TransformF26Dot6PointFloat(&p0, px, py, m);
  849. exp->MoveTo(exp, &p0);
  850. for (; pt <= ep; pt++) {
  851. short prevIndex = pt == 0 ? ep : pt - 1;
  852. short nextIndex = pt == ep ? 0 : pt + 1;
  853. if (onCurve[pt] & 1) {
  854. if (onCurve[prevIndex] & 1) {
  855. px = x[pt];
  856. py = y[pt];
  857. if (this->ppx != px || this->ppy != py) {
  858. TransformF26Dot6PointFloat(&p1, px, py, m);
  859. exp->LineTo(exp, &p1);
  860. this->ppx = px; this->ppy = py;
  861. p0 = p1;
  862. }
  863. }
  864. } else {
  865. F26Dot6 prevX, prevY, nextX, nextY;
  866. px = x[pt];
  867. py = y[pt];
  868. # if AVECTOR_BUG
  869. if(x[pt] < xMin || xMax < x[pt] || y[pt] < yMin || yMax < y[pt]) {
  870. px=AVE(x[prevIndex], x[nextIndex]);
  871. py=AVE(y[prevIndex], y[nextIndex]);
  872. }
  873. # endif
  874. if (onCurve[prevIndex] & 1) {
  875. prevX = x[prevIndex];
  876. prevY = y[prevIndex];
  877. } else {
  878. prevX = AVE(x[prevIndex], px);
  879. prevY = AVE(y[prevIndex], py);
  880. }
  881. if (onCurve[nextIndex] & 1) {
  882. nextX = x[nextIndex];
  883. nextY = y[nextIndex];
  884. } else {
  885. nextX = AVE(px, x[nextIndex]);
  886. nextY = AVE(py, y[nextIndex]);
  887. }
  888. if (this->ppx != nextX || this->ppy != nextY) {
  889. double dx1, dy1, dx2, dy2, dx3, dy3;
  890. const double prec = 1e-6;
  891. TransformF26Dot6PointFloat(&p1, (prevX + (px << 1)) / 3, (prevY + (py << 1)) / 3, m);
  892. TransformF26Dot6PointFloat(&p2, (nextX + (px << 1)) / 3, (nextY + (py << 1)) / 3, m);
  893. TransformF26Dot6PointFloat(&p3, nextX, nextY, m);
  894. dx1 = p1.x - p0.x, dy1 = p1.y - p0.y;
  895. dx2 = p2.x - p0.x, dy2 = p2.y - p0.y;
  896. dx3 = p3.x - p0.x, dy3 = p3.y - p0.y;
  897. if (fabs(dx1 * dy3 - dy1 * dx3) > prec * fabs(dx1 * dx3 - dy1 * dy3) ||
  898. fabs(dx2 * dy3 - dy2 * dx3) > prec * fabs(dx2 * dx3 - dy2 * dy3))
  899. exp->CurveTo(exp, &p1, &p2, &p3);
  900. else
  901. exp->LineTo(exp, &p3);
  902. this->ppx = nextX; this->ppy = nextY;
  903. p0 = p3;
  904. }
  905. }
  906. }
  907. exp->Close(exp);
  908. }
  909. x += pts;
  910. y += pts;
  911. onCurve += pts;
  912. sp = *endP++;
  913. }
  914. }
  915. FontError ttfOutliner__Outline(ttfOutliner *this, int glyphIndex,
  916. float orig_x, float orig_y, FloatMatrix *m1)
  917. { ttfFont *pFont = this->pFont;
  918. FontError error;
  919. this->post_transform = *m1;
  920. this->out.contourCount = 0;
  921. this->out.pointCount = 0;
  922. this->out.bCompound = FALSE;
  923. this->nPointsTotal = 0;
  924. this->nContoursTotal = 0;
  925. this->out.advance.x = this->out.advance.y = 0;
  926. ttfFont__StartGlyph(pFont);
  927. error = ttfOutliner__BuildGlyphOutline(this, glyphIndex, orig_x, orig_y, &this->out);
  928. ttfFont__StopGlyph(pFont);
  929. if (pFont->nUnitsPerEm <= 0)
  930. pFont->nUnitsPerEm = 1024;
  931. if (pFont->design_grid) {
  932. this->post_transform.a /= pFont->nUnitsPerEm;
  933. this->post_transform.b /= pFont->nUnitsPerEm;
  934. this->post_transform.c /= pFont->nUnitsPerEm;
  935. this->post_transform.d /= pFont->nUnitsPerEm;
  936. }
  937. if (error != fNoError && error != fPatented)
  938. return error;
  939. return error;
  940. }