diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2020-06-28 17:52:14 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2020-06-28 17:52:14 +0000 |
commit | 1cd3ef0dd6c2236d0b329879bacd9360d01c88a1 (patch) | |
tree | a60016b5dd48fbf681ebfb43a6ca0d7e20a391d8 /generator | |
parent | cbbf595776cee6b8d8a24becf49ee6468eeba712 (diff) | |
download | netpbm-mirror-1cd3ef0dd6c2236d0b329879bacd9360d01c88a1.tar.gz netpbm-mirror-1cd3ef0dd6c2236d0b329879bacd9360d01c88a1.tar.xz netpbm-mirror-1cd3ef0dd6c2236d0b329879bacd9360d01c88a1.zip |
Promote Development to Advaanced - Release 10.91
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@3877 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'generator')
-rw-r--r-- | generator/pamstereogram.c | 278 | ||||
-rw-r--r-- | generator/pbmtext.c | 382 | ||||
-rw-r--r-- | generator/pbmtextps.c | 2 | ||||
-rw-r--r-- | generator/ppmforge.c | 2 | ||||
-rw-r--r-- | generator/ppmmake.c | 2 | ||||
-rw-r--r-- | generator/ppmrough.c | 2 |
6 files changed, 488 insertions, 180 deletions
diff --git a/generator/pamstereogram.c b/generator/pamstereogram.c index 6e5f5ce0..9b861b51 100644 --- a/generator/pamstereogram.c +++ b/generator/pamstereogram.c @@ -16,7 +16,7 @@ * * ---------------------------------------------------------------------- * - * Copyright (C) 2006-2015 Scott Pakin <scott+pbm@pakin.org> + * Copyright (C) 2006-2020 Scott Pakin <scott+pbm@pakin.org> * * All rights reserved. * @@ -94,6 +94,7 @@ struct cmdlineInfo { enum outputType outputType; /* Type of output file */ unsigned int xbegin; /* -xbegin option */ unsigned int xbeginSpec; /* -xbegin option count */ + unsigned int tileable; /* -tileable option */ }; @@ -207,6 +208,8 @@ parseCommandLine(int argc, &planesSpec, 0); OPTENT3(0, "xbegin", OPT_UINT, &cmdlineP->xbegin, &cmdlineP->xbeginSpec, 0); + OPTENT3(0, "tileable", OPT_FLAG, NULL, + (unsigned int *)&cmdlineP->tileable, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ @@ -291,6 +294,11 @@ parseCommandLine(int argc, if (cmdlineP->makemask && cmdlineP->patfile) pm_error("You may not specify both -makemask and -patfile"); + if (cmdlineP->tileable && cmdlineP->xbeginSpec) + pm_error("You may not specify both -tileable and -xbegin"); + if (cmdlineP->tileable && !cmdlineP->patfile) + pm_error("-tileable is valid only with -patfile"); + if (cmdlineP->patfile && blackandwhite) pm_error("-blackandwhite is not valid with -patfile"); if (cmdlineP->patfile && grayscale) @@ -844,11 +852,12 @@ makeStereoRow(const struct pam * const inPamP, unsigned int const dpi, unsigned int const optWidth, unsigned int const smoothing) { +/*---------------------------------------------------------------------------- + Given a row of the depth map inRow[], compute the sameL and sameR arrays, + which indicate for each pixel which pixel to its left and right it should be + colored the same as. +-----------------------------------------------------------------------------*/ -/* Given a row of the depth map, compute the sameL and sameR arrays, - * which indicate for each pixel which pixel to its left and right it - * should be colored the same as. - */ #define Z(X) (inRow[X][0]/(double)inPamP->maxval) unsigned int col; @@ -865,7 +874,7 @@ makeStereoRow(const struct pam * const inPamP, if (left >= 0 && right < inPamP->width) { bool isVisible; - + if (sameL[right] != right) { /* Right point already linked */ if (sameL[right] < left) { @@ -1114,12 +1123,15 @@ static void makeImageRowMts(outGenerator * const outGenP, unsigned int const row, const unsigned int * const same, - unsigned int * const sameFp, + unsigned int * const colNumBuffer, tuple * const rowBuffer, const tuple * const outRow) { /*---------------------------------------------------------------------------- Make a row of a mapped-texture stereogram. -----------------------------------------------------------------------------*/ + unsigned int * const sameFp = colNumBuffer; + /* Fixed point of same[] */ + unsigned int * tuplesInCol; /* tuplesInCol[C] is the number of tuples averaged together to make Column C. @@ -1165,7 +1177,6 @@ makeImageRowMts(outGenerator * const outGenP, static void makeImageRow(outGenerator * const outGenP, unsigned int const row, - unsigned int const optWidth, unsigned int const xbegin, const unsigned int * const sameL, const unsigned int * const sameR, @@ -1243,6 +1254,165 @@ invertHeightRow(const struct pam * const heightPamP, static void +makeOneImageRow(unsigned int const row, + outGenerator * const outputGeneratorP, + bool const makeMask, + const unsigned int * const sameL, + const unsigned int * const sameR, + unsigned int * const colNumBuffer, + unsigned int const xbegin, + tuple * const rowBuffer, + tuple * const outRow) { + + if (makeMask) + makeMaskRow(&outputGeneratorP->pam, xbegin, sameL, sameR, outRow); + else { + if (outputGeneratorP->textureP) + makeImageRowMts(outputGeneratorP, row, sameR, colNumBuffer, + rowBuffer, outRow); + else + makeImageRow(outputGeneratorP, row, + xbegin, sameL, sameR, outRow); + } +} + + + +static void +constructRowTileable(const struct pam * const inPamP, + outGenerator * const outputGeneratorP, + bool const makeMask, + const unsigned int * const sameL, + const unsigned int * const sameR, + unsigned int const row, + tuple * const outRow, + tuple * const outRowBuf1, + tuple * const outRowBuf2, + unsigned int * const colNumBuf2) { + + tuple * const outRowMax = outRowBuf1; + + unsigned int col; + + /* Create two rows with extreme xbegin values and blend the second + into the first. outRow[] serves as both the buffer for the xbegin=0 + version and the merged output. outRowMax[] is the buffer for the + xbegin=maximum case. + */ + makeOneImageRow(row, outputGeneratorP, makeMask, sameL, sameR, colNumBuf2, + 0, outRowBuf2, outRow); + + makeOneImageRow(row, outputGeneratorP, makeMask, sameL, sameR, colNumBuf2, + inPamP->width - 1, outRowBuf2, outRowMax); + + for (col = 0; col < inPamP->width; ++col) { + unsigned int plane; + unsigned int oplane; + + if (outputGeneratorP->pam.have_opacity) + oplane = outputGeneratorP->pam.opacity_plane; + + for (plane = 0; plane < outputGeneratorP->pam.color_depth; ++plane) { + + sample samp, sampMax; + + if (outputGeneratorP->pam.have_opacity) { + /* If one sample is fully transparent, use the + other sample for both purposes + */ + if (outRow[col][oplane] == 0) + samp = sampMax = outRowMax[col][plane]; + else if (outRowMax[col][oplane] == 0) + samp = sampMax = outRow[col][plane]; + else { + samp = outRow[col][plane]; + sampMax = outRowMax[col][plane]; + } + } else { + samp = outRow[col][plane]; + sampMax = outRowMax[col][plane]; + } + + outRow[col][plane] = + (col*sampMax + (inPamP->width - col - 1)*samp) / + (inPamP->width - 1); + } + if (outputGeneratorP->pam.have_opacity) { + sample samp, sampMax; + + /* Take the maximum alpha for partially transparent samples. */ + samp = outRow[col][oplane]; + sampMax = outRowMax[col][oplane]; + outRow[col][oplane] = MAX(samp, sampMax); + } + } +} + + + +static void +doRow(const struct pam * const inPamP, + outGenerator * const outputGeneratorP, + double const depthOfField, + double const eyesep, + unsigned int const dpi, + bool const crossEyed, + bool const makeMask, + bool const tileable, + unsigned int const magnifypat, + unsigned int const smoothing, + unsigned int const xbegin, + unsigned int const row, + tuple * const inRow, + tuple * const outRowBuf0, + tuple * const outRowBuf1, + tuple * const outRowBuf2, + unsigned int * const colNumBuf0, + unsigned int * const colNumBuf1, + unsigned int * const colNumBuf2) { + + tuple * const outRow = outRowBuf0; + unsigned int * const sameL = colNumBuf0; + /* sameL[N] is the column number of a pixel to the + left forced to have the same color as the one in column N + */ + unsigned int * const sameR = colNumBuf1; + /* sameR[N] is the column number of a pixel to the + right forced to have the same color as the one in column N + */ + + pnm_readpamrow(inPamP, inRow); + + if (crossEyed) + /* Invert heights for cross-eyed (as opposed to wall-eyed) + people. + */ + invertHeightRow(inPamP, inRow); + + /* Determine color constraints. */ + makeStereoRow(inPamP, inRow, sameL, sameR, depthOfField, eyesep, dpi, + ROUNDU(eyesep * dpi)/(magnifypat * 2), + smoothing); + + /* Construct a single row. */ + if (tileable) { + constructRowTileable(inPamP, outputGeneratorP, makeMask, + sameL, sameR, row, outRow, + outRowBuf1, outRowBuf2, colNumBuf2); + + } else { + makeOneImageRow(row, outputGeneratorP, makeMask, + sameL, sameR, colNumBuf2, + xbegin, outRowBuf1, outRow); + } + + /* Write the resulting row. */ + pnm_writepamrow(&outputGeneratorP->pam, outRow); +} + + + +static void makeImageRows(const struct pam * const inPamP, outGenerator * const outputGeneratorP, double const depthOfField, @@ -1250,72 +1420,50 @@ makeImageRows(const struct pam * const inPamP, unsigned int const dpi, bool const crossEyed, bool const makeMask, + bool const tileable, unsigned int const magnifypat, unsigned int const smoothing, unsigned int const xbegin) { - tuple * inRow; /* One row of pixels read from the height-map file */ - tuple * outRow; /* One row of pixels to write to the height-map file */ - unsigned int * sameR; - /* Malloced array: sameR[N] is the column number of a pixel to the - right forced to have the same color as the one in column N - */ - unsigned int * sameL; - /* Malloced array: sameL[N] is the column number of a pixel to the - left forced to have the same color as the one in column N - */ - unsigned int * sameRfp; - /* Malloced array: Fixed point of sameR[] */ - tuple * rowBuffer; /* Scratch row needed for texture manipulation */ + tuple * inRow; /* Buffer for use in reading from the height-map image */ + tuple * outRowBuf0; /* Buffer for use in generating output rows */ + tuple * outRowBuf1; /* Buffer for use in generating output rows */ + tuple * outRowBuf2; /* Buffer for use in generating output rows */ + unsigned int * colNumBuf0; + unsigned int * colNumBuf1; + unsigned int * colNumBuf2; unsigned int row; /* Current row in the input and output files */ inRow = pnm_allocpamrow(inPamP); - outRow = pnm_allocpamrow(&outputGeneratorP->pam); - MALLOCARRAY(sameR, inPamP->width); - if (sameR == NULL) - pm_error("Unable to allocate space for \"sameR\" array."); - MALLOCARRAY(sameL, inPamP->width); - if (sameL == NULL) - pm_error("Unable to allocate space for \"sameL\" array."); - - MALLOCARRAY(sameRfp, inPamP->width); - if (sameRfp == NULL) - pm_error("Unable to allocate space for \"sameRfp\" array."); - rowBuffer = pnm_allocpamrow(&outputGeneratorP->pam); + outRowBuf0 = pnm_allocpamrow(&outputGeneratorP->pam); + outRowBuf1 = pnm_allocpamrow(&outputGeneratorP->pam); + outRowBuf2 = pnm_allocpamrow(&outputGeneratorP->pam); + MALLOCARRAY(colNumBuf0, inPamP->width); + if (colNumBuf0 == NULL) + pm_error("Unable to allocate space for %u column buffer", + inPamP->width); + MALLOCARRAY(colNumBuf1, inPamP->width); + if (colNumBuf1 == NULL) + pm_error("Unable to allocate space for %u column buffer", + inPamP->width); + MALLOCARRAY(colNumBuf2, inPamP->width); + if (colNumBuf2 == NULL) + pm_error("Unable to allocate space for %u column buffer", + inPamP->width); for (row = 0; row < inPamP->height; ++row) { - pnm_readpamrow(inPamP, inRow); - if (crossEyed) - /* Invert heights for cross-eyed (as opposed to wall-eyed) - people. - */ - invertHeightRow(inPamP, inRow); - - /* Determine color constraints. */ - makeStereoRow(inPamP, inRow, sameL, sameR, depthOfField, eyesep, dpi, - ROUNDU(eyesep * dpi)/(magnifypat * 2), - smoothing); - - if (makeMask) - makeMaskRow(&outputGeneratorP->pam, xbegin, sameL, sameR, outRow); - else { - if (outputGeneratorP->textureP) - makeImageRowMts(outputGeneratorP, row, sameR, sameRfp, - rowBuffer, outRow); - else - makeImageRow(outputGeneratorP, row, - ROUNDU(eyesep * dpi)/(magnifypat * 2), - xbegin, sameL, sameR, outRow); - } - /* Write the resulting row. */ - pnm_writepamrow(&outputGeneratorP->pam, outRow); + doRow(inPamP, outputGeneratorP, depthOfField, eyesep, dpi, + crossEyed, makeMask, tileable, magnifypat, smoothing, xbegin, + row, + inRow, outRowBuf0, outRowBuf1, outRowBuf2, + colNumBuf0, colNumBuf1, colNumBuf2); } - pnm_freepamrow(rowBuffer); - free(sameRfp); - free(sameL); - free(sameR); - pnm_freepamrow(outRow); + free(colNumBuf2); + free(colNumBuf1); + free(colNumBuf0); + pnm_freepamrow(outRowBuf1); + pnm_freepamrow(outRowBuf0); pnm_freepamrow(inRow); } @@ -1361,8 +1509,8 @@ produceStereogram(FILE * const ifP, makeImageRows(&inPam, outputGeneratorP, cmdline.depth, cmdline.eyesep, cmdline.dpi, - cmdline.crosseyed, cmdline.makemask, cmdline.magnifypat, - cmdline.smoothing, xbegin); + cmdline.crosseyed, cmdline.makemask, cmdline.tileable, + cmdline.magnifypat, cmdline.smoothing, xbegin); if (cmdline.guidebottom) drawguides(cmdline.guidesize, &outputGeneratorP->pam, diff --git a/generator/pbmtext.c b/generator/pbmtext.c index e52a296e..7ea64857 100644 --- a/generator/pbmtext.c +++ b/generator/pbmtext.c @@ -30,6 +30,7 @@ #include "pbm.h" #include "pbmfont.h" + /* Max length of input text. Valid for text which is part of the command line and also for text fed from standard input. Note that newline is counted as a character. @@ -55,6 +56,7 @@ struct CmdlineInfo { unsigned int nomargins; /* -nomargins option specified */ unsigned int dryrun; /* -dry-run option specified */ unsigned int textdump; /* -text-dump option specified */ + unsigned int entirefont; /* -load-entire-font option specified */ unsigned int verbose; /* -verbose option specified */ /* undocumented option */ unsigned int dumpsheet; /* font data sheet in PBM format for -font */ @@ -133,6 +135,7 @@ parseCommandLine(int argc, const char ** argv, OPTENT3(0, "dry-run", OPT_FLAG, NULL, &cmdlineP->dryrun, 0); OPTENT3(0, "text-dump", OPT_FLAG, NULL, &cmdlineP->textdump, 0); OPTENT3(0, "dump-sheet", OPT_FLAG, NULL, &cmdlineP->dumpsheet, 0); + OPTENT3(0, "load-entire-font", OPT_FLAG, NULL, &cmdlineP->entirefont, 0); /* Set the defaults */ cmdlineP->font = NULL; @@ -166,6 +169,8 @@ parseCommandLine(int argc, const char ** argv, if (cmdlineP->font != NULL && cmdlineP->builtin != NULL) pm_error("You cannot specify both -font and -builtin"); + else if (cmdlineP->font == NULL && cmdlineP->entirefont) + pm_error("You cannot specify -load-entire-font without -font"); if (cmdlineP->textdump) { if (cmdlineP->dryrun) @@ -206,12 +211,10 @@ reportFont(const struct font2 * const fontP) { - - - static struct font2 * -font2FromFile(const char * const fileName, - PM_WCHAR const maxmaxglyph) { +font2FromFile(const char * const fileName, + PM_WCHAR const maxmaxglyph, + const struct pm_selector * const selectorP) { struct font2 * font2P; @@ -224,7 +227,7 @@ font2FromFile(const char * const fileName, /* This is the normal program flow */ pm_setjmpbuf(&jmpbuf); - font2P = pbm_loadfont2(fileName, maxmaxglyph); + font2P = pbm_loadfont2select(fileName, maxmaxglyph, selectorP); pm_setjmpbuf(NULL); } else { @@ -241,23 +244,176 @@ font2FromFile(const char * const fileName, +static bool +codepointIsValid(struct font2 * const fontP, + PM_WCHAR const codepoint) { +/*---------------------------------------------------------------------------- + 'codepoint' is a valid entry in the font indicated by 'fontP'. +-----------------------------------------------------------------------------*/ + bool retval; + + assert(pm_selector_is_marked(fontP->selectorP, codepoint)); + + if (codepoint > fontP->maxglyph || fontP->glyph[codepoint] == NULL) + retval = false; + else retval = true; + + return (retval); + +} + + + +static const char * +charDescription(PM_WCHAR const codepoint) { +/*---------------------------------------------------------------------------- + Descriptive string for codepoint 'codepoint'. + + Certain codepoints appear frequently in text files and cause problems when + missing in the font set, so we give those descriptions. For other + codepoint, we just return a null string. +-----------------------------------------------------------------------------*/ + + const char * name; + + switch (codepoint) { + case '\r' : name="carriage return"; break; + case '\n' : name="line feed"; break; /* for future use */ + case '\t' : name="tab"; break; /* for future use */ + case ' ' : name="space"; break; + case 0xFEFF: name="byte order mark"; break; + default : name=""; break; + } + + return name; +} + + + +enum FixMode {SILENT, /* convert silently */ + WARN, /* output message to stderr */ + QUIT /* abort */ }; + + + +static void +reportAbsentGlyphs(bool const wchar, + struct font2 * const fontP, + const struct pm_selector * const textSelectorP, + unsigned int * const missingCharCtP) { +/*---------------------------------------------------------------------------- + Compare the glyph entries in *fontP with the requests in *textSelectorP. + + Note that we may need the space character as a substitute for missing + glyphs while the input text has no spaces. In rare cases the font may not + have a space character. + + Currently, this program reads the font file only once. A future version + may opt to read it a second time to load the substitute glyph. +-----------------------------------------------------------------------------*/ + PM_WCHAR codepoint; + unsigned int missingCharCt; + + for (codepoint = textSelectorP->min, missingCharCt = 0; + codepoint <= textSelectorP->max; ++codepoint) { + + if (pm_selector_is_marked(textSelectorP, codepoint) && + !codepointIsValid(fontP, codepoint)) { + ++missingCharCt; + if (missingCharCt == 1) { /* initial */ + pm_message("failed to load glyph data for these code points " + "in input:"); + } + + pm_message(wchar ? "+%05X %s" : "%02X %s", + (unsigned int) codepoint, + charDescription(codepoint)); + } + } + + *missingCharCtP = missingCharCt; +} + + + static void -computeFont(struct CmdlineInfo const cmdline, - struct font2 ** const fontPP) { +validateFont(bool const wchar, + struct font2 * const fontP, + const struct pm_selector * const textSelectorP, + enum FixMode const fixmode, + bool const verbose, + bool * const hasAllCharsP) { +/*---------------------------------------------------------------------------- + If any glyphs required by the text indicated by *textSelectorP are missing + from font *fontP, issue a warning message or abort the program according to + 'fixmode'. + + Abort the program if one or more characters are missing and the space + character is one of them. + + Return (if we return) as *hasAllCharsP whether the font has all the glyphs. +-----------------------------------------------------------------------------*/ + unsigned int missingCharCt; + + assert (textSelectorP != NULL); + assert(pm_selector_marked_ct(textSelectorP) >= 0); + + reportAbsentGlyphs(wchar, fontP, textSelectorP, &missingCharCt); + + if (missingCharCt > 0) { + if (verbose) + pm_message("%u characters absent in font", missingCharCt); + + if (fixmode == QUIT) + pm_error("aborting"); + else if (!codepointIsValid(fontP, L' ')) + pm_error ("replacement character (space) absent; aborting"); + else + pm_message("undefined code points will be converted to space"); + } + + *hasAllCharsP = (missingCharCt == 0); +} + - struct font2 * font2P; - if (cmdline.font) - font2P = font2FromFile(cmdline.font, - cmdline.wchar ? PM_FONT2_MAXGLYPH : - PM_FONT_MAXGLYPH); - else if (cmdline.builtin) +static void +computeFont(struct CmdlineInfo const cmdline, + struct font2 ** const fontPP, + const struct pm_selector * const textSelectorP, + enum FixMode const fixmode, + bool * const fontHasAllCharsP) { + + struct font2 * font2P; + struct pm_selector * fontSelectorP; + + if (cmdline.font) { + if(cmdline.entirefont) + fontSelectorP = NULL; + else if(!pm_selector_is_marked(textSelectorP, L' ')) { + pm_selector_copy(MAX(textSelectorP->max, L' '), + textSelectorP, &fontSelectorP); + pm_selector_mark(fontSelectorP, L' '); + } else + fontSelectorP = (struct pm_selector *) textSelectorP; + + font2P = font2FromFile(cmdline.font, cmdline.wchar ? + PM_FONT2_MAXGLYPH : PM_FONT_MAXGLYPH, + fontSelectorP); + } else if (cmdline.builtin) font2P = pbm_defaultfont2(cmdline.builtin); else font2P = pbm_defaultfont2(cmdline.wchar ? "bdf" : "bdf"); - if (cmdline.verbose) + if (cmdline.verbose) { reportFont(font2P); + pm_message("%u code points found in text", + pm_selector_marked_ct(textSelectorP)); + } + + validateFont(cmdline.wchar, font2P, textSelectorP, fixmode, + cmdline.verbose, + fontHasAllCharsP); *fontPP = font2P; } @@ -266,9 +422,6 @@ computeFont(struct CmdlineInfo const cmdline, struct Text { PM_WCHAR ** textArray; /* malloc'ed */ - /* This is strictly characters that are in user's font - no control - characters, no undefined code points. - */ unsigned int allocatedLineCount; unsigned int lineCount; }; @@ -309,28 +462,19 @@ freeTextArray(struct Text const text) { -enum FixMode {SILENT, /* convert silently */ - WARN, /* output message to stderr */ - QUIT /* abort */ }; - static void -fixControlChars(const PM_WCHAR * const input, - struct font2 * const fontP, - const PM_WCHAR ** const outputP, - enum FixMode const fixMode) { +setupSelector(const PM_WCHAR * const input, + const PM_WCHAR ** const outputP, + struct pm_selector * const selectorP) { /*---------------------------------------------------------------------------- - Return a translation of input[] that can be rendered as glyphs in - the font 'fontP'. Return it as newly malloced *outputP. + Read through input[] and record the codepoints encountered. Return it as + newly malloced *outputP. Expand tabs to spaces. Remove any trailing newline. (But leave intermediate ones as line delimiters). - - Depending on value of fixMode, turn anything that isn't a code point - in the font to a single space (which isn't guaranteed to be in the - font either, of course). -----------------------------------------------------------------------------*/ /* We don't know in advance how big the output will be because of the tab expansions. So we make sure before processing each input @@ -370,33 +514,19 @@ fixControlChars(const PM_WCHAR * const input, unsigned int const nextTabStop = (outCursor + tabSize) / tabSize * tabSize; - if (fontP->glyph[L' '] == NULL) - pm_error("space character not defined in font"); - while (outCursor < nextTabStop) output[outCursor++] = L' '; - } else if (currentChar > fontP->maxglyph || - !fontP->glyph[currentChar]) { - if (currentChar > PM_FONT2_MAXGLYPH) + + pm_selector_mark(selectorP, L' '); + + } else if (currentChar > PM_FONT2_MAXGLYPH) pm_message("code point %X is beyond what this program " "can handle. Max=%X", (unsigned int)currentChar, PM_FONT2_MAXGLYPH); - - /* Turn this unknown char into a single space. */ - if (fontP->glyph[L' '] == NULL) - pm_error("space character not defined in font"); - else if (fixMode == QUIT) - pm_error("code point %X not defined in font", - (unsigned int) currentChar ); - else { - if (fixMode == WARN) - pm_message("converting code point %X to space", - (unsigned int) currentChar ); - output[outCursor++] = ' '; - } - } else + else { output[outCursor++] = input[inCursor]; - + pm_selector_mark(selectorP, currentChar); + } assert(outCursor <= outputSize); } output[outCursor++] = L'\0'; @@ -437,7 +567,8 @@ getEdges(double const currentPosition, double rightEdge; if (glyphP == NULL) - pm_error("Unrenderable char: %04X", (unsigned int) currentChar); + pm_error("encountered unrenderable char: %04X", + (unsigned int) currentChar); else { leftEdge = (int) MIN(currentPosition + glyphP->x, currLeftEdge); rightEdge = MAX(currentPosition + glyphP->x + glyphP->width, @@ -475,8 +606,8 @@ advancePosition(double const currentPosition, pm_error("Negative -space value too large"); else pm_error("Abnormal horizontal advance value %d " - "for code point 0x%lx.", - glyphP->xadd, (unsigned long int) currentChar); + "for code point +%05X", + glyphP->xadd, (unsigned int) currentChar); } else if (currentPosition + advance > INT_MAX) pm_error("Image is too wide"); @@ -535,8 +666,8 @@ getLineDimensions(PM_WCHAR const line[], for (cursor = 0; line[cursor] != L'\0'; ++cursor) { PM_WCHAR const currentChar = line[cursor]; - unsigned long int const glyphIndex = (unsigned long int) currentChar; - struct glyph * const glyphP = fontP->glyph[glyphIndex]; + unsigned int const index = (unsigned int) currentChar; + struct glyph * const glyphP = fontP->glyph[index]; getEdges(currentPosition, currentChar, glyphP, leftEdge, rightEdge, &leftEdge, &rightEdge); @@ -593,9 +724,8 @@ getCharsWithinWidth(PM_WCHAR const line[], currentWidth <= targetWidth && line[cursor] != L'\0'; ++cursor) { PM_WCHAR const currentChar = line[cursor]; - unsigned long int const glyphIndex = - (unsigned long int) currentChar; - struct glyph * const glyphP = fontP->glyph[glyphIndex]; + unsigned int const index = (unsigned int) currentChar; + struct glyph * const glyphP = fontP->glyph[index]; getEdges(currentPosition, currentChar, glyphP, leftEdge, rightEdge, &leftEdge, &rightEdge); @@ -694,9 +824,8 @@ insertCharacters(bit ** const bits, for (cursor = 0; lp.textArray[line][cursor] != '\0'; ++cursor) { PM_WCHAR const currentChar = lp.textArray[line][cursor]; - unsigned long int const glyphIndex = - (unsigned long int)currentChar; - struct glyph * const glyphP = fontP->glyph[glyphIndex]; + unsigned int const index = (unsigned int) currentChar; + struct glyph * const glyphP = fontP->glyph[index]; int const toprow = row + fontP->maxheight + fontP->y - glyphP->height - glyphP->y; /* row number in image of top row in glyph */ @@ -943,10 +1072,9 @@ fgetNarrowWideString(PM_WCHAR * const widestring, static void -getText(PM_WCHAR const cmdlineText[], - struct font2 * const fontP, - struct Text * const inputTextP, - enum FixMode const fixMode) { +getText(PM_WCHAR const cmdlineText[], + struct Text * const inputTextP, + struct pm_selector * const selectorP) { /*---------------------------------------------------------------------------- Get as *inputTextP the text to format, given that the text on the command line (one word per command line argument, separated by spaces), @@ -969,8 +1097,8 @@ getText(PM_WCHAR const cmdlineText[], MALLOCARRAY_NOFAIL(inputText.textArray, 1); inputText.allocatedLineCount = 1; inputText.lineCount = 1; - fixControlChars(cmdlineText, fontP, - (const PM_WCHAR**)&inputText.textArray[0], fixMode); + setupSelector(cmdlineText, (const PM_WCHAR**) &inputText.textArray[0], + selectorP); free((void *) cmdlineText); } else { /* Read text from stdin. */ @@ -978,7 +1106,7 @@ getText(PM_WCHAR const cmdlineText[], unsigned int const lineBufTerm = LINEBUFSIZE - 1; unsigned int maxlines; - /* Maximum number of lines for which we presently have space in + /* Maximum number of lines for which we currently have space in the text array */ PM_WCHAR * buf; @@ -1021,9 +1149,9 @@ getText(PM_WCHAR const cmdlineText[], if (textArray == NULL) pm_error("out of memory"); } - fixControlChars(buf, fontP, - (const PM_WCHAR **)&textArray[lineCount], - fixMode); + setupSelector(buf, + (const PM_WCHAR **) &textArray[lineCount], + selectorP); if (textArray[lineCount] == NULL) pm_error("out of memory"); ++lineCount; @@ -1064,6 +1192,33 @@ computeMargins(struct CmdlineInfo const cmdline, static void +refineText(struct Text const inputText, + struct font2 * const fontP) { +/*---------------------------------------------------------------------------- + Replace missing characters with space + + A future version of this program may provide various alternatives + here including simply deleting the offending character, based on a + command-line option +-----------------------------------------------------------------------------*/ + PM_WCHAR ** const textArray = inputText.textArray; + + unsigned int lineNum; + + for (lineNum = 0; lineNum < inputText.lineCount; ++lineNum) { + PM_WCHAR * const line = textArray[lineNum]; + + unsigned int cursor; + + for (cursor = 0; line[cursor] != L'\0'; ++cursor) + if ( !codepointIsValid(fontP, line[cursor]) ) + line[cursor] = L' '; + } +} + + + +static void formatText(struct CmdlineInfo const cmdline, struct Text const inputText, struct font2 * const fontP, @@ -1191,7 +1346,7 @@ renderText(unsigned int const cols, space, cols, rows, lspace, fixedAdvance); /* Free all font data */ - pbm_destroybdffont2(fontP); + pbm_destroybdffont2(fontP); { unsigned int row; @@ -1224,36 +1379,31 @@ L"M \",/^_[`jpqy| M" }; static void -validateText(const PM_WCHAR ** const textArray, - struct font2 * const fontP) { -/*---------------------------------------------------------------------------- - Abort the program if there are characters in 'textArray' which cannot be - rendered in font *fontP. ------------------------------------------------------------------------------*/ - const PM_WCHAR * output; - unsigned int textRow; - - for (textRow = 0; textRow < 12; ++textRow) - fixControlChars(textArray[textRow], fontP, &output, QUIT); - - free((PM_WCHAR *)output); -} +renderSheet(struct CmdlineInfo const cmdline, + FILE * const ofP) { + struct Text const sheetText = + { (PM_WCHAR ** const) sheetTextArray, 12, 12}; + static unsigned char const sheetRequestArray[16] = { + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}; + struct pm_selector * selectorP; + struct font2 * fontP; + bool fontIsComplete; -static void -renderSheet(struct font2 * const fontP, - FILE * const ofP) { + pm_selector_create_fixed(sheetRequestArray, 32, 126,95, &selectorP); - int const cols = fontP->maxwidth * 16; - int const rows = fontP->maxheight * 12; - struct Text const sheetText = - { (PM_WCHAR ** const) sheetTextArray, 12, 12}; + computeFont(cmdline, &fontP, selectorP, QUIT, &fontIsComplete); - validateText(sheetTextArray, fontP); + { + unsigned int const cols = fontP->maxwidth * 16; + unsigned int const rows = fontP->maxheight * 12; - renderText(cols, rows, fontP, 0, 0, sheetText, MAX(-(fontP->x),0), - 0.0, 0, TRUE, ofP); + renderText(cols, rows, fontP, 0, 0, sheetText, MAX(-(fontP->x),0), + 0.0, 0, TRUE, ofP); + } + pm_selector_destroy(selectorP); } @@ -1304,8 +1454,8 @@ textDumpOutput(struct Text const lp, static void pbmtext(struct CmdlineInfo const cmdline, - struct font2 * const fontP, - FILE * const ofP) { + FILE * const ofP, + bool const wchar) { unsigned int rows, cols; /* Dimensions in pixels of the output image */ @@ -1315,19 +1465,30 @@ pbmtext(struct CmdlineInfo const cmdline, unsigned int hmargin0; struct Text inputText; struct Text formattedText; + struct font2 * fontP; + struct pm_selector * selectorP; unsigned int maxleftb, maxleftb0; + bool fontIsComplete; + + pm_selector_create(wchar ? PM_FONT2_MAXGLYPH : PM_FONT_MAXGLYPH, + &selectorP); - getText(cmdline.text, fontP, &inputText, - cmdline.verbose ? WARN : SILENT); + getText(cmdline.text, &inputText, selectorP); + + if (pm_selector_marked_ct(selectorP) == 0) + pm_error("No input text. Aborting."); + + computeFont(cmdline, &fontP, selectorP, cmdline.verbose ? WARN : SILENT, + &fontIsComplete); computeMargins(cmdline, inputText, fontP, &vmargin, &hmargin0); + if (!fontIsComplete) + refineText(inputText, fontP); + formatText(cmdline, inputText, fontP, hmargin0, &formattedText, &maxleftb0); - if (formattedText.lineCount == 0) - pm_error("No input text"); - computeImageHeight(formattedText, fontP, cmdline.lspace, vmargin, &rows); computeImageWidth(formattedText, fontP, cmdline.space, @@ -1361,6 +1522,8 @@ pbmtext(struct CmdlineInfo const cmdline, maxleftb, cmdline.space, cmdline.lspace, FALSE, ofP); freeTextArray(formattedText); + + pm_selector_destroy(selectorP); } @@ -1369,7 +1532,6 @@ int main(int argc, const char *argv[]) { struct CmdlineInfo cmdline; - struct font2 * fontP; pm_proginit(&argc, argv); @@ -1389,12 +1551,10 @@ main(int argc, const char *argv[]) { if (cmdline.verbose) pm_message("LC_CTYPE is set to '%s'", setlocale(LC_CTYPE, NULL) ); - computeFont(cmdline, &fontP); - if (cmdline.dumpsheet) - renderSheet(fontP, stdout); + renderSheet(cmdline, stdout); else - pbmtext(cmdline, fontP, stdout); + pbmtext(cmdline, stdout, cmdline.wchar); pm_close(stdout); diff --git a/generator/pbmtextps.c b/generator/pbmtextps.c index f543618d..0c3656e7 100644 --- a/generator/pbmtextps.c +++ b/generator/pbmtextps.c @@ -190,7 +190,7 @@ parseCommandLine(int argc, const char ** argv, unsigned int leftmarginSpec, rightmarginSpec; unsigned int topmarginSpec, bottommarginSpec; - MALLOCARRAY(option_def, 100); + MALLOCARRAY_NOFAIL(option_def, 100); option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3(0, "resolution", OPT_UINT, diff --git a/generator/ppmforge.c b/generator/ppmforge.c index 8fec9fee..114f7f18 100644 --- a/generator/ppmforge.c +++ b/generator/ppmforge.c @@ -631,7 +631,7 @@ createPlanetStuff(bool const clouds, MALLOCARRAY(bxc, cols); if (u == NULL || u1 == NULL || bxf == NULL || bxc == NULL) - pm_error("Cannot allocate %d element interpolation tables.", cols); + pm_error("Cannot allocate %u element interpolation tables.", cols); { unsigned int j; for (j = 0; j < cols; j++) { diff --git a/generator/ppmmake.c b/generator/ppmmake.c index 2d4bbca8..7bac9601 100644 --- a/generator/ppmmake.c +++ b/generator/ppmmake.c @@ -46,7 +46,7 @@ parseCommandLine(int argc, char ** argv, unsigned int maxvalSpec; unsigned int option_def_index; - MALLOCARRAY(option_def, 100); + MALLOCARRAY_NOFAIL(option_def, 100); option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3(0, "maxval", OPT_UINT, &cmdlineP->maxval, &maxvalSpec, 0); diff --git a/generator/ppmrough.c b/generator/ppmrough.c index e749c9c2..626ee989 100644 --- a/generator/ppmrough.c +++ b/generator/ppmrough.c @@ -47,7 +47,7 @@ parseCommandLine(int argc, const char ** argv, unsigned int option_def_index; - MALLOCARRAY(option_def, 100); + MALLOCARRAY_NOFAIL(option_def, 100); option_def_index = 0; /* incremented by OPTENTRY */ OPTENT3(0, "width", OPT_UINT, &cmdlineP->width, NULL, 0); |