From b5fbc9170fcb0d6837c05f3f829b0416c44c9071 Mon Sep 17 00:00:00 2001 From: CSRG Date: Tue, 2 Sep 1986 02:44:11 -0800 Subject: [PATCH] BSD 4_4_Lite2 development Work on file usr/src/contrib/dipress/src/bin/dipress/ipress.c Synthesized-from: CSRG/cd3/4.4BSD-Lite2 --- .../contrib/dipress/src/bin/dipress/ipress.c | 1030 +++++++++++++++++ 1 file changed, 1030 insertions(+) create mode 100644 usr/src/contrib/dipress/src/bin/dipress/ipress.c diff --git a/usr/src/contrib/dipress/src/bin/dipress/ipress.c b/usr/src/contrib/dipress/src/bin/dipress/ipress.c new file mode 100644 index 0000000000..75a6752cac --- /dev/null +++ b/usr/src/contrib/dipress/src/bin/dipress/ipress.c @@ -0,0 +1,1030 @@ + +/*----------------------------------------------------------------------------- + * Copyright (c) 1984, 1985, 1986 Xerox Corp. + * + * ipress - most of the code directly dependent on interpress used by dipress + * to produce an interpress file from device independent troff + * intermediate code. + * + * William LeFebvre + * + * + * HISTORY + * 12-Aug-86 Lee Moore (lee) at Xerox Webster Research Center + * Added positioning option to the RES command. + * + * + * 07-Jul-86 Lee Moore (lee) at Xerox Webster Research Center + * Updated IPDeviceType for services 10.0 . + * + * 24-Feb-86 Lee Moore (lee) at Xerox Webster Research Center + * Added a subroutine to emit the SequenceInsertFile command. + * + * John Mellor-Crummey 28-aug-1985 + * restructuring and minor modifications + * + * ed flint 10-may-1985 + * coerce device.num_char_wid to unsigned char, change + * ch argument in outputChar to unsigned int + * since we now have > 128 special characters + *---------------------------------------------------------------------------*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "deviceinfo.h" /* typesetter characteristics */ + +#include "iptokens.h" /* \ */ +#include "literal.h" /* > interface levels for interpress */ +#include "operator.h" /* / */ + +#include "defs.h" /* constant and macro definitions */ +#include "externs.h" /* declarations for global variables */ + + + +/* initialize device */ +initDevice() +{ + int lines = 0; + int timapf; + int ret; + register char *ptr; + register char **ipp; + register char **trp; + char temp[60]; + struct stat stbuf; + + if (dbg) printf("initDevice called\n"); + + /* start the preamble */ + ip_select(outputfile); + /* special master instructions go here... */ + AppendOp(OP_beginBlock); + AppendOp(OP_beginBody); + + /* save scaling transform that uses a mica co-ordinate system */ + AppendRational(1L, 100000); + AppendOp(OP_scale); + AppendInteger((long) F_transform); + AppendOp(OP_fset); + + /* select file that holds page bodies */ + ip_select(pagebodyfile); + + /* open file that maps troff names to interpress names */ + (void) sprintf(temp, "%s/dev%s/interpress-fonts", fontdirectory, devicename); + if ((timapf = open(temp, O_RDONLY,0)) == -1) + reportError(QUIT, "can't open %s (%s)", temp, sys_errlist[errno]); + + /* read in the whole thing */ + ret = fstat(timapf, &stbuf); + if (dbg) printf("stat returned %d, errno %d\n", ret, errno); + timap = malloc((unsigned)(stbuf.st_size + 1)); + if (dbg) printf("reading %d bytes from timapf\n", stbuf.st_size); + ret = read(timapf, timap, (int)stbuf.st_size); + if (dbg) printf("read returned %d, errno %d, timapf %d\n", ret, errno, timapf); + timap[(int)stbuf.st_size] = '\0'; + (void) close(timapf); + + /* count the newlines */ + if (dbg) printf("pointer starts at %08x ... ", timap); + + for (ptr = timap; *ptr != '\0'; ptr++) + if (*ptr == '\n') lines++; + + if (dbg) printf("ends at %08x\n", ptr); + if (dbg) printf("found %d lines\n", lines); + + /* allocate the mapping arrays */ + trp = trname = (char **)malloc((unsigned)(lines * 2 * sizeof(char *))); + ipp = ipname = trname + lines; + + /* break out the strings and store pointers in the arrays */ + ptr = timap; + mapcnt = 0; + while (*ptr) + { + if (dbg) printf("loop: ptr = %08x, *ptr = %c\n", ptr, *ptr); + *trp++ = ptr; + while (!white(*ptr)) ptr++; + *ptr++ = '\0'; + while (white(*ptr)) ptr++; + *ipp++ = ptr; + while (*++ptr != '\n') /* nothing */; + *ptr++ = '\0'; + mapcnt++; + } + + if (dbg) + { + int i; + + for (i = 0; i < lines; i++) + printf("%s\t%s\n", trname[i], ipname[i]); + } + + /* reset vertical and horizontal positions */ + hor_pos = ver_pos = old_hor = old_ver = 0; + + /* reset the font information */ + bzero((char *) currfonts, sizeof(currfonts)); +} + +setScale(spi) /* set resolution */ + +int spi; + +{ + /* set the scaling variable used in all x and y calculations */ + scale = floor(2540.0 / (double)spi + 0.5); + if (dbg) printf("setScale(%d) sets scale to %e\n", spi, scale); + + /* + * Set the drawing scale based on the scale. This factor is applied to + * all points drawn in the bitmap for graphical objects. It is scaled + * down from micas to 508 dpi so that the bitmaps aren't of unwieldy + * size, but still retain enough information to look decent on a good + * device. 508/2540 == 0.2 + */ + drawscale = scale * .2; + if (dbg) printf("setScale(%d) sets drawscale to %e\n", spi, drawscale); +} + +pushCurrentEnv() /* begin a new block */ +{ + statep->ssize = size; + statep->sfont = font; + statep->shorig = hor_orig; + statep->svorig = ver_orig; + statep->shpos = hor_pos; + statep->svpos = ver_pos; + hor_orig = hor_pos; + ver_orig = ver_pos; + hor_pos = ver_pos = 0; + if (statep++ >= state + MAXSTATE) + { + reportError(QUIT, "{ nested too deep"); + } + hor_pos = ver_pos = 0; +} + +popSavedEnv() /* pop to previous state */ +{ + if (--statep < state) + { + reportError(QUIT, "extra }"); + } + size = statep->ssize; + font = statep->sfont; + hor_pos = statep->shpos; + ver_pos = statep->svpos; + hor_orig = statep->shorig; + ver_orig = statep->svorig; +} + +newpage(n) /* new page */ +int n; +{ + int i; + char buff[15]; + + /* print any pending bitmap */ + + /* terminate previous page if outputting */ + if (outputflag) + { + print_bitmap(); + AppendOp(OP_endBody); + } + else flush_bitmap(); + + /* reset vertical positions */ + ver_pos = old_ver = 0; + + /* check new page number against those found in the nPageRanges */ + if (nPageRanges == 0) + { + /* no -o specified -- do all pages */ + outputflag = 1; + } + else + { + /* see if new page has been selected for output */ + outputflag = 0; + for (i = 0; i < nPageRanges; i++) + { + if ((n >= pagerange[i][0]) && (n <= pagerange[i][1])) + { + outputflag = 1; + break; + } + } + } + + /* start new page */ + if (outputflag) + { + AppendOp(OP_beginBody); + (void) sprintf(buff, "Page %d", n); + AppendComment(buff); + Fget(F_transform); + AppendOp(OP_concatt); + AppendInteger(2L); + AppendInteger((long) I_strokeEnd); + AppendOp(OP_iset); + } + + /* font/size no longer valid -- force a new assignment */ + oldftsz = -1; +} + +newLine() /* new line (no vertical motion implied) */ +{ + if (dbg == 3) + putchar('\n'); + flushbuff(); + endcorrect(); + hor_pos = 0; + virgin_line = 1; +} + +internalSize(number) /* convert integer to internal size number */ +int number; +{ + int index; + + if (number >= pointsizeTab[device.num_sizes - 1]) + { + /* larger than largest -- use largest */ + return(device.num_sizes-1); + } + else if (number <= pointsizeTab[0]) + { + /* smaller than smallest -- use smallest */ + return(0); + } + + /* else find the size in pointsizeTab and return index */ + for (index = 0; number > pointsizeTab[index]; index++); + return(index); +} + + + + + +/* handle device stop command */ +resetDevice() +{ + int amt; + static int is_reset = 0; + char bigbuff[1024]; + + if (is_reset) return; /* ignore multiple resets */ + + print_bitmap(); + + /* this is the absolute last thing that we do */ + /* wrap up the preamble and the body */ + ip_select(outputfile); + AppendOp(OP_endBody); + ip_select(pagebodyfile); + AppendOp(OP_endBody); + AppendOp(OP_endBlock); + ip_close(); /* close the body */ + + /* + * Reopen the body and copy it onto the end of the real file (which is + * where we have been building the preamble). We don't need to ip_flush + * the preamble since that is done everytime we ip_select the body. + * Conveniently enough, "tempfilename" still holds the name of the body + * temporary. + */ + pagebodyfile = open(tempfilename, O_RDONLY,0); + while ((amt = read(pagebodyfile, bigbuff, sizeof(bigbuff))) != 0) + { + (void) write(outputfile, bigbuff, amt); + } + + /* close and unlink the body temporary file */ + (void) close(pagebodyfile); + (void) unlink(tempfilename); + + /* send the file off to the printer */ + tempfilename[strlen(tempfilename) - 1] = '\0'; + if (outputfile != 1) + { + IPprint(tempfilename); + } + + /* we are now reset */ + is_reset = 1; +} + +outputString(character) /* print a "funny" character */ +char *character; +{ + int i; + + if (!outputflag) + return; + if (dbg > 2) printf("\\(%s", character); + if (dbg > 3) putchar(' '); + for (i = 0; i < device.spec_char_num; i++) + if (strcmp(&specCharStrTab[specCharTab[i]], character) == 0) + break; + if (i < device.spec_char_num) { + /* printf(" i = %d so i+128 = %d\n", i, i+128); */ + outputChar((unsigned int) i + 128); + } + else { + if (dbg > 3) + printf("-- character not found"); + } + + if (dbg > 2) + putchar('\n'); +} + +outputChar(character) /* put a character */ +unsigned int character; +{ + unsigned char *widp; /* pointer to appropriate width table */ + register char *codep; /* pointer to appropriate table of codes */ + register int i, old_font, fnt_index; + int j, value; + + if (!outputflag) + return; + + if (character <= 32) + { + if (dbg) printf("non-existent character 0%o\n", character); + charw = charWidthTab[font][0] * pointsizeTab[size-1] / device.width_units; + return; + } + character -= 32; + + old_font= font; + i = fontIndexTab[font][character] & 255; + if (i != 0) /* it's on this font */ + { + codep = charCodeTab[font]; + widp = charWidthTab[font]; + } + else if (specFontPos > 0) /* on special (we hope) */ + { + /* assertion: i == 0 */ + fnt_index= specFontPos; + for (j=0; j <= device.num_fonts; j++) + { + struct font_entry *fb; + + fnt_index= (fnt_index+1) % (device.num_fonts+1); + + if ((fb = fontPtr[fnt_index]) != NULL) + { + if (fb->special_flag && (i = fontIndexTab[fnt_index][character] & 255) != 0) + { + codep = charCodeTab[fnt_index]; + widp = charWidthTab[fnt_index]; + setFont(fnt_index); + break; + } + } + } + /* assertion: if j > device.num_fonts then i == 0 and character was not found */ + } + + value= codep[i] & 255; + + if (i == 0 || value == 0) + { + if (dbg) printf("character not found 0%o\n", character+32); + return; + } + + /* remember this character's width */ + /* This MUST be done before calling showchar */ + charw = (widp[i] * pointsizeTab[size-1] + device.width_units/2) / device.width_units; + if (dbg == 3) + { + if (isprint(character+32)) + putchar(character+32); + } + if (dbg > 3) + { + if (isprint(character+32)) + printf("character %c %d\n", character+32, value); + else + printf("character %03o %d\n", character+32, value); + } + + if (value == 0377) + { + /* special escape to an extended code */ + value = getexcode(i); + } + + if (dbg < 6) + showchar(value); + + if (font != old_font) + { + setFont(old_font); + } +} + + +/* + * set point size to n + */ +setPointSize(n) + +int n; /* internal value: index into pointsizeTab */ + +{ + size = n; + ftsz = ((long)font << 16) | ((long)size); +} + + +/* + * set the current font to number + */ +setFont(n) + +int n; /* internal index */ + +{ + font = n; + ftsz = ((long)font << 16) | ((long)size); +} + + +/* + * reportError an error reporting hack that uses dummy parameters + * as place holders for arguments that may or may not + * exist, fprintf will sort out how many should be there + */ +/*VARARGS 2*/ +reportError(f, s, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) +char *s, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8; +{ + fprintf(stderr, "dipress: "); + fprintf(stderr, s, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + fprintf(stderr, "\nerror encountered near line %d\n", linenumber); + if (f == QUIT) goodbye(); +} + + + + +/* + * Graphics drawing primitives. These use the vector drawing capabilities of + * interpress to draw straight lines. All other primitive objects (circle, + * ellipse, etc.) are built in a bitmap and printed with a pixel vector. + */ + +drawline(dh, dv) +int dh,dv; +{ + + if(!outputflag) return; + AppendInteger((long) curr_strokewidth); + AppendInteger((long) I_strokeWidth); + AppendOp(OP_iset); + Moveto(xloc(hor_pos), yloc(ver_pos)); + hor_pos += dh; + ver_pos += dv; + Lineto(xloc(hor_pos), yloc(ver_pos)); + AppendOp(OP_maskstroke); +} + +/* routines used by interpress dependent routines */ + +char showbuff[Showbuff_size + 1]; +char *showp = showbuff; +int showcnt = 0; + +showchar(ch) /* buffer "ch" for use in a "show" command */ +int ch; +{ + char *framep; + register int hdiff, vdiff; + + /* set correct position */ + vdiff = ver_pos - old_ver; + hdiff = hor_pos - old_hor; + if (dbg > 4) + { + printf("old_hor %d, hor_pos %d, hdiff %d; old_ver %d, ver_pos %d, vdiff %d %s\n", + old_hor, hor_pos, hdiff, old_ver, ver_pos, vdiff, + virgin_line ? "(virgin)" : ""); + } + + /* NOTE: this expression depends on boolean true being 1! */ + /* See K&R, Appendix A, section 7.7, page 190 */ + switch (((vdiff != 0) << 1) | (hdiff != 0)) + { + case 0: /* no change */ + break; + default: + flushbuff(); + Setxy(xloc(hor_pos), yloc(ver_pos)); + break; + } + + /* + * Update old_hor and old_ver. Account for character width in old_hor but not in + * hor_pos. If the next hInc call is for the width of the character, the + * next time showchar gets called, old_hor will equal hor_pos. + */ + old_ver = ver_pos; + old_hor = hor_pos + charw; + + /* line is no longer virgin */ + virgin_line = 0; + + /* font and point still the same? */ + if (ftsz != oldftsz) + { + flushbuff(); + if ((framep = currfonts[font]->frames) == NULL) + { + /* previously unused -- give it a frame table */ + framep = currfonts[font]->frames = malloc((unsigned)(device.num_sizes * sizeof(char))); + bzero(framep, device.num_sizes * sizeof(char)); + } + + if (framep[size] == 0) + { + /* make a new font */ + ip_select(outputfile); + SetupFont(currfonts[font]->uname, + floor(pointsizeTab[size-1] * 35.28 + .5), + frameindex); + ip_select(pagebodyfile); + framep[size] = frameindex++; + } + + /* switch to new font/size combo */ + Setfont(framep[size]); + oldftsz = ftsz; + } + + /* adjust for character codes > 0377 */ + if (ch > 0377) + { + if (dbg > 4) + { + printf("processing large code: 0%o (%d)\n", ch, ch); + } + + if (showcnt + 5 > Showbuff_size) + { + flushbuff(); + } + *showp++ = '\377'; + *showp++ = (ch & 0177400) >> 8; + *showp++ = ch & 255; + *showp++ = '\377'; + *showp++ = '\0'; + showcnt += 5; + } + else + { + *showp++ = ch; + if (++showcnt > Showbuff_size) + { + flushbuff(); + } + } +} + +/* + * getexcode(findex) - get the extended code for the character "findex" + */ + +getexcode(findex) +int findex; +{ + register int extfd; + register int i; + register unsigned short *tab; + char temp[132]; + + if (dbg > 4) + { + printf("getexcode(%d)\n", findex); + } + + if ((tab = currfonts[font]->extab) == NULL) + { + /* load in the extended code table */ + + (void) sprintf(temp, "%s/dev%s/%s.out.ext", + fontdirectory, devicename, currfonts[font]->name); + if (dbg > 4) + { + printf("opening and reading %s\n", temp); + } + if ((extfd = open(temp, O_RDONLY,0)) == -1) + { + reportError(CONTINUE, "can't open %s (%s)", temp, sys_errlist[errno]); + return(0); + } + currfonts[font]->extab = tab = (unsigned short *) + malloc( (unsigned)(i = (device.spec_char_num + 128-32) * sizeof(short)) ); + (void) read(extfd, (char *)tab, i); /* should test result! */ + (void) close(extfd); + } + + if (dbg > 4) + { + printf("getexcode returning %.7o\n", tab[findex]); + } + return(tab[findex]); +} + +flushbuff() /* flush and reset "showbuff" */ +{ + if (showcnt == 0) + return; + + if (!in_correct) + { + startcorrect(); + } + + /* we must do the append_Sequence explicitly, */ + /* because showbuff might have nulls in it. */ + append_Sequence(sequenceString, showcnt, (unsigned char *)showbuff); + AppendOp(OP_show); + showp = showbuff; + showcnt = 0; +} + +int hstart; + +startcorrect() +{ +#ifdef CORRECT_BLOCKS + AppendOp(OP_correct); + AppendOp(OP_beginBody); +#endif + in_correct = 1; + hstart = hor_pos; +} + +endcorrect() +{ + /* append a Setcorrectmeasure operation */ + /* "hor_pos" or "old_hor"??? Make it "old_hor" for now */ +#ifdef CORRECT_BLOCKS + Setcorrectmeasure(xloc(old_hor), 0.0); + AppendOp(OP_endBody); +#endif + in_correct = 0; +} + +/* + * IPprint(filename) - send the file "filename" to the interpress printer. + * This routine is *very* dependent on local + * environments. + */ + +IPprint(filename) +char *filename; +{ + if (dbg) + { + printf("interpress file saved in %s.\n", filename); + return; + } + + if (vfork() == 0) + { + /* is child */ + execl("/usr/local/bin/qip", "qip", "-nc", "-nk", filename, 0); + exit(1); + } +} + +/* bitmap graphics object sizing functions */ + +g_sizearc(x1, y1, xc, yc, x2, y2) +int x1, y1, xc, yc, x2, y2; +{ + int minx; + int miny; + int maxx; + int maxy; + int quad1; + int quad2; + int radius; + int axc; + int ayc; + int i; + + /* the center and the second point are offsets from the first */ + /* calculate actual center and radius */ + axc = x1 + xc; + ayc = y1 + yc; + radius = (int)(hypot((double)xc, (double)yc) + .5); + if (dbg > 1) + { + printf("g_sizearc(%d, %d, %d, %d, %d, %d): radius is %d\n", + x1, y1, xc, yc, x2, y2, radius); + } + + /* preset the minmal and maximal points -- this is our first guess */ + if ((minx = x1 + xc + x2) > x1) + { + maxx = minx; + minx = x1; + } + else + { + maxx = x1; + } + if ((miny = y1 + yc + y2) > y1) + { + maxy = miny; + miny = y1; + } + else + { + maxy = y1; + } + + /* calculate the offset from the center to the first point */ + x1 = -xc; + y1 = -yc; /* now all three arguments are offsets */ + + /* calculate the quadrant of each endpoint */ + quad1 = quadrant(x1, y1); + quad2 = quadrant(x2, y2); + if (dbg > 1) + { + printf("(%d, %d) in quadrant %d ... ", x1, y1, quad1); + printf("(%d, %d) in quadrant %d\n", x2, y2, quad2); + } + + /* insure that quad1 < quad2 */ + if (quad2 < quad1) + { + quad2 += 4; + } + + /* compensate for arc at each quadrant boundary */ + for (i = quad1 + 1; i <= quad2; i++) + { + switch (i & 3) + { + case 0: /* 1st quadrant */ + maxx = axc + radius; + break; + + case 1: /* 2nd quadrant */ + miny = ayc - radius; + break; + + case 2: /* 3rd quadrant */ + minx = axc - radius; + break; + + case 3: /* 4th quadrant */ + maxy = ayc + radius; + break; + } + } + + /* now set the extremes */ + if (dbg > 1) + { + printf("extremes are %d, %d, %d, %d\n", minx, miny, maxx, maxy); + } + gobj_size(minx, miny, maxx, maxy); +} + +quadrant(dx, dy) +int dx,dy; +{ + register int yplus; + + yplus = dy > 0; + if (dx > 0) + { + return(yplus ? 3 : 0); + } + else + { + return(yplus ? 2 : 1); + } +} + + +g_sizeWigglyLine(str) +char *str; +{ + int minx; + int miny; + int maxx; + int maxy; + int currx; + int curry; + int incx; + int incy; + + currx = minx = maxx = hor_pos; + curry = miny = maxy = ver_pos; + + while(white(*str)) str++; /* trim leading white space */ + + while (*str) + { + + (void) readNumber(&str,&incx); + (void) readNumber(&str,&incy); + currx += incx; + curry += incy; + if (currx > maxx) + maxx = currx; + else if (currx < minx) + minx = currx; + if (curry > maxy) + maxy = curry; + else if (curry < miny) + miny = curry; + } + gobj_size(minx, miny, maxx, maxy); +} + + +/* + * Request the insertion of an Interpress master + */ + +doSequenceInsertIP(fileName) +char *fileName; { + AppendOp(OP_dosavesimplebody); + AppendOp(OP_beginBody); + /* set the IP position at the current troff position */ + Setxy(xloc(hor_pos), yloc(ver_pos)); + + /* undo the Troff scaling */ + AppendRational(spotsPerInch*10000L, 254L); + AppendOp(OP_scale); + AppendOp(OP_concatt); + AppendOp(OP_trans); + + AppendInsertFile(fileName); + AppendOp(OP_endBody); +} + + +#define SAME 0 + +/* + * define frame variables for the RES image + */ +#define IMAGE_EDIT 47L +#define IMAGE_COLOR_OP 46L +#define IMAGE_COLOR 45L +#define IMAGE_MASK 44L +#define IMAGE_Y 43L +#define IMAGE_X 42L +#define IMAGE_SCALE 41L + +/* + * Request the insertion of an RES file + */ + +doSequenceInsertRES(anchor, resolutionString, fileName) +char *anchor, + *resolutionString, + *fileName; { + int resolution; + + resolution = atoi(resolutionString); + + AppendOp(OP_dosavesimplebody); + AppendOp(OP_beginBody); + /* set the IP position at the current troff position */ + Setxy(xloc(hor_pos), yloc(ver_pos)); + + AppendInsertFile(fileName); + + /* pop and store */ + AppendOp(OP_pop); /* for now, don't check the signature */ + AppendInteger(IMAGE_EDIT); + AppendOp(OP_fset); + AppendInteger(IMAGE_COLOR_OP); + AppendOp(OP_fset); + AppendInteger(IMAGE_COLOR); + AppendOp(OP_fset); + AppendOp(OP_pop); /* discard mask image */ + AppendInteger(IMAGE_Y); + AppendOp(OP_fset); + AppendInteger(IMAGE_X); + AppendOp(OP_fset); + AppendInteger(IMAGE_SCALE); + AppendOp(OP_fset); + + /* undo the Troff scaling */ + AppendRational(spotsPerInch*10000L, 254L); + AppendOp(OP_scale); + + /* set the resolution */ + if( resolution != 0 ) { + /* display the RES file at the specified resolution */ + AppendRational(254L, resolution*10000L); + AppendOp(OP_scale); } + else + /* get the default scale from the RES file */ + /* can the device do a "get" operator? */ + if( IPDeviceType == Xerox8044_Services8 || + IPDeviceType == Xerox8044_Services9 || + IPDeviceType == Xerox8044_Services10 ) + reportError(CONTINUE, "requested device can't read resolution from an RES file"); + else { + /* Yes! Use the imageScale suggested by the image */ + Fget(IMAGE_SCALE); + Get(1L); + Fget(IMAGE_SCALE); + Get(2L); + AppendOp(OP_scale2); } + + AppendOp(OP_concat); /* concat undo-scale with image scale */ + + if( strcmp(anchor, "bl") == SAME ) /* bottom left */ + ; + else if( strcmp(anchor, "tl") == SAME ) { /* top left */ + AppendInteger(-1L); /* invert scale */ + AppendOp(OP_scale); + AppendOp(OP_concat); + AppendOp(OP_concatt); + + FGet(IMAGE_Y); + AppendOp(OP_setyrel); + + AppendInteger(-1L); + AppendOp(OP_scale); + } + else if( strcmp(anchor, "c") == SAME ) { /* center */ + AppendRational(-1L, 2L); + AppendOp(OP_scale); + AppendOp(OP_concat); + AppendOp(OP_concatt); /* half normal scale for centering */ + + FGet(IMAGE_X); + FGet(IMAGE_Y); + AppendOp(OP_setxyrel); + + AppendRational(-2L, 1L); + AppendOp(OP_scale); + } + else if( strcmp(anchor, "br") == SAME ) { /* bottom right */ + AppendInteger(-1L); /* invert scale */ + AppendOp(OP_scale); + AppendOp(OP_concat); + AppendOp(OP_concatt); + + FGet(IMAGE_X); + AppendOp(OP_setxrel); + + AppendInteger(-1L); /* invert scale */ + AppendOp(OP_scale); + } + else if( strcmp(anchor, "tr") == SAME ) { /* top right */ + AppendInteger(-1L); /* invert scale */ + AppendOp(OP_scale); + AppendOp(OP_concat); + AppendOp(OP_concatt); + + FGet(IMAGE_X); + FGet(IMAGE_Y); + AppendOp(OP_setxyrel); + + AppendInteger(-1L); /* invert scale */ + AppendOp(OP_scale); + } + else + reportError(CONTINUE, "unknown position in RES command: %s", anchor ); + + AppendOp(OP_concatt); + + AppendOp(OP_trans); + + FGet(IMAGE_COLOR); + AppendOp(OP_maskpixel); + AppendOp(OP_endBody); +} -- 2.20.1