fork download
  1. // copyright ◆en3PGsfOXo http://t...content-available-to-author-only...h.net/test/read.cgi/tech/1363042502/
  2.  
  3. #include <windows.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6.  
  7. #define SHOW_MARK 1
  8.  
  9. char *TITLE = "glyf";
  10. BYTE *gflg = "AQv/8AIYH8k5JMkBA/ACCxeSSSQBA/ABDP/4ARLJ+SACEyDkknySAAIDB/8=";
  11. BYTE *glyf = "AAwASAU7AAD/OgAAAAAC2f0ZAAAAAP0n/zoAAAAABdEAxgAAAAD9uALnAAAAAAJI"
  12. "AMYAAAAgAGUEYAIb/MkAAAAA/5kAPv9nADb/zwA0/9AAj//QAFYAAAByAAAA5wBb"
  13. "ADEALAAKAAAAAP8z/6H/2P86/8r/kwAA/uoAAP7IAS0AAAEVAAABEgErAUIA9AAA"
  14. "AOIAAAD1/vgAAP8N/0kAKv//AJT/bQCi/2oAAP9pAAD/Tf9O//T/fAAEAGwBdwAA"
  15. "/0QAAAAABhQAvAAAABgAbwRxAi4AAP7v/uj+xP8VAAD/EwAA/ukBPAAAAREAAAER"
  16. "ARcBPQDtAAAA6wAAARj+w/8+/u8AAADZ/1YA0/9pAAD/ZwAA/1f/LQAA/ycAAP8u"
  17. "AKr/JwCYAAAAlgAAAKsA1wAEACwCPwEd/ub9cf9uAAAArgKPAA0AdwY2BF3+3fuj"
  18. "/1IAAP7hA13+4/yj/1MAAP7aBF0AxAAAAM38nwEXA2EAmwAAAR78nwDCA2EAEwBy"
  19. "A3IDkP/2AAD/1gAK/7EACf/KAAD/qQAA/17/s/+1/8MAAPzn/0QAAAAABF0AvAAA"
  20. "AAD/WwBwAFoAqwBLAFkAAAAxAAAALP/7ACz/+QAhAGQEQwAA/0QAAAAAAHX/r/+6"
  21. "/1D/sv+ZAAD/OAAA/xUBNAAAAREAAACOAFEA3gBFAE4ARABMALUAUABhAAAAWAAA"
  22. "AIj/2wBL/9kAAAHkALwAAP9E+v8AAAKB/7QAIv+IABr/uQAA/2IAAP9Q/yQAAP82"
  23. "AAD/OQCI/zEAlgAAAFAAAACkAEcACAAhAgMF0f/m+8n/VgAA/+QENwDW+i//NAAA"
  24. "AAAA0wDMAAA=";
  25. int glyf_len = 0;
  26.  
  27. int b64decode(BYTE *dst, size_t *dst_size, BYTE *src, int src_size)
  28. {
  29. static BYTE b64o[80] = {
  30. 62, 0, 62, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
  31. 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  32. 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
  33. 0, 0, 0, 62, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
  34. 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
  35. int i, words = src_size/4, oversize = *dst_size+2, lasti = oversize/3-1;
  36. if(src_size % 4) return 1;
  37. if(*dst_size < words * 3) return 2;
  38. for(i = 0; i <= lasti; i++){
  39. int j;
  40. BYTE c[4];
  41. for(j = 0; j < sizeof(c); j++)
  42. c[j] = b64o[(src[i * sizeof(c) + j] - '+') % sizeof(b64o)];
  43. dst[i * 3 + 0] = ((c[0] << 2) & 0x00fc) | ((c[1] >> 4) & 0x03);
  44. if(i < lasti || oversize % 3)
  45. dst[i * 3 + 1] = ((c[1] << 4) & 0x00f0) | ((c[2] >> 2) & 0x0f);
  46. if(i < lasti || (oversize % 3) == 2)
  47. dst[i * 3 + 2] = ((c[2] << 6) & 0x00c0) | (c[3] & 0x3f);
  48. }
  49. if(src[src_size - 1] == '='){
  50. --(*dst_size);
  51. if(src[src_size - 2] == '=') --(*dst_size);
  52. }
  53. return 0;
  54. }
  55.  
  56. int initGlyph(BYTE *str)
  57. {
  58. int len = (strlen(str) >> 2) * 3;
  59. if(b64decode(str, &len, str, strlen(str))) return 0;
  60. return len;
  61. }
  62.  
  63. short b2h(BYTE *b)
  64. {
  65. return (short)((b[0] << 8) | b[1]);
  66. }
  67.  
  68. int getGlyphData(BYTE **epoc, BYTE **flags, int **xcoords, int **ycoords,
  69. int *numepoc, char ch)
  70. {
  71. int i, j, k, pos = 0, num = 0, code = 0, fpos = 0, epnum = 0, fnum = 0;
  72. *epoc = *flags = NULL, *xcoords = *ycoords = NULL, *numepoc = 0;
  73. while(pos < glyf_len){
  74. num = b2h(&glyf[pos]), code = b2h(&glyf[pos + 2]);
  75. epnum = gflg[fpos], fnum = (num + 7) / 8;
  76. if(code == ch){
  77. if(!(*epoc = (BYTE *)malloc(*numepoc = epnum))) break;
  78. for(i = 0; i < epnum; ++i) (*epoc)[i] = gflg[fpos + 1 + i];
  79. if(!(*flags = (BYTE *)malloc(num))) break;
  80. for(i = 0, k = 0; i < fnum; ++i){
  81. BYTE b = gflg[fpos + 1 + epnum + i];
  82. BYTE m = 0x80;
  83. for(j = 0; j < 8 - (i == fnum - 1 ? fnum * 8 - num : 0); ++j, m >>= 1)
  84. (*flags)[k++] = b & m ? 1 : 0;
  85. }
  86. break;
  87. }
  88. pos += (num + 1) * 4;
  89. fpos += epnum + fnum + 1;
  90. }
  91. if(!*epoc || !*flags) return 0;
  92. if(!(*xcoords = (int *)malloc(num * sizeof(int)))) return 0;
  93. if(!(*ycoords = (int *)malloc(num * sizeof(int)))) return 0;
  94. for(i = 0; i < num; ++i){
  95. (*xcoords)[i] = (i ? (*xcoords)[i-1] : 0) + b2h(&glyf[pos + (i+1)*4]);
  96. (*ycoords)[i] = (i ? (*ycoords)[i-1] : 0) + b2h(&glyf[pos + (i+1)*4 + 2]);
  97. }
  98. return num;
  99. }
  100.  
  101. int drawGlyph(HDC hdc, int scale, int szx, int szy, int ox, int oy,
  102. int *w, int *h, int ch)
  103. {
  104. BYTE *epoc, *flags;
  105. int *xcoords, *ycoords, numepoc, i, j;
  106. int numflags = getGlyphData(&epoc, &flags, &xcoords, &ycoords, &numepoc, ch);
  107. *w = 80, *h = 160;
  108. if(numflags){
  109. for(j = 0; j < numepoc; ++j){
  110. int pflg, px, py, k = j ? epoc[j - 1] + 1 : 0;
  111. for(i = k; i <= epoc[j]; ++i){
  112. int flg = flags[i], x = xcoords[i], y = ycoords[i];
  113. if(SHOW_MARK){
  114. int r = i == k ? 4 : 3;
  115. COLORREF col = flg & 0x01 ? RGB(0, 0, 255) : RGB(255, 0, 0);
  116. HPEN hpen = CreatePen(PS_SOLID, 1, col);
  117. HPEN hopen = (HPEN)SelectObject(hdc, hpen);
  118. HBRUSH hbrush, hobrush;
  119. if(i == k) hbrush = CreateSolidBrush(RGB(0, 255, 0));
  120. else hbrush = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
  121. hobrush = (HBRUSH)SelectObject(hdc, hbrush);
  122. Ellipse(hdc, ox - r + x / scale, szy - (oy - r + y / scale),
  123. ox + r + x / scale, szy - (oy + r + y / scale));
  124. SelectObject(hdc, hobrush);
  125. if(i == k) DeleteObject(hbrush);
  126. SelectObject(hdc, hopen);
  127. DeleteObject(hpen);
  128. }
  129. if(i == k && !(flg & 0x01))
  130. MessageBox(NULL, "off curve first", TITLE, MB_ICONEXCLAMATION|IDOK);
  131. if(i != k){
  132. int n = i == epoc[j] ? k : i + 1;
  133. int nflg = flags[n], nx = xcoords[n], ny = ycoords[n];
  134. if(curve(hdc, scale, szx, szy, ox, oy,
  135. &pflg, &px, &py, flg, x, y, nflg, nx, ny)) continue;
  136. }
  137. pflg = flg, px = x, py = y;
  138. }
  139. curve(hdc, scale, szx, szy, ox, oy, &pflg, &px, &py,
  140. flags[k], xcoords[k], ycoords[k],
  141. flags[k + 1], xcoords[k + 1], ycoords[k + 1]);
  142. }
  143. }
  144. if(epoc) free(epoc);
  145. if(flags) free(flags);
  146. if(xcoords) free(xcoords);
  147. if(ycoords) free(ycoords);
  148. return 0;
  149. }
  150.  
  151. int bezier(HDC hdc, int scale, int szx, int szy, int ox, int oy,
  152. int px, int py, int x, int y, int nx, int ny)
  153. {
  154. int t, m = ((nx - px) * (nx - px) + (ny - py) * (ny - py)) / 5000;
  155. MoveToEx(hdc, ox + px / scale, szy - (oy + py / scale), NULL);
  156. for(t = 1; t < m; ++t){
  157. float f = t / (float)m;
  158. float a[] = {(1 - f) * (1 - f), 2 * f * (1 - f), f * f};
  159. int tx = a[0] * px + a[1] * x + a[2] * nx;
  160. int ty = a[0] * py + a[1] * y + a[2] * ny;
  161. LineTo(hdc, ox + tx / scale, szy - (oy + ty / scale));
  162. }
  163. LineTo(hdc, ox + nx / scale, szy - (oy + ny / scale));
  164. return 0;
  165. }
  166.  
  167. int curve(HDC hdc, int scale, int szx, int szy, int ox, int oy,
  168. int *pflg, int *px, int *py, int flg, int x, int y, int nflg, int nx, int ny)
  169. {
  170. if(flg & 0x01){
  171. if(!(*pflg & 0x01))
  172. MessageBox(NULL, "off curve bug", TITLE, MB_ICONEXCLAMATION|IDOK);
  173. stroke(hdc, scale, szx, szy, ox, oy, *px, *py, x, y);
  174. return 0;
  175. }
  176. if(nflg & 0x01){
  177. bezier(hdc, scale, szx, szy, ox, oy, *px, *py, x, y, nx, ny);
  178. *pflg = nflg, *px = nx, *py = ny;
  179. return !0;
  180. }else{
  181. int mx = (x + nx) / 2, my = (y + ny) / 2;
  182. bezier(hdc, scale, szx, szy, ox, oy, *px, *py, x, y, mx, my);
  183. *pflg = 1, *px = mx, *py = my;
  184. return !0;
  185. }
  186. }
  187.  
  188. int stroke(HDC hdc, int scale, int szx, int szy, int ox, int oy,
  189. int xs, int ys, int xe, int ye)
  190. {
  191. POINT p;
  192. MoveToEx(hdc, ox + xs / scale, szy - (oy + ys / scale), &p);
  193. LineTo(hdc, ox + xe / scale, szy - (oy + ye / scale));
  194. return 0;
  195. }
  196.  
  197. int drawStrokes(int scale, int ofx, int ofy, int spx, int spy, char *str)
  198. {
  199. int szx, szy, ox = ofx, oy = ofy;
  200. char *p;
  201. HWND hwnd = GetDesktopWindow();
  202. HDC hdc = GetDC(hwnd);
  203. HPEN hpen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
  204. HPEN hopen = (HPEN)SelectObject(hdc, hpen);
  205. RECT rc;
  206. GetClientRect(hwnd, &rc);
  207. szx = rc.right - rc.left, szy = rc.bottom - rc.top;
  208. for(p = str; *p; ++p){
  209. int w, h;
  210. drawGlyph(hdc, scale, szx, szy, ox, oy, &w, &h, *p);
  211. if(*p == '\n') ox = ofx, oy -= h + spy;
  212. else ox += w + spx;
  213. }
  214. SelectObject(hdc, hopen);
  215. DeleteObject(hpen);
  216. ReleaseDC(hwnd, hdc);
  217. return 0;
  218. }
  219.  
  220. int main(int ac, char **av)
  221. {
  222. if(!initGlyph(gflg)) fprintf(stderr, "error 1");
  223. if(!(glyf_len = initGlyph(glyf))) fprintf(stderr, "error 2");
  224. drawStrokes(10, 120, 480, 40, 40, "Hello,\nworld!");
  225. return 0;
  226. }
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty