2283 lines
51 KiB
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 ();
|
|
}
|
|
}
|