Leptonica  1.82.0
Image processing and image analysis suite
bmf.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
69 #ifdef HAVE_CONFIG_H
70 #include <config_auto.h>
71 #endif /* HAVE_CONFIG_H */
72 
73 #include <string.h>
74 #include "allheaders.h"
75 #include "bmfdata.h"
76 
77 static const l_float32 VertFractSep = 0.3;
78 
79 #ifndef NO_CONSOLE_IO
80 #define DEBUG_BASELINE 0
81 #define DEBUG_CHARS 0
82 #define DEBUG_FONT_GEN 0
83 #endif /* ~NO_CONSOLE_IO */
84 
85 static PIXA *pixaGenerateFontFromFile(const char *dir, l_int32 fontsize,
86  l_int32 *pbl0, l_int32 *pbl1,
87  l_int32 *pbl2);
88 static PIXA *pixaGenerateFontFromString(l_int32 fontsize, l_int32 *pbl0,
89  l_int32 *pbl1, l_int32 *pbl2);
90 static PIXA *pixaGenerateFont(PIX *pixs, l_int32 fontsize, l_int32 *pbl0,
91  l_int32 *pbl1, l_int32 *pbl2);
92 static l_int32 pixGetTextBaseline(PIX *pixs, l_int32 *tab8, l_int32 *py);
93 static l_int32 bmfMakeAsciiTables(L_BMF *bmf);
94 
95 /*---------------------------------------------------------------------*/
96 /* Bmf create/destroy */
97 /*---------------------------------------------------------------------*/
116 L_BMF *
117 bmfCreate(const char *dir,
118  l_int32 fontsize)
119 {
120 L_BMF *bmf;
121 PIXA *pixa;
122 
123  PROCNAME("bmfCreate");
124 
125  if (fontsize < 4 || fontsize > 20 || (fontsize % 2))
126  return (L_BMF *)ERROR_PTR("fontsize must be in {4, 6, ..., 20}",
127  procName, NULL);
128 
129  bmf = (L_BMF *)LEPT_CALLOC(1, sizeof(L_BMF));
130 
131  if (!dir) { /* Generate from a string */
132  pixa = pixaGenerateFontFromString(fontsize, &bmf->baseline1,
133  &bmf->baseline2, &bmf->baseline3);
134  } else { /* Look for the pixa in a directory */
135  pixa = pixaGetFont(dir, fontsize, &bmf->baseline1, &bmf->baseline2,
136  &bmf->baseline3);
137  if (!pixa) { /* Not found; make it from a file */
138  L_INFO("Generating pixa of bitmap fonts from file\n", procName);
139  pixa = pixaGenerateFontFromFile(dir, fontsize, &bmf->baseline1,
140  &bmf->baseline2, &bmf->baseline3);
141  if (!pixa) { /* Not made; make it from a string after all */
142  L_ERROR("Failed to make font; use string\n", procName);
143  pixa = pixaGenerateFontFromString(fontsize, &bmf->baseline1,
144  &bmf->baseline2, &bmf->baseline3);
145  }
146  }
147  }
148 
149  if (!pixa) {
150  bmfDestroy(&bmf);
151  return (L_BMF *)ERROR_PTR("font pixa not made", procName, NULL);
152  }
153 
154  bmf->pixa = pixa;
155  bmf->size = fontsize;
156  if (dir) bmf->directory = stringNew(dir);
157  bmfMakeAsciiTables(bmf);
158  return bmf;
159 }
160 
161 
168 void
170 {
171 L_BMF *bmf;
172 
173  PROCNAME("bmfDestroy");
174 
175  if (pbmf == NULL) {
176  L_WARNING("ptr address is null!\n", procName);
177  return;
178  }
179 
180  if ((bmf = *pbmf) == NULL)
181  return;
182 
183  pixaDestroy(&bmf->pixa);
184  LEPT_FREE(bmf->directory);
185  LEPT_FREE(bmf->fonttab);
186  LEPT_FREE(bmf->baselinetab);
187  LEPT_FREE(bmf->widthtab);
188  LEPT_FREE(bmf);
189  *pbmf = NULL;
190 }
191 
192 
193 /*---------------------------------------------------------------------*/
194 /* Bmf accessors */
195 /*---------------------------------------------------------------------*/
203 PIX *
205  char chr)
206 {
207 l_int32 i, index;
208 PIXA *pixa;
209 
210  PROCNAME("bmfGetPix");
211 
212  if ((index = (l_int32)chr) == 10) /* NL */
213  return NULL;
214  if (!bmf)
215  return (PIX *)ERROR_PTR("bmf not defined", procName, NULL);
216 
217  i = bmf->fonttab[index];
218  if (i == UNDEF) {
219  L_ERROR("no bitmap representation for %d\n", procName, index);
220  return NULL;
221  }
222 
223  if ((pixa = bmf->pixa) == NULL)
224  return (PIX *)ERROR_PTR("pixa not found", procName, NULL);
225 
226  return pixaGetPix(pixa, i, L_CLONE);
227 }
228 
229 
238 l_ok
240  char chr,
241  l_int32 *pw)
242 {
243 l_int32 i, index;
244 PIXA *pixa;
245 
246  PROCNAME("bmfGetWidth");
247 
248  if (!pw)
249  return ERROR_INT("&w not defined", procName, 1);
250  *pw = -1;
251  if (!bmf)
252  return ERROR_INT("bmf not defined", procName, 1);
253  if ((index = (l_int32)chr) == 10) /* NL */
254  return 0;
255 
256  i = bmf->fonttab[index];
257  if (i == UNDEF) {
258  L_ERROR("no bitmap representation for %d\n", procName, index);
259  return 1;
260  }
261 
262  if ((pixa = bmf->pixa) == NULL)
263  return ERROR_INT("pixa not found", procName, 1);
264 
265  return pixaGetPixDimensions(pixa, i, pw, NULL, NULL);
266 }
267 
268 
277 l_ok
279  char chr,
280  l_int32 *pbaseline)
281 {
282 l_int32 bl, index;
283 
284  PROCNAME("bmfGetBaseline");
285 
286  if (!pbaseline)
287  return ERROR_INT("&baseline not defined", procName, 1);
288  *pbaseline = 0;
289  if (!bmf)
290  return ERROR_INT("bmf not defined", procName, 1);
291  if ((index = (l_int32)chr) == 10) /* NL */
292  return 0;
293 
294  bl = bmf->baselinetab[index];
295  if (bl == UNDEF) {
296  L_ERROR("no bitmap representation for %d\n", procName, index);
297  return 1;
298  }
299 
300  *pbaseline = bl;
301  return 0;
302 }
303 
304 
305 /*---------------------------------------------------------------------*/
306 /* Font bitmap acquisition and generation */
307 /*---------------------------------------------------------------------*/
323 PIXA *
324 pixaGetFont(const char *dir,
325  l_int32 fontsize,
326  l_int32 *pbl0,
327  l_int32 *pbl1,
328  l_int32 *pbl2)
329 {
330 char *pathname;
331 l_int32 fileno;
332 PIXA *pixa;
333 
334  PROCNAME("pixaGetFont");
335 
336  fileno = (fontsize / 2) - 2;
337  if (fileno < 0 || fileno >= NUM_FONTS)
338  return (PIXA *)ERROR_PTR("font size invalid", procName, NULL);
339  if (!pbl0 || !pbl1 || !pbl2)
340  return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
341  *pbl0 = baselines[fileno][0];
342  *pbl1 = baselines[fileno][1];
343  *pbl2 = baselines[fileno][2];
344 
345  pathname = pathJoin(dir, outputfonts[fileno]);
346  pixa = pixaRead(pathname);
347  LEPT_FREE(pathname);
348 
349  if (!pixa)
350  L_WARNING("pixa of char bitmaps not found\n", procName);
351  return pixa;
352 }
353 
354 
373 l_ok
374 pixaSaveFont(const char *indir,
375  const char *outdir,
376  l_int32 fontsize)
377 {
378 char *pathname;
379 l_int32 bl1, bl2, bl3;
380 PIXA *pixa;
381 
382  PROCNAME("pixaSaveFont");
383 
384  if (fontsize < 4 || fontsize > 20 || (fontsize % 2))
385  return ERROR_INT("fontsize must be in {4, 6, ..., 20}", procName, 1);
386 
387  if (!indir) /* Generate from a string */
388  pixa = pixaGenerateFontFromString(fontsize, &bl1, &bl2, &bl3);
389  else /* Generate from an image file */
390  pixa = pixaGenerateFontFromFile(indir, fontsize, &bl1, &bl2, &bl3);
391  if (!pixa)
392  return ERROR_INT("pixa not made", procName, 1);
393 
394  pathname = pathJoin(outdir, outputfonts[(fontsize - 4) / 2]);
395  pixaWrite(pathname, pixa);
396 
397 #if DEBUG_FONT_GEN
398  L_INFO("Found %d chars in font size %d\n", procName, pixaGetCount(pixa),
399  fontsize);
400  L_INFO("Baselines are at: %d, %d, %d\n", procName, bl1, bl2, bl3);
401 #endif /* DEBUG_FONT_GEN */
402 
403  LEPT_FREE(pathname);
404  pixaDestroy(&pixa);
405  return 0;
406 }
407 
408 
435 static PIXA *
436 pixaGenerateFontFromFile(const char *dir,
437  l_int32 fontsize,
438  l_int32 *pbl0,
439  l_int32 *pbl1,
440  l_int32 *pbl2)
441 {
442 char *pathname;
443 l_int32 fileno;
444 PIX *pix;
445 PIXA *pixa;
446 
447  PROCNAME("pixaGenerateFontFromFile");
448 
449  if (!pbl0 || !pbl1 || !pbl2)
450  return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
451  *pbl0 = *pbl1 = *pbl2 = 0;
452  if (!dir)
453  return (PIXA *)ERROR_PTR("dir not defined", procName, NULL);
454  fileno = (fontsize / 2) - 2;
455  if (fileno < 0 || fileno >= NUM_FONTS)
456  return (PIXA *)ERROR_PTR("font size invalid", procName, NULL);
457 
458  pathname = pathJoin(dir, inputfonts[fileno]);
459  pix = pixRead(pathname);
460  LEPT_FREE(pathname);
461  if (!pix) {
462  L_ERROR("pix not found for font size %d\n", procName, fontsize);
463  return NULL;
464  }
465 
466  pixa = pixaGenerateFont(pix, fontsize, pbl0, pbl1, pbl2);
467  pixDestroy(&pix);
468  return pixa;
469 }
470 
471 
486 static PIXA *
487 pixaGenerateFontFromString(l_int32 fontsize,
488  l_int32 *pbl0,
489  l_int32 *pbl1,
490  l_int32 *pbl2)
491 {
492 l_uint8 *data;
493 l_int32 redsize, nbytes;
494 PIX *pix;
495 PIXA *pixa;
496 
497  PROCNAME("pixaGenerateFontFromString");
498 
499  if (!pbl0 || !pbl1 || !pbl2)
500  return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
501  *pbl0 = *pbl1 = *pbl2 = 0;
502  redsize = (fontsize / 2) - 2;
503  if (redsize < 0 || redsize >= NUM_FONTS)
504  return (PIXA *)ERROR_PTR("invalid font size", procName, NULL);
505 
506  if (fontsize == 4) {
507  data = decodeBase64(fontdata_4, strlen(fontdata_4), &nbytes);
508  } else if (fontsize == 6) {
509  data = decodeBase64(fontdata_6, strlen(fontdata_6), &nbytes);
510  } else if (fontsize == 8) {
511  data = decodeBase64(fontdata_8, strlen(fontdata_8), &nbytes);
512  } else if (fontsize == 10) {
513  data = decodeBase64(fontdata_10, strlen(fontdata_10), &nbytes);
514  } else if (fontsize == 12) {
515  data = decodeBase64(fontdata_12, strlen(fontdata_12), &nbytes);
516  } else if (fontsize == 14) {
517  data = decodeBase64(fontdata_14, strlen(fontdata_14), &nbytes);
518  } else if (fontsize == 16) {
519  data = decodeBase64(fontdata_16, strlen(fontdata_16), &nbytes);
520  } else if (fontsize == 18) {
521  data = decodeBase64(fontdata_18, strlen(fontdata_18), &nbytes);
522  } else { /* fontsize == 20 */
523  data = decodeBase64(fontdata_20, strlen(fontdata_20), &nbytes);
524  }
525  if (!data)
526  return (PIXA *)ERROR_PTR("data not made", procName, NULL);
527 
528  pix = pixReadMem(data, nbytes);
529  LEPT_FREE(data);
530  if (!pix)
531  return (PIXA *)ERROR_PTR("pix not made", procName, NULL);
532 
533  pixa = pixaGenerateFont(pix, fontsize, pbl0, pbl1, pbl2);
534  pixDestroy(&pix);
535  return pixa;
536 }
537 
538 
557 static PIXA *
559  l_int32 fontsize,
560  l_int32 *pbl0,
561  l_int32 *pbl1,
562  l_int32 *pbl2)
563 {
564 l_int32 i, j, nrows, nrowchars, nchars, h, yval;
565 l_int32 width, height;
566 l_int32 baseline[3];
567 l_int32 *tab = NULL;
568 BOX *box, *box1, *box2;
569 BOXA *boxar, *boxac, *boxacs;
570 PIX *pix1, *pix2, *pixr, *pixrc, *pixc;
571 PIXA *pixa;
572 l_int32 n, w, inrow, top;
573 l_int32 *ia;
574 NUMA *na;
575 
576  PROCNAME("pixaGenerateFont");
577 
578  if (!pbl0 || !pbl1 || !pbl2)
579  return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
580  *pbl0 = *pbl1 = *pbl2 = 0;
581  if (!pixs)
582  return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
583 
584  /* Locate the 3 rows of characters */
585  w = pixGetWidth(pixs);
586  na = pixCountPixelsByRow(pixs, NULL);
587  boxar = boxaCreate(0);
588  n = numaGetCount(na);
589  ia = numaGetIArray(na);
590  inrow = 0;
591  for (i = 0; i < n; i++) {
592  if (!inrow && ia[i] > 0) {
593  inrow = 1;
594  top = i;
595  } else if (inrow && ia[i] == 0) {
596  inrow = 0;
597  box = boxCreate(0, top, w, i - top);
598  boxaAddBox(boxar, box, L_INSERT);
599  }
600  }
601  LEPT_FREE(ia);
602  numaDestroy(&na);
603  nrows = boxaGetCount(boxar);
604 #if DEBUG_FONT_GEN
605  L_INFO("For fontsize %s, have %d rows\n", procName, fontsize, nrows);
606 #endif /* DEBUG_FONT_GEN */
607  if (nrows != 3) {
608  L_INFO("nrows = %d; skipping fontsize %d\n", procName, nrows, fontsize);
609  boxaDestroy(&boxar);
610  return (PIXA *)ERROR_PTR("3 rows not generated", procName, NULL);
611  }
612 
613  /* Grab the character images and baseline data */
614 #if DEBUG_BASELINE
615  lept_rmdir("baseline");
616  lept_mkdir("baseline");
617 #endif /* DEBUG_BASELINE */
618  tab = makePixelSumTab8();
619  pixa = pixaCreate(95);
620  for (i = 0; i < nrows; i++) {
621  box = boxaGetBox(boxar, i, L_CLONE);
622  pixr = pixClipRectangle(pixs, box, NULL); /* row of chars */
623  pixGetTextBaseline(pixr, tab, &yval);
624  baseline[i] = yval;
625 
626 #if DEBUG_BASELINE
627  L_INFO("Baseline info: row %d, yval = %d, h = %d\n", procName,
628  i, yval, pixGetHeight(pixr));
629  pix1 = pixCopy(NULL, pixr);
630  pixRenderLine(pix1, 0, yval, pixGetWidth(pix1), yval, 1,
631  L_FLIP_PIXELS);
632  if (i == 0 )
633  pixWriteDebug("/tmp/baseline/row0.png", pix1, IFF_PNG);
634  else if (i == 1)
635  pixWriteDebug("/tmp/baseline/row1.png", pix1, IFF_PNG);
636  else
637  pixWriteDebug("/tmp/baseline/row2.png", pix1, IFF_PNG);
638  pixDestroy(&pix1);
639 #endif /* DEBUG_BASELINE */
640 
641  boxDestroy(&box);
642  pixrc = pixCloseSafeBrick(NULL, pixr, 1, 35);
643  boxac = pixConnComp(pixrc, NULL, 8);
644  boxacs = boxaSort(boxac, L_SORT_BY_X, L_SORT_INCREASING, NULL);
645  if (i == 0) { /* consolidate the two components of '"' */
646  box1 = boxaGetBox(boxacs, 1, L_CLONE);
647  box2 = boxaGetBox(boxacs, 2, L_CLONE);
648  box1->w = box2->x + box2->w - box1->x; /* increase width */
649  boxDestroy(&box1);
650  boxDestroy(&box2);
651  boxaRemoveBox(boxacs, 2);
652  }
653  h = pixGetHeight(pixr);
654  nrowchars = boxaGetCount(boxacs);
655  for (j = 0; j < nrowchars; j++) {
656  box = boxaGetBox(boxacs, j, L_COPY);
657  if (box->w <= 2 && box->h == 1) { /* skip 1x1, 2x1 components */
658  boxDestroy(&box);
659  continue;
660  }
661  box->y = 0;
662  box->h = h - 1;
663  pixc = pixClipRectangle(pixr, box, NULL);
664  boxDestroy(&box);
665  if (i == 0 && j == 0) /* add a pix for the space; change later */
666  pixaAddPix(pixa, pixc, L_COPY);
667  if (i == 2 && j == 0) /* add a pix for the '\'; change later */
668  pixaAddPix(pixa, pixc, L_COPY);
669  pixaAddPix(pixa, pixc, L_INSERT);
670  }
671  pixDestroy(&pixr);
672  pixDestroy(&pixrc);
673  boxaDestroy(&boxac);
674  boxaDestroy(&boxacs);
675  }
676  LEPT_FREE(tab);
677 
678  nchars = pixaGetCount(pixa);
679  if (nchars != 95)
680  return (PIXA *)ERROR_PTR("95 chars not generated", procName, NULL);
681 
682  *pbl0 = baseline[0];
683  *pbl1 = baseline[1];
684  *pbl2 = baseline[2];
685 
686  /* Fix the space character up; it should have no ON pixels,
687  * and be about twice as wide as the '!' character. */
688  pix1 = pixaGetPix(pixa, 0, L_CLONE);
689  width = 2 * pixGetWidth(pix1);
690  height = pixGetHeight(pix1);
691  pixDestroy(&pix1);
692  pix1 = pixCreate(width, height, 1);
693  pixaReplacePix(pixa, 0, pix1, NULL);
694 
695  /* Fix up the '\' character; use a LR flip of the '/' char */
696  pix1 = pixaGetPix(pixa, 15, L_CLONE);
697  pix2 = pixFlipLR(NULL, pix1);
698  pixDestroy(&pix1);
699  pixaReplacePix(pixa, 60, pix2, NULL);
700 
701 #if DEBUG_CHARS
702  pix1 = pixaDisplayTiled(pixa, 1500, 0, 10);
703  pixDisplay(pix1, 100 * i, 200);
704  pixDestroy(&pix1);
705 #endif /* DEBUG_CHARS */
706 
707  boxaDestroy(&boxar);
708  return pixa;
709 }
710 
711 
728 static l_int32
730  l_int32 *tab8,
731  l_int32 *py)
732 {
733 l_int32 i, h, val1, val2, diff, diffmax, ymax;
734 l_int32 *tab;
735 NUMA *na;
736 
737  PROCNAME("pixGetTextBaseline");
738 
739  if (!pixs)
740  return ERROR_INT("pixs not defined", procName, 1);
741  if (!py)
742  return ERROR_INT("&y not defined", procName, 1);
743  *py = 0;
744  if (!tab8)
745  tab = makePixelSumTab8();
746  else
747  tab = tab8;
748 
749  na = pixCountPixelsByRow(pixs, tab);
750  h = numaGetCount(na);
751  diffmax = 0;
752  ymax = 0;
753  for (i = 1; i < h; i++) {
754  numaGetIValue(na, i - 1, &val1);
755  numaGetIValue(na, i, &val2);
756  diff = L_MAX(0, val1 - val2);
757  if (diff > diffmax) {
758  diffmax = diff;
759  ymax = i - 1; /* upper raster line */
760  }
761  }
762  *py = ymax;
763 
764  if (!tab8)
765  LEPT_FREE(tab);
766  numaDestroy(&na);
767  return 0;
768 }
769 
770 
803 static l_int32
805 {
806 l_int32 i, maxh, height, charwidth, xwidth, kernwidth;
807 l_int32 *fonttab, *baselinetab, *widthtab;
808 PIX *pix;
809 
810  PROCNAME("bmfMakeAsciiTables");
811 
812  if (!bmf)
813  return ERROR_INT("bmf not defined", procName, 1);
814 
815  /* First get the fonttab; we use this later for the char widths */
816  fonttab = (l_int32 *)LEPT_CALLOC(128, sizeof(l_int32));
817  bmf->fonttab = fonttab;
818  for (i = 0; i < 128; i++)
819  fonttab[i] = UNDEF;
820  for (i = 32; i < 127; i++)
821  fonttab[i] = i - 32;
822 
823  baselinetab = (l_int32 *)LEPT_CALLOC(128, sizeof(l_int32));
824  bmf->baselinetab = baselinetab;
825  for (i = 0; i < 128; i++)
826  baselinetab[i] = UNDEF;
827  for (i = 32; i <= 57; i++)
828  baselinetab[i] = bmf->baseline1;
829  for (i = 58; i <= 91; i++)
830  baselinetab[i] = bmf->baseline2;
831  baselinetab[92] = bmf->baseline1; /* the '\' char */
832  for (i = 93; i < 127; i++)
833  baselinetab[i] = bmf->baseline3;
834 
835  /* Generate array of character widths; req's fonttab to exist */
836  widthtab = (l_int32 *)LEPT_CALLOC(128, sizeof(l_int32));
837  bmf->widthtab = widthtab;
838  for (i = 0; i < 128; i++)
839  widthtab[i] = UNDEF;
840  for (i = 32; i < 127; i++) {
841  bmfGetWidth(bmf, i, &charwidth);
842  widthtab[i] = charwidth;
843  }
844 
845  /* Get the line height of text characters, from the highest
846  * ascender to the lowest descender; req's fonttab to exist. */
847  pix = bmfGetPix(bmf, 32);
848  maxh = pixGetHeight(pix);
849  pixDestroy(&pix);
850  pix = bmfGetPix(bmf, 58);
851  height = pixGetHeight(pix);
852  pixDestroy(&pix);
853  maxh = L_MAX(maxh, height);
854  pix = bmfGetPix(bmf, 93);
855  height = pixGetHeight(pix);
856  pixDestroy(&pix);
857  maxh = L_MAX(maxh, height);
858  bmf->lineheight = maxh;
859 
860  /* Get the kern width (distance between characters).
861  * We let it be the same for all characters in a given
862  * font size, and scale it linearly with the size;
863  * req's fonttab to be built first. */
864  bmfGetWidth(bmf, 120, &xwidth);
865  kernwidth = (l_int32)(0.08 * (l_float32)xwidth + 0.5);
866  bmf->kernwidth = L_MAX(1, kernwidth);
867 
868  /* Save the space width (between words) */
869  bmfGetWidth(bmf, 32, &charwidth);
870  bmf->spacewidth = charwidth;
871 
872  /* Save the extra vertical space between lines */
873  bmf->vertlinesep = (l_int32)(VertFractSep * bmf->lineheight + 0.5);
874 
875  return 0;
876 }
PIXA * pixaGetFont(const char *dir, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGetFont()
Definition: bmf.c:324
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:169
static PIXA * pixaGenerateFontFromFile(const char *dir, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFontFromFile()
Definition: bmf.c:436
static PIXA * pixaGenerateFont(PIX *pixs, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFont()
Definition: bmf.c:558
PIX * bmfGetPix(L_BMF *bmf, char chr)
bmfGetPix()
Definition: bmf.c:204
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:117
static PIXA * pixaGenerateFontFromString(l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFontFromString()
Definition: bmf.c:487
l_ok bmfGetBaseline(L_BMF *bmf, char chr, l_int32 *pbaseline)
bmfGetBaseline()
Definition: bmf.c:278
static l_int32 bmfMakeAsciiTables(L_BMF *bmf)
bmfMakeAsciiTables
Definition: bmf.c:804
l_ok pixaSaveFont(const char *indir, const char *outdir, l_int32 fontsize)
pixaSaveFont()
Definition: bmf.c:374
static l_int32 pixGetTextBaseline(PIX *pixs, l_int32 *tab8, l_int32 *py)
pixGetTextBaseline()
Definition: bmf.c:729
l_ok bmfGetWidth(L_BMF *bmf, char chr, l_int32 *pw)
bmfGetWidth()
Definition: bmf.c:239
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
l_ok boxaRemoveBox(BOXA *boxa, l_int32 index)
boxaRemoveBox()
Definition: boxbasic.c:1048
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:734
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:620
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:583
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:502
BOXA * boxaSort(BOXA *boxas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex)
boxaSort()
Definition: boxfunc2.c:637
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:151
l_ok pixRenderLine(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width, l_int32 op)
pixRenderLine()
Definition: graphics.c:1496
PIX * pixCloseSafeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseSafeBrick()
Definition: morph.c:977
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:847
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2411
NUMA * pixCountPixelsByRow(PIX *pix, l_int32 *tab8)
pixCountPixelsByRow()
Definition: pix3.c:2143
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
@ L_FLIP_PIXELS
Definition: pix.h:774
@ L_SORT_BY_X
Definition: pix.h:735
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_INSERT
Definition: pix.h:711
@ L_SORT_INCREASING
Definition: pix.h:729
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
l_ok pixaGetPixDimensions(PIXA *pixa, l_int32 index, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixaGetPixDimensions()
Definition: pixabasic.c:726
PIXA * pixaRead(const char *filename)
pixaRead()
Definition: pixabasic.c:2610
l_ok pixaReplacePix(PIXA *pixa, l_int32 index, PIX *pix, BOX *box)
pixaReplacePix()
Definition: pixabasic.c:1320
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:650
l_ok pixaWrite(const char *filename, PIXA *pixa)
pixaWrite()
Definition: pixabasic.c:2777
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:691
PIX * pixaDisplayTiled(PIXA *pixa, l_int32 maxwidth, l_int32 background, l_int32 spacing)
pixaDisplayTiled()
Definition: pixafunc2.c:632
PIX * pixReadMem(const l_uint8 *data, size_t size)
pixReadMem()
Definition: readfile.c:844
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:193
PIX * pixFlipLR(PIX *pixd, PIX *pixs)
pixFlipLR()
Definition: rotateorth.c:427
Definition: pix.h:481
l_int32 y
Definition: pix.h:483
l_int32 x
Definition: pix.h:482
l_int32 w
Definition: pix.h:484
l_int32 h
Definition: pix.h:485
Definition: pix.h:492
Definition: bmf.h:47
l_int32 * baselinetab
Definition: bmf.h:59
l_int32 baseline3
Definition: bmf.h:53
l_int32 * fonttab
Definition: bmf.h:58
l_int32 * widthtab
Definition: bmf.h:60
char * directory
Definition: bmf.h:50
l_int32 baseline1
Definition: bmf.h:51
l_int32 spacewidth
Definition: bmf.h:56
l_int32 vertlinesep
Definition: bmf.h:57
struct Pixa * pixa
Definition: bmf.h:48
l_int32 size
Definition: bmf.h:49
l_int32 kernwidth
Definition: bmf.h:55
l_int32 baseline2
Definition: bmf.h:52
l_int32 lineheight
Definition: bmf.h:54
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:456
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2295
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition: utils2.c:2973
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218