diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2016-03-27 01:38:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2016-03-27 01:38:28 +0000 |
commit | 367c9cb514c9da766488b9bdb218a18e31cb7624 (patch) | |
tree | f9e343be94161a4837f0f1c1d072a35538ae0f63 /generator | |
parent | 6e88e3326cb0c7f7975b56189278cab3f84ba1bd (diff) | |
download | netpbm-mirror-367c9cb514c9da766488b9bdb218a18e31cb7624.tar.gz netpbm-mirror-367c9cb514c9da766488b9bdb218a18e31cb7624.tar.xz netpbm-mirror-367c9cb514c9da766488b9bdb218a18e31cb7624.zip |
Promote Stable (10.47) to Super Stable
git-svn-id: http://svn.code.sf.net/p/netpbm/code/super_stable@2691 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'generator')
-rw-r--r-- | generator/Makefile | 4 | ||||
-rw-r--r-- | generator/pamgradient.c | 13 | ||||
-rw-r--r-- | generator/pamseq.c | 1 | ||||
-rw-r--r-- | generator/pamstereogram.c | 10 | ||||
-rw-r--r-- | generator/pamstereogram.test | 8 | ||||
-rw-r--r-- | generator/pbmmake.c | 13 | ||||
-rw-r--r-- | generator/pbmtext.c | 426 | ||||
-rw-r--r-- | generator/pbmtextps.c | 275 | ||||
-rw-r--r-- | generator/pbmupc.c | 17 | ||||
-rw-r--r-- | generator/pgmcrater.c | 8 | ||||
-rw-r--r-- | generator/pgmmake.c | 10 | ||||
-rw-r--r-- | generator/pgmnoise.c | 182 | ||||
-rw-r--r-- | generator/pgmramp.c | 12 | ||||
-rw-r--r-- | generator/ppmcolors.c | 1 | ||||
-rw-r--r-- | generator/ppmforge.c | 6 | ||||
-rw-r--r-- | generator/ppmmake.c | 10 | ||||
-rw-r--r-- | generator/ppmpat.c | 1384 | ||||
-rwxr-xr-x | generator/ppmrainbow | 14 | ||||
-rw-r--r-- | generator/ppmrough.c | 5 |
19 files changed, 1368 insertions, 1031 deletions
diff --git a/generator/Makefile b/generator/Makefile index 52de9b10..3c30cdd0 100644 --- a/generator/Makefile +++ b/generator/Makefile @@ -5,7 +5,7 @@ endif SUBDIR = generator VPATH=.:$(SRCDIR)/$(SUBDIR) -include $(BUILDDIR)/Makefile.config +include $(BUILDDIR)/config.mk # We tend to separate out the build targets so that we don't have # any more dependencies for a given target than it really needs. @@ -37,4 +37,4 @@ MERGE_OBJECTS = $(MERGEBINARIES:%=%.o2) .PHONY: all all: $(BINARIES) -include $(SRCDIR)/Makefile.common +include $(SRCDIR)/common.mk diff --git a/generator/pamgradient.c b/generator/pamgradient.c index 08db86e3..aa559d27 100644 --- a/generator/pamgradient.c +++ b/generator/pamgradient.c @@ -1,5 +1,6 @@ #include <string.h> +#include "pm_c_util.h" #include "pam.h" #include "shhopt.h" #include "mallocvar.h" @@ -11,7 +12,6 @@ struct cmdlineInfo { tuple colorTopRight; tuple colorBottomLeft; tuple colorBottomRight; - unsigned depth; unsigned int cols; unsigned int rows; unsigned int maxval; @@ -121,8 +121,7 @@ interpolate(struct pam * const pamP, static int -isgray(struct pam * const pamP, - tuple const color) { +isgray(tuple const color) { return (color[PAM_RED_PLANE] == color[PAM_GRN_PLANE]) && (color[PAM_RED_PLANE] == color[PAM_BLU_PLANE]); @@ -176,10 +175,10 @@ main(int argc, char *argv[]) { pam.maxval = cmdline.maxval; pam.bytes_per_sample = pnm_bytespersample(pam.maxval); pam.format = PAM_FORMAT; - if (isgray(&pam, cmdline.colorTopLeft) - && isgray(&pam, cmdline.colorTopRight) - && isgray(&pam, cmdline.colorBottomLeft) - && isgray(&pam, cmdline.colorBottomRight)) { + if (isgray(cmdline.colorTopLeft) + && isgray(cmdline.colorTopRight) + && isgray(cmdline.colorBottomLeft) + && isgray(cmdline.colorBottomRight)) { pam.depth = 1; strcpy(pam.tuple_type, PAM_PGM_TUPLETYPE); } else { diff --git a/generator/pamseq.c b/generator/pamseq.c index 58419d12..98eac1cc 100644 --- a/generator/pamseq.c +++ b/generator/pamseq.c @@ -3,6 +3,7 @@ #include <stdlib.h> #include <stdio.h> +#include "pm_c_util.h" #include "pam.h" #include "shhopt.h" diff --git a/generator/pamstereogram.c b/generator/pamstereogram.c index 0e6e6cc9..0ce63853 100644 --- a/generator/pamstereogram.c +++ b/generator/pamstereogram.c @@ -50,6 +50,7 @@ #include <assert.h> #include "pm_config.h" +#include "pm_c_util.h" #include "pam.h" #include "shhopt.h" #include "mallocvar.h" @@ -455,12 +456,17 @@ termPatternPixel(outGenerator * const outGenP) { static void initPatternPixel(outGenerator * const outGenP, struct cmdlineInfo const cmdline) { - +/*---------------------------------------------------------------------------- + Initialize parts of output generator *outGenP that are based on the + supplied pattern file, assuming there is one. +-----------------------------------------------------------------------------*/ struct patternPixelState * stateP; FILE * patternFileP; MALLOCVAR_NOFAIL(stateP); - + + assert(cmdline.patFilespec); + patternFileP = pm_openr(cmdline.patFilespec); stateP->patTuples = diff --git a/generator/pamstereogram.test b/generator/pamstereogram.test index 7eb01fff..80f70ee0 100644 --- a/generator/pamstereogram.test +++ b/generator/pamstereogram.test @@ -20,7 +20,7 @@ echo Test 10. Should print 1266273778 293: ./pamstereogram -randomseed=1 -makemask ../testgrid.pbm | cksum echo Test 11. Should print 3034751595 1070: -./pamgauss 100 10 -maxval=10000 -sigma 20 | pamfunc -multiplier=500 | \ +pamgauss 100 10 -maxval=10000 -sigma 20 | pamfunc -multiplier=500 | \ ./pamstereogram -randomseed=1 -dpi=10 -makemask | cksum # Grayscale @@ -28,11 +28,11 @@ echo Test 11. Should print 3034751595 1070: echo Test 20. Should print 2468969328 289: ./pamstereogram -randomseed=1 -grayscale ../testgrid.pbm | cksum echo Test 21. Should print 1946982115 4068: -./pamseq 1 100 | pnmtile 200 20 | \ +pamseq 1 100 | pnmtile 200 20 | \ ./pamstereogram -randomseed=1 -dpi=10 -grayscale | \ cksum echo Test 22. Should print 2078013430 4068: -./pamseq 1 100 | pnmtile 200 20 | \ +pamseq 1 100 | pnmtile 200 20 | \ ./pamstereogram -randomseed=1 -dpi=10 -grayscale -maxval 255 | \ cksum @@ -41,7 +41,7 @@ echo Test 22. Should print 2078013430 4068: echo Test 30. Should print 1319392622 731: ./pamstereogram -randomseed=1 -color ../testgrid.pbm | cksum echo Test 31. Should print 389886159 12062: -./pamseq 1 100 | pnmtile 200 20 | \ +pamseq 1 100 | pnmtile 200 20 | \ ./pamstereogram -randomseed=1 -dpi=10 -color | \ cksum diff --git a/generator/pbmmake.c b/generator/pbmmake.c index afe1dac3..41d80274 100644 --- a/generator/pbmmake.c +++ b/generator/pbmmake.c @@ -11,6 +11,7 @@ ** */ +#include "pm_c_util.h" #include "shhopt.h" #include "mallocvar.h" #include "pbm.h" @@ -75,16 +76,8 @@ parseCommandLine(int argc, char ** argv, "non-option arguments: width and height in pixels", argc-1); else { - cmdlineP->width = atoi(argv[1]); - cmdlineP->height = atoi(argv[2]); - - if (cmdlineP->width < 1) - pm_error("Width must be positive. You specified %d.", - cmdlineP->width); - - if (cmdlineP->height < 1) - pm_error("Height must be positive. You specified %d.", - cmdlineP->height); + cmdlineP->width = pm_parse_width(argv[1]); + cmdlineP->height = pm_parse_height(argv[2]); } } diff --git a/generator/pbmtext.c b/generator/pbmtext.c index d0a6291b..693c3f59 100644 --- a/generator/pbmtext.c +++ b/generator/pbmtext.c @@ -14,69 +14,76 @@ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #include <string.h> +#include <limits.h> +#include <assert.h> +#include "pm_c_util.h" +#include "mallocvar.h" +#include "shhopt.h" #include "pbm.h" #include "pbmfont.h" -#include "shhopt.h" -#include "mallocvar.h" -struct cmdline_info { +struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - const char *text; /* text from command line or NULL if none */ - const char *font; /* -font option value or NULL if none */ - const char *builtin; /* -builtin option value or NULL if none */ + const char * text; /* text from command line or NULL if none */ + const char * font; /* -font option value or NULL if none */ + const char * builtin; /* -builtin option value or NULL if none */ unsigned int dump; /* undocumented dump option for installing a new built-in font */ float space; /* -space option value or default */ unsigned int width; /* -width option value or zero */ int lspace; /* lspace option value or default */ unsigned int nomargins; /* -nomargins */ + unsigned int verbose; }; static void -parse_command_line(int argc, char ** argv, - struct cmdline_info *cmdline_p) { +parseCommandLine(int argc, const char ** argv, + struct cmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. -----------------------------------------------------------------------------*/ - optEntry *option_def = malloc(100*sizeof(optEntry)); + optEntry * option_def; /* Instructions to OptParseOptions3 on how to parse our options. */ optStruct3 opt; unsigned int option_def_index; + MALLOCARRAY_NOFAIL(option_def, 100); + option_def_index = 0; /* incremented by OPTENTRY */ - OPTENT3(0, "font", OPT_STRING, &cmdline_p->font, NULL, 0); - OPTENT3(0, "builtin", OPT_STRING, &cmdline_p->builtin, NULL, 0); - OPTENT3(0, "dump", OPT_FLAG, NULL, &cmdline_p->dump, 0); - OPTENT3(0, "space", OPT_FLOAT, &cmdline_p->space, NULL, 0); - OPTENT3(0, "width", OPT_UINT, &cmdline_p->width, NULL, 0); - OPTENT3(0, "lspace", OPT_INT, &cmdline_p->lspace, NULL, 0); - OPTENT3(0, "nomargins", OPT_FLAG, NULL, &cmdline_p->nomargins, 0); + OPTENT3(0, "font", OPT_STRING, &cmdlineP->font, NULL, 0); + OPTENT3(0, "builtin", OPT_STRING, &cmdlineP->builtin, NULL, 0); + OPTENT3(0, "dump", OPT_FLAG, NULL, &cmdlineP->dump, 0); + OPTENT3(0, "space", OPT_FLOAT, &cmdlineP->space, NULL, 0); + OPTENT3(0, "width", OPT_UINT, &cmdlineP->width, NULL, 0); + OPTENT3(0, "lspace", OPT_INT, &cmdlineP->lspace, NULL, 0); + OPTENT3(0, "nomargins", OPT_FLAG, NULL, &cmdlineP->nomargins, 0); + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); /* Set the defaults */ - cmdline_p->font = NULL; - cmdline_p->builtin = NULL; - cmdline_p->space = 0.0; - cmdline_p->width = 0; - cmdline_p->lspace = 0; + cmdlineP->font = NULL; + cmdlineP->builtin = NULL; + cmdlineP->space = 0.0; + cmdlineP->width = 0; + cmdlineP->lspace = 0; opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - optParseOptions3(&argc, argv, opt, sizeof(opt), 0); - /* Uses and sets argc, argv, and some of *cmdline_p and others. */ + optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (argc-1 == 0) - cmdline_p->text = NULL; + cmdlineP->text = NULL; else { char *text; int i; @@ -87,7 +94,7 @@ parse_command_line(int argc, char ** argv, text = malloc(totaltextsize); /* initial allocation */ text[0] = '\0'; - for (i = 1; i < argc; i++) { + for (i = 1; i < argc; ++i) { if (i > 1) { totaltextsize += 1; text = realloc(text, totaltextsize); @@ -101,11 +108,59 @@ parse_command_line(int argc, char ** argv, pm_error("out of memory allocating space for input text"); strcat(text, argv[i]); } - cmdline_p->text = text; + cmdlineP->text = text; + } +} + + + +static void +reportFont(struct font * const fontP) { + + unsigned int n; + unsigned int c; + + pm_message("FONT:"); + pm_message(" character dimensions: %uw x %uh", + fontP->maxwidth, fontP->maxheight); + pm_message(" Additional vert white space: %d pixels", fontP->y); + + for (c = 0, n = 0; c < ARRAY_SIZE(fontP->glyph); ++c) + if (fontP->glyph[c]) + ++n; + + pm_message(" # characters: %u", n); +} + + + +static void +computeFont(struct cmdlineInfo const cmdline, + struct font ** const fontPP) { + + struct font * fontP; + + if (cmdline.font) + fontP = pbm_loadfont(cmdline.font); + else { + if (cmdline.builtin) + fontP = pbm_defaultfont(cmdline.builtin); + else + fontP = pbm_defaultfont("bdf"); } + + if (cmdline.verbose) + reportFont(fontP); + + if (cmdline.dump) { + pbm_dumpfont(fontP); + exit(0); + } + *fontPP = fontP; } + struct text { char ** textArray; /* malloc'ed */ unsigned int allocatedLineCount; @@ -113,6 +168,7 @@ struct text { }; + static void allocTextArray(struct text * const textP, unsigned int const maxLineCount, @@ -131,6 +187,7 @@ allocTextArray(struct text * const textP, } + static void freeTextArray(struct text const text) { @@ -145,30 +202,72 @@ freeTextArray(struct text const text) { static void -fix_control_chars(char * const buf, struct font * const fn) { +fixControlChars(const char * const input, + struct font * const fontP, + const char ** const outputP) { +/*---------------------------------------------------------------------------- + Return a translation of input[] that can be rendered as glyphs in + the font 'fontP'. Return it as newly malloced *outputP. - int i; + Expand tabs to spaces. - /* chop off terminating newline */ - if (strlen(buf) >= 1 && buf[strlen(buf)-1] == '\n') - buf[strlen(buf)-1] = '\0'; - - for ( i = 0; buf[i] != '\0'; ++i ) { - if ( buf[i] == '\t' ) { - /* Turn tabs into the right number of spaces. */ - int j, n, l; - n = ( i + 8 ) / 8 * 8; - l = strlen( buf ); - for ( j = l; j > i; --j ) - buf[j + n - i - 1] = buf[j]; - for ( ; i < n; ++i ) - buf[i] = ' '; - --i; + Remove any trailing newline. (But leave intermediate ones as line + delimiters). + + 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 + character that there is space in the output buffer for a worst + case tab expansion, plus a terminating NUL, reallocating as + necessary. And we originally allocate enough for the entire line + assuming no tabs. + */ + + unsigned int const tabSize = 8; + + unsigned int inCursor, outCursor; + char * output; /* Output buffer. Malloced */ + size_t outputSize; /* Currently allocated size of 'output' */ + + outputSize = strlen(input) + 1 + tabSize; + /* Leave room for one worst case tab expansion and NUL terminator */ + MALLOCARRAY(output, outputSize); + + if (output == NULL) + pm_error("Couldn't allocate %u bytes for a line of text.", outputSize); + + for (inCursor = 0, outCursor = 0; input[inCursor] != '\0'; ++inCursor) { + if (outCursor + 1 + tabSize > outputSize) { + outputSize = outCursor + 1 + 4 * tabSize; + REALLOCARRAY(output, outputSize); + if (output == NULL) + pm_error("Couldn't allocate %u bytes for a line of text.", + outputSize); } - else if ( !fn->glyph[(unsigned char)buf[i]] ) - /* Turn unknown chars into a single space. */ - buf[i] = ' '; + if (input[inCursor] == '\n' && input[inCursor+1] == '\0') { + /* This is a terminating newline. We don't do those. */ + } else if (input[inCursor] == '\t') { + /* Expand this tab into the right number of spaces. */ + unsigned int const nextTabStop = + (outCursor + tabSize) / tabSize * tabSize; + + while (outCursor < nextTabStop) + output[outCursor++] = ' '; + } else if (!fontP->glyph[(unsigned char)input[inCursor]]) { + /* Turn this unknown char into a single space. */ + output[outCursor++] = ' '; + } else + output[outCursor++] = input[inCursor]; + + assert(outCursor <= outputSize); } + output[outCursor++] = '\0'; + + assert(outCursor <= outputSize); + + *outputP = output; } @@ -195,35 +294,34 @@ fill_rect(bit** const bits, static void get_line_dimensions(const char line[], const struct font * const font_p, const float intercharacter_space, - int * const bwid_p, int * const backup_space_needed_p) { + double * const bwidP, int * const backup_space_needed_p) { /*---------------------------------------------------------------------------- Determine the width in pixels of the line of text line[] in the font - *font_p, and return it as *bwid_p. Also determine how much of this + *font_p, and return it as *bwidP. Also determine how much of this width goes to the left of the nominal starting point of the line because the first character in the line has a "backup" distance. Return that as *backup_space_needed_p. -----------------------------------------------------------------------------*/ int cursor; /* cursor into the line of text */ - float accumulated_ics; + double accumulatedIcs; /* accumulated intercharacter space so far in the line we are stepping through. Because the intercharacter space might not be an integer, we accumulate it here and realize full pixels whenever - we have more than one pixel. - */ - - int no_chars_yet; - /* logical: we haven't seen any renderable characters yet in - the line. + we have more than one pixel. Note that this can be negative + (which means were crowding, rather than spreading, text). */ + double bwid; + bool no_chars_yet; + /* We haven't seen any renderable characters yet in the line. */ struct glyph * lastGlyphP; /* Glyph of last character processed so far. Undefined if 'no_chars_yet'. */ no_chars_yet = TRUE; /* initial value */ - *bwid_p = 0; /* initial value */ - accumulated_ics = 0.0; /* initial value */ - + accumulatedIcs = 0.0; /* initial value */ + bwid = 0.0; /* initial value */ + for (cursor = 0; line[cursor] != '\0'; cursor++) { struct glyph * const glyphP = font_p->glyph[(unsigned char)line[cursor]]; @@ -235,18 +333,23 @@ get_line_dimensions(const char line[], const struct font * const font_p, *backup_space_needed_p = -glyphP->x; else { *backup_space_needed_p = 0; - *bwid_p += glyphP->x; + bwid += glyphP->x; } } else { /* handle extra intercharacter space (-space option) */ - int full_pixels; /* integer part of accumulated_ics */ - accumulated_ics += intercharacter_space; - full_pixels = (int) accumulated_ics; - *bwid_p += full_pixels; - accumulated_ics -= full_pixels; + accumulatedIcs += intercharacter_space; + if (accumulatedIcs >= INT_MAX) + pm_error("Image width too large."); + if (accumulatedIcs <= INT_MIN) + pm_error("Absurdly large negative -space value."); + { + int const fullPixels = (int) accumulatedIcs; + bwid += fullPixels; + accumulatedIcs -= fullPixels; + } } lastGlyphP = glyphP; - *bwid_p += glyphP->xadd; + bwid += glyphP->xadd; } } if (no_chars_yet) @@ -258,9 +361,13 @@ get_line_dimensions(const char line[], const struct font * const font_p, right at the right edge of the glyph (no extra space to anticipate another character). */ - *bwid_p -= lastGlyphP->xadd; - *bwid_p += lastGlyphP->width + lastGlyphP->x; + bwid -= lastGlyphP->xadd; + bwid += lastGlyphP->width + lastGlyphP->x; } + if (bwid > INT_MAX) + pm_error("Image width too large."); + else + *bwidP = bwid; } @@ -377,7 +484,8 @@ struct outputTextCursor { are stepping through. Because the intercharacter space might not be an integer, we accumulate it here and realize full pixels whenever we have more than one - pixel. + pixel. Note that this is negative if we're crowding, rather + than spreading, characters. */ }; @@ -442,11 +550,12 @@ placeCharacterInOutput(char const lastch, cursorP->widthSoFar += fontP->glyph[glyphIndex]->x; } else { /* handle extra intercharacter space (-space option) */ - int fullPixels; /* integer part of accumulatedIcs */ cursorP->accumulatedIcs += cursorP->intercharacterSpace; - fullPixels = (int) cursorP->accumulatedIcs; - cursorP->widthSoFar += fullPixels; - cursorP->accumulatedIcs -= fullPixels; + { + int const fullPixels = (int)cursorP->accumulatedIcs; + cursorP->widthSoFar += fullPixels; + cursorP->accumulatedIcs -= fullPixels; + } } cursorP->widthSoFar += fontP->glyph[glyphIndex]->xadd; } @@ -522,8 +631,9 @@ truncateText(struct text const inputText, /* accumulated intercharacter space so far in the line we are stepping through. Because the intercharacter space might not be an integer, we accumulate it here and realize full pixels whenever - we have more than one pixel. - */ + we have more than one pixel. Note that this is negative if we're + crowding, not spreading, characters. + */ int noCharsYet; /* logical: we haven't seen any renderable characters yet in @@ -546,11 +656,12 @@ truncateText(struct text const inputText, widthSoFar += fontP->glyph[lastch]->x; } else { /* handle extra intercharacter space (-space option) */ - int fullPixels; /* integer part of accumulatedIcs */ accumulatedIcs += intercharacterSpace; - fullPixels = (int) intercharacterSpace; - widthSoFar += fullPixels; - accumulatedIcs -= fullPixels; + { + int const fullPixels = (int) intercharacterSpace; + widthSoFar += fullPixels; + accumulatedIcs -= fullPixels; + } } widthSoFar += fontP->glyph[lastch]->xadd; } @@ -569,16 +680,17 @@ truncateText(struct text const inputText, static void getText(const char cmdline_text[], - struct font * const fn, + struct font * const fontP, struct text * const input_textP) { struct text input_text; if (cmdline_text) { - allocTextArray(&input_text, 1, strlen(cmdline_text)*8); - strcpy(input_text.textArray[0], cmdline_text); - fix_control_chars(input_text.textArray[0], fn); + MALLOCARRAY_NOFAIL(input_text.textArray, 1); + input_text.allocatedLineCount = 1; input_text.lineCount = 1; + fixControlChars(cmdline_text, fontP, + (const char**)&input_text.textArray[0]); } else { /* Read text from stdin. */ @@ -595,18 +707,16 @@ getText(const char cmdline_text[], lineCount = 0; /* initial value */ while (fgets(buf, sizeof(buf), stdin) != NULL) { - if (strlen(buf)*8 + 1 >= sizeof(buf)) + if (strlen(buf) + 1 >= sizeof(buf)) pm_error("A line of input text is longer than %u characters." - "Cannot process.", (sizeof(buf)-1)/8); - fix_control_chars(buf, fn); + "Cannot process.", sizeof(buf)-1); if (lineCount >= maxlines) { maxlines *= 2; - text_array = (char**) realloc((char*) text_array, - maxlines * sizeof(char*)); + REALLOCARRAY(text_array, maxlines); if (text_array == NULL) pm_error("out of memory"); } - text_array[lineCount] = strdup(buf); + fixControlChars(buf, fontP, (const char **)&text_array[lineCount]); if (text_array[lineCount] == NULL) pm_error("out of memory"); ++lineCount; @@ -621,62 +731,97 @@ getText(const char cmdline_text[], static void -compute_image_width(struct text const lp, - const struct font * const fn, - float const intercharacter_space, - int * const maxwidthP, - int * const maxleftbP) { - int line; - - *maxwidthP = 0; /* initial value */ - *maxleftbP = 0; /* initial value */ - for (line = 0; line < lp.lineCount; ++line) { - int bwid, backup_space_needed; - - get_line_dimensions(lp.textArray[line], fn, intercharacter_space, - &bwid, &backup_space_needed); +computeImageHeight(struct text const formattedText, + const struct font * const fontP, + int const interlineSpace, + unsigned int const vmargin, + unsigned int * const rowsP) { + + if (interlineSpace < 0 && fontP->maxheight < -interlineSpace) + pm_error("-lspace value (%d) negative and exceeds font height.", + interlineSpace); + else { + double const rowsD = 2 * (double) vmargin + + (double) formattedText.lineCount * fontP->maxheight + + (double) (formattedText.lineCount-1) * interlineSpace; - *maxwidthP = MAX(*maxwidthP, bwid); - *maxleftbP = MAX(*maxleftbP, backup_space_needed); + if (rowsD > INT_MAX-10) + pm_error("Image height too large."); + else + *rowsP = (unsigned int) rowsD; + } +} + + + +static void +computeImageWidth(struct text const formattedText, + const struct font * const fontP, + float const intercharacterSpace, + unsigned int const hmargin, + unsigned int * const colsP, + int * const maxleftbP) { + + if (intercharacterSpace < 0 && fontP->maxwidth < -intercharacterSpace) + pm_error("-space value (%f) negative; exceeds font width.", + intercharacterSpace); + else { + /* Find the widest line, and the one that backs up the most past + the nominal start of the line. + */ + + unsigned int line; + double maxwidth; + int maxleftb; + double colsD; + + for (line = 0, maxwidth = 0.0, maxleftb = 0; + line < formattedText.lineCount; + ++line) { + + double bwid; + int backupSpaceNeeded; + + get_line_dimensions(formattedText.textArray[line], fontP, + intercharacterSpace, + &bwid, &backupSpaceNeeded); + + maxwidth = MAX(maxwidth, bwid); + maxleftb = MAX(maxleftb, backupSpaceNeeded); + } + colsD = 2 * (double) hmargin + (double) maxwidth; + + if (colsD > INT_MAX-10) + pm_error("Image width too large."); + else + *colsP = (unsigned int) colsD; + + *maxleftbP = maxleftb; } } int -main(int argc, char *argv[]) { +main(int argc, const char *argv[]) { - struct cmdline_info cmdline; - bit** bits; - int rows, cols; - struct font* fontP; - int vmargin, hmargin; + struct cmdlineInfo cmdline; + bit ** bits; + unsigned int rows, cols; + struct font * fontP; + unsigned int vmargin, hmargin; struct text inputText; struct text formattedText; - int maxwidth; - /* width in pixels of the longest line of text in the image */ int maxleftb; - pbm_init( &argc, argv ); + pm_proginit(&argc, argv); - parse_command_line(argc, argv, &cmdline); + parseCommandLine(argc, argv, &cmdline); - if (cmdline.font) - fontP = pbm_loadfont(cmdline.font); - else { - if (cmdline.builtin) - fontP = pbm_defaultfont(cmdline.builtin); - else - fontP = pbm_defaultfont("bdf"); - } - - if (cmdline.dump) { - pbm_dumpfont(fontP); - exit(0); - } + computeFont(cmdline, &fontP); getText(cmdline.text, fontP, &inputText); - + if (cmdline.nomargins) { vmargin = 0; hmargin = 0; @@ -689,8 +834,11 @@ main(int argc, char *argv[]) { hmargin = 2 * fontP->maxwidth; } } - + if (cmdline.width > 0) { + if (cmdline.width > INT_MAX -10) + pm_error("-width value too large: %u", cmdline.width); + /* Flow or truncate lines to meet user's width request */ if (inputText.lineCount == 1) flowText(inputText, cmdline.width, fontP, cmdline.space, @@ -701,19 +849,18 @@ main(int argc, char *argv[]) { freeTextArray(inputText); } else formattedText = inputText; + + if (formattedText.lineCount == 0) + pm_error("No input text."); - rows = 2 * vmargin + - formattedText.lineCount * fontP->maxheight + - (formattedText.lineCount-1) * cmdline.lspace; - - compute_image_width(formattedText, fontP, cmdline.space, - &maxwidth, &maxleftb); + computeImageHeight(formattedText, fontP, cmdline.lspace, vmargin, + &rows); - cols = 2 * hmargin + maxwidth; + computeImageWidth(formattedText, fontP, cmdline.space, hmargin, + &cols, &maxleftb); if (cols == 0 || rows == 0) - pm_error("Input is all whitespace and/or non-renderable characters. " - "No output."); + pm_error("Input is all whitespace and/or non-renderable characters."); bits = pbm_allocarray(cols, rows); @@ -724,9 +871,10 @@ main(int argc, char *argv[]) { insert_characters(bits, formattedText, fontP, vmargin, hmargin + maxleftb, cmdline.space, cmdline.lspace); - /* All done. */ pbm_writepbm(stdout, bits, cols, rows, 0); + pbm_freearray(bits, rows); + freeTextArray(formattedText); pm_close(stdout); diff --git a/generator/pbmtextps.c b/generator/pbmtextps.c index 08c77564..f879fa88 100644 --- a/generator/pbmtextps.c +++ b/generator/pbmtextps.c @@ -17,37 +17,27 @@ */ #define _XOPEN_SOURCE /* Make sure popen() is in stdio.h */ #define _BSD_SOURCE /* Make sure stdrup() is in string.h */ +#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> -#include "pbm.h" + +#include "pm_c_util.h" +#include "mallocvar.h" #include "nstring.h" #include "shhopt.h" +#include "pbm.h" #define BUFFER_SIZE 2048 -static const char *gs_exe_path = -#ifdef GHOSTSCRIPT_EXECUTABLE_PATH -GHOSTSCRIPT_EXECUTABLE_PATH; -#else -0; -#endif - -static const char *pnmcrop_exe_path = -#ifdef PNMCROP_EXECUTABLE_PATH -PNMCROP_EXECUTABLE_PATH; -#else -0; -#endif - struct cmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - int res; /* resolution, DPI */ - int fontsize; /* Size of font in points */ + unsigned int res; /* resolution, DPI */ + unsigned int fontsize; /* Size of font in points */ const char * font; /* Name of postscript font */ float stroke; /* Width of stroke in points (only for outline font) */ @@ -58,26 +48,85 @@ struct cmdlineInfo { static void +writeFileToStdout(const char * const fileName){ + /* simple pbmtopbm */ + + FILE * ifP; + int format; + int cols, rows, row ; + unsigned char * bitrow; + + ifP = pm_openr(fileName); + pbm_readpbminit(ifP, &cols, &rows, &format); + + if (cols==0 || rows==0 || cols>INT_MAX-10 || rows>INT_MAX-10) + pm_error("Abnormal output from gs program. " + "width x height = %u x %u", cols, rows); + + pbm_writepbminit(stdout, cols, rows, 0); + + bitrow = pbm_allocrow_packed(cols); + + for (row = 0; row < rows; ++row) { + pbm_readpbmrow_packed(ifP, bitrow, cols, format); + pbm_writepbmrow_packed(stdout, bitrow, cols, 0); + } + pbm_freerow_packed(bitrow); +} + + + +static void +buildTextFromArgs(int const argc, + char ** const argv, + const char ** const textP) { + + char * text; + unsigned int totalTextSize; + unsigned int i; + + text = strdup(""); + totalTextSize = 1; + + for (i = 1; i < argc; ++i) { + if (i > 1) { + totalTextSize += 1; + text = realloc(text, totalTextSize); + if (text == NULL) + pm_error("out of memory"); + strcat(text, " "); + } + totalTextSize += strlen(argv[i]); + text = realloc(text, totalTextSize); + if (text == NULL) + pm_error("out of memory"); + strcat(text, argv[i]); + } + *textP = text; +} + + + +static void parseCommandLine(int argc, char ** argv, struct cmdlineInfo *cmdlineP) { /*--------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. ---------------------------------------------------------------------------*/ - optEntry *option_def = malloc(100*sizeof(optEntry)); + optEntry * option_def; /* Instructions to OptParseOptions2 on how to parse our options. */ optStruct3 opt; unsigned int option_def_index; - int i; - char * text; - int totaltextsize = 0; + + MALLOCARRAY(option_def, 100); option_def_index = 0; /* incremented by OPTENTRY */ - OPTENT3(0, "resolution", OPT_INT, &cmdlineP->res, NULL, 0); + OPTENT3(0, "resolution", OPT_UINT, &cmdlineP->res, NULL, 0); OPTENT3(0, "font", OPT_STRING, &cmdlineP->font, NULL, 0); - OPTENT3(0, "fontsize", OPT_INT, &cmdlineP->fontsize, NULL, 0); + OPTENT3(0, "fontsize", OPT_UINT, &cmdlineP->fontsize, NULL, 0); OPTENT3(0, "stroke", OPT_FLOAT, &cmdlineP->stroke, NULL, 0); OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); @@ -93,48 +142,43 @@ parseCommandLine(int argc, char ** argv, optParseOptions3(&argc, argv, opt, sizeof(opt), 0); - text = strdup(""); - totaltextsize = 1; - - for (i = 1; i < argc; i++) { - if (i > 1) { - totaltextsize += 1; - text = realloc(text, totaltextsize); - if (text == NULL) - pm_error("out of memory"); - strcat(text, " "); - } - totaltextsize += strlen(argv[i]); - text = realloc(text, totaltextsize); - if (text == NULL) - pm_error("out of memory"); - strcat(text, argv[i]); - } - cmdlineP->text = text; + buildTextFromArgs(argc, argv, &cmdlineP->text); } static const char * -construct_postscript(struct cmdlineInfo const cmdl) { +construct_postscript(struct cmdlineInfo const cmdline) { const char * retval; const char * template; - if (cmdl.stroke <= 0) - template = "/%s findfont\n%d scalefont\nsetfont\n12 36 moveto\n" - "(%s) show\nshowpage\n"; + if (cmdline.stroke < 0) + template = + "/%s findfont\n" + "%d scalefont\n" + "setfont\n" + "12 36 moveto\n" + "(%s) show\n" + "showpage\n"; else - template = "/%s findfont\n%d scalefont\nsetfont\n12 36 moveto\n" - "%f setlinewidth\n0 setgray\n" - "(%s) true charpath\nstroke\nshowpage\n"; - - if (cmdl.stroke < 0) - asprintfN(&retval, template, cmdl.font, cmdl.fontsize, - cmdl.text); + template = + "/%s findfont\n" + "%d scalefont\n" + "setfont\n" + "12 36 moveto\n" + "%f setlinewidth\n" + "0 setgray\n" + "(%s) true charpath\n" + "stroke\n" + "showpage\n"; + + if (cmdline.stroke < 0) + asprintfN(&retval, template, cmdline.font, cmdline.fontsize, + cmdline.text); else - asprintfN(&retval, template, cmdl.font, cmdl.fontsize, - cmdl.stroke, cmdl.text); + asprintfN(&retval, template, cmdline.font, cmdline.fontsize, + cmdline.stroke, cmdline.text); return retval; } @@ -142,24 +186,27 @@ construct_postscript(struct cmdlineInfo const cmdl) { static const char * -gs_executable_name() -{ +gsExecutableName() { + + const char * const which = "which gs"; + static char buffer[BUFFER_SIZE]; - if(! gs_exe_path) { - const char * const which = "which gs"; - FILE *f; - memset(buffer, 0, BUFFER_SIZE); - if(!(f = popen(which, "r"))) - pm_error("Can't find ghostscript"); - fread(buffer, 1, BUFFER_SIZE, f); - if(buffer[strlen(buffer) - 1] == '\n') - buffer[strlen(buffer) - 1] = 0; - pclose(f); - if(buffer[0] != '/' && buffer[0] != '.') - pm_error("Can't find ghostscript"); - } - else - strcpy(buffer, gs_exe_path); + + FILE * f; + + memset(buffer, 0, BUFFER_SIZE); + + f = popen(which, "r"); + if (!f) + pm_error("Can't find ghostscript"); + + fread(buffer, 1, BUFFER_SIZE, f); + if (buffer[strlen(buffer) - 1] == '\n') + buffer[strlen(buffer) - 1] = '\0'; + pclose(f); + + if (buffer[0] != '/' && buffer[0] != '.') + pm_error("Can't find ghostscript"); return buffer; } @@ -167,30 +214,33 @@ gs_executable_name() static const char * -crop_executable_name() -{ +cropExecutableName(void) { + + const char * const which = "which pnmcrop"; + static char buffer[BUFFER_SIZE]; - if(! pnmcrop_exe_path) { - const char * const which = "which pnmcrop"; - FILE *f; - memset(buffer, 0, BUFFER_SIZE); - if(!(f = popen(which, "r"))) { - return 0; - } - + const char * retval; + + FILE * f; + + memset(buffer, 0, BUFFER_SIZE); + + f = popen(which, "r"); + if (!f) + retval = NULL; + else { fread(buffer, 1, BUFFER_SIZE, f); - if(buffer[strlen(buffer) - 1] == '\n') + if (buffer[strlen(buffer) - 1] == '\n') buffer[strlen(buffer) - 1] = 0; pclose(f); - if(buffer[0] != '/' && buffer[0] != '.') { - buffer[0] = 0; + + if (buffer[0] != '/' && buffer[0] != '.') { + retval = NULL; pm_message("Can't find pnmcrop"); - } + } else + retval = buffer; } - else - strcpy(buffer, pnmcrop_exe_path); - - return buffer; + return retval; } @@ -201,12 +251,33 @@ gsCommand(const char * const psFname, struct cmdlineInfo const cmdline) { const char * retval; - int const x = cmdline.res * 11; - int const y = cmdline.res * (cmdline.fontsize * 2 + 72) / 72.; + double const x = (double) cmdline.res * 11; + double const y = (double) cmdline.res * + ((double) cmdline.fontsize * 2 + 72) / 72; + + if (cmdline.res <= 0) + pm_error("Resolution (dpi) must be positive."); + + if (cmdline.fontsize <= 0) + pm_error("Font size must be positive."); + + /* The following checks are for guarding against overflows in this + function. Huge x,y values that pass these checks may be + rejected by the 'gs' program. + */ + + if (x > (double) INT_MAX-10) + pm_error("Absurdly fine resolution: %u. Output width too large.", + cmdline.res ); + if (y > (double) INT_MAX-10) + pm_error("Absurdly fine resolution (%u) and/or huge font size (%u). " + "Output height too large.", cmdline.res, cmdline.fontsize); + asprintfN(&retval, "%s -g%dx%d -r%d -sDEVICE=pbm " "-sOutputFile=%s -q -dBATCH -dNOPAUSE %s </dev/null >/dev/null", - gs_executable_name(), x, y, cmdline.res, + gsExecutableName(), (int) x, (int) y, cmdline.res, outputFilename, psFname); + return retval; } @@ -216,11 +287,12 @@ static const char * cropCommand(const char * const inputFileName) { const char * retval; + const char * plainOpt = pm_plain_output ? "-plain" : "" ; - if (crop_executable_name()) { - asprintfN(&retval, "%s -top -right %s", - crop_executable_name(), inputFileName); - if (retval == NULL) + if (cropExecutableName()) { + asprintfN(&retval, "%s -top -right %s %s", + cropExecutableName(), plainOpt, inputFileName); + if (retval == strsol) pm_error("Unable to allocate memory"); } else retval = NULL; @@ -234,7 +306,7 @@ static void writeProgram(const char * const psFname, struct cmdlineInfo const cmdline) { - const char *ps; + const char * ps; FILE * psfile; psfile = fopen(psFname, "w"); @@ -288,14 +360,13 @@ cropToStdout(const char * const inputFileName, const char * com; com = cropCommand(inputFileName); + if (com == NULL) { /* No pnmcrop. So don't crop. */ pm_message("Can't find pnmcrop command, image will be large"); - asprintfN(&com, "cat %s", inputFileName); - if (com == NULL) - pm_error("Unable to allocate memory."); + writeFileToStdout(inputFileName); } else { - FILE *pnmcrop; + FILE * pnmcrop; if (verbose) pm_message("Running crop command '%s'", com); @@ -326,8 +397,8 @@ cropToStdout(const char * const inputFileName, } fclose(pnmcrop); } + strfree(com); } - strfree(com); } diff --git a/generator/pbmupc.c b/generator/pbmupc.c index 5f694a00..6ef75654 100644 --- a/generator/pbmupc.c +++ b/generator/pbmupc.c @@ -433,17 +433,8 @@ putdigit( d, bits, row0, col0 ) bits[row0 + row][col0 + col] = digits[d][row][col]; } -#if __STDC__ static int addlines( int d, bit** bits, int row0, int col0, int height, bit color ) -#else /*__STDC__*/ -static int -addlines( d, bits, row0, col0, height, color ) - int d; - bit** bits; - int row0, col0, height; - bit color; -#endif /*__STDC__*/ { switch ( d ) { @@ -524,16 +515,8 @@ addlines( d, bits, row0, col0, height, color ) return col0; } -#if __STDC__ static int rect( bit** bits, int row0, int col0, int height, int width, bit color ) -#else /*__STDC__*/ -static int -rect( bits, row0, col0, height, width, color ) - bit** bits; - int row0, col0, height, width; - bit color; -#endif /*__STDC__*/ { int row, col; diff --git a/generator/pgmcrater.c b/generator/pgmcrater.c index a48f3de1..ec592381 100644 --- a/generator/pgmcrater.c +++ b/generator/pgmcrater.c @@ -53,7 +53,6 @@ #include <assert.h> #include <math.h> -#include <unistd.h> #include "pm_c_util.h" #include "pgm.h" @@ -107,11 +106,10 @@ static int modulo(int t, int n) static void initseed() { - int i; + unsigned int i; - i = time(NULL) ^ getpid(); - srand(i); - for (i = 0; i < 7; i++) + srand(pm_randseed()); + for (i = 0; i < 7; ++i) V rand(); } diff --git a/generator/pgmmake.c b/generator/pgmmake.c index 42d96581..bc7f025c 100644 --- a/generator/pgmmake.c +++ b/generator/pgmmake.c @@ -70,14 +70,8 @@ parseCommandLine(int argc, char ** argv, pm_error("Gray level must be in the range [0.0, 1.0]. " "You specified %f", grayLevel); cmdlineP->grayLevel = ROUNDU(grayLevel * cmdlineP->maxval); - cmdlineP->cols = atoi(argv[2]); - cmdlineP->rows = atoi(argv[3]); - if (cmdlineP->cols <= 0) - pm_error("width argument must be a positive number. You " - "specified '%s'", argv[2]); - if (cmdlineP->rows <= 0) - pm_error("height argument must be a positive number. You " - "specified '%s'", argv[3]); + cmdlineP->cols = pm_parse_width(argv[2]); + cmdlineP->rows = pm_parse_height(argv[3]); } } diff --git a/generator/pgmnoise.c b/generator/pgmnoise.c index 708d0cd9..215cbfeb 100644 --- a/generator/pgmnoise.c +++ b/generator/pgmnoise.c @@ -1,79 +1,115 @@ +/********************************************************************* + pgmnoise - create a PGM with white noise + Frank Neumann, October 1993 +*********************************************************************/ + +#include "pm_c_util.h" +#include "mallocvar.h" +#include "shhopt.h" +#include "pgm.h" -/*********************************************************************/ -/* pgmnoise - create a portable graymap with white noise */ -/* Frank Neumann, October 1993 */ -/* V1.1 16.11.1993 */ -/* */ -/* version history: */ -/* V1.0 12.10.1993 first version */ -/* V1.1 16.11.1993 Rewritten to be NetPBM.programming conforming */ -/*********************************************************************/ -#include <unistd.h> +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + unsigned int width; + unsigned int height; + unsigned int randomseed; + unsigned int randomseedSpec; +}; + + + + +static void +parseCommandLine(int argc, const char ** const argv, + struct cmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Note that the file spec array we return is stored in the storage that + was passed to us as the argv array. +-----------------------------------------------------------------------------*/ + optEntry * option_def; + /* Instructions to OptParseOptions3 on how to parse our options. + */ + optStruct3 opt; + unsigned int option_def_index; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "randomseed", OPT_INT, &cmdlineP->randomseed, + &cmdlineP->randomseedSpec, 0); + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* We may have parms that are negative numbers */ + + optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (argc-1 != 2) + pm_error("Wrong number of arguments: %u. " + "Arguments are width and height of image, in pixels", + argc-1); + else { + int const width = atoi(argv[1]); + int const height = atoi(argv[2]); + + if (width <= 0) + pm_error("Width must be positive, not %d", width); + else + cmdlineP->width = width; + + if (height <= 0) + pm_error("Height must be positive, not %d", width); + else + cmdlineP->height = height; + } +} -#include "pgm.h" -/* global variables */ -#ifdef AMIGA -static char *version = "$VER: pgmnoise 1.1 (16.11.93)"; /* Amiga version identification */ -#endif - -/**************************/ -/* start of main function */ -/**************************/ -int main(argc, argv) -int argc; -char *argv[]; -{ - int argn, rows, cols, i, j; - gray *destrow; - const char * const usage = "width height\n width and height are picture dimensions in pixels\n"; - time_t timenow; - - /* parse in 'default' parameters */ - pgm_init(&argc, argv); - - argn = 1; - - /* parse in dim factor */ - if (argn == argc) - pm_usage(usage); - if (sscanf(argv[argn], "%d", &cols) != 1) - pm_usage(usage); - argn++; - if (argn == argc) - pm_usage(usage); - if (sscanf(argv[argn], "%d", &rows) != 1) - pm_usage(usage); - - if (cols <= 0 || rows <= 0) - pm_error("picture dimensions should be positive numbers"); - ++argn; - - if (argn != argc) - pm_usage(usage); - - /* no error checking required here, ppmlib does it all for us */ - destrow = pgm_allocrow(cols); - - pgm_writepgminit(stdout, cols, rows, PGM_MAXMAXVAL, 0); - - /* get time of day to feed the random number generator */ - timenow = time(NULL); - srand(timenow ^ getpid()); - - /* create the (gray) noise */ - for (i = 0; i < rows; i++) - { - for (j = 0; j < cols; j++) - destrow[j] = rand() % (PGM_MAXMAXVAL+1); - - /* write out one line of graphic data */ - pgm_writepgmrow(stdout, destrow, cols, PGM_MAXMAXVAL, 0); - } - - pgm_freerow(destrow); - - exit(0); + + +static void +pgmnoise(FILE * const ofP, + unsigned int const cols, + unsigned int const rows, + gray const maxval) { + + unsigned int row; + gray * destrow; + + destrow = pgm_allocrow(cols); + + pgm_writepgminit(ofP, cols, rows, maxval, 0); + + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) + destrow[col] = rand() % (maxval + 1); + + pgm_writepgmrow(ofP, destrow, cols, maxval, 0); + } + + pgm_freerow(destrow); +} + + + +int main(int argc, + const char * argv[]) { + + struct cmdlineInfo cmdline; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + srand(cmdline.randomseedSpec ? cmdline.randomseed : pm_randseed()); + + pgmnoise(stdout, cmdline.width, cmdline.height, PGM_MAXMAXVAL); + + return 0; } diff --git a/generator/pgmramp.c b/generator/pgmramp.c index b84ed345..c0fb42b1 100644 --- a/generator/pgmramp.c +++ b/generator/pgmramp.c @@ -11,6 +11,8 @@ */ #include <math.h> + +#include "pm_c_util.h" #include "pgm.h" #include "shhopt.h" @@ -96,14 +98,8 @@ parseCommandLine(int argc, char ** argv, pm_error("Only two arguments allowed: width and height. " "You specified %d", argc-1); else { - cmdlineP->cols = atoi(argv[1]); - cmdlineP->rows = atoi(argv[2]); - if (cmdlineP->cols <= 0) - pm_error("width argument must be a positive number. You " - "specified '%s'", argv[1]); - if (cmdlineP->rows <= 0) - pm_error("height argument must be a positive number. You " - "specified '%s'", argv[2]); + cmdlineP->cols = pm_parse_width(argv[1]); + cmdlineP->rows = pm_parse_height(argv[2]); } } diff --git a/generator/ppmcolors.c b/generator/ppmcolors.c index 9112e1b8..ecae2285 100644 --- a/generator/ppmcolors.c +++ b/generator/ppmcolors.c @@ -9,6 +9,7 @@ ******************************************************************************/ +#include "pm_c_util.h" #include "ppm.h" #include "shhopt.h" #include "nstring.h" diff --git a/generator/ppmforge.c b/generator/ppmforge.c index cac56e38..c77076e3 100644 --- a/generator/ppmforge.c +++ b/generator/ppmforge.c @@ -35,7 +35,6 @@ #include <math.h> #include <assert.h> -#include <unistd.h> #include "pm_c_util.h" #include "ppm.h" @@ -283,10 +282,9 @@ static unsigned int initseed(void) { /* Generate initial random seed. */ - int i; + unsigned int i; - i = time(NULL) ^ getpid(); - srand(i); + srand(pm_randseed()); for (i = 0; i < 7; ++i) rand(); return rand(); diff --git a/generator/ppmmake.c b/generator/ppmmake.c index eee32485..e59b47d5 100644 --- a/generator/ppmmake.c +++ b/generator/ppmmake.c @@ -76,14 +76,8 @@ parseCommandLine(int argc, char ** argv, "You specified %d", argc-1); else { cmdlineP->color = ppm_parsecolor(argv[1], cmdlineP->maxval); - cmdlineP->cols = atoi(argv[2]); - cmdlineP->rows = atoi(argv[3]); - if (cmdlineP->cols <= 0) - pm_error("width argument must be a positive number. You " - "specified '%s'", argv[2]); - if (cmdlineP->rows <= 0) - pm_error("height argument must be a positive number. You " - "specified '%s'", argv[3]); + cmdlineP->cols = pm_parse_width(argv[2]); + cmdlineP->rows = pm_parse_height(argv[3]); } } diff --git a/generator/ppmpat.c b/generator/ppmpat.c index 89585c3e..772fa51d 100644 --- a/generator/ppmpat.c +++ b/generator/ppmpat.c @@ -12,17 +12,244 @@ #define _XOPEN_SOURCE /* get M_PI in math.h */ +#include <assert.h> #include <math.h> +#include <limits.h> #include "pm_c_util.h" +#include "mallocvar.h" +#include "shhopt.h" #include "ppm.h" #include "ppmdraw.h" +typedef enum { + PAT_GINGHAM2, + PAT_GINGHAM3, + PAT_MADRAS, + PAT_TARTAN, + PAT_POLES, + PAT_SQUIG, + PAT_CAMO, + PAT_ANTICAMO +} pattern; + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + pattern basePattern; + unsigned int width; + unsigned int height; +}; + + + +static void +parseCommandLine(int argc, const char ** argv, + struct cmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Note that the file spec array we return is stored in the storage that + was passed to us as the argv array. +-----------------------------------------------------------------------------*/ + optEntry * option_def; + /* Instructions to OptParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + unsigned int basePatternCount; + unsigned int gingham2; + unsigned int gingham3; + unsigned int madras; + unsigned int tartan; + unsigned int poles; + unsigned int squig; + unsigned int camo; + unsigned int anticamo; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENTRY */ + OPTENT3(0, "gingham2", OPT_FLAG, NULL, &gingham2, 0); + OPTENT3(0, "g2", OPT_FLAG, NULL, &gingham2, 0); + OPTENT3(0, "gingham3", OPT_FLAG, NULL, &gingham3, 0); + OPTENT3(0, "g3", OPT_FLAG, NULL, &gingham3, 0); + OPTENT3(0, "madras", OPT_FLAG, NULL, &madras, 0); + OPTENT3(0, "tartan", OPT_FLAG, NULL, &tartan, 0); + OPTENT3(0, "poles", OPT_FLAG, NULL, &poles, 0); + OPTENT3(0, "squig", OPT_FLAG, NULL, &squig, 0); + OPTENT3(0, "camo", OPT_FLAG, NULL, &camo, 0); + OPTENT3(0, "anticamo", OPT_FLAG, NULL, &anticamo, 0); + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + + optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + basePatternCount = + gingham2 + + gingham3 + + madras + + tartan + + poles + + squig + + camo + + anticamo; + + if (basePatternCount < 1) + pm_error("You must specify a base pattern option such as -gingham2"); + else if (basePatternCount > 1) + pm_error("You may not specify more than one base pattern option. " + "You specified %u", basePatternCount); + else { + if (gingham2) + cmdlineP->basePattern = PAT_GINGHAM2; + else if (gingham3) + cmdlineP->basePattern = PAT_GINGHAM3; + else if (madras) + cmdlineP->basePattern = PAT_MADRAS; + else if (tartan) + cmdlineP->basePattern = PAT_TARTAN; + else if (poles) + cmdlineP->basePattern = PAT_POLES; + else if (squig) + cmdlineP->basePattern = PAT_SQUIG; + else if (camo) + cmdlineP->basePattern = PAT_CAMO; + else if (anticamo) + cmdlineP->basePattern = PAT_ANTICAMO; + else + assert(false); /* Every possibility is accounted for */ + } + if (argc-1 != 2) + pm_error("You must specify 2 non-option arguments: width and height " + "in pixels. You specified %u", argc-1); + else { + cmdlineP->width = atoi(argv[1]); + cmdlineP->height = atoi(argv[2]); + + if (cmdlineP->width < 1) + pm_error("Width must be at least 1 pixel"); + if (cmdlineP->height < 1) + pm_error("Height must be at least 1 pixel"); + } +} + + + +static void +validateComputableDimensions(unsigned int const cols, + unsigned int const rows) { + + /* + Notes on width and height limits: + + cols * 3, rows * 3 appear in madras, tartan + cols*rows appears in poles + cols+rows appears in squig + + PPMD functions use signed integers for pixel positions + (because they allow you to specify points off the canvas). + */ + + if (cols > INT_MAX/4 || rows > INT_MAX/4 || rows > INT_MAX/cols) + pm_error("Width and/or height are way too large: %u x %u", + cols, rows); +} + static pixel -random_anticamo_color(pixval const maxval) { +randomColor(pixval const maxval) { + + pixel p; + + PPM_ASSIGN(p, + rand() % (maxval + 1), + rand() % (maxval + 1), + rand() % (maxval + 1) + ); + + return p; +} + + + +#define DARK_THRESH 0.25 + +static pixel +randomBrightColor(pixval const maxval) { + + pixel p; + + do { + p = randomColor(maxval); + } while (PPM_LUMIN(p) <= maxval * DARK_THRESH); + + return p; +} + + + +static pixel +randomDarkColor(pixval const maxval) { + + pixel p; + + do { + p = randomColor(maxval); + } while (PPM_LUMIN(p) > maxval * DARK_THRESH); + + return p; +} + + + +static pixel +averageTwoColors(pixel const p1, + pixel const p2) { + + pixel p; + + PPM_ASSIGN(p, + (PPM_GETR(p1) + PPM_GETR(p2)) / 2, + (PPM_GETG(p1) + PPM_GETG(p2)) / 2, + (PPM_GETB(p1) + PPM_GETB(p2)) / 2); + + return p; +} + + + +static ppmd_drawproc average_drawproc; + +static void +average_drawproc(pixel ** const pixels, + int const cols, + int const rows, + pixval const maxval, + int const col, + int const row, + const void * const clientdata) { + + if (col >= 0 && col < cols && row >= 0 && row < rows) + pixels[row][col] = + averageTwoColors(pixels[row][col], *((const pixel*) clientdata)); +} + + + +/*---------------------------------------------------------------------------- + Camouflage stuff +-----------------------------------------------------------------------------*/ + + + +static pixel +randomAnticamoColor(pixval const maxval) { int v1, v2, v3; pixel p; @@ -70,17 +297,14 @@ random_anticamo_color(pixval const maxval) { -/* Camouflage stuff. */ - static pixel -random_camo_color(pixval const maxval) { +randomCamoColor(pixval const maxval) { - int v1, v2, v3; - pixel p; + int const v1 = (maxval + 1 ) / 8; + int const v2 = (maxval + 1 ) / 4; + int const v3 = (maxval + 1 ) / 2; - v1 = (maxval + 1 ) / 8; - v2 = (maxval + 1 ) / 4; - v3 = (maxval + 1 ) / 2; + pixel p; switch (rand() % 10) { case 0: @@ -122,6 +346,46 @@ rnduni(void) { +static void +clearBackground(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + bool const antiflag) { + + pixel color; + + if (antiflag) + color = randomAnticamoColor(maxval); + else + color = randomCamoColor(maxval); + + ppmd_filledrectangle( + pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, + &color); +} + + +static void +camoFill(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + struct fillobj * const fh, + bool const antiflag) { + + pixel color; + + if (antiflag) + color = randomAnticamoColor(maxval); + else + color = randomCamoColor(maxval); + + ppmd_fill(pixels, cols, rows, maxval, fh, PPMD_NULLDRAWPROC, &color); +} + + + #define BLOBRAD 50 #define MIN_POINTS 7 @@ -136,63 +400,68 @@ rnduni(void) { static void +computeXsYs(int * const xs, + int * const ys, + unsigned int const cols, + unsigned int const rows, + unsigned int const pointCt) { + + unsigned int const cx = rand() % cols; + unsigned int const cy = rand() % rows; + double const a = rnduni() * (MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR) + + MIN_ELLIPSE_FACTOR; + double const b = rnduni() * (MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR) + + MIN_ELLIPSE_FACTOR; + double const theta = rnduni() * 2.0 * M_PI; + + unsigned int p; + + for (p = 0; p < pointCt; ++p) { + double const c = rnduni() * (MAX_POINT_FACTOR - MIN_POINT_FACTOR) + + MIN_POINT_FACTOR; + double const tx = a * sin(p * 2.0 * M_PI / pointCt); + double const ty = b * cos(p * 2.0 * M_PI / pointCt); + double const tang = atan2(ty, tx) + theta; + xs[p] = MAX(0, MIN(cols-1, cx + BLOBRAD * c * sin(tang))); + ys[p] = MAX(0, MIN(rows-1, cy + BLOBRAD * c * cos(tang))); + } +} + + + +static void camo(pixel ** const pixels, unsigned int const cols, unsigned int const rows, pixval const maxval, bool const antiflag) { - pixel color; - int n, i, cx, cy; - struct fillobj * fh; + unsigned int const n = (rows * cols) / (BLOBRAD * BLOBRAD) * 5; - /* Clear background. */ - if (antiflag) - color = random_anticamo_color( maxval ); - else - color = random_camo_color( maxval ); + unsigned int i; - ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, - &color); + clearBackground(pixels, cols, rows, maxval, antiflag); - n = (rows * cols) / (BLOBRAD * BLOBRAD) * 5; for (i = 0; i < n; ++i) { - int points, p, xs[MAX_POINTS], ys[MAX_POINTS], x0, y0; - float a, b, c, theta, tang, tx, ty; - - cx = rand() % cols; - cy = rand() % rows; - - points = rand() % ( MAX_POINTS - MIN_POINTS + 1 ) + MIN_POINTS; - a = rnduni() * (MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR) + - MIN_ELLIPSE_FACTOR; - b = rnduni() * (MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR) + - MIN_ELLIPSE_FACTOR; - theta = rnduni() * 2.0 * M_PI; - for (p = 0; p < points; ++p) { - tx = a * sin(p * 2.0 * M_PI / points); - ty = b * cos(p * 2.0 * M_PI / points); - tang = atan2(ty, tx) + theta; - c = rnduni() * (MAX_POINT_FACTOR - MIN_POINT_FACTOR) + - MIN_POINT_FACTOR; - xs[p] = cx + BLOBRAD * c * sin(tang); - ys[p] = cy + BLOBRAD * c * cos(tang); - } - x0 = (xs[0] + xs[points - 1]) / 2; - y0 = (ys[0] + ys[points - 1]) / 2; + unsigned int const pointCt = + rand() % (MAX_POINTS - MIN_POINTS + 1) + MIN_POINTS; + + int xs[MAX_POINTS], ys[MAX_POINTS]; + int x0, y0; + struct fillobj * fh; + + computeXsYs(xs, ys, cols, rows, pointCt); + + x0 = (xs[0] + xs[pointCt - 1]) / 2; + y0 = (ys[0] + ys[pointCt - 1]) / 2; fh = ppmd_fill_create(); ppmd_polyspline( - pixels, cols, rows, maxval, x0, y0, points, xs, ys, x0, y0, - ppmd_fill_drawproc, fh ); + pixels, cols, rows, maxval, x0, y0, pointCt, xs, ys, x0, y0, + ppmd_fill_drawproc, fh); - if (antiflag) - color = random_anticamo_color(maxval); - else - color = random_camo_color(maxval); - ppmd_fill(pixels, cols, rows, maxval, fh, PPMD_NULLDRAWPROC, &color); + camoFill(pixels, cols, rows, maxval, fh, antiflag); ppmd_fill_destroy(fh); } @@ -200,454 +469,398 @@ camo(pixel ** const pixels, -static pixel -random_color(pixval const maxval) { - - pixel p; - - PPM_ASSIGN(p, - rand() % (maxval + 1), - rand() % (maxval + 1), - rand() % (maxval + 1) - ); - - return p; -} - - - -#define DARK_THRESH 0.25 - -#if __STDC__ -static pixel -random_bright_color( pixval maxval ) -#else /*__STDC__*/ -static pixel -random_bright_color( maxval ) - pixval maxval; -#endif /*__STDC__*/ - { - pixel p; - - do - { - p = random_color( maxval ); - } - while ( PPM_LUMIN( p ) <= maxval * DARK_THRESH ); - - return p; - } - -#if __STDC__ -static pixel -random_dark_color( pixval maxval ) -#else /*__STDC__*/ -static pixel -random_dark_color( maxval ) - pixval maxval; -#endif /*__STDC__*/ - { - pixel p; - - do - { - p = random_color( maxval ); - } - while ( PPM_LUMIN( p ) > maxval * DARK_THRESH ); - - return p; - } - -static pixel -average_two_colors( p1, p2 ) -pixel p1, p2; - { - pixel p; - - PPM_ASSIGN( - p, ( (int) PPM_GETR(p1) + (int) PPM_GETR(p2) ) / 2, - ( (int) PPM_GETG(p1) + (int) PPM_GETG(p2) ) / 2, - ( (int) PPM_GETB(p1) + (int) PPM_GETB(p2) ) / 2 ); +/*---------------------------------------------------------------------------- + Gingham stuff +-----------------------------------------------------------------------------*/ - return p; - } -/* Gingham stuff. */ static void -average_drawproc(pixel** const pixels, - int const cols, - int const rows, - pixval const maxval, - int const col, - int const row, - const void* const clientdata ) -{ - if ( col >= 0 && col < cols && row >= 0 && row < rows ) - pixels[row][col] = - average_two_colors( pixels[row][col], *( (pixel*) clientdata ) ); -} +gingham2(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { -static void -gingham2( pixel** pixels, int cols, int rows, pixval maxval ) -{ - pixel const backcolor = random_dark_color( maxval ); - pixel const forecolor = random_bright_color( maxval ); - int const colso2 = cols / 2; - int const rowso2 = rows / 2; + pixel const backcolor = randomDarkColor(maxval); + pixel const forecolor = randomBrightColor(maxval); + unsigned int const colso2 = cols / 2; + unsigned int const rowso2 = rows / 2; /* Warp. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, colso2, rows, PPMD_NULLDRAWPROC, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, colso2, 0, cols - colso2, rows, - PPMD_NULLDRAWPROC, &forecolor ); + PPMD_NULLDRAWPROC, &forecolor); /* Woof. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rowso2, average_drawproc, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rowso2, cols, rows - rowso2, - average_drawproc, &forecolor ); - } + average_drawproc, &forecolor); +} + + -#if __STDC__ -static void -gingham3( pixel** pixels, int cols, int rows, pixval maxval ) -#else /*__STDC__*/ static void -gingham3( pixels, cols, rows, maxval ) - pixel** pixels; - int cols, rows; - pixval maxval; -#endif /*__STDC__*/ - { - int colso4, rowso4; - pixel backcolor, fore1color, fore2color; - - colso4 = cols / 4; - rowso4 = rows / 4; - backcolor = random_dark_color( maxval ); - fore1color = random_bright_color( maxval ); - fore2color = random_bright_color( maxval ); +gingham3(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { + + unsigned int const colso4 = cols / 4; + unsigned int const rowso4 = rows / 4; + + pixel const backcolor = randomDarkColor(maxval); + pixel const fore1color = randomBrightColor(maxval); + pixel const fore2color = randomBrightColor(maxval); /* Warp. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, colso4, rows, PPMD_NULLDRAWPROC, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, colso4, 0, colso4, rows, PPMD_NULLDRAWPROC, - &fore1color ); + &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 2 * colso4, 0, colso4, rows, - PPMD_NULLDRAWPROC, &fore2color ); + PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 3 * colso4, 0, cols - colso4, rows, - PPMD_NULLDRAWPROC, &fore1color ); + PPMD_NULLDRAWPROC, &fore1color); /* Woof. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rowso4, average_drawproc, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rowso4, cols, rowso4, average_drawproc, - &fore1color ); + &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 2 * rowso4, cols, rowso4, - average_drawproc, &fore2color ); + average_drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 3 * rowso4, cols, rows - rowso4, - average_drawproc, &fore1color ); - } + average_drawproc, &fore1color); +} + + -#if __STDC__ -static void -madras( pixel** pixels, int cols, int rows, pixval maxval ) -#else /*__STDC__*/ static void -madras( pixels, cols, rows, maxval ) - pixel** pixels; - int cols, rows; - pixval maxval; -#endif /*__STDC__*/ - { - int cols2, rows2, cols3, rows3, cols12, rows12, cols6a, rows6a, cols6b, - rows6b; - pixel backcolor, fore1color, fore2color; - - cols2 = cols * 2 / 44; - rows2 = rows * 2 / 44; - cols3 = cols * 3 / 44; - rows3 = rows * 3 / 44; - cols12 = cols - 10 * cols2 - 4 * cols3; - rows12 = rows - 10 * rows2 - 4 * rows3; - cols6a = cols12 / 2; - rows6a = rows12 / 2; - cols6b = cols12 - cols6a; - rows6b = rows12 - rows6a; - backcolor = random_dark_color( maxval ); - fore1color = random_bright_color( maxval ); - fore2color = random_bright_color( maxval ); +madras(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { + + unsigned int const cols2 = cols * 2 / 44; + unsigned int const rows2 = rows * 2 / 44; + unsigned int const cols3 = cols * 3 / 44; + unsigned int const rows3 = rows * 3 / 44; + unsigned int const cols12 = cols - 10 * cols2 - 4 * cols3; + unsigned int const rows12 = rows - 10 * rows2 - 4 * rows3; + unsigned int const cols6a = cols12 / 2; + unsigned int const rows6a = rows12 / 2; + unsigned int const cols6b = cols12 - cols6a; + unsigned int const rows6b = rows12 - rows6a; + pixel const backcolor = randomDarkColor(maxval); + pixel const fore1color = randomBrightColor(maxval); + pixel const fore2color = randomBrightColor(maxval); /* Warp. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols2, rows, PPMD_NULLDRAWPROC, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, cols2, 0, cols3, rows, PPMD_NULLDRAWPROC, - &fore1color ); + &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, cols2 + cols3, 0, cols2, rows, - PPMD_NULLDRAWPROC, &backcolor ); + PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 2 * cols2 + cols3, 0, cols2, rows, - PPMD_NULLDRAWPROC, &fore2color ); + PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 3 * cols2 + cols3, 0, cols2, rows, - PPMD_NULLDRAWPROC, &backcolor ); + PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 4 * cols2 + cols3, 0, cols6a, rows, - PPMD_NULLDRAWPROC, &fore1color ); + PPMD_NULLDRAWPROC, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 4 * cols2 + cols3 + cols6a, 0, cols2, rows, - PPMD_NULLDRAWPROC, &backcolor ); + PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 5 * cols2 + cols3 + cols6a, 0, cols3, rows, - PPMD_NULLDRAWPROC, &fore2color ); + PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 5 * cols2 + 2 * cols3 + cols6a, 0, cols2, - rows, PPMD_NULLDRAWPROC, &backcolor ); + rows, PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 6 * cols2 + 2 * cols3 + cols6a, 0, cols3, - rows, PPMD_NULLDRAWPROC, &fore2color ); + rows, PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 6 * cols2 + 3 * cols3 + cols6a, 0, cols2, - rows, PPMD_NULLDRAWPROC, &backcolor ); + rows, PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 7 * cols2 + 3 * cols3 + cols6a, 0, cols6b, - rows, PPMD_NULLDRAWPROC, &fore1color ); + rows, PPMD_NULLDRAWPROC, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 7 * cols2 + 3 * cols3 + cols6a + cols6b, 0, - cols2, rows, PPMD_NULLDRAWPROC, &backcolor ); + cols2, rows, PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 8 * cols2 + 3 * cols3 + cols6a + cols6b, 0, - cols2, rows, PPMD_NULLDRAWPROC, &fore2color ); + cols2, rows, PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 9 * cols2 + 3 * cols3 + cols6a + cols6b, 0, - cols2, rows, PPMD_NULLDRAWPROC, &backcolor ); + cols2, rows, PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 10 * cols2 + 3 * cols3 + cols6a + cols6b, - 0, cols3, rows, PPMD_NULLDRAWPROC, &fore1color ); + 0, cols3, rows, PPMD_NULLDRAWPROC, &fore1color); /* Woof. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rows2, average_drawproc, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows2, cols, rows3, average_drawproc, - &fore2color ); + &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows2 + rows3, cols, rows2, - average_drawproc, &backcolor ); + average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 2 * rows2 + rows3, cols, rows2, - average_drawproc, &fore1color ); + average_drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 3 * rows2 + rows3, cols, rows2, - average_drawproc, &backcolor ); + average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 4 * rows2 + rows3, cols, rows6a, - average_drawproc, &fore2color ); + average_drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 4 * rows2 + rows3 + rows6a, cols, rows2, - average_drawproc, &backcolor ); + average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 5 * rows2 + rows3 + rows6a, cols, rows3, - average_drawproc, &fore1color ); + average_drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 5 * rows2 + 2 * rows3 + rows6a, cols, - rows2, average_drawproc, &backcolor ); + rows2, average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 6 * rows2 + 2 * rows3 + rows6a, cols, - rows3, average_drawproc, &fore1color ); + rows3, average_drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 6 * rows2 + 3 * rows3 + rows6a, cols, - rows2, average_drawproc, &backcolor ); + rows2, average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 7 * rows2 + 3 * rows3 + rows6a, cols, - rows6b, average_drawproc, &fore2color ); + rows6b, average_drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 7 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows2, average_drawproc, &backcolor ); + cols, rows2, average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 8 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows2, average_drawproc, &fore1color ); + cols, rows2, average_drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 9 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows2, average_drawproc, &backcolor ); + cols, rows2, average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 10 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows3, average_drawproc, &fore2color ); - } + cols, rows3, average_drawproc, &fore2color); +} + + -#if __STDC__ -static void -tartan( pixel** pixels, int cols, int rows, pixval maxval ) -#else /*__STDC__*/ static void -tartan( pixels, cols, rows, maxval ) - pixel** pixels; - int cols, rows; - pixval maxval; -#endif /*__STDC__*/ - { - int cols1, rows1, cols3, rows3, cols10, rows10, cols5a, rows5a, cols5b, - rows5b; - pixel backcolor, fore1color, fore2color; - - cols1 = cols / 22; - rows1 = rows / 22; - cols3 = cols * 3 / 22; - rows3 = rows * 3 / 22; - cols10 = cols - 3 * cols1 - 3 * cols3; - rows10 = rows - 3 * rows1 - 3 * rows3; - cols5a = cols10 / 2; - rows5a = rows10 / 2; - cols5b = cols10 - cols5a; - rows5b = rows10 - rows5a; - backcolor = random_dark_color( maxval ); - fore1color = random_bright_color( maxval ); - fore2color = random_bright_color( maxval ); +tartan(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { + + unsigned int const cols1 = cols / 22; + unsigned int const rows1 = rows / 22; + unsigned int const cols3 = cols * 3 / 22; + unsigned int const rows3 = rows * 3 / 22; + unsigned int const cols10 = cols - 3 * cols1 - 3 * cols3; + unsigned int const rows10 = rows - 3 * rows1 - 3 * rows3; + unsigned int const cols5a = cols10 / 2; + unsigned int const rows5a = rows10 / 2; + unsigned int const cols5b = cols10 - cols5a; + unsigned int const rows5b = rows10 - rows5a; + pixel const backcolor = randomDarkColor(maxval); + pixel const fore1color = randomBrightColor(maxval); + pixel const fore2color = randomBrightColor(maxval); /* Warp. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols5a, rows, PPMD_NULLDRAWPROC, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, cols5a, 0, cols1, rows, PPMD_NULLDRAWPROC, - &fore1color ); + &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, cols5a + cols1, 0, cols5b, rows, PPMD_NULLDRAWPROC, &backcolor ); ppmd_filledrectangle( pixels, cols, rows, maxval, cols10 + cols1, 0, cols3, rows, - PPMD_NULLDRAWPROC, &fore2color ); + PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, cols10 + cols1 + cols3, 0, cols1, rows, - PPMD_NULLDRAWPROC, &backcolor ); + PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, cols10 + 2 * cols1 + cols3, 0, cols3, rows, - PPMD_NULLDRAWPROC, &fore2color ); + PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, cols10 + 2 * cols1 + 2 * cols3, 0, cols1, - rows, PPMD_NULLDRAWPROC, (char*) &backcolor ); + rows, PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, cols10 + 3 * cols1 + 2 * cols3, 0, cols3, - rows, PPMD_NULLDRAWPROC, &fore2color ); + rows, PPMD_NULLDRAWPROC, &fore2color); /* Woof. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rows5a, average_drawproc, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows5a, cols, rows1, average_drawproc, - &fore1color ); + &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows5a + rows1, cols, rows5b, - average_drawproc, &backcolor ); + average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + rows1, cols, rows3, - average_drawproc, &fore2color ); + average_drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + rows1 + rows3, cols, rows1, - average_drawproc, &backcolor ); + average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + 2 * rows1 + rows3, cols, rows3, - average_drawproc, &fore2color ); + average_drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + 2 * rows1 + 2 * rows3, cols, - rows1, average_drawproc, &backcolor ); + rows1, average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + 3 * rows1 + 2 * rows3, cols, - rows3, average_drawproc, &fore2color ); - } + rows3, average_drawproc, &fore2color); +} + + + +/*---------------------------------------------------------------------------- + Poles stuff +-----------------------------------------------------------------------------*/ + -/* Poles stuff. */ #define MAXPOLES 500 -#if __STDC__ -static void -poles( pixel** pixels, int cols, int rows, pixval maxval ) -#else /*__STDC__*/ + + static void -poles( pixels, cols, rows, maxval ) - pixel** pixels; - int cols, rows; - pixval maxval; -#endif /*__STDC__*/ - { - int poles, i, xs[MAXPOLES], ys[MAXPOLES], col, row; - pixel colors[MAXPOLES]; +placeAndColorPolesRandomly(int * const xs, + int * const ys, + pixel * const colors, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + unsigned int const poleCt) { - poles = cols * rows / 30000; + unsigned int i; - /* Place and color poles randomly. */ - for ( i = 0; i < poles; ++i ) - { - xs[i] = rand() % cols; - ys[i] = rand() % rows; - colors[i] = random_bright_color( maxval ); + for (i = 0; i < poleCt; ++i) { + xs[i] = rand() % cols; + ys[i] = rand() % rows; + colors[i] = randomBrightColor(maxval); } +} + + + +static void +assignInterpolatedColor(pixel * const resultP, + pixel const color1, + double const dist1, + pixel const color2, + double const dist2) { + + if (dist1 == 0) + /* pixel is a pole */ + *resultP = color1; + else { + double const sum = dist1 + dist2; + + pixval const r = (PPM_GETR(color1)*dist2 + PPM_GETR(color2)*dist1)/sum; + pixval const g = (PPM_GETG(color1)*dist2 + PPM_GETG(color2)*dist1)/sum; + pixval const b = (PPM_GETB(color1)*dist2 + PPM_GETB(color2)*dist1)/sum; + + PPM_ASSIGN(*resultP, r, g, b); + } +} - /* Now interpolate points. */ - for ( row = 0; row < rows; ++row ) - for ( col = 0; col < cols; ++col ) - { - register long dist1, dist2, newdist, r, g, b; - pixel color1, color2; - /* Find two closest poles. */ - dist1 = dist2 = 2000000000; - for ( i = 0; i < poles; ++i ) - { - newdist = ( col - xs[i] ) * ( col - xs[i] ) + - ( row - ys[i] ) * ( row - ys[i] ); - if ( newdist < dist1 ) - { - dist2 = dist1; - color2 = color1; - dist1 = newdist; - color1 = colors[i]; - } - else if ( newdist < dist2 ) - { - dist2 = newdist; - color2 = colors[i]; - } - } - /* And assign interpolated color. */ - newdist = dist1 + dist2; - r = PPM_GETR(color1)*dist2/newdist + PPM_GETR(color2)*dist1/newdist; - g = PPM_GETG(color1)*dist2/newdist + PPM_GETG(color2)*dist1/newdist; - b = PPM_GETB(color1)*dist2/newdist + PPM_GETB(color2)*dist1/newdist; - PPM_ASSIGN( pixels[row][col], r, g, b ); +static void +poles(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { + + unsigned int const poleCt = MAX(2, MIN(MAXPOLES, cols * rows / 30000)); + + int xs[MAXPOLES], ys[MAXPOLES]; + pixel colors[MAXPOLES]; + unsigned int row; + + placeAndColorPolesRandomly(xs, ys, colors, cols, rows, maxval, poleCt); + + /* Interpolate points */ + + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) { + double dist1, dist2; + pixel color1, color2; + unsigned int i; + + /* Find two closest poles. */ + dist1 = dist2 = (SQR((double)cols) + SQR((double)rows)); + for (i = 0; i < poleCt; ++i) { + double const newdist = + (double)((int)col - xs[i]) * ((int)col - xs[i]) + + (double)((int)row - ys[i]) * ((int)row - ys[i]); + if (newdist < dist1) { + dist2 = dist1; + color2 = color1; + dist1 = newdist; + color1 = colors[i]; + } else if (newdist < dist2) { + dist2 = newdist; + color2 = colors[i]; + } + } + assignInterpolatedColor(&pixels[row][col], + color1, dist1, color2, dist2); } } +} + + -/* Squig stuff. */ +/*---------------------------------------------------------------------------- + Squig stuff +-----------------------------------------------------------------------------*/ #define SQUIGS 5 #define SQ_POINTS 7 #define SQ_MAXCIRCLE_POINTS 5000 -static int sq_radius, sq_circlecount; +static int sq_circlecount; static pixel sq_colors[SQ_MAXCIRCLE_POINTS]; -static int sq_xoffs[SQ_MAXCIRCLE_POINTS], sq_yoffs[SQ_MAXCIRCLE_POINTS]; +static ppmd_point sq_offs[SQ_MAXCIRCLE_POINTS]; + + static void validateSquigAspect(unsigned int const cols, @@ -662,52 +875,61 @@ validateSquigAspect(unsigned int const cols, -static void -sq_measurecircle_drawproc(pixel** const pixels, - int const cols, - int const rows, - pixval const maxval, - int const col, - int const row, - const void* const clientdata) -{ - sq_xoffs[sq_circlecount] = col; - sq_yoffs[sq_circlecount] = row; - ++sq_circlecount; +static ppmd_point +vectorSum(ppmd_point const a, + ppmd_point const b) { + + return ppmd_makePoint(a.x + b.x, a.y + b.y); } + + +static ppmd_drawprocp sqMeasureCircleDrawproc; + static void -sq_rainbowcircle_drawproc(pixel** const pixels, - int const cols, - int const rows, - pixval const maxval, - int const col, - int const row, - const void* const clientdata ) -{ - int i; +sqMeasureCircleDrawproc(pixel** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + ppmd_point const p, + const void * const clientdata) { + + sq_offs[sq_circlecount++] = p; +} - for ( i = 0; i < sq_circlecount; ++i ) - ppmd_point_drawproc( - pixels, cols, rows, maxval, col + sq_xoffs[i], row + sq_yoffs[i], - &(sq_colors[i]) ); - } +static ppmd_drawprocp sqRainbowCircleDrawproc; static void -sq_assign_colors(int const circlecount, - pixval const maxval, - pixel * const colors) { +sqRainbowCircleDrawproc(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + ppmd_point const p, + const void * const clientdata) { - pixel rc1, rc2, rc3; - float cco3; unsigned int i; - rc1 = random_bright_color(maxval); - rc2 = random_bright_color(maxval); - rc3 = random_bright_color(maxval); - cco3 = (circlecount - 1) / 3.0; + for (i = 0; i < sq_circlecount; ++i) + ppmd_point_drawprocp( + pixels, cols, rows, maxval, vectorSum(p, sq_offs[i]), + &sq_colors[i]); +} + + + +static void +sqAssignColors(unsigned int const circlecount, + pixval const maxval, + pixel * const colors) { + + pixel const rc1 = randomBrightColor(maxval); + pixel const rc2 = randomBrightColor(maxval); + pixel const rc3 = randomBrightColor(maxval); + float const cco3 = (circlecount - 1) / 3.0; + + unsigned int i; for (i = 0; i < circlecount ; ++i) { if (i < cco3) { @@ -745,338 +967,224 @@ sq_assign_colors(int const circlecount, } -#if __STDC__ -static void -squig( pixel** pixels, int cols, int rows, pixval maxval ) -#else /*__STDC__*/ + static void -squig( pixels, cols, rows, maxval ) - pixel** pixels; - int cols, rows; - pixval maxval; -#endif /*__STDC__*/ - { +clearImageToBlack(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { + pixel color; - int i, j, xc[SQ_POINTS], yc[SQ_POINTS], x0, y0, x1, y1, x2, y2, x3, y3; - validateSquigAspect(cols, rows); - - /* Clear image to black. */ - PPM_ASSIGN( color, 0, 0, 0 ); + PPM_ASSIGN(color, 0, 0, 0); + ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, - &color ); + &color); +} - /* Draw the squigs. */ - (void) ppmd_setlinetype( PPMD_LINETYPE_NODIAGS ); - (void) ppmd_setlineclip( 0 ); - for ( i = SQUIGS; i > 0; --i ) - { - /* Measure circle. */ - sq_radius = ( cols + rows ) / 2 / ( 25 + i * 2 ); - sq_circlecount = 0; - ppmd_circle( - pixels, cols, rows, maxval, 0, 0, sq_radius, - sq_measurecircle_drawproc, NULL ); - sq_assign_colors( sq_circlecount, maxval, sq_colors ); - - /* Choose wrap-around point. */ - switch ( rand() % 4 ) - { - case 0: - x1 = rand() % cols; - y1 = 0; - if ( x1 < cols / 2 ) - xc[0] = rand() % ( x1 * 2 + 1); + + +static void +chooseWrapAroundPoint(unsigned int const cols, + unsigned int const rows, + ppmd_point * const pFirstP, + ppmd_point * const pLastP, + ppmd_point * const p0P, + ppmd_point * const p1P, + ppmd_point * const p2P, + ppmd_point * const p3P) { + + switch (rand() % 4) { + case 0: + p1P->x = rand() % cols; + p1P->y = 0; + if (p1P->x < cols / 2) + pFirstP->x = rand() % (p1P->x * 2 + 1); else - xc[0] = cols - 1 - rand() % ( ( cols - x1 ) * 2 ); - yc[0] = rand() % rows; - x2 = x1; - y2 = rows - 1; - xc[SQ_POINTS - 1] = 2 * x2 - xc[0]; - yc[SQ_POINTS - 1] = y2 - yc[0]; - x0 = xc[SQ_POINTS - 1]; - y0 = yc[SQ_POINTS - 1] - rows; - x3 = xc[0]; - y3 = yc[0] + rows; + pFirstP->x = cols - 1 - rand() % ((cols - p1P->x) * 2); + pFirstP->y = rand() % rows; + p2P->x = p1P->x; + p2P->y = rows - 1; + pLastP->x = 2 * p2P->x - pFirstP->x; + pLastP->y = p2P->y - pFirstP->y; + p0P->x = pLastP->x; + p0P->y = pLastP->y - rows; + p3P->x = pFirstP->x; + p3P->y = pFirstP->y + rows; break; - case 1: - x2 = rand() % cols; - y2 = 0; - if ( x2 < cols / 2 ) - xc[SQ_POINTS - 1] = rand() % ( x2 * 2 + 1); + case 1: + p2P->x = rand() % cols; + p2P->y = 0; + if (p2P->x < cols / 2) + pLastP->x = rand() % (p2P->x * 2 + 1); else - xc[SQ_POINTS - 1] = cols - 1 - rand() % ( ( cols - x2 ) * 2 ); - yc[SQ_POINTS - 1] = rand() % rows; - x1 = x2; - y1 = rows - 1; - xc[0] = 2 * x1 - xc[SQ_POINTS - 1]; - yc[0] = y1 - yc[SQ_POINTS - 1]; - x0 = xc[SQ_POINTS - 1]; - y0 = yc[SQ_POINTS - 1] + rows; - x3 = xc[0]; - y3 = yc[0] - rows; + pLastP->x = cols - 1 - rand() % ((cols - p2P->x) * 2); + pLastP->y = rand() % rows; + p1P->x = p2P->x; + p1P->y = rows - 1; + pFirstP->x = 2 * p1P->x - pLastP->x; + pFirstP->y = p1P->y - pLastP->y; + p0P->x = pLastP->x; + p0P->y = pLastP->y + rows; + p3P->x = pFirstP->x; + p3P->y = pFirstP->y - rows; break; - case 2: - x1 = 0; - y1 = rand() % rows; - xc[0] = rand() % cols; - if ( y1 < rows / 2 ) - yc[0] = rand() % ( y1 * 2 + 1); + case 2: + p1P->x = 0; + p1P->y = rand() % rows; + pFirstP->x = rand() % cols; + if (p1P->y < rows / 2) + pFirstP->y = rand() % (p1P->y * 2 + 1); else - yc[0] = rows - 1 - rand() % ( ( rows - y1 ) * 2 ); - x2 = cols - 1; - y2 = y1; - xc[SQ_POINTS - 1] = x2 - xc[0]; - yc[SQ_POINTS - 1] = 2 * y2 - yc[0]; - x0 = xc[SQ_POINTS - 1] - cols; - y0 = yc[SQ_POINTS - 1]; - x3 = xc[0] + cols; - y3 = yc[0]; + pFirstP->y = rows - 1 - rand() % ((rows - p1P->y) * 2); + p2P->x = cols - 1; + p2P->y = p1P->y; + pLastP->x = p2P->x - pFirstP->x; + pLastP->y = 2 * p2P->y - pFirstP->y; + p0P->x = pLastP->x - cols; + p0P->y = pLastP->y; + p3P->x = pFirstP->x + cols; + p3P->y = pFirstP->y; break; - case 3: - x2 = 0; - y2 = rand() % rows; - xc[SQ_POINTS - 1] = rand() % cols; - if ( y2 < rows / 2 ) - yc[SQ_POINTS - 1] = rand() % ( y2 * 2 + 1); + case 3: + p2P->x = 0; + p2P->y = rand() % rows; + pLastP->x = rand() % cols; + if (p2P->y < rows / 2) + pLastP->y = rand() % (p2P->y * 2 + 1); else - yc[SQ_POINTS - 1] = rows - 1 - rand() % ( ( rows - y2 ) * 2 ); - x1 = cols - 1; - y1 = y2; - xc[0] = x1 - xc[SQ_POINTS - 1]; - yc[0] = 2 * y1 - yc[SQ_POINTS - 1]; - x0 = xc[SQ_POINTS - 1] + cols; - y0 = yc[SQ_POINTS - 1]; - x3 = xc[0] - cols; - y3 = yc[0]; + pLastP->y = rows - 1 - rand() % ((rows - p2P->y) * 2); + p1P->x = cols - 1; + p1P->y = p2P->y; + pFirstP->x = p1P->x - pLastP->x; + pFirstP->y = 2 * p1P->y - pLastP->y; + p0P->x = pLastP->x + cols; + p0P->y = pLastP->y; + p3P->x = pFirstP->x - cols; + p3P->y = pFirstP->y; break; - } - - for ( j = 1; j < SQ_POINTS - 1; ++j ) - { - xc[j] = ( rand() % ( cols - 2 * sq_radius ) ) + sq_radius; - yc[j] = ( rand() % ( rows - 2 * sq_radius ) ) + sq_radius; - } - - ppmd_line( - pixels, cols, rows, maxval, x0, y0, x1, y1, - sq_rainbowcircle_drawproc, NULL ); - ppmd_polyspline( - pixels, cols, rows, maxval, x1, y1, SQ_POINTS, xc, yc, x2, y2, - sq_rainbowcircle_drawproc, NULL ); - ppmd_line( - pixels, cols, rows, maxval, x2, y2, x3, y3, - sq_rainbowcircle_drawproc, NULL ); } - } - +} -/* Test pattern. Just a place to put ppmdraw exercises. */ static void -test(pixel ** const pixels, - unsigned int const cols, - unsigned int const rows, - pixval const maxval) { +squig(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { - pixel color; - struct fillobj * fh; + int i; - /* Clear image to black. */ - PPM_ASSIGN( color, 0, 0, 0 ); - ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, - &color); + validateSquigAspect(cols, rows); + + clearImageToBlack(pixels, cols, rows, maxval); - fh = ppmd_fill_create(); - - ppmd_line(pixels, cols, rows, maxval, - cols/8, rows/8, cols/2, rows/4, ppmd_fill_drawproc, fh); - ppmd_line(pixels, cols, rows, maxval, - cols/2, rows/4, cols-cols/8, rows/8, ppmd_fill_drawproc, fh); - ppmd_line(pixels, cols, rows, maxval, - cols-cols/8, rows/8, cols/2, rows/2, ppmd_fill_drawproc, fh); - ppmd_spline3(pixels, cols, rows, maxval, - cols/2, rows/2, cols/2-cols/16, rows/2-rows/10, - cols/2-cols/8, rows/2, ppmd_fill_drawproc, fh); - ppmd_spline3(pixels, cols, rows, maxval, - cols/2-cols/8, rows/2, cols/4+cols/16, rows/2+rows/10, - cols/4, rows/2, ppmd_fill_drawproc, fh); - ppmd_line(pixels, cols, rows, maxval, - cols/4, rows/2, cols/8, rows/2, ppmd_fill_drawproc, fh); - ppmd_line(pixels, cols, rows, maxval, - cols/8, rows/2, cols/8, rows/8, ppmd_fill_drawproc, fh); - - PPM_ASSIGN(color, maxval, maxval, maxval); - ppmd_fill(pixels, cols, rows, maxval, fh, PPMD_NULLDRAWPROC, &color); + /* Draw the squigs. */ + ppmd_setlinetype(PPMD_LINETYPE_NODIAGS); + ppmd_setlineclip(0); + for (i = SQUIGS; i > 0; --i) { + unsigned int const radius = (cols + rows) / 2 / (25 + i * 2); + + ppmd_point c[SQ_POINTS]; + ppmd_point p0, p1, p2, p3; + sq_circlecount = 0; + ppmd_circlep(pixels, cols, rows, maxval, + ppmd_makePoint(0, 0), radius, + sqMeasureCircleDrawproc, NULL); + sqAssignColors(sq_circlecount, maxval, sq_colors); + + chooseWrapAroundPoint(cols, rows, &c[0], &c[SQ_POINTS-1], + &p0, &p1, &p2, &p3); - ppmd_fill_destroy(fh); + { + /* Do the middle points */ + unsigned int j; + + for (j = 1; j < SQ_POINTS - 1; ++j) { + /* validateSquigAspect() assures that + cols - 2 * radius, rows -2 * radius are positive + */ + c[j].x = (rand() % (cols - 2 * radius)) + radius; + c[j].y = (rand() % (rows - 2 * radius)) + radius; + } + } + ppmd_linep( + pixels, cols, rows, maxval, p0, p1, + sqRainbowCircleDrawproc, NULL); + ppmd_polysplinep( + pixels, cols, rows, maxval, p1, SQ_POINTS, c, p2, + sqRainbowCircleDrawproc, NULL); + ppmd_linep( + pixels, cols, rows, maxval, p2, p3, + sqRainbowCircleDrawproc, NULL); + } } int -main(int argc, char ** argv) { - - pixel** pixels; - int argn, pattern, cols, rows; -#define PAT_NONE 0 -#define PAT_GINGHAM2 1 -#define PAT_GINGHAM3 2 -#define PAT_MADRAS 3 -#define PAT_TARTAN 4 -#define PAT_POLES 5 -#define PAT_SQUIG 6 -#define PAT_CAMO 7 -#define PAT_ANTICAMO 8 -#define PAT_TEST 9 - const char* const usage = "-gingham2|-g2|-gingham3|-g3|-madras|-tartan|-poles|-squig|-camo|-anticamo <width> <height>"; - - - ppm_init(&argc, argv); - - argn = 1; - pattern = PAT_NONE; - - while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) - { - if ( pm_keymatch( argv[argn], "-gingham2", 9 ) || - pm_keymatch( argv[argn], "-g2", 3 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_GINGHAM2; - } - else if ( pm_keymatch( argv[argn], "-gingham3", 9 ) || - pm_keymatch( argv[argn], "-g3", 3 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_GINGHAM3; - } - else if ( pm_keymatch( argv[argn], "-madras", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_MADRAS; - } - else if ( pm_keymatch( argv[argn], "-tartan", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_TARTAN; - } - else if ( pm_keymatch( argv[argn], "-poles", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_POLES; - } - else if ( pm_keymatch( argv[argn], "-squig", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_SQUIG; - } - else if ( pm_keymatch( argv[argn], "-camo", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_CAMO; - } - else if ( pm_keymatch( argv[argn], "-anticamo", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_ANTICAMO; - } - else if ( pm_keymatch( argv[argn], "-test", 3 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_TEST; - } - else - pm_usage( usage ); - ++argn; - } - if ( pattern == PAT_NONE ) - pm_error( "a base pattern must be specified" ); - - if ( argn == argc ) - pm_usage( usage); - if ( sscanf( argv[argn], "%d", &cols ) != 1 ) - pm_usage( usage ); - ++argn; - if ( argn == argc ) - pm_usage( usage); - if ( sscanf( argv[argn], "%d", &rows ) != 1 ) - pm_usage( usage ); - ++argn; - - if ( argn != argc ) - pm_usage( usage); - - if (cols < 1) - pm_error("width must be at least 1"); - if (rows < 1) - pm_error("height must be at least 1"); - - srand( (int) ( time( 0 ) ^ getpid( ) ) ); - pixels = ppm_allocarray( cols, rows ); - - switch ( pattern ) - { +main(int argc, const char ** argv) { + + struct cmdlineInfo cmdline; + pixel ** pixels; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + validateComputableDimensions(cmdline.width, cmdline.height); + + srand(pm_randseed()); + pixels = ppm_allocarray(cmdline.width, cmdline.height); + + switch (cmdline.basePattern) { case PAT_GINGHAM2: - gingham2( pixels, cols, rows, PPM_MAXMAXVAL ); + gingham2(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_GINGHAM3: - gingham3( pixels, cols, rows, PPM_MAXMAXVAL ); + gingham3(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_MADRAS: - madras( pixels, cols, rows, PPM_MAXMAXVAL ); + madras(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_TARTAN: - tartan( pixels, cols, rows, PPM_MAXMAXVAL ); + tartan(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_POLES: - poles( pixels, cols, rows, PPM_MAXMAXVAL ); + poles(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_SQUIG: - squig( pixels, cols, rows, PPM_MAXMAXVAL ); + squig(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_CAMO: - camo( pixels, cols, rows, PPM_MAXMAXVAL, 0 ); + camo(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL, 0); break; case PAT_ANTICAMO: - camo( pixels, cols, rows, PPM_MAXMAXVAL, 1 ); - break; - - case PAT_TEST: - test( pixels, cols, rows, PPM_MAXMAXVAL ); + camo(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL, 1); break; default: - pm_error( "can't happen!" ); + pm_error("can't happen!"); } - /* All done, write it out. */ - ppm_writeppm( stdout, pixels, cols, rows, PPM_MAXMAXVAL, 0 ); - pm_close( stdout ); + ppm_writeppm(stdout, pixels, cmdline.width, cmdline.height, + PPM_MAXMAXVAL, 0); + + ppm_freearray(pixels, cmdline.height); - exit( 0 ); + return 0; } diff --git a/generator/ppmrainbow b/generator/ppmrainbow index f98536cd..96e304ac 100755 --- a/generator/ppmrainbow +++ b/generator/ppmrainbow @@ -47,7 +47,10 @@ if (!$norepeat) { push @colorlist, $ARGV[0]; } -my $tmpprefix = $tmpdir . "/$myname.$$."; +my $ourtmp = "$tmpdir/ppmrainbow$$"; +mkdir($ourtmp, 0777) or + die("Unable to create directory for temporary files '$ourtmp"); + my $widthRemaining; my $n; @@ -58,7 +61,7 @@ $widthRemaining = $Twid; @outlist = (); while (@colorlist >= 2) { - my $outfile = sprintf("%s%03u.ppm", $tmpprefix, $n); + my $outfile = sprintf("%s/file.%03u.ppm", $ourtmp, $n); push(@outlist, $outfile); my $w = int(($widthRemaining-1)/(@colorlist-1))+1; @@ -78,5 +81,10 @@ while (@colorlist >= 2) { exit 0; END { - unlink @outlist if @outlist; + if (@outlist) { + unlink(@outlist); + } + if (defined($ourtmp)) { + rmdir($ourtmp); + } } diff --git a/generator/ppmrough.c b/generator/ppmrough.c index f8823173..b21adedf 100644 --- a/generator/ppmrough.c +++ b/generator/ppmrough.c @@ -10,10 +10,13 @@ ** documentation. This software is provided "as is" without express or ** implied warranty. */ +#include <stdlib.h> #include <math.h> #include <sys/time.h> -#include "ppm.h" + +#include "pm_c_util.h" #include "shhopt.h" +#include "ppm.h" static pixel** PIX; static pixval BG_RED, BG_GREEN, BG_BLUE; |