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
77static 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
85static PIXA *pixaGenerateFontFromFile(const char *dir, l_int32 fontsize,
86 l_int32 *pbl0, l_int32 *pbl1,
87 l_int32 *pbl2);
88static PIXA *pixaGenerateFontFromString(l_int32 fontsize, l_int32 *pbl0,
89 l_int32 *pbl1, l_int32 *pbl2);
90static PIXA *pixaGenerateFont(PIX *pixs, l_int32 fontsize, l_int32 *pbl0,
91 l_int32 *pbl1, l_int32 *pbl2);
92static l_int32 pixGetTextBaseline(PIX *pixs, l_int32 *tab8, l_int32 *py);
93static l_int32 bmfMakeAsciiTables(L_BMF *bmf);
94
95/*---------------------------------------------------------------------*/
96/* Bmf create/destroy */
97/*---------------------------------------------------------------------*/
116L_BMF *
117bmfCreate(const char *dir,
118 l_int32 fontsize)
119{
120L_BMF *bmf;
121PIXA *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);
158 return bmf;
159}
160
161
168void
170{
171L_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/*---------------------------------------------------------------------*/
203PIX *
205 char chr)
206{
207l_int32 i, index;
208PIXA *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
238l_ok
240 char chr,
241 l_int32 *pw)
242{
243l_int32 i, index;
244PIXA *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
277l_ok
279 char chr,
280 l_int32 *pbaseline)
281{
282l_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/*---------------------------------------------------------------------*/
323PIXA *
324pixaGetFont(const char *dir,
325 l_int32 fontsize,
326 l_int32 *pbl0,
327 l_int32 *pbl1,
328 l_int32 *pbl2)
329{
330char *pathname;
331l_int32 fileno;
332PIXA *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
373l_ok
374pixaSaveFont(const char *indir,
375 const char *outdir,
376 l_int32 fontsize)
377{
378char *pathname;
379l_int32 bl1, bl2, bl3;
380PIXA *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
435static PIXA *
437 l_int32 fontsize,
438 l_int32 *pbl0,
439 l_int32 *pbl1,
440 l_int32 *pbl2)
441{
442char *pathname;
443l_int32 fileno;
444PIX *pix;
445PIXA *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
486static PIXA *
488 l_int32 *pbl0,
489 l_int32 *pbl1,
490 l_int32 *pbl2)
491{
492l_uint8 *data;
493l_int32 redsize, nbytes;
494PIX *pix;
495PIXA *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
557static PIXA *
559 l_int32 fontsize,
560 l_int32 *pbl0,
561 l_int32 *pbl1,
562 l_int32 *pbl2)
563{
564l_int32 i, j, nrows, nrowchars, nchars, h, yval;
565l_int32 width, height;
566l_int32 baseline[3];
567l_int32 *tab = NULL;
568BOX *box, *box1, *box2;
569BOXA *boxar, *boxac, *boxacs;
570PIX *pix1, *pix2, *pixr, *pixrc, *pixc;
571PIXA *pixa;
572l_int32 n, w, inrow, top;
573l_int32 *ia;
574NUMA *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,
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
728static l_int32
730 l_int32 *tab8,
731 l_int32 *py)
732{
733l_int32 i, h, val1, val2, diff, diffmax, ymax;
734l_int32 *tab;
735NUMA *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
803static l_int32
805{
806l_int32 i, maxh, height, charwidth, xwidth, kernwidth;
807l_int32 *fonttab, *baselinetab, *widthtab;
808PIX *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}
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
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:117
static PIXA * pixaGenerateFont(PIX *pixs, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFont()
Definition: bmf.c:558
static PIXA * pixaGenerateFontFromString(l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGenerateFontFromString()
Definition: bmf.c:487
PIXA * pixaGetFont(const char *dir, l_int32 fontsize, l_int32 *pbl0, l_int32 *pbl1, l_int32 *pbl2)
pixaGetFont()
Definition: bmf.c:324
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
PIX * bmfGetPix(L_BMF *bmf, char chr)
bmfGetPix()
Definition: bmf.c:204
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
l_ok boxaRemoveBox(BOXA *boxa, l_int32 index)
boxaRemoveBox()
Definition: boxbasic.c:1048
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:734
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:502
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:620
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:583
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
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:847
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
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
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 * pixaRead(const char *filename)
pixaRead()
Definition: pixabasic.c:2610
l_ok pixaGetPixDimensions(PIXA *pixa, l_int32 index, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixaGetPixDimensions()
Definition: pixabasic.c:726
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
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 * pixRead(const char *filename)
pixRead()
Definition: readfile.c:193
PIX * pixReadMem(const l_uint8 *data, size_t size)
pixReadMem()
Definition: readfile.c:844
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
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
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223