bmf2bdf.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. /*
  2. bmf2bdf.c
  3. Converter for bmf font file format to bdf file format
  4. bmf: http://bmf.php5.cz/
  5. bdf: https://en.wikipedia.org/wiki/Glyph_Bitmap_Distribution_Format
  6. Copyright (c) 2022, olikraus@gmail.com
  7. All rights reserved.
  8. Redistribution and use in source and binary forms, with or without modification,
  9. are permitted provided that the following conditions are met:
  10. * Redistributions of source code must retain the above copyright notice, this list
  11. of conditions and the following disclaimer.
  12. * Redistributions in binary form must reproduce the above copyright notice, this
  13. list of conditions and the following disclaimer in the documentation and/or other
  14. materials provided with the distribution.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  16. CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  17. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  20. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  25. STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  27. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. Features
  29. - Convert .bmf to .bdf, result will be written to stdout
  30. - Converts DOS codepage to Unicode (-u option)
  31. - Convert monospaced proportional font back to none-monospaced font (-p)
  32. - Optional glyph spacing with -x
  33. - Optional baseline adjustment with -y
  34. - Brightness threshold with -l
  35. - Generated BDF can be modified with gbdfed and FontForge
  36. (http://sofia.nmsu.edu/~mleisher/Software/gbdfed/, https://github.com/andrewshadura/gbdfed)
  37. Example:
  38. http://bmf.php5.cz/index.php?font=goth16
  39. bmf2bdf -u -p -y -2 goth16.bmf > goth16.bdf
  40. or
  41. bmf2bdf -u -p -x 1 -y -2 goth16.bmf > goth16.bdf
  42. */
  43. #include <stdio.h>
  44. #include <stdint.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. /* http://bmf.php5.cz/index.php?page=format */
  48. //uint8_t threshold = 128; // gray level threshold
  49. FILE *bdf_fp = NULL;
  50. /*
  51. option "-p"
  52. default: Use the shift value from bmf format for the BDF DWIDTH property
  53. "-p": Calculate the bdf DWIDTH from width, relx and addSpace vales.
  54. This will force a none-fixed = proportional font
  55. */
  56. int optionForceProportional = 0;
  57. /*
  58. option "-u"
  59. default: No glyph number mapping
  60. "-u": Apply dos to unicode translation
  61. */
  62. int optionUnicodeMapping = 0;
  63. /*
  64. option "-x #"
  65. default: Do not add any extra space
  66. "-x #": Add # pixel extra space between chars, might be useful for -p
  67. */
  68. int optionAddExtraSpace = 0;
  69. /*
  70. option "-y #"
  71. default: Do not shift chars vertically
  72. "-y #": Vertical shift of all glyphs (useful to adjust baseline, # can be negative);
  73. */
  74. int optionShiftY = 0;
  75. /*
  76. options "-l #" "-h #"
  77. default: 0 ... 255
  78. Specified the low and high gray color range for pixel which should appear as set.
  79. */
  80. int optionGrayLow = 0;
  81. int optionGrayHigh = 255;
  82. int16_t lineHeight;
  83. int16_t sizeOver;
  84. int16_t sizeUnder;
  85. int16_t addSpace;
  86. int16_t sizeInner;
  87. int16_t usedColors;
  88. int16_t highestColor;
  89. int16_t alphaBits;
  90. int16_t extraPalettes;
  91. int16_t reserved;
  92. int16_t numColors;
  93. uint8_t titleLength;
  94. uint16_t asciiChars;
  95. uint8_t whichChar;
  96. uint8_t palette[256*3];
  97. char title[256+2];
  98. int8_t tablo[5];
  99. #define BITMAP_SIZE (256*256)
  100. uint8_t bitmap[BITMAP_SIZE];
  101. uint32_t dos2unicode[256];
  102. int totalGlyphSize = 0;
  103. int cntGlyphSize = 0;
  104. int averageGlyphSize = 0;
  105. void write_bdf_header(void)
  106. {
  107. fprintf(bdf_fp, "STARTFONT 2.1\n");
  108. fprintf(bdf_fp, "FONT");
  109. fprintf(bdf_fp, " \"%s\"\n", title);
  110. fprintf(bdf_fp, "SIZE 16 75 75\n");
  111. fprintf(bdf_fp, "FONTBOUNDINGBOX 16 16 0 0\n");
  112. fprintf(bdf_fp, "STARTPROPERTIES 3\n");
  113. fprintf(bdf_fp, "COPYRIGHT \"http://bmf.php5.cz\"\n");
  114. fprintf(bdf_fp, "FONT_ASCENT %d\n", -sizeOver);
  115. fprintf(bdf_fp, "FONT_DESCENT %d\n", sizeUnder);
  116. fprintf(bdf_fp, "ENDPROPERTIES\n");
  117. fprintf(bdf_fp, "CHARS %d\n", asciiChars);
  118. }
  119. uint8_t get_pixel(int x, int y)
  120. {
  121. int width, height;
  122. int intensity;
  123. uint16_t idx;
  124. width = (uint8_t)tablo[0];
  125. height = (uint8_t)tablo[1];
  126. if ( x < 0 )
  127. return 0;
  128. if ( x >= width )
  129. return 0;
  130. if ( y < 0 )
  131. return 0;
  132. if ( y >= height )
  133. return 0;
  134. idx = bitmap[x+y*width];
  135. if ( idx == 0 )
  136. return 0;
  137. intensity = (palette[(idx-1)*3]+palette[(idx-1)*3+1]+palette[(idx-1)*3+2])/3;
  138. if ( intensity >= optionGrayLow && intensity <= optionGrayHigh )
  139. return 1;
  140. return 0;
  141. }
  142. uint8_t get_pixel_byte(int x, int y)
  143. {
  144. uint8_t b = 0;
  145. int i;
  146. for( i = 0; i < 8; i++ )
  147. {
  148. b <<= 1;
  149. b |= get_pixel(x + i,y);
  150. }
  151. return b;
  152. }
  153. void write_4bit(int x)
  154. {
  155. if ( bdf_fp == NULL )
  156. return;
  157. if ( x < 10 )
  158. fprintf(bdf_fp, "%c", x + '0' );
  159. else
  160. fprintf(bdf_fp, "%c", x - 10 + 'a' );
  161. }
  162. void write_byte(int x)
  163. {
  164. write_4bit(x >> 4);
  165. write_4bit(x & 15);
  166. }
  167. void write_bdf_bitmap(uint32_t encoding)
  168. {
  169. int x, y;
  170. int width, height, relx, rely;
  171. int dwidth;
  172. width = (uint8_t)tablo[0];
  173. height = (uint8_t)tablo[1];
  174. relx = (int8_t)tablo[2];
  175. rely = (int8_t)tablo[3];
  176. dwidth = tablo[4]+addSpace;
  177. if ( optionForceProportional )
  178. {
  179. if ( width == 0 )
  180. dwidth = averageGlyphSize + relx + addSpace;
  181. else
  182. dwidth = width + relx + addSpace;
  183. }
  184. dwidth+=optionAddExtraSpace;
  185. if ( bdf_fp == NULL )
  186. return;
  187. fprintf(bdf_fp, "STARTCHAR %u\n", encoding);
  188. fprintf(bdf_fp, "ENCODING %u\n", encoding);
  189. fprintf(bdf_fp, "DWIDTH %d 0\n", dwidth);
  190. //fprintf(bdf_fp, "BBX %d %d %d %d\n", width, height, relx, sizeOver+rely);
  191. fprintf(bdf_fp, "BBX %d %d %d %d\n",
  192. width, height, relx, -(sizeOver+height+rely)+optionShiftY);
  193. fprintf(bdf_fp, "BITMAP\n");
  194. for( y = 0; y < height; y++ )
  195. {
  196. x = 0;
  197. while( x < width )
  198. {
  199. write_byte(get_pixel_byte(x,y));
  200. x+=8;
  201. }
  202. fprintf(bdf_fp, "\n" );
  203. }
  204. fprintf(bdf_fp, "ENDCHAR\n");
  205. encoding++;
  206. }
  207. uint16_t readWord(FILE *file)
  208. {
  209. uint16_t l, h;
  210. l = (uint8_t)fgetc(file);
  211. h = (uint8_t)fgetc(file);
  212. return h*256+l;
  213. }
  214. int processBMF(const char *filename, int isAnalyze)
  215. {
  216. FILE *file = fopen(filename, "rb");
  217. static int8_t buffer[18];
  218. int8_t version;
  219. uint8_t w, h;
  220. //uint8_t x, y;
  221. uint16_t bitmapSize;
  222. int i;
  223. if ( fread(buffer, 17, 1, file) != 1 )
  224. return fclose(file), 0;
  225. version = buffer[4];
  226. if (strncmp((char *)buffer, "\xE1\xE6\xD5\x1A", 4) != 0 || (version != 0x11 && version != 0x12))
  227. {
  228. return fclose(file), 0; // not a BMF, version 1.1 or 1.2
  229. }
  230. lineHeight = buffer[5];
  231. sizeOver = buffer[6];
  232. sizeUnder = buffer[7];
  233. addSpace = buffer[8];
  234. sizeInner = buffer[9];
  235. usedColors = buffer[10];
  236. highestColor = buffer[11];
  237. alphaBits = buffer[12];
  238. extraPalettes = buffer[13];
  239. reserved = buffer[14];
  240. numColors = buffer[16];
  241. //printf("numColors=%d\n", (int)numColors);
  242. if ( fread(palette, numColors * 3, 1, file) != 1 )
  243. return fclose(file), 0;
  244. for (i = 0; i < numColors * 3; i++)
  245. {
  246. palette[i] *= 4; // stretch 0..63 values to 0..255
  247. }
  248. /*
  249. for (i = 0; i < numColors ; i++)
  250. {
  251. uint8_t intensity = (palette[i*3]+palette[i*3+1]+palette[i*3+2])/3;
  252. printf("color %d: %d %d %d --> %d\n", i,
  253. palette[i*3], palette[i*3+1], palette[i*3+2], intensity);
  254. }
  255. */
  256. titleLength = (uint8_t)fgetc(file);
  257. if ( fread(title, titleLength, 1, file) != 1 )
  258. return fclose(file), 0;
  259. title[titleLength] = '\0';
  260. //printf("title=%s\n", title);
  261. asciiChars = readWord(file);
  262. //printf("asciiChars=%d\n", (int)asciiChars);
  263. if ( isAnalyze == 0 )
  264. {
  265. write_bdf_header();
  266. }
  267. for (i = 0; i < asciiChars; i++)
  268. {
  269. memset(bitmap, 0, BITMAP_SIZE);
  270. whichChar = (uint8_t)fgetc(file);
  271. //printf("whichChar=%d\n", (int)whichChar);
  272. if ( fread(tablo, 5, 1, file) != 1 )
  273. return fclose(file), 0;
  274. w = tablo[0];
  275. h = tablo[1];
  276. bitmapSize = ((uint16_t)w*(uint16_t)h);
  277. if ( bitmapSize > 0 )
  278. {
  279. if ( fread(bitmap, bitmapSize, 1, file) != 1 )
  280. return fclose(file), 0;
  281. }
  282. /*
  283. for( y = 0; y < h; y++)
  284. {
  285. for( x = 0; x < w; x++)
  286. {
  287. uint16_t idx = bitmap[x+y*w];
  288. if ( idx == 0 ) // color 0 is transparent
  289. {
  290. printf(" ");
  291. }
  292. else
  293. {
  294. uint8_t intensity = (palette[(idx-1)*3]+palette[(idx-1)*3+1]+palette[(idx-1)*3+2])/3;
  295. if ( intensity < threshold )
  296. {
  297. printf(" ");
  298. }
  299. else
  300. {
  301. printf("*");
  302. }
  303. }
  304. }
  305. printf("\n");
  306. }
  307. */
  308. if ( isAnalyze )
  309. {
  310. if ( (whichChar >= 'A' && whichChar <= 'Z') || (whichChar >= 'a' && whichChar <= 'z') )
  311. {
  312. totalGlyphSize += w;
  313. cntGlyphSize++;
  314. averageGlyphSize = ((totalGlyphSize*2) / (cntGlyphSize*3));
  315. }
  316. }
  317. else
  318. {
  319. if ( optionUnicodeMapping )
  320. {
  321. write_bdf_bitmap(dos2unicode[whichChar]);
  322. }
  323. else
  324. {
  325. write_bdf_bitmap(whichChar);
  326. }
  327. //write_bdf_bitmap(whichChar);
  328. }
  329. }
  330. /*
  331. if (version >= 0x12) { // next goes for version 1.2 only
  332. unicodeChars = fread(file, 4);
  333. for (i = 0; i < unicodeChars; i++) {
  334. whichChar = fread(file, 4);
  335. tablo[whichChar] = fread(file, 5);
  336. if (bitmapSize = tablo[whichChar][0] * tablo[whichChar][1]) {
  337. bitmaps[whichChar] = fread(file, bitmapSize);
  338. }
  339. }
  340. numKerningPairs = fread(file, 4);
  341. kerningPairs = [];
  342. for (i = 0; i < numKerningPairs; i++) {
  343. fread(file, buffer, 10);
  344. kerningPairs []= buffer;
  345. }
  346. }
  347. */
  348. fclose(file);
  349. if ( !isAnalyze )
  350. {
  351. fprintf(bdf_fp, "ENDFONT\n");
  352. }
  353. return 1;
  354. }
  355. void initDos2Unicode(void)
  356. {
  357. dos2unicode[0x00]=0x0000; //NULL
  358. dos2unicode[0x01]=0x263A; //START OF HEADING
  359. dos2unicode[0x02]=0x263B; //START OF TEXT
  360. dos2unicode[0x03]=0x2665; //END OF TEXT
  361. dos2unicode[0x04]=0x2666; //END OF TRANSMISSION
  362. dos2unicode[0x05]=0x2663; //ENQUIRY
  363. dos2unicode[0x06]=0x2660; //ACKNOWLEDGE
  364. dos2unicode[0x07]=0x2022; //BELL
  365. dos2unicode[0x08]=0x25D8; //BACKSPACE
  366. dos2unicode[0x09]=0x25CB; //HORIZONTAL TABULATION
  367. dos2unicode[0x0a]=0x25D9; //LINE FEED
  368. dos2unicode[0x0b]=0x2642; //VERTICAL TABULATION
  369. dos2unicode[0x0c]=0x2640; //FORM FEED
  370. dos2unicode[0x0d]=0x266A; //CARRIAGE RETURN
  371. dos2unicode[0x0e]=0x266B; //SHIFT OUT
  372. dos2unicode[0x0f]=0x263C; //SHIFT IN
  373. dos2unicode[0x10]=0x25BA; //DATA LINK ESCAPE
  374. dos2unicode[0x11]=0x25C4; //DEVICE CONTROL ONE
  375. dos2unicode[0x12]=0x2195; //DEVICE CONTROL TWO
  376. dos2unicode[0x13]=0x203C; //DEVICE CONTROL THREE
  377. dos2unicode[0x14]=0x00B6; //DEVICE CONTROL FOUR
  378. dos2unicode[0x15]=0x00A7; //NEGATIVE ACKNOWLEDGE
  379. dos2unicode[0x16]=0x25AC; //SYNCHRONOUS IDLE
  380. dos2unicode[0x17]=0x21A8; //END OF TRANSMISSION BLOCK
  381. dos2unicode[0x18]=0x2191; //CANCEL
  382. dos2unicode[0x19]=0x2192; //END OF MEDIUM
  383. dos2unicode[0x1a]=0x2190; //SUBSTITUTE
  384. dos2unicode[0x1b]=0x221F; //ESCAPE
  385. dos2unicode[0x1c]=0x2194; //FILE SEPARATOR
  386. dos2unicode[0x1d]=0x25B2; //GROUP SEPARATOR
  387. dos2unicode[0x1e]=0x25BC; //RECORD SEPARATOR
  388. dos2unicode[0x1f]=0x001f; //UNIT SEPARATOR
  389. dos2unicode[0x20]=0x0020; //SPACE
  390. dos2unicode[0x21]=0x0021; //EXCLAMATION MARK
  391. dos2unicode[0x22]=0x0022; //QUOTATION MARK
  392. dos2unicode[0x23]=0x0023; //NUMBER SIGN
  393. dos2unicode[0x24]=0x0024; //DOLLAR SIGN
  394. dos2unicode[0x25]=0x0025; //PERCENT SIGN
  395. dos2unicode[0x26]=0x0026; //AMPERSAND
  396. dos2unicode[0x27]=0x0027; //APOSTROPHE
  397. dos2unicode[0x28]=0x0028; //LEFT PARENTHESIS
  398. dos2unicode[0x29]=0x0029; //RIGHT PARENTHESIS
  399. dos2unicode[0x2a]=0x002a; //ASTERISK
  400. dos2unicode[0x2b]=0x002b; //PLUS SIGN
  401. dos2unicode[0x2c]=0x002c; //COMMA
  402. dos2unicode[0x2d]=0x002d; //HYPHEN-MINUS
  403. dos2unicode[0x2e]=0x002e; //FULL STOP
  404. dos2unicode[0x2f]=0x002f; //SOLIDUS
  405. dos2unicode[0x30]=0x0030; //DIGIT ZERO
  406. dos2unicode[0x31]=0x0031; //DIGIT ONE
  407. dos2unicode[0x32]=0x0032; //DIGIT TWO
  408. dos2unicode[0x33]=0x0033; //DIGIT THREE
  409. dos2unicode[0x34]=0x0034; //DIGIT FOUR
  410. dos2unicode[0x35]=0x0035; //DIGIT FIVE
  411. dos2unicode[0x36]=0x0036; //DIGIT SIX
  412. dos2unicode[0x37]=0x0037; //DIGIT SEVEN
  413. dos2unicode[0x38]=0x0038; //DIGIT EIGHT
  414. dos2unicode[0x39]=0x0039; //DIGIT NINE
  415. dos2unicode[0x3a]=0x003a; //COLON
  416. dos2unicode[0x3b]=0x003b; //SEMICOLON
  417. dos2unicode[0x3c]=0x003c; //LESS-THAN SIGN
  418. dos2unicode[0x3d]=0x003d; //EQUALS SIGN
  419. dos2unicode[0x3e]=0x003e; //GREATER-THAN SIGN
  420. dos2unicode[0x3f]=0x003f; //QUESTION MARK
  421. dos2unicode[0x40]=0x0040; //COMMERCIAL AT
  422. dos2unicode[0x41]=0x0041; //LATIN CAPITAL LETTER A
  423. dos2unicode[0x42]=0x0042; //LATIN CAPITAL LETTER B
  424. dos2unicode[0x43]=0x0043; //LATIN CAPITAL LETTER C
  425. dos2unicode[0x44]=0x0044; //LATIN CAPITAL LETTER D
  426. dos2unicode[0x45]=0x0045; //LATIN CAPITAL LETTER E
  427. dos2unicode[0x46]=0x0046; //LATIN CAPITAL LETTER F
  428. dos2unicode[0x47]=0x0047; //LATIN CAPITAL LETTER G
  429. dos2unicode[0x48]=0x0048; //LATIN CAPITAL LETTER H
  430. dos2unicode[0x49]=0x0049; //LATIN CAPITAL LETTER I
  431. dos2unicode[0x4a]=0x004a; //LATIN CAPITAL LETTER J
  432. dos2unicode[0x4b]=0x004b; //LATIN CAPITAL LETTER K
  433. dos2unicode[0x4c]=0x004c; //LATIN CAPITAL LETTER L
  434. dos2unicode[0x4d]=0x004d; //LATIN CAPITAL LETTER M
  435. dos2unicode[0x4e]=0x004e; //LATIN CAPITAL LETTER N
  436. dos2unicode[0x4f]=0x004f; //LATIN CAPITAL LETTER O
  437. dos2unicode[0x50]=0x0050; //LATIN CAPITAL LETTER P
  438. dos2unicode[0x51]=0x0051; //LATIN CAPITAL LETTER Q
  439. dos2unicode[0x52]=0x0052; //LATIN CAPITAL LETTER R
  440. dos2unicode[0x53]=0x0053; //LATIN CAPITAL LETTER S
  441. dos2unicode[0x54]=0x0054; //LATIN CAPITAL LETTER T
  442. dos2unicode[0x55]=0x0055; //LATIN CAPITAL LETTER U
  443. dos2unicode[0x56]=0x0056; //LATIN CAPITAL LETTER V
  444. dos2unicode[0x57]=0x0057; //LATIN CAPITAL LETTER W
  445. dos2unicode[0x58]=0x0058; //LATIN CAPITAL LETTER X
  446. dos2unicode[0x59]=0x0059; //LATIN CAPITAL LETTER Y
  447. dos2unicode[0x5a]=0x005a; //LATIN CAPITAL LETTER Z
  448. dos2unicode[0x5b]=0x005b; //LEFT SQUARE BRACKET
  449. dos2unicode[0x5c]=0x005c; //REVERSE SOLIDUS
  450. dos2unicode[0x5d]=0x005d; //RIGHT SQUARE BRACKET
  451. dos2unicode[0x5e]=0x005e; //CIRCUMFLEX ACCENT
  452. dos2unicode[0x5f]=0x005f; //LOW LINE
  453. dos2unicode[0x60]=0x0060; //GRAVE ACCENT
  454. dos2unicode[0x61]=0x0061; //LATIN SMALL LETTER A
  455. dos2unicode[0x62]=0x0062; //LATIN SMALL LETTER B
  456. dos2unicode[0x63]=0x0063; //LATIN SMALL LETTER C
  457. dos2unicode[0x64]=0x0064; //LATIN SMALL LETTER D
  458. dos2unicode[0x65]=0x0065; //LATIN SMALL LETTER E
  459. dos2unicode[0x66]=0x0066; //LATIN SMALL LETTER F
  460. dos2unicode[0x67]=0x0067; //LATIN SMALL LETTER G
  461. dos2unicode[0x68]=0x0068; //LATIN SMALL LETTER H
  462. dos2unicode[0x69]=0x0069; //LATIN SMALL LETTER I
  463. dos2unicode[0x6a]=0x006a; //LATIN SMALL LETTER J
  464. dos2unicode[0x6b]=0x006b; //LATIN SMALL LETTER K
  465. dos2unicode[0x6c]=0x006c; //LATIN SMALL LETTER L
  466. dos2unicode[0x6d]=0x006d; //LATIN SMALL LETTER M
  467. dos2unicode[0x6e]=0x006e; //LATIN SMALL LETTER N
  468. dos2unicode[0x6f]=0x006f; //LATIN SMALL LETTER O
  469. dos2unicode[0x70]=0x0070; //LATIN SMALL LETTER P
  470. dos2unicode[0x71]=0x0071; //LATIN SMALL LETTER Q
  471. dos2unicode[0x72]=0x0072; //LATIN SMALL LETTER R
  472. dos2unicode[0x73]=0x0073; //LATIN SMALL LETTER S
  473. dos2unicode[0x74]=0x0074; //LATIN SMALL LETTER T
  474. dos2unicode[0x75]=0x0075; //LATIN SMALL LETTER U
  475. dos2unicode[0x76]=0x0076; //LATIN SMALL LETTER V
  476. dos2unicode[0x77]=0x0077; //LATIN SMALL LETTER W
  477. dos2unicode[0x78]=0x0078; //LATIN SMALL LETTER X
  478. dos2unicode[0x79]=0x0079; //LATIN SMALL LETTER Y
  479. dos2unicode[0x7a]=0x007a; //LATIN SMALL LETTER Z
  480. dos2unicode[0x7b]=0x007b; //LEFT CURLY BRACKET
  481. dos2unicode[0x7c]=0x007c; //VERTICAL LINE
  482. dos2unicode[0x7d]=0x007d; //RIGHT CURLY BRACKET
  483. dos2unicode[0x7e]=0x007e; //TILDE
  484. dos2unicode[0x7f]=0x007f; //DELETE
  485. dos2unicode[0x80]=0x00c7; //LATIN CAPITAL LETTER C WITH CEDILLA
  486. dos2unicode[0x81]=0x00fc; //LATIN SMALL LETTER U WITH DIAERESIS
  487. dos2unicode[0x82]=0x00e9; //LATIN SMALL LETTER E WITH ACUTE
  488. dos2unicode[0x83]=0x00e2; //LATIN SMALL LETTER A WITH CIRCUMFLEX
  489. dos2unicode[0x84]=0x00e4; //LATIN SMALL LETTER A WITH DIAERESIS
  490. dos2unicode[0x85]=0x00e0; //LATIN SMALL LETTER A WITH GRAVE
  491. dos2unicode[0x86]=0x00e5; //LATIN SMALL LETTER A WITH RING ABOVE
  492. dos2unicode[0x87]=0x00e7; //LATIN SMALL LETTER C WITH CEDILLA
  493. dos2unicode[0x88]=0x00ea; //LATIN SMALL LETTER E WITH CIRCUMFLEX
  494. dos2unicode[0x89]=0x00eb; //LATIN SMALL LETTER E WITH DIAERESIS
  495. dos2unicode[0x8a]=0x00e8; //LATIN SMALL LETTER E WITH GRAVE
  496. dos2unicode[0x8b]=0x00ef; //LATIN SMALL LETTER I WITH DIAERESIS
  497. dos2unicode[0x8c]=0x00ee; //LATIN SMALL LETTER I WITH CIRCUMFLEX
  498. dos2unicode[0x8d]=0x00ec; //LATIN SMALL LETTER I WITH GRAVE
  499. dos2unicode[0x8e]=0x00c4; //LATIN CAPITAL LETTER A WITH DIAERESIS
  500. dos2unicode[0x8f]=0x00c5; //LATIN CAPITAL LETTER A WITH RING ABOVE
  501. dos2unicode[0x90]=0x00c9; //LATIN CAPITAL LETTER E WITH ACUTE
  502. dos2unicode[0x91]=0x00e6; //LATIN SMALL LIGATURE AE
  503. dos2unicode[0x92]=0x00c6; //LATIN CAPITAL LIGATURE AE
  504. dos2unicode[0x93]=0x00f4; //LATIN SMALL LETTER O WITH CIRCUMFLEX
  505. dos2unicode[0x94]=0x00f6; //LATIN SMALL LETTER O WITH DIAERESIS
  506. dos2unicode[0x95]=0x00f2; //LATIN SMALL LETTER O WITH GRAVE
  507. dos2unicode[0x96]=0x00fb; //LATIN SMALL LETTER U WITH CIRCUMFLEX
  508. dos2unicode[0x97]=0x00f9; //LATIN SMALL LETTER U WITH GRAVE
  509. dos2unicode[0x98]=0x00ff; //LATIN SMALL LETTER Y WITH DIAERESIS
  510. dos2unicode[0x99]=0x00d6; //LATIN CAPITAL LETTER O WITH DIAERESIS
  511. dos2unicode[0x9a]=0x00dc; //LATIN CAPITAL LETTER U WITH DIAERESIS
  512. dos2unicode[0x9b]=0x00a2; //CENT SIGN
  513. dos2unicode[0x9c]=0x00a3; //POUND SIGN
  514. dos2unicode[0x9d]=0x00a5; //YEN SIGN
  515. dos2unicode[0x9e]=0x20a7; //PESETA SIGN
  516. dos2unicode[0x9f]=0x0192; //LATIN SMALL LETTER F WITH HOOK
  517. dos2unicode[0xa0]=0x00e1; //LATIN SMALL LETTER A WITH ACUTE
  518. dos2unicode[0xa1]=0x00ed; //LATIN SMALL LETTER I WITH ACUTE
  519. dos2unicode[0xa2]=0x00f3; //LATIN SMALL LETTER O WITH ACUTE
  520. dos2unicode[0xa3]=0x00fa; //LATIN SMALL LETTER U WITH ACUTE
  521. dos2unicode[0xa4]=0x00f1; //LATIN SMALL LETTER N WITH TILDE
  522. dos2unicode[0xa5]=0x00d1; //LATIN CAPITAL LETTER N WITH TILDE
  523. dos2unicode[0xa6]=0x00aa; //FEMININE ORDINAL INDICATOR
  524. dos2unicode[0xa7]=0x00ba; //MASCULINE ORDINAL INDICATOR
  525. dos2unicode[0xa8]=0x00bf; //INVERTED QUESTION MARK
  526. dos2unicode[0xa9]=0x2310; //REVERSED NOT SIGN
  527. dos2unicode[0xaa]=0x00ac; //NOT SIGN
  528. dos2unicode[0xab]=0x00bd; //VULGAR FRACTION ONE HALF
  529. dos2unicode[0xac]=0x00bc; //VULGAR FRACTION ONE QUARTER
  530. dos2unicode[0xad]=0x00a1; //INVERTED EXCLAMATION MARK
  531. dos2unicode[0xae]=0x00ab; //LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
  532. dos2unicode[0xaf]=0x00bb; //RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
  533. dos2unicode[0xb0]=0x2591; //LIGHT SHADE
  534. dos2unicode[0xb1]=0x2592; //MEDIUM SHADE
  535. dos2unicode[0xb2]=0x2593; //DARK SHADE
  536. dos2unicode[0xb3]=0x2502; //BOX DRAWINGS LIGHT VERTICAL
  537. dos2unicode[0xb4]=0x2524; //BOX DRAWINGS LIGHT VERTICAL AND LEFT
  538. dos2unicode[0xb5]=0x2561; //BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
  539. dos2unicode[0xb6]=0x2562; //BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
  540. dos2unicode[0xb7]=0x2556; //BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
  541. dos2unicode[0xb8]=0x2555; //BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
  542. dos2unicode[0xb9]=0x2563; //BOX DRAWINGS DOUBLE VERTICAL AND LEFT
  543. dos2unicode[0xba]=0x2551; //BOX DRAWINGS DOUBLE VERTICAL
  544. dos2unicode[0xbb]=0x2557; //BOX DRAWINGS DOUBLE DOWN AND LEFT
  545. dos2unicode[0xbc]=0x255d; //BOX DRAWINGS DOUBLE UP AND LEFT
  546. dos2unicode[0xbd]=0x255c; //BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
  547. dos2unicode[0xbe]=0x255b; //BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
  548. dos2unicode[0xbf]=0x2510; //BOX DRAWINGS LIGHT DOWN AND LEFT
  549. dos2unicode[0xc0]=0x2514; //BOX DRAWINGS LIGHT UP AND RIGHT
  550. dos2unicode[0xc1]=0x2534; //BOX DRAWINGS LIGHT UP AND HORIZONTAL
  551. dos2unicode[0xc2]=0x252c; //BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
  552. dos2unicode[0xc3]=0x251c; //BOX DRAWINGS LIGHT VERTICAL AND RIGHT
  553. dos2unicode[0xc4]=0x2500; //BOX DRAWINGS LIGHT HORIZONTAL
  554. dos2unicode[0xc5]=0x253c; //BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
  555. dos2unicode[0xc6]=0x255e; //BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
  556. dos2unicode[0xc7]=0x255f; //BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
  557. dos2unicode[0xc8]=0x255a; //BOX DRAWINGS DOUBLE UP AND RIGHT
  558. dos2unicode[0xc9]=0x2554; //BOX DRAWINGS DOUBLE DOWN AND RIGHT
  559. dos2unicode[0xca]=0x2569; //BOX DRAWINGS DOUBLE UP AND HORIZONTAL
  560. dos2unicode[0xcb]=0x2566; //BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
  561. dos2unicode[0xcc]=0x2560; //BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
  562. dos2unicode[0xcd]=0x2550; //BOX DRAWINGS DOUBLE HORIZONTAL
  563. dos2unicode[0xce]=0x256c; //BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
  564. dos2unicode[0xcf]=0x2567; //BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
  565. dos2unicode[0xd0]=0x2568; //BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
  566. dos2unicode[0xd1]=0x2564; //BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
  567. dos2unicode[0xd2]=0x2565; //BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
  568. dos2unicode[0xd3]=0x2559; //BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
  569. dos2unicode[0xd4]=0x2558; //BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
  570. dos2unicode[0xd5]=0x2552; //BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
  571. dos2unicode[0xd6]=0x2553; //BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
  572. dos2unicode[0xd7]=0x256b; //BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
  573. dos2unicode[0xd8]=0x256a; //BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
  574. dos2unicode[0xd9]=0x2518; //BOX DRAWINGS LIGHT UP AND LEFT
  575. dos2unicode[0xda]=0x250c; //BOX DRAWINGS LIGHT DOWN AND RIGHT
  576. dos2unicode[0xdb]=0x2588; //FULL BLOCK
  577. dos2unicode[0xdc]=0x2584; //LOWER HALF BLOCK
  578. dos2unicode[0xdd]=0x258c; //LEFT HALF BLOCK
  579. dos2unicode[0xde]=0x2590; //RIGHT HALF BLOCK
  580. dos2unicode[0xdf]=0x2580; //UPPER HALF BLOCK
  581. dos2unicode[0xe0]=0x03b1; //GREEK SMALL LETTER ALPHA
  582. dos2unicode[0xe1]=0x00df; //LATIN SMALL LETTER SHARP S
  583. dos2unicode[0xe2]=0x0393; //GREEK CAPITAL LETTER GAMMA
  584. dos2unicode[0xe3]=0x03c0; //GREEK SMALL LETTER PI
  585. dos2unicode[0xe4]=0x03a3; //GREEK CAPITAL LETTER SIGMA
  586. dos2unicode[0xe5]=0x03c3; //GREEK SMALL LETTER SIGMA
  587. dos2unicode[0xe6]=0x00b5; //MICRO SIGN
  588. dos2unicode[0xe7]=0x03c4; //GREEK SMALL LETTER TAU
  589. dos2unicode[0xe8]=0x03a6; //GREEK CAPITAL LETTER PHI
  590. dos2unicode[0xe9]=0x0398; //GREEK CAPITAL LETTER THETA
  591. dos2unicode[0xea]=0x03a9; //GREEK CAPITAL LETTER OMEGA
  592. dos2unicode[0xeb]=0x03b4; //GREEK SMALL LETTER DELTA
  593. dos2unicode[0xec]=0x221e; //INFINITY
  594. dos2unicode[0xed]=0x03c6; //GREEK SMALL LETTER PHI
  595. dos2unicode[0xee]=0x03b5; //GREEK SMALL LETTER EPSILON
  596. dos2unicode[0xef]=0x2229; //INTERSECTION
  597. dos2unicode[0xf0]=0x2261; //IDENTICAL TO
  598. dos2unicode[0xf1]=0x00b1; //PLUS-MINUS SIGN
  599. dos2unicode[0xf2]=0x2265; //GREATER-THAN OR EQUAL TO
  600. dos2unicode[0xf3]=0x2264; //LESS-THAN OR EQUAL TO
  601. dos2unicode[0xf4]=0x2320; //TOP HALF INTEGRAL
  602. dos2unicode[0xf5]=0x2321; //BOTTOM HALF INTEGRAL
  603. dos2unicode[0xf6]=0x00f7; //DIVISION SIGN
  604. dos2unicode[0xf7]=0x2248; //ALMOST EQUAL TO
  605. dos2unicode[0xf8]=0x00b0; //DEGREE SIGN
  606. dos2unicode[0xf9]=0x2219; //BULLET OPERATOR
  607. dos2unicode[0xfa]=0x00b7; //MIDDLE DOT
  608. dos2unicode[0xfb]=0x221a; //SQUARE ROOT
  609. dos2unicode[0xfc]=0x207f; //SUPERSCRIPT LATIN SMALL LETTER N
  610. dos2unicode[0xfd]=0x00b2; //SUPERSCRIPT TWO
  611. dos2unicode[0xfe]=0x25a0; //BLACK SQUARE
  612. dos2unicode[0xff]=0x00a0; //NO-BREAK SPACE
  613. }
  614. void help(void)
  615. {
  616. puts("bmf2bdf [options] <file.bmf>");
  617. puts("Options:");
  618. puts(" -l # Lower edge of the gray level range which maps bmf colors to black (0..255, defaults to 0)");
  619. puts(" -h # Upper edge of the gray level range which maps bmf colors to black (0..255, defaults to 255)");
  620. puts(" -p Ignore the BMF shift value and try to recalculate it (creates a proportional font)");
  621. puts(" -u Apply DOS/ASCII to unicode translation");
  622. puts(" -x # Add # pixel of extra space after each glyph (increases DWIDTH by one, defaults to 0)");
  623. puts(" -y # Shift all glyphs by # pixel (# can be negative)");
  624. puts("Hints:");
  625. puts(" Usually '-u' is required for proper glyph encoding.");
  626. puts(" Use '-x 1' to increase the gap between chars.");
  627. puts(" Use '-l 127' to get an improved color mapping for multicolor .bmf fonts.");
  628. puts(" Use '-p' for monospaced .bmf fonts which seem to be proportional fonts.");
  629. puts("Example:");
  630. puts(" bmf2bdf -u -p -l 128 -x 1 font.bms > font.bdf");
  631. }
  632. int main(int argc, char **argv)
  633. {
  634. char *bmf_name = NULL;
  635. bdf_fp = stdout;
  636. if ( argc < 2 )
  637. {
  638. help();
  639. return 0;
  640. }
  641. argv++;
  642. argc--;
  643. while( argv != NULL && argc > 0)
  644. {
  645. if ( (*argv)[0] != '-' )
  646. {
  647. bmf_name = *argv;
  648. }
  649. else if ( strcmp(*argv, "-p") == 0 )
  650. {
  651. optionForceProportional = 1;
  652. }
  653. else if ( strcmp(*argv, "-u") == 0 )
  654. {
  655. optionUnicodeMapping = 1;
  656. }
  657. else if ( strcmp(*argv, "-x") == 0 )
  658. {
  659. argv++;
  660. argc--;
  661. optionAddExtraSpace = atoi(*argv);
  662. }
  663. else if ( strcmp(*argv, "-y") == 0 )
  664. {
  665. argv++;
  666. argc--;
  667. optionShiftY = atoi(*argv);
  668. }
  669. else if ( strcmp(*argv, "-l") == 0 )
  670. {
  671. argv++;
  672. argc--;
  673. optionGrayLow = atoi(*argv);
  674. }
  675. else if ( strcmp(*argv, "-h") == 0 )
  676. {
  677. argv++;
  678. argc--;
  679. optionGrayHigh = atoi(*argv);
  680. }
  681. else
  682. {
  683. fprintf(stderr, "Wrong option %s\n", *argv);
  684. return 1;
  685. }
  686. argv++;
  687. argc--;
  688. }
  689. if ( bmf_name != NULL )
  690. {
  691. initDos2Unicode();
  692. processBMF(bmf_name, 1);
  693. processBMF(bmf_name, 0);
  694. }
  695. return 0;
  696. }