Leptonica  1.83.1
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 "pix_internal.h"
76 #include "bmfdata.h"
77 
78 static const l_float32 VertFractSep = 0.3;
79 
80 #ifndef NO_CONSOLE_IO
81 #define DEBUG_BASELINE 0
82 #define DEBUG_CHARS 0
83 #define DEBUG_FONT_GEN 0
84 #endif /* ~NO_CONSOLE_IO */
85 
86 static PIXA *pixaGenerateFontFromFile(const char *dir, l_int32 fontsize,
87  l_int32 *pbl0, l_int32 *pbl1,
88  l_int32 *pbl2);
89 static PIXA *pixaGenerateFontFromString(l_int32 fontsize, l_int32 *pbl0,
90  l_int32 *pbl1, l_int32 *pbl2);
91 static PIXA *pixaGenerateFont(PIX *pixs, l_int32 fontsize, l_int32 *pbl0,
92  l_int32 *pbl1, l_int32 *pbl2);
93 static l_int32 pixGetTextBaseline(PIX *pixs, l_int32 *tab8, l_int32 *py);
94 static l_int32 bmfMakeAsciiTables(L_BMF *bmf);
95 
96 /*---------------------------------------------------------------------*/
97 /* Bmf create/destroy */
98 /*---------------------------------------------------------------------*/
117 L_BMF *
118 bmfCreate(const char *dir,
119  l_int32 fontsize)
120 {
121 L_BMF *bmf;
122 PIXA *pixa;
123 
124  if (fontsize < 4 || fontsize > 20 || (fontsize % 2))
125  return (L_BMF *)ERROR_PTR("fontsize must be in {4, 6, ..., 20}",
126  __func__, NULL);
127 
128  bmf = (L_BMF *)LEPT_CALLOC(1, sizeof(L_BMF));
129 
130  if (!dir) { /* Generate from a string */
131  pixa = pixaGenerateFontFromString(fontsize, &bmf->baseline1,
132  &bmf->baseline2, &bmf->baseline3);
133  } else { /* Look for the pixa in a directory */
134  pixa = pixaGetFont(dir, fontsize, &bmf->baseline1, &bmf->baseline2,
135  &bmf->baseline3);
136  if (!pixa) { /* Not found; make it from a file */
137  L_INFO("Generating pixa of bitmap fonts from file\n", __func__);
138  pixa = pixaGenerateFontFromFile(dir, fontsize, &bmf->baseline1,
139  &bmf->baseline2, &bmf->baseline3);
140  if (!pixa) { /* Not made; make it from a string after all */
141  L_ERROR("Failed to make font; use string\n", __func__);
142  pixa = pixaGenerateFontFromString(fontsize, &bmf->baseline1,
143  &bmf->baseline2, &bmf->baseline3);
144  }
145  }
146  }
147 
148  if (!pixa) {
149  bmfDestroy(&bmf);
150  return (L_BMF *)ERROR_PTR("font pixa not made", __func__, NULL);
151  }
152 
153  bmf->pixa = pixa;
154  bmf->size = fontsize;
155  if (dir) bmf->directory = stringNew(dir);
156  bmfMakeAsciiTables(bmf);
157  return bmf;
158 }
159 
160 
167 void
169 {
170 L_BMF *bmf;
171 
172  if (pbmf == NULL) {
173  L_WARNING("ptr address is null!\n", __func__);
174  return;
175  }
176 
177  if ((bmf = *pbmf) == NULL)
178  return;
179 
180  pixaDestroy(&bmf->pixa);
181  LEPT_FREE(bmf->directory);
182  LEPT_FREE(bmf->fonttab);
183  LEPT_FREE(bmf->baselinetab);
184  LEPT_FREE(bmf->widthtab);
185  LEPT_FREE(bmf);
186  *pbmf = NULL;
187 }
188 
189 
190 /*---------------------------------------------------------------------*/
191 /* Bmf accessors */
192 /*---------------------------------------------------------------------*/
200 PIX *
202  char chr)
203 {
204 l_int32 i, index;
205 PIXA *pixa;
206 
207  if ((index = (l_int32)chr) == 10) /* NL */
208  return NULL;
209  if (!bmf)
210  return (PIX *)ERROR_PTR("bmf not defined", __func__, NULL);
211 
212  i = bmf->fonttab[index];
213  if (i == UNDEF) {
214  L_ERROR("no bitmap representation for %d\n", __func__, index);
215  return NULL;
216  }
217 
218  if ((pixa = bmf->pixa) == NULL)
219  return (PIX *)ERROR_PTR("pixa not found", __func__, NULL);
220 
221  return pixaGetPix(pixa, i, L_CLONE);
222 }
223 
224 
233 l_ok
235  char chr,
236  l_int32 *pw)
237 {
238 l_int32 i, index;
239 PIXA *pixa;
240 
241  if (!pw)
242  return ERROR_INT("&w not defined", __func__, 1);
243  *pw = -1;
244  if (!bmf)
245  return ERROR_INT("bmf not defined", __func__, 1);
246  if ((index = (l_int32)chr) == 10) /* NL */
247  return 0;
248 
249  i = bmf->fonttab[index];
250  if (i == UNDEF) {
251  L_ERROR("no bitmap representation for %d\n", __func__, index);
252  return 1;
253  }
254 
255  if ((pixa = bmf->pixa) == NULL)
256  return ERROR_INT("pixa not found", __func__, 1);
257 
258  return pixaGetPixDimensions(pixa, i, pw, NULL, NULL);
259 }
260 
261 
270 l_ok
272  char chr,
273  l_int32 *pbaseline)
274 {
275 l_int32 bl, index;
276 
277  if (!pbaseline)
278  return ERROR_INT("&baseline not defined", __func__, 1);
279  *pbaseline = 0;
280  if (!bmf)
281  return ERROR_INT("bmf not defined", __func__, 1);
282  if ((index = (l_int32)chr) == 10) /* NL */
283  return 0;
284 
285  bl = bmf->baselinetab[index];
286  if (bl == UNDEF) {
287  L_ERROR("no bitmap representation for %d\n", __func__, index);
288  return 1;
289  }
290 
291  *pbaseline = bl;
292  return 0;
293 }
294 
295 
296 /*---------------------------------------------------------------------*/
297 /* Font bitmap acquisition and generation */
298 /*---------------------------------------------------------------------*/
314 PIXA *
315 pixaGetFont(const char *dir,
316  l_int32 fontsize,
317  l_int32 *pbl0,
318  l_int32 *pbl1,
319  l_int32 *pbl2)
320 {
321 char *pathname;
322 l_int32 fileno;
323 PIXA *pixa;
324 
325  fileno = (fontsize / 2) - 2;
326  if (fileno < 0 || fileno >= NUM_FONTS)
327  return (PIXA *)ERROR_PTR("font size invalid", __func__, NULL);
328  if (!pbl0 || !pbl1 || !pbl2)
329  return (PIXA *)ERROR_PTR("&bl not all defined", __func__, NULL);
330  *pbl0 = baselines[fileno][0];
331  *pbl1 = baselines[fileno][1];
332  *pbl2 = baselines[fileno][2];
333 
334  pathname = pathJoin(dir, outputfonts[fileno]);
335  pixa = pixaRead(pathname);
336  LEPT_FREE(pathname);
337 
338  if (!pixa)
339  L_WARNING("pixa of char bitmaps not found\n", __func__);
340  return pixa;
341 }
342 
343 
362 l_ok
363 pixaSaveFont(const char *indir,
364  const char *outdir,
365  l_int32 fontsize)
366 {
367 char *pathname;
368 l_int32 bl1, bl2, bl3;
369 PIXA *pixa;
370 
371  if (fontsize < 4 || fontsize > 20 || (fontsize % 2))
372  return ERROR_INT("fontsize must be in {4, 6, ..., 20}", __func__, 1);
373 
374  if (!indir) /* Generate from a string */
375  pixa = pixaGenerateFontFromString(fontsize, &bl1, &bl2, &bl3);
376  else /* Generate from an image file */
377  pixa = pixaGenerateFontFromFile(indir, fontsize, &bl1, &bl2, &bl3);
378  if (!pixa)
379  return ERROR_INT("pixa not made", __func__, 1);
380 
381  pathname = pathJoin(outdir, outputfonts[(fontsize - 4) / 2]);
382  pixaWrite(pathname, pixa);
383 
384 #if DEBUG_FONT_GEN
385  L_INFO("Found %d chars in font size %d\n", __func__, pixaGetCount(pixa),
386  fontsize);
387  L_INFO("Baselines are at: %d, %d, %d\n", __func__, bl1, bl2, bl3);
388 #endif /* DEBUG_FONT_GEN */
389 
390  LEPT_FREE(pathname);
391  pixaDestroy(&pixa);
392  return 0;
393 }
394 
395 
422 static PIXA *
423 pixaGenerateFontFromFile(const char *dir,
424  l_int32 fontsize,
425  l_int32 *pbl0,
426  l_int32 *pbl1,
427  l_int32 *pbl2)
428 {
429 char *pathname;
430 l_int32 fileno;
431 PIX *pix;
432 PIXA *pixa;
433 
434  if (!pbl0 || !pbl1 || !pbl2)
435  return (PIXA *)ERROR_PTR("&bl not all defined", __func__, NULL);
436  *pbl0 = *pbl1 = *pbl2 = 0;
437  if (!dir)
438  return (PIXA *)ERROR_PTR("dir not defined", __func__, NULL);
439  fileno = (fontsize / 2) - 2;
440  if (fileno < 0 || fileno >= NUM_FONTS)
441  return (PIXA *)ERROR_PTR("font size invalid", __func__, NULL);
442 
443  pathname = pathJoin(dir, inputfonts[fileno]);
444  pix = pixRead(pathname);
445  LEPT_FREE(pathname);
446  if (!pix) {
447  L_ERROR("pix not found for font size %d\n", __func__, fontsize);
448  return NULL;
449  }
450 
451  pixa = pixaGenerateFont(pix, fontsize, pbl0, pbl1, pbl2);
452  pixDestroy(&pix);
453  return pixa;
454 }
455 
456 
471 static PIXA *
472 pixaGenerateFontFromString(l_int32 fontsize,
473  l_int32 *pbl0,
474  l_int32 *pbl1,
475  l_int32 *pbl2)
476 {
477 l_uint8 *data;
478 l_int32 redsize, nbytes;
479 PIX *pix;
480 PIXA *pixa;
481 
482  if (!pbl0 || !pbl1 || !pbl2)
483  return (PIXA *)ERROR_PTR("&bl not all defined", __func__, NULL);
484  *pbl0 = *pbl1 = *pbl2 = 0;
485  redsize = (fontsize / 2) - 2;
486  if (redsize < 0 || redsize >= NUM_FONTS)
487  return (PIXA *)ERROR_PTR("invalid font size", __func__, NULL);
488 
489  if (fontsize == 4) {
490  data = decodeBase64(fontdata_4, strlen(fontdata_4), &nbytes);
491  } else if (fontsize == 6) {
492  data = decodeBase64(fontdata_6, strlen(fontdata_6), &nbytes);
493  } else if (fontsize == 8) {
494  data = decodeBase64(fontdata_8, strlen(fontdata_8), &nbytes);
495  } else if (fontsize == 10) {
496  data = decodeBase64(fontdata_10, strlen(fontdata_10), &nbytes);
497  } else if (fontsize == 12) {
498  data = decodeBase64(fontdata_12, strlen(fontdata_12), &nbytes);
499  } else if (fontsize == 14) {
500  data = decodeBase64(fontdata_14, strlen(fontdata_14), &nbytes);
501  } else if (fontsize == 16) {
502  data = decodeBase64(fontdata_16, strlen(fontdata_16), &nbytes);
503  } else if (fontsize == 18) {
504  data = decodeBase64(fontdata_18, strlen(fontdata_18), &nbytes);
505  } else { /* fontsize == 20 */
506  data = decodeBase64(fontdata_20, strlen(fontdata_20), &nbytes);
507  }
508  if (!data)
509  return (PIXA *)ERROR_PTR("data not made", __func__, NULL);
510 
511  pix = pixReadMem(data, nbytes);
512  LEPT_FREE(data);
513  if (!pix)
514  return (PIXA *)ERROR_PTR("pix not made", __func__, NULL);
515 
516  pixa = pixaGenerateFont(pix, fontsize, pbl0, pbl1, pbl2);
517  pixDestroy(&pix);
518  return pixa;
519 }
520 
521 
540 static PIXA *
542  l_int32 fontsize,
543  l_int32 *pbl0,
544  l_int32 *pbl1,
545  l_int32 *pbl2)
546 {
547 l_int32 i, j, nrows, nrowchars, nchars, h, yval;
548 l_int32 width, height;
549 l_int32 baseline[3];
550 l_int32 *tab = NULL;
551 BOX *box, *box1, *box2;
552 BOXA *boxar, *boxac, *boxacs;
553 PIX *pix1, *pix2, *pixr, *pixrc, *pixc;
554 PIXA *pixa;
555 l_int32 n, w, inrow, top;
556 l_int32 *ia;
557 NUMA *na;
558 
559  if (!pbl0 || !pbl1 || !pbl2)
560  return (PIXA *)ERROR_PTR("&bl not all defined", __func__, NULL);
561  *pbl0 = *pbl1 = *pbl2 = 0;
562  if (!pixs)
563  return (PIXA *)ERROR_PTR("pixs not defined", __func__, NULL);
564 
565  /* Locate the 3 rows of characters */
566  w = pixGetWidth(pixs);
567  na = pixCountPixelsByRow(pixs, NULL);
568  boxar = boxaCreate(0);
569  n = numaGetCount(na);
570  ia = numaGetIArray(na);
571  inrow = 0;
572  for (i = 0; i < n; i++) {
573  if (!inrow && ia[i] > 0) {
574  inrow = 1;
575  top = i;
576  } else if (inrow && ia[i] == 0) {
577  inrow = 0;
578  box = boxCreate(0, top, w, i - top);
579  boxaAddBox(boxar, box, L_INSERT);
580  }
581  }
582  LEPT_FREE(ia);
583  numaDestroy(&na);
584  nrows = boxaGetCount(boxar);
585 #if DEBUG_FONT_GEN
586  L_INFO("For fontsize %s, have %d rows\n", __func__, fontsize, nrows);
587 #endif /* DEBUG_FONT_GEN */
588  if (nrows != 3) {
589  L_INFO("nrows = %d; skipping fontsize %d\n", __func__, nrows, fontsize);
590  boxaDestroy(&boxar);
591  return (PIXA *)ERROR_PTR("3 rows not generated", __func__, NULL);
592  }
593 
594  /* Grab the character images and baseline data */
595 #if DEBUG_BASELINE
596  lept_rmdir("baseline");
597  lept_mkdir("baseline");
598 #endif /* DEBUG_BASELINE */
599  tab = makePixelSumTab8();
600  pixa = pixaCreate(95);
601  for (i = 0; i < nrows; i++) {
602  box = boxaGetBox(boxar, i, L_CLONE);
603  pixr = pixClipRectangle(pixs, box, NULL); /* row of chars */
604  pixGetTextBaseline(pixr, tab, &yval);
605  baseline[i] = yval;
606 
607 #if DEBUG_BASELINE
608  L_INFO("Baseline info: row %d, yval = %d, h = %d\n", __func__,
609  i, yval, pixGetHeight(pixr));
610  pix1 = pixCopy(NULL, pixr);
611  pixRenderLine(pix1, 0, yval, pixGetWidth(pix1), yval, 1,
612  L_FLIP_PIXELS);
613  if (i == 0 )
614  pixWriteDebug("/tmp/baseline/row0.png", pix1, IFF_PNG);
615  else if (i == 1)
616  pixWriteDebug("/tmp/baseline/row1.png", pix1, IFF_PNG);
617  else
618  pixWriteDebug("/tmp/baseline/row2.png", pix1, IFF_PNG);
619  pixDestroy(&pix1);
620 #endif /* DEBUG_BASELINE */
621 
622  boxDestroy(&box);
623  pixrc = pixCloseSafeBrick(NULL, pixr, 1, 35);
624  boxac = pixConnComp(pixrc, NULL, 8);
625  boxacs = boxaSort(boxac, L_SORT_BY_X, L_SORT_INCREASING, NULL);
626  if (i == 0) { /* consolidate the two components of '"' */
627  box1 = boxaGetBox(boxacs, 1, L_CLONE);
628  box2 = boxaGetBox(boxacs, 2, L_CLONE);
629  box1->w = box2->x + box2->w - box1->x; /* increase width */
630  boxDestroy(&box1);
631  boxDestroy(&box2);
632  boxaRemoveBox(boxacs, 2);
633  }
634  h = pixGetHeight(pixr);
635  nrowchars = boxaGetCount(boxacs);
636  for (j = 0; j < nrowchars; j++) {
637  box = boxaGetBox(boxacs, j, L_COPY);
638  if (box->w <= 2 && box->h == 1) { /* skip 1x1, 2x1 components */
639  boxDestroy(&box);
640  continue;
641  }
642  box->y = 0;
643  box->h = h - 1;
644  pixc = pixClipRectangle(pixr, box, NULL);
645  boxDestroy(&box);
646  if (i == 0 && j == 0) /* add a pix for the space; change later */
647  pixaAddPix(pixa, pixc, L_COPY);
648  if (i == 2 && j == 0) /* add a pix for the '\'; change later */
649  pixaAddPix(pixa, pixc, L_COPY);
650  pixaAddPix(pixa, pixc, L_INSERT);
651  }
652  pixDestroy(&pixr);
653  pixDestroy(&pixrc);
654  boxaDestroy(&boxac);
655  boxaDestroy(&boxacs);
656  }
657  LEPT_FREE(tab);
658 
659  nchars = pixaGetCount(pixa);
660  if (nchars != 95)
661  return (PIXA *)ERROR_PTR("95 chars not generated", __func__, NULL);
662 
663  *pbl0 = baseline[0];
664  *pbl1 = baseline[1];
665  *pbl2 = baseline[2];
666 
667  /* Fix the space character up; it should have no ON pixels,
668  * and be about twice as wide as the '!' character. */
669  pix1 = pixaGetPix(pixa, 0, L_CLONE);
670  width = 2 * pixGetWidth(pix1);
671  height = pixGetHeight(pix1);
672  pixDestroy(&pix1);
673  pix1 = pixCreate(width, height, 1);
674  pixaReplacePix(pixa, 0, pix1, NULL);
675 
676  /* Fix up the '\' character; use a LR flip of the '/' char */
677  pix1 = pixaGetPix(pixa, 15, L_CLONE);
678  pix2 = pixFlipLR(NULL, pix1);
679  pixDestroy(&pix1);
680  pixaReplacePix(pixa, 60, pix2, NULL);
681 
682 #if DEBUG_CHARS
683  pix1 = pixaDisplayTiled(pixa, 1500, 0, 10);
684  pixDisplay(pix1, 100 * i, 200);
685  pixDestroy(&pix1);
686 #endif /* DEBUG_CHARS */
687 
688  boxaDestroy(&boxar);
689  return pixa;
690 }
691 
692 
709 static l_int32
711  l_int32 *tab8,
712  l_int32 *py)
713 {
714 l_int32 i, h, val1, val2, diff, diffmax, ymax;
715 l_int32 *tab;
716 NUMA *na;
717 
718  if (!pixs)
719  return ERROR_INT("pixs not defined", __func__, 1);
720  if (!py)
721  return ERROR_INT("&y not defined", __func__, 1);
722  *py = 0;
723  if (!tab8)
724  tab = makePixelSumTab8();
725  else
726  tab = tab8;
727 
728  na = pixCountPixelsByRow(pixs, tab);
729  h = numaGetCount(na);
730  diffmax = 0;
731  ymax = 0;
732  for (i = 1; i < h; i++) {
733  numaGetIValue(na, i - 1, &val1);
734  numaGetIValue(na, i, &val2);
735  diff = L_MAX(0, val1 - val2);
736  if (diff > diffmax) {
737  diffmax = diff;
738  ymax = i - 1; /* upper raster line */
739  }
740  }
741  *py = ymax;
742 
743  if (!tab8)
744  LEPT_FREE(tab);
745  numaDestroy(&na);
746  return 0;
747 }
748 
749 
782 static l_int32
784 {
785 l_int32 i, maxh, height, charwidth, xwidth, kernwidth;
786 l_int32 *fonttab, *baselinetab, *widthtab;
787 PIX *pix;
788 
789  if (!bmf)
790  return ERROR_INT("bmf not defined", __func__, 1);
791 
792  /* First get the fonttab; we use this later for the char widths */
793  fonttab = (l_int32 *)LEPT_CALLOC(128, sizeof(l_int32));
794  bmf->fonttab = fonttab;
795  for (i = 0; i < 128; i++)
796  fonttab[i] = UNDEF;
797  for (i = 32; i < 127; i++)
798  fonttab[i] = i - 32;
799 
800  baselinetab = (l_int32 *)LEPT_CALLOC(128, sizeof(l_int32));
801  bmf->baselinetab = baselinetab;
802  for (i = 0; i < 128; i++)
803  baselinetab[i] = UNDEF;
804  for (i = 32; i <= 57; i++)
805  baselinetab[i] = bmf->baseline1;
806  for (i = 58; i <= 91; i++)
807  baselinetab[i] = bmf->baseline2;
808  baselinetab[92] = bmf->baseline1; /* the '\' char */
809  for (i = 93; i < 127; i++)
810  baselinetab[i] = bmf->baseline3;
811 
812  /* Generate array of character widths; req's fonttab to exist */
813  widthtab = (l_int32 *)LEPT_CALLOC(128, sizeof(l_int32));
814  bmf->widthtab = widthtab;
815  for (i = 0; i < 128; i++)
816  widthtab[i] = UNDEF;
817  for (i = 32; i < 127; i++) {
818  bmfGetWidth(bmf, i, &charwidth);
819  widthtab[i] = charwidth;
820  }
821 
822  /* Get the line height of text characters, from the highest
823  * ascender to the lowest descender; req's fonttab to exist. */
824  pix = bmfGetPix(bmf, 32);
825  maxh = pixGetHeight(pix);
826  pixDestroy(&pix);
827  pix = bmfGetPix(bmf, 58);
828  height = pixGetHeight(pix);
829  pixDestroy(&pix);
830  maxh = L_MAX(maxh, height);
831  pix = bmfGetPix(bmf, 93);
832  height = pixGetHeight(pix);
833  pixDestroy(&pix);
834  maxh = L_MAX(maxh, height);
835  bmf->lineheight = maxh;
836 
837  /* Get the kern width (distance between characters).
838  * We let it be the same for all characters in a given
839  * font size, and scale it linearly with the size;
840  * req's fonttab to be built first. */
841  bmfGetWidth(bmf, 120, &xwidth);
842  kernwidth = (l_int32)(0.08 * (l_float32)xwidth + 0.5);
843  bmf->kernwidth = L_MAX(1, kernwidth);
844 
845  /* Save the space width (between words) */
846  bmfGetWidth(bmf, 32, &charwidth);
847  bmf->spacewidth = charwidth;
848 
849  /* Save the extra vertical space between lines */
850  bmf->vertlinesep = (l_int32)(VertFractSep * bmf->lineheight + 0.5);
851 
852  return 0;
853 }
PIXA * pixaGetFont(const char *dir, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGetFont()
Definition: bmf.c:315
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:168
static PIXA * pixaGenerateFontFromFile(const char *dir, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFontFromFile()
Definition: bmf.c:423
static PIXA * pixaGenerateFont(PIX *pixs, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFont()
Definition: bmf.c:541
PIX * bmfGetPix(L_BMF *bmf, char chr)
bmfGetPix()
Definition: bmf.c:201
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:118
static PIXA * pixaGenerateFontFromString(l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFontFromString()
Definition: bmf.c:472
l_ok bmfGetBaseline(L_BMF *bmf, char chr, l_int32 *pbaseline)
bmfGetBaseline()
Definition: bmf.c:271
static l_int32 bmfMakeAsciiTables(L_BMF *bmf)
bmfMakeAsciiTables
Definition: bmf.c:783
l_ok pixaSaveFont(const char *indir, const char *outdir, l_int32 fontsize)
pixaSaveFont()
Definition: bmf.c:363
static l_int32 pixGetTextBaseline(PIX *pixs, l_int32 *tab8, l_int32 *py)
pixGetTextBaseline()
Definition: bmf.c:710
l_ok bmfGetWidth(L_BMF *bmf, char chr, l_int32 *pw)
bmfGetWidth()
Definition: bmf.c:234
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:273
l_ok boxaRemoveBox(BOXA *boxa, l_int32 index)
boxaRemoveBox()
Definition: boxbasic.c:957
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:553
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:519
l_int32 boxaGetCount(const BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:661
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:702
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:171
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:442
BOXA * boxaSort(BOXA *boxas, l_int32 sorttype, l_int32 sortorder, NUMA **pnaindex)
boxaSort()
Definition: boxfunc2.c:624
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:152
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:1455
PIX * pixCloseSafeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseSafeBrick()
Definition: morph.c:953
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:720
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:807
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2354
NUMA * pixCountPixelsByRow(PIX *pix, l_int32 *tab8)
pixCountPixelsByRow()
Definition: pix3.c:2096
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:994
@ L_FLIP_PIXELS
Definition: pix.h:567
@ L_SORT_BY_X
Definition: pix.h:528
@ L_COPY
Definition: pix.h:505
@ L_CLONE
Definition: pix.h:506
@ L_INSERT
Definition: pix.h:504
@ L_SORT_INCREASING
Definition: pix.h:522
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:493
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:404
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:680
PIXA * pixaRead(const char *filename)
pixaRead()
Definition: pixabasic.c:2480
l_ok pixaReplacePix(PIXA *pixa, l_int32 index, PIX *pix, BOX *box)
pixaReplacePix()
Definition: pixabasic.c:1246
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:629
l_ok pixaWrite(const char *filename, PIXA *pixa)
pixaWrite()
Definition: pixabasic.c:2639
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:647
PIX * pixaDisplayTiled(PIXA *pixa, l_int32 maxwidth, l_int32 background, l_int32 spacing)
pixaDisplayTiled()
Definition: pixafunc2.c:618
PIX * pixReadMem(const l_uint8 *data, size_t size)
pixReadMem()
Definition: readfile.c:822
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:189
PIX * pixFlipLR(PIX *pixd, PIX *pixs)
pixFlipLR()
Definition: rotateorth.c:421
l_int32 y
Definition: pix_internal.h:258
l_int32 x
Definition: pix_internal.h:257
l_int32 w
Definition: pix_internal.h:259
l_int32 h
Definition: pix_internal.h:260
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
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2213
char * pathJoin(const char *dir, const char *fname)
pathJoin()
Definition: utils2.c:2873
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2138