PageRenderTime 34ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/archive/olddraw/PdfDraw/TTFReader.cpp

http://upp-mirror.googlecode.com/
C++ | 311 lines | 271 code | 38 blank | 2 comment | 54 complexity | a056d2c5e158ac36422a71c4a4baf1b5 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, BSD-2-Clause, BSD-3-Clause, LGPL-3.0, GPL-3.0
  1. #include "PdfDraw.h"
  2. NAMESPACE_UPP
  3. #define LLOG(x) // LOG(x)
  4. #define LDUMP(x) // LLOG(#x << " = " << x);
  5. int TTFReader::Peek8(const char *s)
  6. {
  7. if(s + 1 > font.End())
  8. Error();
  9. return (byte)*s;
  10. }
  11. int TTFReader::Peek16(const char *s)
  12. {
  13. if(s + 2 > font.End())
  14. Error();
  15. return ((byte)s[0] << 8) | (byte)s[1];
  16. }
  17. int TTFReader::Peek32(const char *s)
  18. {
  19. if(s + 4 > font.End())
  20. Error();
  21. return ((byte)s[0] << 24) | ((byte)s[1] << 16) | ((byte)s[2] << 8) | (byte)s[3];
  22. }
  23. int TTFReader::Peek8(const char *s, int i)
  24. {
  25. return Peek16(s + i);
  26. }
  27. int TTFReader::Peek16(const char *s, int i)
  28. {
  29. return Peek16(s + 2 * i);
  30. }
  31. int TTFReader::Peek32(const char *s, int i)
  32. {
  33. return Peek32(s + 4 * i);
  34. }
  35. int TTFReader::Read8(const char *&s)
  36. {
  37. int q = byte(*s); s++; return q;
  38. }
  39. int TTFReader::Read16(const char *&s)
  40. {
  41. int q = Peek16(s); s += 2; return q;
  42. }
  43. int TTFReader::Read32(const char *&s)
  44. {
  45. int q = Peek32(s); s += 4; return q;
  46. }
  47. String TTFReader::Read(const char *&s, int n)
  48. {
  49. if(s + n > font.End())
  50. Error();
  51. String q(s, n);
  52. s += n;
  53. return q;
  54. }
  55. void TTFReader::Reset()
  56. {
  57. memset(zero, 0, sizeof(zero));
  58. for(int i = 0; i < 256; i++)
  59. cmap[i] = zero;
  60. }
  61. void TTFReader::Free()
  62. {
  63. for(int i = 0; i < 256; i++)
  64. if(cmap[i] != zero)
  65. delete[] cmap[i];
  66. }
  67. void TTFReader::SetGlyph(wchar chr, word glyph)
  68. {
  69. int h = HIBYTE(chr);
  70. if(cmap[h] == zero)
  71. memset(cmap[h] = new word[256], 0, 256 * sizeof(word));
  72. cmap[h][LOBYTE(chr)] = glyph;
  73. }
  74. const char *TTFReader::Seek(const char *tab, int& len)
  75. {
  76. ASSERT(strlen(tab) == 4);
  77. int q = table.Find(tab);
  78. if(q < 0)
  79. Error();
  80. len = table[q].length;
  81. return ~font + table[q].offset;
  82. }
  83. const char *TTFReader::Seek(const char *tab)
  84. {
  85. int dummy;
  86. return Seek(tab, dummy);
  87. }
  88. void TTFReader::Seek(const char *tab, TTFStreamIn& s)
  89. {
  90. int len;
  91. s.beg = s.s = Seek(tab, len);
  92. s.lim = s.s + len;
  93. }
  94. String TTFReader::GetTable(const char *tab)
  95. {
  96. ASSERT(strlen(tab) == 4);
  97. int q = table.Find(tab);
  98. if(q < 0)
  99. return Null;
  100. return String(~font + table[q].offset, table[q].length);
  101. }
  102. bool TTFReader::Open(const String& fnt, bool symbol, bool justcheck)
  103. {
  104. try {
  105. int i;
  106. Free();
  107. Reset();
  108. table.Clear();
  109. glyphinfo.Clear();
  110. font = fnt;
  111. const char *s = fnt;
  112. int q = Read32(s);
  113. if(q != 0x74727565 && q != 0x00010000)
  114. Error();
  115. int n = Read16(s);
  116. s += 6;
  117. while(n--) {
  118. Table& t = table.Add(Read(s, 4));
  119. s += 4;
  120. t.offset = Read32(s);
  121. t.length = Read32(s);
  122. }
  123. for(i = 0; i < table.GetCount(); i++)
  124. LLOG("table: " << table.GetKey(i) << " offset: " << table[i].offset << " length: " << table[i].length);
  125. TTFStreamIn is;
  126. Seek("head", is);
  127. head.Serialize(is);
  128. if(head.magicNumber != 0x5F0F3CF5)
  129. Error();
  130. LDUMP(head.unitsPerEm);
  131. LDUMP(head.xMin);
  132. LDUMP(head.yMin);
  133. LDUMP(head.xMax);
  134. LDUMP(head.yMax);
  135. LDUMP(head.indexToLocFormat);
  136. Seek("maxp", is);
  137. maxp.Serialize(is);
  138. LDUMP(maxp.numGlyphs);
  139. Seek("post", is);
  140. post.Serialize(is);
  141. // LLOGHEXLDUMP(is.s, is.lim - is.s);
  142. LDUMP((post.format >> 16));
  143. LDUMP(post.italicAngle);
  144. LDUMP(post.italicAngle);
  145. LDUMP(post.underlinePosition);
  146. LDUMP(post.underlineThickness);
  147. LDUMP(post.italicAngle);
  148. if(justcheck)
  149. return true;
  150. Seek("hhea", is);
  151. hhea.Serialize(is);
  152. LDUMP(hhea.ascent);
  153. LDUMP(hhea.descent);
  154. LDUMP(hhea.lineGap);
  155. LDUMP(hhea.advanceWidthMax);
  156. LDUMP(hhea.numOfLongHorMetrics);
  157. if(hhea.numOfLongHorMetrics > maxp.numGlyphs)
  158. Error();
  159. glyphinfo.SetCount(maxp.numGlyphs);
  160. s = Seek("hmtx");
  161. int aw = 0;
  162. for(i = 0; i < hhea.numOfLongHorMetrics; i++) {
  163. aw = glyphinfo[i].advanceWidth = (uint16)Read16(s);
  164. glyphinfo[i].leftSideBearing = (int16)Read16(s);
  165. }
  166. for(; i < maxp.numGlyphs; i++) {
  167. glyphinfo[i].advanceWidth = aw;
  168. glyphinfo[i].leftSideBearing = (int16)Read16(s);
  169. }
  170. s = Seek("loca");
  171. for(i = 0; i < maxp.numGlyphs; i++)
  172. if(head.indexToLocFormat) {
  173. glyphinfo[i].offset = Peek32(s, i);
  174. glyphinfo[i].size = Peek32(s, i + 1) - glyphinfo[i].offset;
  175. }
  176. else {
  177. glyphinfo[i].offset = 2 * (word)Peek16(s, i);
  178. glyphinfo[i].size = 2 * (word)Peek16(s, i + 1) - glyphinfo[i].offset;
  179. }
  180. for(i = 0; i < maxp.numGlyphs; i++)
  181. LLOG(i << " advance: " << glyphinfo[i].advanceWidth << ", left: " << glyphinfo[i].leftSideBearing
  182. << ", offset: " << glyphinfo[i].offset << ", size: " << glyphinfo[i].size);
  183. s = Seek("cmap");
  184. const char *p = s;
  185. p += 2;
  186. n = Read16(p);
  187. while(n--) {
  188. int pid = Read16(p);
  189. int psid = Read16(p);
  190. int offset = Read32(p);
  191. LLOG("cmap pid: " << pid << " psid: " << psid << " format: " << Peek16(s + offset));
  192. //Test with Symbol font !!!; improve - Unicode first, 256 bytes later..., symbol...
  193. if(symbol) {
  194. if(pid == 1 && psid == 0 && Peek16(s + offset) == 0) {
  195. LLOG("Reading symbol table");
  196. p = s + offset + 6;
  197. for(int i = 0; i < 256; i++)
  198. SetGlyph(i, (byte)p[i]);
  199. break;
  200. }
  201. }
  202. else
  203. if(pid == 3 && psid == 1) {
  204. p = s + offset;
  205. n = Peek16(p + 6) >> 1;
  206. LLOG("Found UNICODE encoding, offset " << offset << ", segments " << n);
  207. const char *seg_end = p + 14;
  208. const char *seg_start = seg_end + 2 * n + 2;
  209. const char *idDelta = seg_start + 2 * n;
  210. const char *idRangeOffset = idDelta + 2 * n;
  211. for(int i = 0; i < n; i++) {
  212. int start = Peek16(seg_start, i);
  213. int end = Peek16(seg_end, i);
  214. int delta = Peek16(idDelta, i);
  215. int ro = Peek16(idRangeOffset, i);
  216. if (ro && delta == 0) {
  217. LLOG("RangeOffset start: " << start << ", end: " << end << ", delta: " << (int16)delta);
  218. LLOG("ro " << ro);
  219. const char *q = idRangeOffset + 2 * i + ro;
  220. for(int c = start; c <= end; c++) {
  221. SetGlyph(c, (word)Read16(q));
  222. }
  223. }
  224. else {
  225. LLOG("start: " << start << ", end: " << end << ", delta: " << (int16)delta);
  226. for(int c = start; c <= end; c++)
  227. SetGlyph(c, c + delta);
  228. }
  229. }
  230. break;
  231. }
  232. }
  233. const char *strings = Seek("name");
  234. s = strings + 2;
  235. int count = Read16(s);
  236. strings += (word)Read16(s);
  237. for(int i = 0; i < count; i++) {
  238. int platform = Read16(s);
  239. s += 4;
  240. if(Read16(s) == 6) {
  241. int len = Read16(s);
  242. int offset = Read16(s);
  243. if(platform == 1)
  244. ps_name = String(strings + offset, len);
  245. else {
  246. s = strings + offset;
  247. len >>= 1;
  248. while(len--)
  249. ps_name.Cat(Read16(s));
  250. }
  251. break;
  252. }
  253. s += 4;
  254. }
  255. LDUMP(ps_name);
  256. }
  257. catch(Fail) {
  258. return false;
  259. }
  260. catch(TTFStream::Fail) {
  261. return false;
  262. }
  263. return true;
  264. }
  265. TTFReader::TTFReader()
  266. {
  267. Reset();
  268. }
  269. TTFReader::~TTFReader()
  270. {
  271. Free();
  272. }
  273. END_UPP_NAMESPACE