executor/src/PSprint.c

2283 lines
51 KiB
C

/*
* Copyright 1992 - 2000 by Abacus Research and Development, Inc.
* All rights reserved.
*
* $Id: PSprint.c 87 2005-05-25 01:57:33Z ctm $
*/
#include "rsys/common.h"
#include <stdarg.h>
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_PSprint[] =
"$Id: PSprint.c 87 2005-05-25 01:57:33Z ctm $";
#endif
#if defined(NEXTSTEP)
#if !defined(OPENSTEP)
#include <dpsclient/wraps.h>
#include <dpsclient/dpsclient.h>
#else
#include <AppKit/AppKit.h>
#include <AppKit/dpsclient.h>
#include <AppKit/psops.h>
#endif
#include <objc/objc.h>
#endif
#include "MemoryMgr.h"
#include "QuickDraw.h"
#include "OSEvent.h"
#include "FontMgr.h"
#include "rsys/nextprint.h"
#include "rsys/blockinterrupts.h"
#include "rsys/next.h"
#include "rsys/PSstrings.h"
#include "rsys/tempalloc.h"
#include "rsys/print.h"
#include "rsys/text.h"
#include "rsys/cquick.h"
#include "rsys/quick.h"
#include <ctype.h>
typedef struct
{
boolean_t rotated_p;
float center_x;
float center_y;
float angle;
}
rotation_t;
PRIVATE rotation_t rotation;
#if !defined(NEXTSTEP)
PUBLIC FILE *ROMlib_printfile;
#define DPSContext long
typedef enum { NO, YES } boolean;
PRIVATE DPSContext DPSGetCurrentContext(void)
{
return 0;
}
PRIVATE void DPSPrintf(DPSContext unused, const char *format, ...)
{
va_list ap;
va_start(ap, format);
if (ROMlib_printfile)
vfprintf(ROMlib_printfile, format, ap);
va_end(ap);
}
PRIVATE void DPSWritePostScript(DPSContext unused, const char *bufp, int n)
{
if (ROMlib_printfile)
fwrite(bufp, n, 1, ROMlib_printfile);
}
PRIVATE void PSFontDirectory(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "FontDirectory\n");
}
PRIVATE void PSarc(float x, float y, float radius, float angle1, float angle2)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f %f %f %f %f arc\n",
x, y, radius, angle1, angle2);
}
PRIVATE void PSarcn(float x, float y, float radius, float angle1, float angle2)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f %f %f %f %f arcn\n",
x, y, radius, angle1, angle2);
}
PRIVATE void PSarct(float x1, float y1, float x2, float y2, float radius)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f %f %f %f %f arcto pop pop pop pop\n",
x1, y1, x2, y2, radius);
}
PRIVATE void PSbegin(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "begin\n");
}
PRIVATE void PSclip(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "clip\n");
}
PRIVATE void PSclippath(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "clippath\n");
}
PRIVATE void PSclosepath(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "closepath\n");
}
PRIVATE void PScurrentdict(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "currentdict\n");
}
PRIVATE void PSdefinefont(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "definefont\n");
}
PRIVATE void PSdiv(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "div\n");
}
PRIVATE void PSdup(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "dup\n");
}
PRIVATE void PSend(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "end\n");
}
PRIVATE void PSexch(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "exch\n");
}
PRIVATE void PSfill(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "fill\n");
}
PRIVATE void PSget(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "get\n");
}
PRIVATE void PSgrestore(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "grestore\n");
}
PRIVATE void PSgsave(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "gsave\n");
}
PRIVATE void PSimage(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "image\n");
}
PRIVATE void PScolorimage(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "colorimage\n");
}
PRIVATE void PSimagemask(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "imagemask\n");
}
PRIVATE void PSindex(int n)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%d index\n", n);
}
PRIVATE void PSlineto(float x, float y)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f %f lineto\n", x, y);
}
PRIVATE void PSmoveto(float x, float y)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f %f moveto\n", x, y);
}
PRIVATE void PSmul(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "mul\n");
}
PRIVATE void PSnewpath(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "newpath\n");
}
PRIVATE void PSpop(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "pop\n");
}
PRIVATE void PSrectclip(float x, float y, float width, float height)
{
if (ROMlib_printfile)
{
#if 0
/* rectclip is level 2, believe it or not */
fprintf(ROMlib_printfile, "%f %f %f %f rectclip\n", x, y, width, height);
#else
fprintf(ROMlib_printfile, ("newpath\n"
"%f %f moveto\n"
"%f 0 rlineto\n"
"0 %f rlineto\n"
"%f neg 0 rlineto\n"
"closepath\n"
"clip\n"
"newpath\n"), x, y, width, height, width);
#endif
}
}
PRIVATE void PSrlineto(float x, float y)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f %f rlineto\n", x, y);
}
PRIVATE void PSroll(int n, int j)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%d %d roll\n", n, j);
}
PRIVATE void PSrotate(float angle)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f rotate\n", angle);
}
PRIVATE void PSscale(float sx, float sy)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f %f scale\n", sx, sy);
}
PRIVATE void PSsendboolean(boolean flag)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%s\n", flag ? "true" : "false");
}
PRIVATE void output_quoted_character(unsigned char c)
{
if (isprint(c)) {
switch (c) {
case '(':
case ')':
case '\\':
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "\\");
/* FALL THROUGH */
default:
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%c", c);
}
} else
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "\\%03o", c);
}
PRIVATE void PSsendchararray(const char *stringp, int size)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "(");
while (--size >= 0)
output_quoted_character(*stringp++);
if (ROMlib_printfile)
fprintf(ROMlib_printfile, ")\n");
}
PRIVATE void PSsendfloat(float value)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f\n", value);
}
PRIVATE void PSsendfloatarray(const float *arrayp, int size)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "[\n");
while (--size >= 0)
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f\n", *arrayp++);
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "]\n");
}
PRIVATE void PSsendint(int value)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%d\n", value);
}
PRIVATE void PSsetgray(float num)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f setgray\n", num);
}
PRIVATE void PSstroke(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "stroke\n");
}
PRIVATE void PSsub(void)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "sub\n");
}
PRIVATE void PStranslate(float x, float y)
{
if (ROMlib_printfile)
fprintf(ROMlib_printfile, "%f %f translate\n", x, y);
}
#endif
typedef struct {
char *macfontname;
char *nextfontname;
char *suffix[4];
} fontentry_t;
static fontentry_t fonttable[] = {
{ "Avant Garde", "AvantGarde",
{ "-Book", "-Demi", "-BookOblique", "-DemiOblique" } },
{ "Bookman", "Bookman",
{ "-Light", "-Demi", "-LightItalic", "-DemiItalic" } },
{ "Chicago", "Chicago",
{ "-Roman", "-Bold", "-Italic", "-BoldItalic" } },
{ "Courier", "Courier",
{ "", "-Bold", "-Oblique", "-BoldOblique" } },
{ "Garamond", "Garamond",
{ "-Light", "-Bold", "-LightItalic", "-BoldItalic" } },
{ "Geneva", "Geneva",
{ "", "-Bold", "-Oblique", "-BoldOblique" } },
{ "Helvetica", "Helvetica",
{ "", "-Bold", "-Oblique", "-BoldOblique" } },
{ "Lubalin Graph", "LubalinGraph",
{ "-Book", "-Demi", "-BookOblique", "-DemiOblique" } },
{ "Monaco", "Monaco",
{ "", "-Bold", "-Oblique", "-BoldOblique" } },
{ "N Helvetica Narrow", "Helvetica-Narrow",
{ "", "-Bold", "-Oblique", "-BoldOblique" } },
{ "New Century Schlbk", "NewCenturySchlbk",
{ "-Roman", "-Bold", "-Italic", "-BoldItalic" } },
{ "New York", "NewYork",
{ "-Roman", "-Bold", "-Italic", "-BoldItalic" } },
{ "Optima", "Optima",
{ "", "-Bold", "-Oblique", "-BoldOblique" } },
{ "Palatino", "Palatino",
{ "-Roman", "-Bold", "-Italic", "-BoldItalic" } },
{ "Souvenir", "Souvenir",
{ "-Light", "-Demi", "-LightItalic", "-DemiItalic" } },
{ "Symbol", "Symbol",
{ "", "", "", "" } },
{ "Times", "Times",
{ "-Roman", "-Bold", "-Italic", "-BoldItalic" } },
{ "Zapf Chancery", "ZapfChancery-MediumItalic",
{ "", "", "", "" } },
{ "Zapf Dingbats", "ZapfDingbats",
{ "", "", "", "" } },
};
comGrafPort printport;
#define patCopy 8
/*
* NOTE: for now we use alloca for a temporary buffer, even though
* sending big char arrays no longer works... We should just
* blast out the hex without an intermediate buffer.
*/
#define DONTSENDBIGARRAYS
static void ourimageproc( int numbytes )
{
DPSPrintf(DPSGetCurrentContext(),
"{ currentfile %d string readhexstring pop }\n", numbytes);
}
static void dumpimage( unsigned char *p, int numrows, int numbytes,
int rowbytes )
{
DPSContext context;
int i, j;
int toskip;
toskip = rowbytes - numbytes;
context = DPSGetCurrentContext();
for (i = 0; i < numrows; ++i)
{
for (j = 0; j < numbytes; ++j)
DPSPrintf(context, "%02X", *p++);
DPSPrintf(context, "\n");
p += toskip;
}
}
static void
dumpcolorimage (unsigned char *p, int numrows, int numbytes,
int rowbytes, int pixelsize)
{
DPSContext context;
int i, j;
int toskip;
/* TODO: split up values into RGB(and ignored) components and pump them out
in the right order */
toskip = rowbytes - numbytes;
context = DPSGetCurrentContext();
for (i = 0; i < numrows; ++i)
{
for (j = 0; j < numbytes; )
{
int r, g, b;
switch (pixelsize)
{
case 16:
r = (p[0] << 1) & 0xF8;
g = ((p[0] << 6) | (p[1]>>2)) & 0xF8;
b = (p[1] << 3); /* 5 bits of b */
p += 2;
j += 2;
break;
default:
case 24:
warning_unexpected ("pixelsize %d", pixelsize);
/* fall through */
case 32:
if (pixelsize == 32)
{
++p;
++j;
}
r = *p++;
g = *p++;
b = *p++;
j += 3;
break;
}
DPSPrintf(context, "%02X%02X%02X", r, g, b);
}
DPSPrintf(context, "\n");
p += toskip;
}
}
PRIVATE float
mac_old_color_to_ps_gray (long color)
{
float retval;
switch (color)
{
case blackColor:
retval = 0;
break;
case whiteColor:
retval = 1.0;
break;
default:
/* really not sure what to do here */
warning_unexpected ("%ld", color);
retval = 1.0;
break;
}
return retval;
}
PRIVATE boolean_t
graymatch(unsigned char patp[8], INTEGER pnMode,
comGrafPtr thePortp, float *grayp)
{
uint32 *pl;
boolean_t pat_is_black;
boolean_t pat_is_white;
boolean_t retval;
float gray_fore, gray_back;
int i, j;
static struct {
float graylevel;
unsigned pat[8];
} table [] = {
{ 0.0000, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } },
{ 0.2500, { 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD } },
{ 0.5000, { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 } },
{ 0.7500, { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 } },
{ 0.9375, { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 } },
{ 1.0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
};
gray_fore = mac_old_color_to_ps_gray (CL (thePortp->fgColor));
gray_back = mac_old_color_to_ps_gray (CL (thePortp->bkColor));
pl = (uint32 *) patp;
pat_is_black = ((gray_fore == 0 && gray_back == 0) ||
(gray_fore == 0 && pl[0] == -1 && pl[1] == -1) ||
(gray_back == 0 && pl[0] == 0 && pl[1] == 0));
pat_is_white = ((gray_fore == 1 && gray_back == 1) ||
(gray_fore == 1 && pl[0] == -1 && pl[1] == -1) ||
(gray_back == 1 && pl[0] == 0 && pl[1] == 0));
#if 0
#warning DO NOT CHECK THIS IN
{
long fg, bk;
const char *fgs, *bks;
fg = CL (thePortp->fgColor);
bk = CL (thePortp->bkColor);
if (fg == whiteColor)
fgs = "white";
else if (fg == blackColor)
fgs = "black";
else
fgs = "unknown";
if (bk == whiteColor)
bks = "white";
else if (bk == blackColor)
bks = "black";
else
bks = "unknown";
fprintf (stderr, "gray_fore = %f, gray_back = %f, fg = %s(%ld), bk = %s(%ld), is_black = %s, is_white = %s\n", gray_fore, gray_back, fgs, fg, bks, bk, pat_is_black ? "true" : "false", pat_is_white ? "true" : "false");
}
#endif
retval = FALSE;
if (((pnMode == patOr || pnMode == patCopy ) && pat_is_black) ||
((pnMode == notPatOr || pnMode == notPatCopy) && pat_is_white))
{
retval = TRUE;
*grayp = gray_fore;
}
else if (((pnMode == patBic || pnMode == notPatCopy) && pat_is_black) ||
((pnMode == notPatBic || pnMode == patCopy ) && pat_is_white))
{
retval = TRUE;
*grayp = gray_back;
}
else if (pnMode == patCopy || pnMode == notPatCopy)
{
if (gray_fore == gray_back)
{
retval = TRUE;
*grayp = gray_fore;
}
else
{
for (i = 0; !retval && i < (int) NELEM(table); ++i)
{
float darkness;
for (j = 0 ; j < 8; ++j)
{
if (table[i].pat[j] != patp[j])
/*-->*/ goto CONT;
}
darkness = table[i].graylevel;
if (pnMode == notPatCopy)
darkness = 1.0 - darkness;
*grayp = (darkness * gray_fore) + ((1 - darkness) * gray_back);
retval = TRUE;
CONT:;
}
}
}
return retval;
}
static void doimage(LONGINT verb, comRect *rp, comGrafPtr thePortp)
{
unsigned char *patp, pat[8], c, *bytes, *p;
int rowbytes, i, j, toshift, numbytesneeded;
float gray_val;
int numrows;
float matrix[6];
short pnMode;
TEMP_ALLOC_DECL (temp_alloc_space);
pnMode = CW (thePortp->pnMode);
switch (verb) {
default:
case paintVerb:
patp = thePortp->pnPat;
break;
case eraseVerb:
patp = thePortp->bkPat;
pnMode = patCopy;
break;
case fillVerb:
patp = thePortp->fillPat;
pnMode = patCopy;
break;
}
/* convert erroneous srcXXX to patXXX */
if (pnMode >= srcCopy && pnMode <= notSrcBic)
pnMode |= 8;
if (graymatch (patp, pnMode, thePortp, &gray_val)) {
PSclippath();
PSsetgray(gray_val);
PSfill();
} else {
PSmoveto(CW(rp->left), CW(rp->bottom));
PSlineto(CW(rp->left), CW(rp->top));
PSlineto(CW(rp->right), CW(rp->top));
PSlineto(CW(rp->right), CW(rp->bottom));
PSclosepath();
PSmoveto(CW(rp->left)-1, CW(rp->bottom)+1);
PSlineto(CW(rp->right)+1, CW(rp->bottom)+1);
PSlineto(CW(rp->right)+1, CW(rp->top)-1);
PSlineto(CW(rp->left)-1, CW(rp->top)-1);
PSclip();
rowbytes = ((CW(rp->right) - CW(rp->left)) * 72 + 72 * 8 - 1)/ 72 / 8;
numrows = ((CW(rp->bottom) - CW(rp->top)) * 72 + 71) / 72;
if (rowbytes > 0 && numrows > 0)
{
numbytesneeded = rowbytes * numrows;
TEMP_ALLOC_ALLOCATE (bytes, temp_alloc_space, numbytesneeded);
toshift = (CW(rp->left) - CW(thePortp->portBits.bounds.left)) & 7;
for (i = 0; i < 8; ++i)
pat[i] = (patp[i] << toshift) | (patp[i]>>(8 - toshift));
p = bytes;
for (i = CW(rp->top) - CW(thePortp->portBits.bounds.top);
i < CW(rp->top) + numrows - CW(thePortp->portBits.bounds.top);
++i)
{
c = pat[i&7];
if (pnMode == patCopy)
c = ~c;
for (j = rowbytes; --j >= 0;)
*p++ = c;
}
PStranslate(CW(rp->left), CW(rp->top));
#if !defined(DONTSENDBIGARRAYS)
PSsendchararray((char *) bytes, numbytesneeded);
#endif /* DONTSENDBIGARRAYS */
PSsendint(rowbytes * 8);
PSsendint(numrows);
if (pnMode == patCopy)
PSsendint(1);
else
PSsendboolean(YES);
matrix[0] = 72/(float)72;
matrix[1] = 0;
matrix[2] = 0;
matrix[3] = -72/(float)72;
matrix[4] = 0;
matrix[5] = numrows;
PSsendfloatarray(matrix, 6);
#if !defined(DONTSENDBIGARRAYS)
PSsendintarray((int *)0, 0);
PScvx();
#else /* DONTSENDBIGARRAYS */
ourimageproc( rowbytes );
#endif /* DONTSENDBIGARRAYS */
if (pnMode == patCopy)
PSimage();
else
PSimagemask();
#if defined(DONTSENDBIGARRAYS)
dumpimage( bytes, numrows, rowbytes, rowbytes );
#endif
}
}
TEMP_ALLOC_FREE (temp_alloc_space);
}
void ROMlib_gsave( void )
{
virtual_int_state_t block;
block = block_virtual_ints ();
PSgsave();
restore_virtual_ints (block);
}
void ROMlib_grestore( void )
{
virtual_int_state_t block;
block = block_virtual_ints ();
PSgrestore();
restore_virtual_ints (block);
}
char ROMlib_suppressclip = NO;
static char reloadclip = NO;
PRIVATE double save_xoffset, save_yoffset;
void ROMlib_rotatebegin( LONGINT flippage, LONGINT angle )
{
virtual_int_state_t block;
block = block_virtual_ints ();
PSrotate(angle);
PStranslate(-save_xoffset, -save_yoffset);
ROMlib_suppressclip = YES;
printport.pnLoc.h = CWC(-32768); /* force reload */
printport.txFont = CWC(-32768); /* force reload */
restore_virtual_ints (block);
}
void ROMlib_rotatecenter( double yoffset, double xoffset )
{
DPSContext context;
virtual_int_state_t block;
/*
* TODO: support flippage
*/
block = block_virtual_ints ();
context = DPSGetCurrentContext();
PSgsave ();
PStranslate(xoffset, yoffset);
save_xoffset = xoffset;
save_yoffset = yoffset;
restore_virtual_ints (block);
}
void ROMlib_rotateend( void )
{
virtual_int_state_t block;
block = block_virtual_ints ();
PSgrestore ();
ROMlib_suppressclip = NO;
reloadclip = YES;
restore_virtual_ints (block);
}
static void NeXTClip(comRect *rp)
{
virtual_int_state_t block;
block = block_virtual_ints ();
/* we used to do a `grestore' `gsave' sequence here, to get the clip
path before the previous call to `NeXTClip ()', and then add the
new `rectclip'. but this causes serious problems, because the
`grestore' `gsave' sequence undoes more than just the previous
rectclip, it also undoes `translate's and other graphics state
modifications that can't be undone here.
as far as i can tell, the `grestore' `gsave' sequence just got
you back to the intial (unbounded) clip path */
DPSPrintf (DPSGetCurrentContext (), "initclip\n");
if ((rp->left != CWC (-32767) && rp->left != CWC (-32768)) ||
(rp->top != CWC (-32767) && rp->top != CWC (-32768)) ||
rp->right != CWC (32767) ||
rp->bottom != CWC (32767))
PSrectclip (CW (rp->left), CW (rp->top),
CW (rp->right) - CW(rp->left), CW (rp->bottom) - CW (rp->top));
restore_virtual_ints (block);
}
static int myEqualRect(comRect *r1, comRect *r2)
{
return r1->top == r2->top &&
r1->bottom == r2->bottom &&
r1->left == r2->left &&
r1->right == r2->right;
}
/*
* updates the fields that *all* drawing routines care about
*/
static void commonupdate(comGrafPtr thePortp)
{
int dx, dy;
if (thePortp->portBits.bounds.top != printport.portBits.bounds.top ||
thePortp->portBits.bounds.left != printport.portBits.bounds.left) {
dx = CW(printport.portBits.bounds.left) - CW(thePortp->portBits.bounds.left);
dy = CW(printport.portBits.bounds.top) - CW(thePortp->portBits.bounds.top);
PStranslate(dx, dy);
printport.portBits.bounds = thePortp->portBits.bounds;
}
if (!ROMlib_suppressclip && (reloadclip ||
!myEqualRect(&MR(*MR(thePortp->clipRgn))->rgnBBox,
&MR(*MR(printport.clipRgn))->rgnBBox))) {
NeXTClip(&MR(*MR(thePortp->clipRgn))->rgnBBox);
MR(*MR(printport.clipRgn))->rgnBBox = MR(*MR(thePortp->clipRgn))->rgnBBox;
printport.pnLoc.h = CWC(-32768); /* force reload */
printport.txFont = CWC(-32768); /* force reload */
}
if (thePortp->pnLoc.h != printport.pnLoc.h ||
thePortp->pnLoc.v != printport.pnLoc.v) {
PSmoveto(CW(thePortp->pnLoc.h), CW(thePortp->pnLoc.v));
printport.pnLoc = thePortp->pnLoc;
}
#if 0
if (thePortp->fgColor != printport.fgColor) {
}
if (thePortp->bkColor != printport.bkColor) {
}
#endif
}
#define bold 1
#define italic 2
#define underline 4
#define outline 8
/*
* TODO: tons of this better... (pay attention to spExtra)
*/
/*
* TODO: Barlow wants more fonts
*/
/*
* findprefered looks for a match in fonttable and constructs the
* appropriate fontname. If no match is found, fname is copied
* over to retval.
*/
static char match255c(StringPtr str, char *p)
{
int n;
n = strlen(p);
if (n != str[0])
return NO;
else
return strncmp((char *) str+1, p, n) == 0;
}
PRIVATE void
substitute_chars (char *string, char find, char replace)
{
while (*string)
{
if (*string == find)
*string = replace;
++string;
}
}
static void findpreferred(StringPtr fname, int index, char *retval)
{
int i;
for (i = 0; i < (int) NELEM(fonttable); ++i) {
if (match255c(fname, fonttable[i].macfontname))
/*-->*/ break;
}
if (i < (int) NELEM(fonttable))
sprintf(retval, "%s%s", fonttable[i].nextfontname,
fonttable[i].suffix[index]);
else {
strncpy(retval, (char *) fname+1, (unsigned char) fname[0]);
retval[(unsigned char) fname[0]] = 0;
substitute_chars (retval, ' ', '-');
}
}
#if defined(NEXTSTEP)
/*
* Trytomatch looks at the fonts that are actually present and verifies
* that what we're trying to do is legit. If it isn't, a substitution
* is made.
*/
static char *normals[] = { "UltraLight",
"Thin",
"Light",
"ExtraLight",
"Book",
"Regular",
"Plain",
"Roman"
"Medium",
};
static char *bolds[] = { "Demi",
"DemiBold",
"SemiBold",
"Bold",
"ExtraBold",
"Heavy",
"Heavyface",
"Black",
"Ultra",
"UltraBlack",
"Fat",
"ExtraBlack",
"Obese"
};
static char *italics[] = { "Italic", "Oblique" };
static int lookfor( char *str, char *table[], int tablelen, char startatleft )
{
int i, retval, n1, n2;
char *start;
retval = 0;
n1 = strlen(str);
start = str;
for (i = 0; i < tablelen; ++i) {
n2 = strlen(table[i]);
if (n1 >= n2) {
if (!startatleft)
start = str + n1 - n2;
if (strncmp(table[i], start, n2) == 0) {
retval = 1;
break;
}
}
}
return retval;
}
#if 0
static int ndashes(char *name)
{
int retval;
retval = 0;
while (*name)
if (*name++ == '-')
++retval;
return retval;
}
#endif
static int matchpercentage(char *value, int indx, const char *tomatch)
{
char *dash, isnormal, isbold, isitalic;
int retval;
dash = rindex(tomatch, '-');
retval = 0;
if (( dash && strncmp(value, tomatch, dash - tomatch) == 0) ||
(!dash && strcmp (value, tomatch) == 0)) {
#if 0
if (!dash || ndashes(value) == ndashes(tomatch))
if (!indx)
retval = 100; /* perfect match */
else
retval = 25; /* got the name, but nothing else */
else { /* } */
#else
{
#endif
++dash;
isnormal = lookfor(dash, normals, NELEM(normals), YES);
isbold = lookfor(dash, bolds, NELEM(bolds), YES);
isitalic = lookfor(dash, italics, NELEM(italics), NO);
switch (indx) {
case 0:
if (isnormal)
retval += 50;
if (!isbold)
retval += 25;
if (!isitalic)
retval += 25;
break;
case bold:
if (isbold)
retval += 50;
if (!isnormal)
retval += 25;
if (!isitalic)
retval += 25;
break;
case italic:
if (isitalic)
retval += 75;
if (!isbold)
retval += 25;
break;
case bold|italic:
if (isitalic)
retval += 75;
if (isbold)
retval += 25;
break;
}
}
}
return retval;
}
void ROMlib_trytomatch(char *retval, LONGINT index)
{
#ifndef OPENSTEP
char **list, **pp;
#endif /* not OPENSTEP */
/* id fmgr; */
const char *bestp;
int bestn;
int n;
#ifdef OPENSTEP
NSArray *font_list;
int i;
#endif /* OPENSTEP */
virtual_int_state_t block;
block = block_virtual_ints ();
#ifndef OPENSTEP
list = ROMlib_availableFonts();
#else /* OPENSTEP */
font_list = [[NSFontManager sharedFontManager] availableFonts];
#endif /* OPENSTEP */
bestn = 0;
#if !defined(LETGCCWAIL)
bestp = 0;
#endif
#ifndef OPENSTEP
for (pp = list; *pp && bestn != 100; ++pp) {
n = matchpercentage(retval, index, *pp);
#else /* OPENSTEP */
for (i = 0; i < [font_list count] && bestn != 100; ++i) {
const char *font_name;
font_name = [[font_list objectAtIndex:i] cString];
n = matchpercentage(retval, index, font_name);
#endif /* OPENSTEP */
if (n > bestn) {
bestn = n;
#ifndef OPENSTEP
bestp = *pp;
#else /* OPENSTEP */
bestp = font_name;
#endif /* OPENSTEP */
}
}
if (bestn > 0)
strcpy(retval, bestp);
else {
switch(index) {
#ifdef OPENSTEP
#warning We can do much better matching fonts under OpenStep
#endif /* OPENSTEP */
default:
strcpy(retval, "Times-Roman");
break;
case bold:
strcpy(retval, "Times-Bold");
break;
case italic:
strcpy(retval, "Times-Italic");
break;
case bold|italic:
strcpy(retval, "Times-BoldItalic");
break;
}
}
#ifndef OPENSTEP
free(list);
#endif /* not OPENSTEP */
restore_virtual_ints (block);
}
#endif
static char *fnametofont(StringPtr fname, LONGINT txFace)
{
int index;
static char retval[80];
index = txFace & (bold|italic);
findpreferred(fname, index, retval);
#if defined(NEXTSTEP)
ROMlib_trytomatch(retval, index);
#endif
if (txFace & outline)
strcat(retval, "-Outline");
if (txFace & outline) {
PSFontDirectory();
PSsendchararray(retval, strlen(retval));
DPSPrintf(DPSGetCurrentContext(), "known not {\n");
PSsendchararray(retval, strlen(retval));
PSsendchararray(retval, strlen(retval) - 8);
DPSPrintf(DPSGetCurrentContext(), "findfont2\n");
DPSPrintf(DPSGetCurrentContext(), "dup length 1 add dict\n");
PSbegin();
DPSPrintf(DPSGetCurrentContext(), "{ 1 index /FID ne {def} {pop pop} ifelse } forall\n");
DPSPrintf(DPSGetCurrentContext(), "(PaintType) 2 def\n");
DPSPrintf(DPSGetCurrentContext(), "(StrokeWidth) 0 def\n");
PScurrentdict();
PSend();
PSdefinefont();
PSpop();
DPSPrintf(DPSGetCurrentContext(), "} \nif\n");
}
return retval;
}
typedef struct
{
const char *old;
const char *new;
float multiplier;
}
substitute_t;
PUBLIC boolean_t substitute_fonts_p = FALSE;
PRIVATE float
substitute_font_if_needed (char **fontp, LONGINT orig_size,
boolean_t *need_to_freep)
{
float retval;
static substitute_t substitutions[] =
{
{ "Geneva", "Helvetica", 1.0, },
{ "Monaco", "Courier", 1.0, },
{ "New York", "Times", 1.0, },
};
retval = orig_size;
*need_to_freep = FALSE;
if (substitute_fonts_p)
{
int i;
char *font;
font = *fontp;
for (i = 0; i < (int) NELEM (substitutions); ++i)
{
int len;
len = strlen (substitutions[i].old);
if (strncmp (substitutions[i].old, font, len) == 0)
{
char *newname;
newname = malloc (strlen (font) - len +
strlen (substitutions[i].new) + 1);
sprintf (newname, "%s%s", substitutions[i].new, font + len);
*fontp = newname;
*need_to_freep = TRUE;
retval = orig_size * substitutions[i].multiplier;
/*-->*/ break;
}
}
}
return retval;
}
void NeXTSetText(StringPtr fname, LONGINT txFace, LONGINT txSize,
LONGINT spExtra)
{
char *font;
float matrix[6];
virtual_int_state_t block;
float font_size;
boolean_t need_to_free;
block = block_virtual_ints ();
font = fnametofont(fname, txFace);
if (txSize < 0)
txSize = 1;
else if (txSize == 0)
txSize = 12;
font_size = substitute_font_if_needed (&font, txSize, &need_to_free);
#if defined(NEXTSTEP)
ROMlib_newFont(font, font_size);
#endif
PSsendchararray(font, strlen(font));
matrix[0] = font_size;
matrix[1] = 0;
matrix[2] = 0;
matrix[3] = -font_size;
matrix[4] = 0;
matrix[5] = 0;
PSsendfloatarray(matrix, 6);
DPSPrintf(DPSGetCurrentContext(), "selectfont\n");
restore_virtual_ints (block);
if (need_to_free)
free (font);
}
PRIVATE void
SmartGetFontName (comGrafPtr thePortp, StringPtr fname)
{
C_GetFontName (CW (thePortp->txFont), fname);
if (!fname[0])
C_GetFontName (CW (ApFontID), fname);
if (!fname[0])
C_GetFontName (CW (SysFontFam), fname);
}
/*
* updates the fields that text routines care about
*/
static void txupdate(comGrafPtr thePortp)
{
unsigned char fname[256];
SETUPA5;
commonupdate(thePortp);
if (thePortp->txMode != printport.txMode) {
}
if (thePortp->txFont != printport.txFont ||
thePortp->txFace != printport.txFace ||
thePortp->txSize != printport.txSize ||
thePortp->spExtra != printport.spExtra) {
SmartGetFontName(thePortp, fname);
NeXTSetText(fname, thePortp->txFace, CW(thePortp->txSize),
CL(thePortp->spExtra));
printport.txFont = thePortp->txFont;
printport.txFace = thePortp->txFace;
printport.txSize = thePortp->txSize;
}
RESTOREA5;
}
void pnupdate(comGrafPtr thePortp)
{
commonupdate(thePortp);
#if 0
if (thePortp->pnSize.h != printport.pnSize.h ||
thePortp->pnSize.v != printport.pnSize.v) {
NeXTSetWidth(CW(thePortp->pnSize));
printport.pnSize = thePortp->pnSize;
}
#endif
/* TODO: more stuff here */
}
void NeXTPrArc(LONGINT verb, comRect *rp, LONGINT starta, LONGINT arca,
comGrafPtr thePortp)
{
if (rp->left != rp->right &&
rp->top != rp->bottom) /* ignore empty rectangles */
{
short psh, psv;
float xdiam, ydiam, midx, midy;
LONGINT froma, toa;
virtual_int_state_t block;
block = block_virtual_ints ();
pnupdate(thePortp);
PSgsave();
if (arca > 0) {
froma = -90 + starta;
toa = -90 + starta + arca;
} else {
froma = -90 + starta + arca;
toa = -90 + starta;
}
midx = ((float)CW(rp->left) + CW(rp->right ))/2;
midy = ((float)CW(rp->top) + CW(rp->bottom))/2;
xdiam = CW(rp->right) - CW(rp->left);
ydiam = CW(rp->bottom) - CW(rp->top);
PStranslate(midx, (midy));
PSnewpath();
PSscale(1, ydiam/xdiam);
PSarc(0, 0, xdiam/2, froma, toa);
if (verb == frameVerb) {
psh = CW(thePortp->pnSize.h);
psv = CW(thePortp->pnSize.v);
if (ydiam > (2 * psv) && xdiam > (2 * psh)) {
PSscale(1, xdiam/ydiam * (ydiam - 2*psv) / (xdiam - 2*psh));
PSarcn(0, 0, xdiam/2 - psh, toa, froma);
PSclosepath();
PSscale(1, ydiam/xdiam * (xdiam - 2*psh) / (ydiam - 2*psv));
}
} else
PSlineto(0, 0);
PSclosepath();
PSclip();
PSscale(1, xdiam/ydiam);
PStranslate(-midx, -(midy));
doimage(verb, rp, thePortp);
PSgrestore();
restore_virtual_ints (block);
}
}
PRIVATE int
num_image_bytes (numbytes, pixelsize, direct_color_p)
{
int retval;
if (!direct_color_p)
retval = numbytes;
else
{
switch (pixelsize)
{
case 16:
retval = numbytes / 2 * 3;
break;
default:
case 24:
retval = numbytes;
break;
case 32:
retval = numbytes / 4 * 3;
break;
}
}
return retval;
}
#define srcCopy 0
#define srcBic 3
#if !defined(ROWMASK)
#define ROWMASK 0x1FFF
#endif
void NeXTPrBits(comBitMap *srcbmp, comRect *srcrp, comRect *dstrp,
LONGINT mode, comRgnHandle mask, comGrafPtr thePortp)
{
float scalex, scaley;
float srcwidth, srcheight, dstwidth, dstheight;
float matrix[6];
unsigned char *p1, *p2, *ep, *bytes, *baseaddr;
int numbytesneeded;
comPixMap *srcpmp;
short rowbytes, numbytes, pixelsize;
virtual_int_state_t block;
boolean_t direct_color_p;
boolean_t indexed_color_p;
TEMP_ALLOC_DECL (temp_alloc_space);
direct_color_p = FALSE;
indexed_color_p = FALSE;
block = block_virtual_ints ();
commonupdate(thePortp);
srcwidth = CW(srcrp->right) - CW(srcrp->left);
srcheight = CW(srcrp->bottom) - CW(srcrp->top);
dstwidth = CW(dstrp->right) - CW(dstrp->left);
dstheight = CW(dstrp->bottom) - CW(dstrp->top);
if (srcwidth && srcheight && dstwidth && dstheight) /* put in for output */
{ /* from Tex-Edit 2.5 */
/* see the comment at the grestore below */
PSgsave ();
scalex = dstwidth / srcwidth;
scaley = dstheight / srcheight;
if (srcbmp->rowBytes & CWC(0x8000))
{
srcpmp = (comPixMap *) srcbmp;
pixelsize = CW(srcpmp->pixelSize);
if (pixelsize != 1 && mode != srcCopy)
/*-->*/ goto DONE;
direct_color_p = pixelsize > 8;
if (!direct_color_p)
indexed_color_p = TRUE;
}
else
{
srcpmp = 0;
pixelsize = 1;
}
rowbytes = CW(srcbmp->rowBytes) & ROWMASK;
PStranslate(CW(dstrp->left), CW(dstrp->top));
baseaddr = (unsigned char *)MR(srcbmp->baseAddr)
+ (CW(srcrp->top) - CW(srcbmp->bounds.top)) * (LONGINT) rowbytes;
/* NOTE: now that we don't send big arrays, I believe that doing
the transformation below is a memory waste... Shouldn't we
be able to do that on the fly? -- I don't want to mess with
this now, but it does make sense to fix it sometime. */
if (mode == srcCopy && !direct_color_p && !indexed_color_p)
{
numbytesneeded = rowbytes * srcheight;
TEMP_ALLOC_ALLOCATE (bytes, temp_alloc_space, numbytesneeded);
ep = bytes + numbytesneeded;
for (p1 = bytes, p2 = baseaddr; p1 < ep ; )
*p1++ = ~*p2++;
baseaddr = bytes;
}
#if !defined(DONTSENDBIGARRAYS)
PSsendchararray((char *) baseaddr, rowbytes * srcheight);
#endif
matrix[0] = 1 / scalex;
matrix[1] = 0;
matrix[2] = 0;
matrix[3] = 1 / scaley;
matrix[4] = CW(srcrp->left) - CW(srcbmp->bounds.left);
matrix[5] = 0;
numbytes = ((int) srcwidth * pixelsize + 7) / 8;
if (!indexed_color_p)
{
PSsendint((int) srcwidth);
PSsendint(srcheight);
if (mode != srcCopy)
PSsendboolean(YES);
else
{
if (direct_color_p)
PSsendint (8);
else
PSsendint(pixelsize);
}
PSsendfloatarray(matrix, 6);
#if !defined(DONTSENDBIGARRAYS)
PSsendintarray((int *)0, 0);
PScvx();
#else
ourimageproc (num_image_bytes (numbytes, pixelsize, direct_color_p));
#endif
if (mode == srcBic)
PSsetgray(1);
if (mode != srcCopy)
PSimagemask();
else
{
if (!direct_color_p)
PSimage();
else
{
PSsendboolean (FALSE);
PSsendint (3);
PScolorimage();
}
}
}
else
{
ColorSpec *ctab;
int i;
HIDDEN_PixMapPtr pxp;
boolean_t has_warned_p;
pxp.p = (PixMapPtr) RM (srcpmp);
DPSPrintf (DPSGetCurrentContext (),
"[/Indexed /DeviceRGB %d <\n", (1 << pixelsize) - 1);
ctab = CTAB_TABLE (PIXMAP_TABLE (&pxp));
/* NOTE: we're ignoring the value field below. We could do
a quick test to see if it's sorted and if it is use it
directly and if not, copy and qsort it and then use
the result. It's not clear when that's necessary. TODO
look into this further. */
has_warned_p = FALSE;
for (i = 0; i < (1 << pixelsize); ++i)
{
unsigned char r;
unsigned char g;
unsigned char b;
if (CW (ctab[i].value) != i && !has_warned_p)
{
warning_unexpected ("value = %d, i = %d",
CW (ctab[i].value), i);
has_warned_p = TRUE;
}
r = CW (ctab[i].rgb.red ) >> 8;
g = CW (ctab[i].rgb.green) >> 8;
b = CW (ctab[i].rgb.blue ) >> 8;
DPSPrintf (DPSGetCurrentContext (),
"%02x%02x%02x%c", r, g, b, (i % 8) == 7 ? '\n' : ' ');
}
DPSPrintf (DPSGetCurrentContext (),
">]\nsetcolorspace\n<<\n/ImageType 1\n/Width %d\n"
"/Height %d\n"
"/BitsPerComponent %d\n/Decode [0 %d]\n"
"/ImageMatrix [%f %f %f %f %f %f]\n"
"/DataSource currentfile /ASCIIHexDecode filter\n"
">>\nimage\n", (int) srcwidth, (int) srcheight, pixelsize,
(1 << pixelsize) - 1,
matrix[0], matrix[1], matrix[2],
matrix[3], matrix[4], matrix[5]);
}
#if defined(DONTSENDBIGARRAYS)
if (direct_color_p)
dumpcolorimage (baseaddr, srcheight, numbytes, rowbytes, pixelsize);
else
dumpimage( baseaddr, srcheight, numbytes, rowbytes );
#endif
/* #### this grestore used to be commented out with the
following comment:
`This seems to mess up Compact Pro's output'
but there was no corresponding `gsave' earlier in this
function. i added it, and uncommented this grestore, because
it is clear someone has to undo the `translate' done to set
the location for the `image' command */
DONE:
PSgrestore();
}
restore_virtual_ints (block);
TEMP_ALLOC_FREE (temp_alloc_space);
}
void NeXTPrLine(comPoint to, comGrafPtr thePortp)
{
float temp, fromh, fromv, toh, tov;
short psh, psv;
comRect r;
virtual_int_state_t block;
block = block_virtual_ints ();
pnupdate(thePortp);
if (CW(thePortp->pnSize.h) || CW(thePortp->pnSize.v)) {
fromh = CW(thePortp->pnLoc.h);
fromv = CW(thePortp->pnLoc.v);
toh = to.h;
tov = to.v;
if (fromh > toh) {
temp = fromh;
fromh = toh;
toh = temp;
temp = fromv;
fromv = tov;
tov = temp;
}
psh = CW(thePortp->pnSize.h);
psv = CW(thePortp->pnSize.v);
r.right = CW(toh + psh);
r.left = CW(fromh);
PSgsave();
PSnewpath();
PSmoveto(fromh, fromv);
if (fromv < tov) {
r.top = CW(fromv);
r.bottom = CW(tov + psv);
PSlineto(fromh + psh, fromv);
PSlineto(toh + psh, tov);
PSlineto(toh + psh, tov + psv);
PSlineto(toh, tov + psv);
PSlineto(fromh, fromv + psv);
} else {
r.top = CW(tov);
r.bottom = CW(fromv + psv);
PSlineto(toh, tov);
PSlineto(toh + psh, tov);
PSlineto(toh + psh, tov + psv);
PSlineto(fromh + psh, fromv + psv);
PSlineto(fromh, fromv + psv);
}
PSclosepath();
PSclip();
doimage((LONGINT) paintVerb, &r, thePortp);
PSgrestore();
}
restore_virtual_ints (block);
}
void NeXTPrOval(LONGINT verb, comRect *rp, comGrafPtr thePortp)
{
NeXTPrArc(verb, rp, 0, 360, thePortp);
}
#if 1
void NeXTPrGetPic(comPtr dp, LONGINT bc, comGrafPtr thePortp)
{
gui_abort();
}
#endif
void NeXTPrPutPic(comPtr sp, LONGINT bc, comGrafPtr thePortp)
{
}
void NeXTPrPoly(LONGINT verb, comPolyHandle ph, comGrafPtr thePortp)
{
comPoint *pp, *ep, firstp;
virtual_int_state_t block;
comPoint pt;
block = block_virtual_ints ();
pnupdate(thePortp);
pp = MR(*ph)->polyPoints;
ep = (comPoint *) ((char *)MR(*ph) + CW((MR(*ph))->polySize));
firstp.h = CW(pp[0].h);
firstp.v = CW(pp[0].v);
thePortp->pnLoc = pp[0];
if (CW(ep[-1].h) == firstp.h && CW(ep[-1].v) == firstp.v)
ep--;
if (ep > pp)
{
if (verb == frameVerb) {
PSmoveto(firstp.h, firstp.v);
for (++pp; pp < ep; pp++) {
pt.h = CW(pp[0].h);
pt.v = CW(pp[0].v);
NeXTPrLine(pt, thePortp);
thePortp->pnLoc = pp[0];
}
NeXTPrLine(firstp, thePortp);
} else {
PSgsave();
PSnewpath();
PSmoveto(firstp.h, firstp.v);
for (++pp; pp < ep; pp++) {
PSlineto(CW(pp->h), CW(pp->v));
}
PSlineto(firstp.h, firstp.v);
PSclosepath();
PSclip();
doimage(verb, & (MR(*ph))->polyBBox, thePortp);
PSgrestore();
}
}
restore_virtual_ints (block);
}
void NeXTPrRRect(LONGINT verb, comRect *rp, LONGINT width, LONGINT height,
comGrafPtr thePortp)
{
float sfactor, midy, rt, rb, rl, rr, sfactor2;
short psh, psv;
virtual_int_state_t block;
if (width <= 0 || height <= 0)
NeXTPrRect (verb, rp, thePortp);
else
{
block = block_virtual_ints ();
pnupdate(thePortp);
sfactor = (float)height/width;
midy = ((float)CW(rp->top) + CW(rp->bottom))/2;
PSgsave();
PSnewpath();
PSscale(1, sfactor);
PSmoveto(CW(rp->left), midy/sfactor);
rl = CW(rp->left);
rr = CW(rp->right);
rt = CW(rp->top)/sfactor;
rb = CW(rp->bottom)/sfactor;
PSarct(rl, rb, rr, rb, (float)width / 2);
PSarct(rr, rb, rr, rt, (float)width / 2);
PSarct(rr, rt, rl, rt, (float)width / 2);
PSarct(rl, rt, rl, rb, (float)width / 2);
PSclosepath();
if (verb == frameVerb) {
psh = CW(thePortp->pnSize.h);
psv = CW(thePortp->pnSize.v);
sfactor2 = ((float)height - 2*psv) / (width - 2*psh) / sfactor;
rl = CW(rp->left) + psh;
rr = CW(rp->right) - psh;
rt = CW(rp->top) + psv/sfactor2;
rb = CW(rp->bottom) - psv/sfactor2;
PSscale(1, sfactor2);
PSmoveto(rl, midy/sfactor);
PSarct(rl, rt, rr, rt, (float)width/2 - psh);
PSarct(rr, rt, rr, rb, (float)width/2 - psh);
PSarct(rr, rb, rl, rb, (float)width/2 - psh);
PSarct(rl, rb, rl, rt, (float)width/2 - psh);
PSscale(1, 1/sfactor2);
PSclosepath();
}
PSscale(1, 1/sfactor);
PSclip();
doimage(verb, rp, thePortp);
PSgrestore();
restore_virtual_ints (block);
}
}
void NeXTPrRect(LONGINT verb, comRect *rp, comGrafPtr thePortp)
{
short psh, psv;
virtual_int_state_t block;
block = block_virtual_ints ();
pnupdate(thePortp);
PSgsave();
PSnewpath();
PSmoveto(CW(rp->left) , CW(rp->top));
PSlineto(CW(rp->left) , CW(rp->bottom));
PSlineto(CW(rp->right), CW(rp->bottom));
PSlineto(CW(rp->right), CW(rp->top));
PSclosepath();
if (verb == frameVerb) {
psh = CW(thePortp->pnSize.h);
psv = CW(thePortp->pnSize.v);
PSmoveto(CW(rp->left) + psh, CW(rp->top) + psv);
PSlineto(CW(rp->right) - psh, CW(rp->top) + psv);
PSlineto(CW(rp->right) - psh, CW(rp->bottom) - psv);
PSlineto(CW(rp->left) + psh, CW(rp->bottom) - psv);
PSclosepath();
}
PSclip();
doimage(verb, rp, thePortp);
PSgrestore();
restore_virtual_ints (block);
}
void NeXTPrRgn(LONGINT verb, comRgnHandle rgn, comGrafPtr thePortp)
{
/* NOP */
}
short NeXTPrTxMeas(LONGINT n, comPtr p, comPoint *nump, comPoint *denp,
comFontInfo *finfop, comGrafPtr thePortp)
{
Point num, den;
virtual_int_state_t block;
short retval;
SETUPA5;
block = block_virtual_ints ();
num.h = num.v = den.h = den.v = CWC (0x100);
retval = ROMlib_StdTxMeas(n,
(Ptr) p, (Point *) &num, (Point *) &den, NULL);
restore_virtual_ints (block);
RESTOREA5;
return (float) retval * CW (num.h) / CW (den.h);
}
static int numspacesin(const char *str)
{
int retval;
retval = 0;
while (*str)
if (*str++ == ' ')
++retval;
return retval;
}
static void dopsunderline(comGrafPtr thePortp, short total,
boolean_t substitute_p, char *translated, LONGINT n)
{
unsigned char fname[256];
char *font;
SETUPA5;
/* If we are substituting fonts, then we need to use PS's idea of
how long a string is rather than use "total". So before we do
a findfond we need to measure the string and leave that width
on the stack */
if (substitute_p)
{
PSsendchararray (translated, n);
DPSPrintf (DPSGetCurrentContext(), "stringwidth pop\n");
}
SmartGetFontName(thePortp, fname);
font = fnametofont(fname, thePortp->txFace);
{
boolean_t need_to_free;
substitute_font_if_needed (&font, 0, &need_to_free);
PSgsave();
PSnewpath();
PSsendfloat(CW(thePortp->pnLoc.h));
PSsendfloat(CW(thePortp->pnLoc.v));
PSsendfloat(CW(thePortp->txSize));
PSsendchararray(font, strlen(font));
if (need_to_free)
free (font);
}
DPSPrintf(DPSGetCurrentContext(), "findfont2\n");
PSdup();
PSsendchararray("FontInfo", 8);
DPSPrintf(DPSGetCurrentContext(), "known {\n");
PSdup();
PSsendchararray("FontMatrix", 10);
PSget();
PSsendint(3);
PSget();
PSindex(2);
PSmul();
PSindex(1);
PSsendchararray("FontInfo", 8);
PSget();
PSdup();
PSsendchararray("UnderlineThickness", 18);
PSget();
PSindex(2);
PSmul();
DPSPrintf(DPSGetCurrentContext(), "setlinewidth\n");
PSsendchararray("UnderlinePosition", 17);
PSget();
PSmul();
PSroll(3, 1);
PSpop();
PSpop();
PSsub();
DPSPrintf(DPSGetCurrentContext(), "}\n{\n");
PSpop();
PSpop();
DPSPrintf(DPSGetCurrentContext(), "}\nifelse\n");
DPSPrintf(DPSGetCurrentContext(), "moveto\n");
if (!substitute_p)
PSrlineto(total, 0);
else
{
/* The width is already on the stack. See above */
DPSPrintf (DPSGetCurrentContext(), "0 rlineto\n");
}
PSstroke();
PSgrestore();
RESTOREA5;
}
static void doshow(char *translated, LONGINT n)
{
PSsendchararray (translated, n);
DPSPrintf(DPSGetCurrentContext(), "show\n");
}
static void dowidthshow(char *translated, LONGINT n, int i, short total)
{
PSsendint (n);
PSsendint (i);
PSsendint (total);
PSsendchararray(translated, n);
DPSPrintf(DPSGetCurrentContext(), "__char_spaces_width_show\n");
}
static void doashow(char *translated, LONGINT n, int i, short total)
{
PSsendchararray(translated, n);
PSdup();
DPSPrintf(DPSGetCurrentContext(), "stringwidth\n");
PSpop();
PSsendint(total);
PSexch();
PSsub();
PSsendint(n);
PSdiv();
PSexch();
PSsendint(0);
PSexch();
DPSPrintf(DPSGetCurrentContext(), "ashow\n");
}
void NeXTsendps (LONGINT n, comPtr textbufp)
{
virtual_int_state_t block;
block = block_virtual_ints ();
DPSWritePostScript(DPSGetCurrentContext(), textbufp, n);
restore_virtual_ints (block);
}
enum { BULLET = 0xa5 };
/* beginning of ugly parallel enums and parallel switches */
enum mac_char
{
mac_char_notequal = 0xad,
mac_char_infinity = 0xb0,
mac_char_plusminus = 0xb1,
mac_char_lessequal = 0xb2,
mac_char_greaterequal = 0xb3,
mac_char_mu = 0xb5,
mac_char_partialdiff = 0xb6,
mac_char_Sigma = 0xb7,
mac_char_Pi = 0xb8,
mac_char_pi = 0xb9,
mac_char_integral = 0xba,
mac_char_Omega = 0xbd,
mac_char_logicalnot = 0xc2,
mac_char_radical = 0xc3,
mac_char_florin = 0xc4,
mac_char_approxequal = 0xc5,
mac_char_Delta = 0xc6,
mac_char_divide = 0xd6,
};
enum symbol_char
{
symbol_char_notequal = 0271,
symbol_char_infinity = 0245,
symbol_char_plusminus = 0261,
symbol_char_lessequal = 0243,
symbol_char_greaterequal = 0263,
symbol_char_mu = 0155,
symbol_char_partialdiff = 0266,
symbol_char_Sigma = 0123,
symbol_char_Pi = 0120,
symbol_char_pi = 0160,
symbol_char_integral = 0362,
symbol_char_Omega = 0127,
symbol_char_logicalnot = 0330,
symbol_char_radical = 0326,
symbol_char_florin = 0246,
symbol_char_approxequal = 0273,
symbol_char_Delta = 0104,
symbol_char_divide = 0270,
};
#define CHAR_REPLACE(s) \
case mac_char_ ## s: \
retval = symbol_char_ ##s; \
is_symbol = TRUE; \
break
PRIVATE unsigned char
symbol_translate_char (unsigned char c, boolean_t *is_symbolp)
{
unsigned char retval;
boolean_t is_symbol;
retval = c;
is_symbol = FALSE;
switch ((enum mac_char) c)
{
CHAR_REPLACE (notequal);
CHAR_REPLACE (infinity);
CHAR_REPLACE (plusminus);
CHAR_REPLACE (lessequal);
CHAR_REPLACE (greaterequal);
CHAR_REPLACE (mu);
CHAR_REPLACE (partialdiff);
CHAR_REPLACE (Sigma);
CHAR_REPLACE (Pi);
CHAR_REPLACE (pi);
CHAR_REPLACE (integral);
CHAR_REPLACE (Omega);
CHAR_REPLACE (logicalnot);
CHAR_REPLACE (radical);
CHAR_REPLACE (florin);
CHAR_REPLACE (approxequal);
CHAR_REPLACE (Delta);
CHAR_REPLACE (divide);
}
if (is_symbolp)
*is_symbolp = is_symbol;
return retval;
}
#undef CHAR_REPLACE
/* end of ugly parallel enums and parallel switches */
PRIVATE boolean_t
is_symbol (unsigned char c)
{
boolean_t retval;
symbol_translate_char (c, &retval);
return retval;
}
PRIVATE void
find_run_of_symbol_chars (LONGINT n, comPtr textbufp, int *run_startp,
int *run_stopp)
{
int start, stop;
int i;
start = -1;
stop = -1;
for (i = 0; i < n && !is_symbol (textbufp[i]); ++i)
;
if (i < n)
{
start = i;
for (; i < n && is_symbol (textbufp[i]); ++i)
;
stop = i;
}
*run_startp = start;
*run_stopp = stop;
}
void NeXTPrText(LONGINT n, comPtr textbufp, comPoint num, comPoint den,
comGrafPtr thePortp)
{
virtual_int_state_t block;
/* right now blow off num and den */
char *translated;
short total;
int i;
int n_leading_spaces;
int run_start, run_stop;
if (thePortp->txFont != CWC (symbol))
{
find_run_of_symbol_chars (n, textbufp, &run_start, &run_stop);
if (run_start >= 0)
{
typeof (thePortp->txFont) save_font;
if (run_start > 0)
NeXTPrText (run_start, textbufp, num, den, thePortp);
save_font = thePortp->txFont;
thePortp->txFont = CWC (symbol);
NeXTPrText (run_stop - run_start, textbufp + run_start, num, den,
thePortp);
thePortp->txFont = save_font;
if (run_stop < n)
NeXTPrText (n - run_stop, textbufp + run_stop, num, den,
thePortp);
return;
}
}
for (n_leading_spaces = 0;
n_leading_spaces < n && (textbufp[n_leading_spaces] == ' '
||
(unsigned char) textbufp[n_leading_spaces]
== BULLET);
++n_leading_spaces)
;
if (n_leading_spaces && n_leading_spaces != n)
{
NeXTPrText (n_leading_spaces, textbufp, num, den, thePortp);
NeXTPrText (n - n_leading_spaces, textbufp + n_leading_spaces,
num, den, thePortp);
}
else
{
if (n != 0)
{
block = block_virtual_ints ();
txupdate(thePortp);
if (rotation.rotated_p)
{
PSgsave ();
DPSPrintf (DPSGetCurrentContext (), "initclip\n");
PStranslate (CW (thePortp->pnLoc.h) + rotation.center_x,
CW (thePortp->pnLoc.v) + rotation.center_y);
PSrotate (rotation.angle);
PSmoveto (-rotation.center_x, -rotation.center_y);
}
total = NeXTPrTxMeas(n, textbufp, &num, &den, (comFontInfo *) 0,
thePortp);
translated = alloca(n + 1);
memcpy(translated, textbufp, n);
/* strip trailing <CR>s */
while (n > 0 && translated[n-1] == '\r')
--n;
translated[n] = 0;
if (n)
{
if (thePortp->txFont == CWC (symbol))
{
int i;
for (i = 0; i < n; ++i)
translated[i]
= symbol_translate_char (translated[i], NULL);
}
#if 0
PSxshow(translated, fwidths, n);
#else
if (substitute_fonts_p && (thePortp->txFont == CWC (geneva)))
doshow (translated, n);
else if ((i = numspacesin(translated)))
dowidthshow(translated, n, i, total);
else
doashow(translated, n, i, total);
#endif
if (thePortp->txFace & underline)
dopsunderline(thePortp, total,
substitute_fonts_p
&& (thePortp->txFont == CWC (geneva)),
translated, n);
thePortp->pnLoc.h = CW(CW(thePortp->pnLoc.h) + total);
printport.pnLoc.h = thePortp->pnLoc.h;
}
if (rotation.rotated_p)
PSgrestore ();
restore_virtual_ints (block);
}
}
}
void NeXTOpenPage( void )
{
/*
* TODO: make sure that the open page really conforms to what InitPort
* gave us.
*/
}
PRIVATE boolean_t text_state;
PRIVATE void
disable_copybits (void)
{
if (!ROMlib_text_output_disabled_p)
text_state = disable_text_printing ();
}
PRIVATE void
enable_copybits (void)
{
set_text_printing (text_state);
}
#define FIX_TO_FLOAT(x) ((float) (x) / (1 << 16))
PUBLIC void
do_textbegin (TTxtPicHdl h)
{
disable_copybits ();
rotation.angle = GetHandleSize ((Handle) h) >= 10
? FIX_TO_FLOAT (TEXTPIC_ANGLE_FIXED (h)) : TEXTPIC_ANGLE (h);
rotation.rotated_p = TRUE;
}
PUBLIC void
do_textcenter (TCenterRecHdl h)
{
rotation.center_x = FIX_TO_FLOAT (TEXTCENTER_X (h));
rotation.center_y = FIX_TO_FLOAT (TEXTCENTER_Y (h));
}
PUBLIC void
do_textend (void)
{
if (rotation.rotated_p)
{
rotation.rotated_p = FALSE;
enable_copybits ();
}
}