bdf_glyph.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. #include "bdf_glyph.h"
  6. bg_t *bg_Open(void)
  7. {
  8. bg_t *bg;
  9. bg = (bg_t *)malloc(sizeof(bg_t));
  10. if ( bg != NULL )
  11. {
  12. bg->encoding = 0;
  13. bg->map_to = -1;
  14. bg->bitmap_data = NULL;
  15. bg->target_data = NULL;
  16. bg->target_max = 0;
  17. bg->target_cnt = 0;
  18. bg->shift_x = 0;
  19. bg->is_excluded_from_kerning = 0;
  20. return bg;
  21. }
  22. return NULL;
  23. }
  24. void bg_Close(bg_t *bg)
  25. {
  26. if ( bg->bitmap_data != NULL )
  27. free(bg->bitmap_data);
  28. if ( bg->target_data != NULL )
  29. free(bg->target_data);
  30. bg->bitmap_data = NULL;
  31. bg->target_data =NULL;
  32. bg->target_max = 0;
  33. bg->target_cnt = 0;
  34. bg->target_bit_pos = 0;
  35. bg->encoding = 0;
  36. free(bg);
  37. }
  38. static int bg_extend_target_data(bg_t *bg)
  39. {
  40. int extend = 16;
  41. int i;
  42. void *ptr;
  43. if ( bg->target_data == NULL )
  44. {
  45. ptr = malloc(extend*sizeof(uint8_t));
  46. bg->target_max = 0;
  47. }
  48. else
  49. {
  50. ptr = realloc(bg->target_data, (bg->target_max + extend)*sizeof(uint8_t));
  51. }
  52. if ( ptr == NULL )
  53. return 0;
  54. bg->target_data = (uint8_t *)ptr;
  55. for( i = bg->target_max; i < bg->target_max + extend; i++ )
  56. bg->target_data[i] = 0;
  57. bg->target_max += extend;
  58. return 1;
  59. }
  60. int bg_AddTargetData(bg_t *bg, uint8_t data)
  61. {
  62. while( bg->target_max <= bg->target_cnt )
  63. if ( bg_extend_target_data(bg) == 0 )
  64. return -1;
  65. bg->target_data[bg->target_cnt] = data;
  66. bg->target_cnt++;
  67. return bg->target_cnt-1;
  68. }
  69. void bg_ClearTargetData(bg_t *bg)
  70. {
  71. int i;
  72. for( i = 0; i < bg->target_max; i++ )
  73. bg->target_data[i] = 0;
  74. bg->target_cnt = 0;
  75. bg->target_bit_pos = 0;
  76. }
  77. /*
  78. Desc:
  79. Output a field to the target bitstream. The field size in bits is given by "cnt" and
  80. the value of the field is "val".
  81. Args:
  82. cnt: Fieldsize in bits, must be lower or equal to 8
  83. val: The value (content) of the field. Side condition: val < (1<<cnt) && val >= 0
  84. */
  85. int bg_AddTargetBits(bg_t *bg, unsigned cnt, unsigned val)
  86. {
  87. assert( val < (1<<cnt) );
  88. while( bg->target_max <= bg->target_cnt+1 )
  89. if ( bg_extend_target_data(bg) == 0 )
  90. return 0;
  91. bg->target_data[bg->target_cnt] |= (val << bg->target_bit_pos);
  92. if ( bg->target_bit_pos+cnt >= 8 )
  93. {
  94. bg->target_cnt++;
  95. val >>= 8-bg->target_bit_pos;
  96. bg->target_data[bg->target_cnt] = val;
  97. bg->target_bit_pos+=cnt;
  98. bg->target_bit_pos-=8;
  99. }
  100. else
  101. {
  102. bg->target_bit_pos+=cnt;
  103. }
  104. return 1;
  105. }
  106. int bg_FlushTargetBits(bg_t *bg)
  107. {
  108. while( bg->target_bit_pos != 0 )
  109. if ( bg_AddTargetBits(bg, 1, 0) == 0 )
  110. return 0;
  111. return 1;
  112. }
  113. int bg_SetBitmapSizeInBytes(bg_t *bg, size_t bytes)
  114. {
  115. if ( bg->bitmap_data != NULL )
  116. free(bg->bitmap_data);
  117. bg->bitmap_data = (uint8_t *)malloc(bytes);
  118. if ( bg->bitmap_data == NULL )
  119. return 0;
  120. memset(bg->bitmap_data, 0, bytes);
  121. return 1;
  122. }
  123. int bg_SetBitmapSize(bg_t *bg, int w, int h)
  124. {
  125. return bg_SetBitmapSizeInBytes(bg, w*h);
  126. }
  127. void bg_SetBitmapPixel(bg_t *bg, int x, int y, int value)
  128. {
  129. static long last_encoding = 0xffffffff;
  130. static long biggest_x = -1;
  131. if ( x >= bg->bitmap_width || y >= bg->bitmap_height )
  132. {
  133. if ( last_encoding != bg->encoding )
  134. {
  135. biggest_x = x;
  136. printf("Glyph size problem: ");
  137. printf("encoding=%ld/0x%lx, ", bg->encoding, bg->encoding);
  138. printf("width=%d, height=%d, ", bg->bitmap_width, bg->bitmap_height);
  139. printf("requested position x=%d, y=%d (use BBX %d ...?)\n", x, y, x+1);
  140. last_encoding = bg->encoding;
  141. }
  142. else if ( biggest_x < x )
  143. {
  144. biggest_x = x;
  145. printf("Glyph size problem: ");
  146. printf("encoding=%ld/0x%lx, ", bg->encoding, bg->encoding);
  147. printf("width=%d, height=%d, ", bg->bitmap_width, bg->bitmap_height);
  148. printf("requested position x=%d, y=%d (use BBX %d ...?)\n", x, y, x+1);
  149. }
  150. }
  151. assert( x < ((bg->bitmap_width+7)/8)*8 );
  152. assert( y < bg->bitmap_height );
  153. assert( x >= 0 );
  154. assert( y >= 0 );
  155. bg->bitmap_data[y*bg->bitmap_width + x] = value;
  156. }
  157. int bg_GetBitmapPixel(bg_t *bg, int x, int y)
  158. {
  159. if ( x >= bg->bitmap_width )
  160. return 0;
  161. if ( y >= bg->bitmap_height )
  162. return 0;
  163. if ( x < 0 )
  164. return 0;
  165. if ( y < 0 )
  166. return 0;
  167. return bg->bitmap_data[y*bg->bitmap_width + x];
  168. }
  169. /*
  170. Return a pixel with the provided bbx
  171. Coordinates are within the bbx.
  172. */
  173. int bg_GetBBXPixel(bg_t *bg, int x, int y)
  174. {
  175. /* glyph rectangle */
  176. long glyph_x0, glyph_x1, glyph_y0, glyph_y1;
  177. /* local bitmap coordinates */
  178. long bitmap_x, bitmap_y;
  179. /* perform x offset alignment (used in BDF_BBX_MODE_HEIGHT mode only)*/
  180. x += bg->shift_x;
  181. /* calculate the rectangle for the glyph */
  182. glyph_x0 = bg->bbx.x;
  183. glyph_y0 = bg->bbx.y;
  184. glyph_x1 = bg->bbx.x+bg->bbx.w;
  185. glyph_y1 = bg->bbx.y+bg->bbx.h;
  186. if ( x < glyph_x0 )
  187. return 0;
  188. if ( x >= glyph_x1 )
  189. return 0;
  190. if ( y < glyph_y0 )
  191. return 0;
  192. if ( y >= glyph_y1 )
  193. return 0;
  194. bitmap_x = x - glyph_x0;
  195. bitmap_y = bg->bbx.h - 1 - ( y - glyph_y0);
  196. return bg_GetBitmapPixel( bg, bitmap_x, bitmap_y );
  197. }
  198. void bg_ShowBitmap(bg_t *bg, bbx_t *bbx)
  199. {
  200. int x, y;
  201. if ( bbx == NULL )
  202. bbx = &(bg->bbx);
  203. printf("Encoding %ld, mapped to %ld, w=%ld, h=%ld, x=%ld, y=%ld\n", bg->encoding, bg->map_to, bg->bbx.w, bg->bbx.h, bg->bbx.x, bg->bbx.y);
  204. for( y = bbx->y+bbx->h-1; y >= bbx->y; y--)
  205. {
  206. printf("%03d ", y);
  207. for( x = bbx->x; x < bbx->x + bbx->w; x++)
  208. {
  209. if ( bg_GetBBXPixel(bg, x, y) == 0 )
  210. {
  211. printf(" .");
  212. }
  213. else
  214. {
  215. printf(" #");
  216. }
  217. }
  218. printf("\n");
  219. }
  220. }
  221. int bg_IsColZero(bg_t *bg, int x)
  222. {
  223. int y;
  224. for( y = 0; y < bg->bitmap_height; y++ )
  225. {
  226. if ( bg_GetBitmapPixel(bg, x, y) != 0 )
  227. return 0;
  228. }
  229. return 1;
  230. }
  231. int bg_IsRowZero(bg_t *bg, int y)
  232. {
  233. int x;
  234. for( x = 0; x < bg->bitmap_width; x++ )
  235. {
  236. if ( bg_GetBitmapPixel(bg, x, y) != 0 )
  237. return 0;
  238. }
  239. return 1;
  240. }
  241. void bg_DeleteFirstCol(bg_t *bg)
  242. {
  243. int x,y;
  244. for( y = 0; y < bg->bitmap_height; y++ )
  245. for( x = 0; x+1 < bg->bitmap_width; x++ )
  246. {
  247. bg_SetBitmapPixel(bg, x, y, bg_GetBitmapPixel(bg, x+1, y));
  248. }
  249. }
  250. void bg_DeleteFirstRow(bg_t *bg)
  251. {
  252. int x,y;
  253. for( y = 0; y+1 < bg->bitmap_height; y++ )
  254. for( x = 0; x < bg->bitmap_width; x++ )
  255. {
  256. bg_SetBitmapPixel(bg, x, y, bg_GetBitmapPixel(bg, x, y+1));
  257. }
  258. }
  259. void bg_ReduceGlyph(bg_t *bg)
  260. {
  261. //long w;
  262. /* assign bitmap dimension (should be done already) */
  263. //bg->bbx.w = bg->bitmap_width;
  264. //bg->bbx.h = bg->bitmap_height;
  265. /* do not assign x,y because they are already set correctly */
  266. //w = bg->bbx.w;
  267. while( bg->bbx.w > 0 )
  268. {
  269. if ( bg_IsColZero(bg, bg->bbx.w-1) == 0 )
  270. break;
  271. bg->bbx.w--;
  272. }
  273. while( bg->bbx.h > 0 )
  274. {
  275. if ( bg_IsRowZero(bg, bg->bbx.h-1) == 0 )
  276. break;
  277. bg->bbx.y++;
  278. bg->bbx.h--;
  279. }
  280. while( bg->bbx.w > 0)
  281. {
  282. if ( bg_IsColZero(bg, 0) == 0 )
  283. break;
  284. bg_DeleteFirstCol(bg);
  285. bg->bbx.x++;
  286. bg->bbx.w--;
  287. }
  288. while( bg->bbx.h > 0 )
  289. {
  290. if ( bg_IsRowZero(bg, 0) == 0 )
  291. break;
  292. bg_DeleteFirstRow(bg);
  293. bg->bbx.h--;
  294. }
  295. /*
  296. problem: pixel width calculation failes, because a blank at
  297. the end is not calculated correctly.
  298. analysis:
  299. - bbx.w is reduced to 0
  300. - original bbx.w is sometimes identical to dwidth_x (6x10.bdf)
  301. or is 1 (helvR10.bdf)
  302. -the bdf file for helvR10.bdf does not contain any other information then
  303. delta x, so this should be used as bbx.w
  304. solution:
  305. Nothing done on the converter side, but handle this as a special case in the
  306. pixel width calculation
  307. */
  308. //if ( bg->bbx.w == 0 && bg->bbx.h == 0 )
  309. //{
  310. //printf("enc=%ld, new bbx,w=%ld, original width=%ld, dx=%ld\n", bg->encoding, bg->bbx.w, w, bg->dwidth_x);
  311. //printf("enc=%ld, new bbx.w=%ld, original width=%ld, dx=%ld\n", bg->encoding, bg->bbx.w, w, bg->dwidth_x);
  312. //}
  313. }
  314. /*
  315. maximize the provided bbx so that the bbxof the glyph completly is covered by the max bbx
  316. */
  317. int bg_Max(bg_t *bg, bbx_t *max)
  318. {
  319. int r = 0;
  320. /* glyph rectangle */
  321. long glyph_x0, glyph_x1, glyph_y0, glyph_y1;
  322. /* max rectangle */
  323. long max_x0, max_x1, max_y0, max_y1;
  324. // printf("Encoding %ld, mapped to %ld, w=%ld, h=%ld, x=%ld, y=%ld\n", bg->encoding, bg->map_to, bg->bbx.w, bg->bbx.h, bg->bbx.x, bg->bbx.y);
  325. /* calculate the rectangle for the glyph */
  326. glyph_x0 = bg->bbx.x;
  327. glyph_y0 = bg->bbx.y;
  328. glyph_x1 = bg->bbx.x+bg->bbx.w;
  329. glyph_y1 = bg->bbx.y+bg->bbx.h;
  330. /* calculate the rectangle for the max bbx */
  331. max_x0 = max->x;
  332. max_y0 = max->y;
  333. max_x1 = max->x+max->w;
  334. max_y1 = max->y+max->h;
  335. /* maximize the max rectrangle so that the glyph rectangle full fits inside */
  336. if ( max_x0 > glyph_x0 )
  337. {
  338. max_x0 = glyph_x0;
  339. r = 3;
  340. }
  341. /* 28 Mar dwidth_x and x0???? */
  342. if ( max_x0 > bg->dwidth_x ) /* include dwidth_x into the box */
  343. {
  344. max_x0 = bg->dwidth_x; /* is this correct??? */
  345. r = 3;
  346. }
  347. if ( max_x1 < glyph_x1 )
  348. {
  349. r = 1;
  350. max_x1 = glyph_x1;
  351. }
  352. if ( max_y0 > glyph_y0 )
  353. {
  354. r = 4;
  355. max_y0 = glyph_y0;
  356. }
  357. if ( max_y1 < glyph_y1 )
  358. {
  359. r = 2;
  360. max_y1 = glyph_y1;
  361. }
  362. /* reconstruct the max bbx from the max rectangle */
  363. max->x = max_x0;
  364. max->y = max_y0;
  365. max->w = max_x1 - max->x;
  366. max->h = max_y1 - max->y;
  367. return r;
  368. }