/* -*- objc -*-
* $Id: aquaterm.trm,v 1.58 2017/02/09 21:13:23 sfeam Exp $
*
*/
/* GNUPLOT - aquaTerm.trm */
/*
* This file is included by ../term.c via ../term.h.
*
* This terminal driver supports:
* Aqua (Mac OS X/Cocoa)
*
* AUTHORS
* Per Persson from openstep.trm by Robert Lutwak
*
* Homepage: http://aquaterm.sourceforge.net
* send your comments or suggestions to (persquare@users.sourceforge.net).
*
* This terminal attempts to connect, via the Mac OS X Distributed
* Objects system, to the "aquatermServer." If there is no such
* service registered with the OS, the terminal attempts to fire
* up AquaTerm.app. If the user has not set the environment variable
* AQUATERM_PATH, the terminal searches for AquaTerm.app in standard
* locations like /Applications, ~/Applications, etc.
* In order to use this filter, you MUST have AquaTerm.app installed
* on your system.
*
* Once connected to the server, all gnuplot graphs are sent,
* via the D.O. system, to AquaTerm.app, which produces renders graphs,
* manages the windows, takes care of printing etc.
*
*/
#include "driver.h"
#ifdef TERM_REGISTER
register_term(aqua)
#endif
#ifdef TERM_PROTO
/* Required entries */
TERM_PUBLIC void AQUA_options __PROTO((void));
TERM_PUBLIC void AQUA_init __PROTO((void));
TERM_PUBLIC void AQUA_reset __PROTO((void));
TERM_PUBLIC void AQUA_text __PROTO((void));
TERM_PUBLIC void AQUA_graphics __PROTO((void));
TERM_PUBLIC void AQUA_move __PROTO((unsigned int x, unsigned int y));
TERM_PUBLIC void AQUA_vector __PROTO((unsigned int x, unsigned int y));
TERM_PUBLIC void AQUA_linetype __PROTO((int linetype));
TERM_PUBLIC void AQUA_dashtype(int type, t_dashtype *custom_dash_type);
TERM_PUBLIC void AQUA_put_text __PROTO((unsigned int x, unsigned int y,const char *str));
/* Optional entries */
TERM_PUBLIC int AQUA_text_angle __PROTO((int));
TERM_PUBLIC int AQUA_justify_text __PROTO((enum JUSTIFY));
TERM_PUBLIC int AQUA_set_font __PROTO((const char *font)); /* "font,size" */
TERM_PUBLIC void AQUA_set_pointsize __PROTO((double size)); /* notification of set pointsize */
TERM_PUBLIC void AQUA_point __PROTO((unsigned int, unsigned int, int));
TERM_PUBLIC int flags; /* various flags */
TERM_PUBLIC void AQUA_suspend __PROTO((void)); /* after one plot of multiplot */
TERM_PUBLIC void AQUA_resume __PROTO((void)); /* before subsequent plot of multiplot */
TERM_PUBLIC void AQUA_boxfill __PROTO((int style, unsigned int x1, unsigned int y1, unsigned int width, unsigned int height)); /* clear part of multiplot */
TERM_PUBLIC void AQUA_linewidth __PROTO((double linewidth));
TERM_PUBLIC void AQUA_pointsize __PROTO((double pointsize));
TERM_PUBLIC int AQUA_make_palette __PROTO((t_sm_palette *palette));
TERM_PUBLIC void AQUA_previous_palette __PROTO((void));
TERM_PUBLIC void AQUA_set_color __PROTO((t_colorspec *));
TERM_PUBLIC void AQUA_filled_polygon __PROTO((int points, gpiPoint *corners));
TERM_PUBLIC void AQUA_image __PROTO((unsigned, unsigned, coordval *, gpiPoint *, t_imagecolor));
TERM_PUBLIC void ENHAQUA_put_text __PROTO((unsigned int x, unsigned int y, const char str[]));
TERM_PUBLIC void ENHAQUA_open __PROTO((char * fontname, double fontsize,
double base, TBOOLEAN widthflag, TBOOLEAN showflag,
int overprint));
TERM_PUBLIC void ENHAQUA_flush __PROTO((void));
TERM_PUBLIC void ENHAQUA_writec __PROTO((int c));
/* End of entries */
#define AQUA_RESOLUTION (20.0) /* Increase resolution */
#define AQUA_XMAX (11.75 * 72 * AQUA_RESOLUTION) /* = paper width (in) times screen resolution */
#define AQUA_YMAX (8.25 * 72 * AQUA_RESOLUTION) /* = paper height (in) times screen resolution */
#define AQUA_VTIC (8.0*AQUA_RESOLUTION)
#define AQUA_HTIC (8.0*AQUA_RESOLUTION)
#define AQUA_VCHAR (16.0*AQUA_RESOLUTION) /* default font is Times at 14 points */
#define AQUA_HCHAR (AQUA_VCHAR*6.0/10.0)
#define AQUA_DASH_PATTERNS 8
#define AQUA_DEFAULT_DASHLENGTH_FACTOR 0.5
#define SPECIAL_COLORS 4
#define CYCLIC_COLORS 9
#define GOT_AQUA_PROTO
#endif /* TERM_PROTO */
#ifndef TERM_PROTO_ONLY
#ifdef TERM_BODY
#import <AquaTerm/AQTAdapter.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSAttributedString.h>
#import <stdarg.h>
/* Debugging extras */
static inline void NOOP_(id x, ...) {;}
#ifdef LOGGING
#define LOG NSLog
#else
#define LOG NOOP_
#endif /* LOGGING */
/* AquaTerm specific */
static NSAutoreleasePool *arpool;
static NSAutoreleasePool *loopPool;
static AQTAdapter *adapter;
/* Supported features */
static TBOOLEAN AQUA_hasAlphaSupport = FALSE;
/* Internal state */
static int AQUA_plotRef = 0; /* A ref to the current plot */
static char AQUA_title[MAX_LINE_LEN + 1] = "Figure 0"; /* Plot title (in windowbar) */
static unsigned int AQUA_xSize = AQUA_XMAX; /* plot horizontal size */
static unsigned int AQUA_ySize = AQUA_YMAX; /* plot vertical size*/
static int AQUA_LineType = LT_UNDEFINED; /* current line type*/
static float AQUA_LineWidth = 1.0; /* current line width*/
static float AQUA_TextAngle = 0.0; /* current text orientation*/
static enum JUSTIFY AQUA_TextJust = LEFT; /* current text justification*/
/* default text font family: */
static char AQUA_fontNameDef[MAX_ID_LEN + 1] = "Times-Roman";
static double AQUA_fontSizeDef = 14; /* default text size*/
/* current text font family: */
static char AQUA_fontNameCur[MAX_ID_LEN + 1] = "Times-Roman";
static double AQUA_fontSizeCur = 14; /* current text size*/
/* dash patterns */
static TBOOLEAN AQUA_dashedlines = FALSE;
static float AQUA_dashlength_factor = AQUA_DEFAULT_DASHLENGTH_FACTOR;
static int AQUA_dashPatternLengths[AQUA_DASH_PATTERNS] = {0, 2, 2, 2, 4, 4, 4, 6};
static int AQUA_dashPatterns[AQUA_DASH_PATTERNS][6] = {
{0, 0, 0, 0, 0, 0},
{8, 8, 0, 0, 0, 0},
{4, 6, 0, 0, 0, 0},
{2, 3, 0, 0, 0, 0},
{12, 4, 2, 4, 0, 0},
{6, 6, 2, 6, 0, 0},
{4, 4, 4, 12, 0, 0},
{1, 4, 12, 4, 1, 4}
};
/* Helper functions */
static NSString* AQUA_convert_using_encoding __PROTO((const char *string));
/*
* ----------------------------------------------------------------
* Aquaterm driver implementation
* ----------------------------------------------------------------
*
* Current options are:
* <n> title "theTitle" size <x> <y> fname "fontface" fsize <fontsize>
*/
TERM_PUBLIC void
AQUA_options()
{
char *s;
TBOOLEAN set_number = FALSE;
AQUA_title[0] = '\0'; /* Force re-interpretation of title string */
/* Default to enhanced text mode */
if (!almost_equals(c_token-1, "termopt$ion")) {
term->put_text = ENHAQUA_put_text;
term->flags |= TERM_ENHANCED_TEXT;
}
while (!END_OF_COMMAND) {
if (almost_equals(c_token, "ti$tle")) {
c_token++;
if (!(s = try_to_get_string()))
int_error(c_token,"fname: expecting plot title");
strncpy(AQUA_title,s,sizeof(AQUA_title));
free(s);
continue;
}
if (almost_equals(c_token, "s$ize")) {
double value;
c_token++;
if (END_OF_COMMAND)
int_error(c_token,"expecting x size");
value = real_expression();
if (value < 2 || value > 2048)
int_error(c_token,"x size out of range");
AQUA_xSize = (unsigned int) value * AQUA_RESOLUTION;
if (END_OF_COMMAND)
int_error(c_token,"expecting y size");
if (equals(c_token, ","))
c_token++;
value = real_expression();
if (value < 2 || value > 2048)
int_error(c_token,"y size out of range");
AQUA_ySize = (unsigned int) value * AQUA_RESOLUTION;
continue;
}
if (almost_equals(c_token, "fn$ame") || almost_equals(c_token, "font")) {
char *comma;
c_token++;
if (!(s = try_to_get_string()))
int_error(c_token,"expecting font specifier");
comma = strrchr(s, ',');
if (comma && (1 == sscanf(comma+1, "%lf", &AQUA_fontSizeCur)))
*comma = '\0';
if (*s)
strncpy(AQUA_fontNameCur, s, sizeof(AQUA_fontNameCur));
free(s);
continue;
}
if (almost_equals(c_token, "fs$ize")) {
c_token++;
if (END_OF_COMMAND)
int_error(c_token,"expecting font size");
AQUA_fontSizeCur = real_expression();
continue;
}
if (equals(c_token, "solid")) {
c_token++;
AQUA_dashedlines = FALSE;
continue;
}
if (almost_equals(c_token, "dash$ed")) {
c_token++;
AQUA_dashedlines = TRUE;
continue;
}
if (equals(c_token, "lw") || almost_equals(c_token, "linew$idth")) {
c_token++;
if (END_OF_COMMAND)
int_error(c_token, "expecting line width");
AQUA_LineWidth = real_expression();
if (AQUA_LineWidth < 0.0)
AQUA_LineWidth = 1.0;
continue;
}
if (equals(c_token, "dl") || almost_equals(c_token, "dashl$ength")) {
c_token++;
if (END_OF_COMMAND)
int_error(c_token, "expecting dashlength multiplier");
AQUA_dashlength_factor = real_expression();
if (AQUA_dashlength_factor < 0.0)
AQUA_dashlength_factor = AQUA_DEFAULT_DASHLENGTH_FACTOR;
continue;
}
if (almost_equals(c_token, "enh$anced")) {
term->put_text = ENHAQUA_put_text;
c_token++;
term->flags |= TERM_ENHANCED_TEXT;
continue;
}
if (almost_equals(c_token, "noenh$anced")) {
term->put_text = AQUA_put_text;
c_token++;
term->flags &= ~TERM_ENHANCED_TEXT;
continue;
}
if (!set_number) { /* plot ref number*/
AQUA_plotRef = int_expression();
set_number = TRUE;
continue;
}
int_error(c_token, "unexpected text at end of command");
}
if (AQUA_title[0]=='\0') /* always set title */
sprintf(AQUA_title, "Figure %d", AQUA_plotRef);
/* Save options back into options string in normalized format */
sprintf(term_options, "%d title \"%s\" size %d,%d font \"%s,%g\" %s %s",
AQUA_plotRef,
AQUA_title,
(unsigned int) (AQUA_xSize/AQUA_RESOLUTION), (unsigned int) (AQUA_ySize/AQUA_RESOLUTION),
AQUA_fontNameCur, AQUA_fontSizeCur,
term->put_text == ENHAQUA_put_text?"enhanced":"noenhanced",
AQUA_dashedlines?"dashed":"solid");
if (AQUA_dashedlines)
sprintf(&(term_options[strlen(term_options)]), " dl %3.1f", AQUA_dashlength_factor);
if (AQUA_LineWidth != 1.0)
sprintf(&(term_options[strlen(term_options)]), " linewidth %3.1f", AQUA_LineWidth);
}
static NSString*
AQUA_convert_using_encoding(const char *string)
{
static bool didCheckEncodingSupport = false;
static bool hasStringEncodingSupport = false;
NSStringEncoding currentEncoding;
NSString *translatedString;
/* Check encoding support in system on first call */
if(!didCheckEncodingSupport) {
didCheckEncodingSupport = true;
hasStringEncodingSupport = [NSString respondsToSelector:@selector(stringWithCString:encoding:)];
}
/* Set encoding as requested by user via "set encoding" */
switch(encoding){
case S_ENC_ISO8859_1:
currentEncoding = NSISOLatin1StringEncoding;
break;
case S_ENC_ISO8859_2:
currentEncoding = NSISOLatin2StringEncoding;
break;
case S_ENC_ISO8859_9:
currentEncoding = NSWindowsCP1254StringEncoding;
break;
case S_ENC_CP1250:
currentEncoding = NSWindowsCP1250StringEncoding;
break;
case S_ENC_CP1252:
currentEncoding = NSWindowsCP1252StringEncoding;
break;
/* FIXME: Add more encodings... */
case S_ENC_DEFAULT: /* Fallthrough */
default :
/* UTF8 is 'default' */
currentEncoding = NSUTF8StringEncoding;
break;
}
/* Perform translation (into UTF8 encoding used by Mac OS X) */
if (hasStringEncodingSupport) {
translatedString = [NSString stringWithCString:string encoding:currentEncoding];
} else {
translatedString = [NSString stringWithCString:string];
}
/* Check for nil result before returning */
return translatedString?translatedString:@"";
}
TERM_PUBLIC void
AQUA_init()
{
float fontSize, fontWHRatio;
NSString *title;
LOG(@"Aqua Init (open plot)");
if (arpool == NULL) {
/* FIXME: This should be removed when pools are handled in gnuplot proper */
arpool = [[NSAutoreleasePool alloc] init];
}
if (adapter == NULL) {
adapter = [[AQTAdapter alloc] init];
if (!adapter) { /* server could be invalid (=nil) for several reasons */
/* FIXME: Issue warning here? */
}
}
/* Must open plot before all other commands */
[adapter openPlotWithIndex:AQUA_plotRef];
/* Check for support of version-dependent features */
AQUA_hasAlphaSupport = [AQTAdapter instancesRespondToSelector:@selector(setColorRed:green:blue:alpha:)];
/* set xmax, ymax*/
term->xmax = AQUA_xSize;
term->ymax = AQUA_ySize;
/* set current font*/
[adapter setFontname:AQUA_convert_using_encoding(AQUA_fontNameCur)];
[adapter setFontsize:AQUA_fontSizeCur];
/* set h_char, v_char*/
term->h_char = (int) (AQUA_fontSizeCur * 0.6 * AQUA_RESOLUTION);
term->v_char = (int) (AQUA_fontSizeCur * 1.5 * AQUA_RESOLUTION);
/* set h_tic, v_tic*/
term->h_tic = term->v_char / 3;
term->v_tic = term->v_char / 3;
[adapter setPlotSize:NSMakeSize(AQUA_xSize/AQUA_RESOLUTION, AQUA_ySize/AQUA_RESOLUTION)];
[adapter setPlotTitle:AQUA_convert_using_encoding(AQUA_title)];
/*
* Set up the basic indexed colormap for gnuplot
*/
/* Special colors */
[adapter setColormapEntry:0 red:1.0 green:1.0 blue:1.0]; /* linetype -4 */
[adapter setColormapEntry:1 red:0.9 green:0.9 blue:0.9]; /* linetype -3 (xor;interactive) light gray */
[adapter setColormapEntry:2 red:0.0 green:0.0 blue:0.0]; /* linetype -2 (border) black */
[adapter setColormapEntry:3 red:0.8 green:0.8 blue:0.8]; /* linetype -1 (gridlines) light grey */
/* Cyclic colors */
[adapter setColormapEntry:4 red:1.0 green:0.0 blue:0.0]; /* red */
[adapter setColormapEntry:5 red:0.0 green:1.0 blue:0.0]; /* green */
[adapter setColormapEntry:6 red:0.0 green:0.0 blue:1.0]; /* blue */
[adapter setColormapEntry:7 red:1.0 green:0.0 blue:1.0]; /* magenta */
[adapter setColormapEntry:8 red:0.0 green:1.0 blue:1.0]; /* cyan */
[adapter setColormapEntry:9 red:0.6275 green:0.3216 blue:0.1765]; /* sienna */
[adapter setColormapEntry:10 red:1.0 green:0.6471 blue:0.0]; /* orange */
[adapter setColormapEntry:11 red:0.5 green:0.4980 blue:0.3137]; /* coral */
[adapter setColormapEntry:12 red:0.25 green:0.25 blue:0.25]; /* grey */
}
TERM_PUBLIC void
AQUA_reset()
{
LOG(@"Aqua reset");
}
TERM_PUBLIC void
AQUA_text()
{
LOG(@"Aqua text (render)");
[adapter renderPlot];
}
TERM_PUBLIC void
AQUA_graphics()
{
#ifdef LOGGING
/* Keep the compiler quiet when not debugging */
LOG(@"Pre: (arpool + loopPool, loopPool) =(%d, %d)", [NSAutoreleasePool autoreleasedObjectCount],
[NSAutoreleasePool topAutoreleasePoolCount]);
#endif
/* Avoid buildup of objects in the autoreleasepools */
[loopPool release];
loopPool = [[NSAutoreleasePool alloc] init];
#ifdef LOGGING
/* Keep the compiler quiet when not debugging */
LOG(@"Post: (arpool + loopPool, loopPool) =(%d, %d)",[NSAutoreleasePool autoreleasedObjectCount],
[NSAutoreleasePool topAutoreleasePoolCount]);
#endif
[adapter eraseRect:NSMakeRect(0.0, 0.0, AQUA_xSize/AQUA_RESOLUTION, AQUA_ySize/AQUA_RESOLUTION)];
AQUA_LineType = LT_UNDEFINED;
}
TERM_PUBLIC void
AQUA_move(unsigned int x, unsigned int y)
{
[adapter moveToPoint:NSMakePoint(x/AQUA_RESOLUTION, y/AQUA_RESOLUTION)];
}
TERM_PUBLIC void
AQUA_vector(unsigned int x, unsigned int y)
{
[adapter addLineToPoint:NSMakePoint(x/AQUA_RESOLUTION, y/AQUA_RESOLUTION)];
}
TERM_PUBLIC void
AQUA_linetype(int linetype)
{
float dash[8];
int i, style;
LOG(@"AQUA_linetype(%d) ---> entry: %d", linetype, (linetype%CYCLIC_COLORS)+SPECIAL_COLORS);
if (linetype != AQUA_LineType) {
/* Note: this operation maps linestyle -4 to -1 onto colormap entries 0 to 3 */
AQUA_LineType = linetype;
[adapter takeColorFromColormapEntry:(linetype%CYCLIC_COLORS)+SPECIAL_COLORS];
}
if (AQUA_dashedlines) {
style = linetype%AQUA_DASH_PATTERNS;
if (style <= 0) {
[adapter setLinestyleSolid];
} else {
// Set up a dash array
for(i = 0; i<AQUA_dashPatternLengths[style]; i++) {
dash[i] = AQUA_dashPatterns[style][i] * AQUA_dashlength_factor;
}
[adapter setLinestylePattern:dash count:AQUA_dashPatternLengths[style] phase:0.0];
}
}
}
TERM_PUBLIC void
AQUA_dashtype(int type, t_dashtype *custom_dash_type)
{
float dash[DASHPATTERN_LENGTH];
int i;
LOG(@"AQUA_dashtype(%d)", type);
if(!AQUA_dashedlines) {
return;
}
switch(type) {
case DASHTYPE_SOLID:
[adapter setLinestyleSolid];
break;
case DASHTYPE_AXIS:
break;
case DASHTYPE_CUSTOM:
if (custom_dash_type) {
for(i = 0; i < DASHPATTERN_LENGTH && custom_dash_type->pattern[i] > 0; i++) {
dash[i] = custom_dash_type->pattern[i] * AQUA_dashlength_factor;
}
[adapter setLinestylePattern:dash count:i phase:0.0];
}
break;
default:
if(type > 0) {
type %= AQUA_DASH_PATTERNS;
for(i = 0; i<AQUA_dashPatternLengths[type]; i++) {
dash[i] = AQUA_dashPatterns[type][i] * AQUA_dashlength_factor;
}
[adapter setLinestylePattern:dash count:AQUA_dashPatternLengths[type] phase:0.0];
}
else {
[adapter setLinestyleSolid];
}
}
}
TERM_PUBLIC void
AQUA_put_text(unsigned int x, unsigned int y, const char *str)
{
if (!strlen(str))
return;
[adapter addLabel:AQUA_convert_using_encoding(str)
atPoint:NSMakePoint(x/AQUA_RESOLUTION, y/AQUA_RESOLUTION)
angle:AQUA_TextAngle
align:(AQUA_TextJust | AQTAlignMiddle)];
}
TERM_PUBLIC int
AQUA_justify_text (enum JUSTIFY mode)
{
AQUA_TextJust = mode;
return (TRUE);
}
TERM_PUBLIC int
AQUA_text_angle (int angle)
{
AQUA_TextAngle = (float)angle;
return (TRUE);
}
TERM_PUBLIC int
AQUA_set_font(const char *font) /* "font,size" */
{
/* Obtain default fontname and fontsize. If these are invalid, AquaTerm will handle it. */
NSString *fontFace = AQUA_convert_using_encoding(AQUA_fontNameCur);
float fontSize = AQUA_fontSizeCur;
if (strlen(font) > 0) {
/* Try to split the non-empty string into array parts (as string objects) */
NSArray *parts = [AQUA_convert_using_encoding(font) componentsSeparatedByString:@","];
/* Check that we have both non-empty name and size, otherwise stay with defaults */
if ([parts count] > 0 && ![[parts objectAtIndex:0] isEqualToString:@""] ) {
fontFace = [parts objectAtIndex:0]; /* fontname */
if ([parts count] > 1 && ![[parts objectAtIndex:1] isEqualToString:@""] ) {
fontSize = [[parts objectAtIndex:1] floatValue]; /* Convert (optional) 2nd string object (fontsize) to float */
}
}
}
LOG(@"Setting:(%@,%f)", fontFace, fontSize);
[adapter setFontname:fontFace];
[adapter setFontsize:fontSize];
term->h_char = (int) (fontSize * 0.6 * AQUA_RESOLUTION);
term->v_char = (int) (fontSize * 1.5 * AQUA_RESOLUTION);
return (TRUE);
}
TERM_PUBLIC void
AQUA_set_pointsize(double size) /* notification of set pointsize */
{
LOG(@"AQUA_set_pointsize(%f)", size);
}
TERM_PUBLIC void
AQUA_point(unsigned int x, unsigned int y, int number)
{
/* The default dot-routine doesn't work with AQT */
[adapter setLinestyleSolid]; /* Symbols should never be dashed */
[adapter setLinewidth:1.0];
[adapter setLineCapStyle:AQTRoundLineCapStyle]; /* Set line cap style to round to create a dot */
[adapter moveToPoint:NSMakePoint(x/AQUA_RESOLUTION-0.005, y/AQUA_RESOLUTION)];
[adapter addLineToPoint:NSMakePoint(x/AQUA_RESOLUTION+0.005, y/AQUA_RESOLUTION)];
[adapter moveToPoint:NSMakePoint(0,0)]; /* Force a path end to work around a bug in AquaTerm 1.0.0 */
/* Round caps results in nicer symbols too */
if (number>=0) {
do_point(x, y, number);
}
[adapter moveToPoint:NSMakePoint(0,0)]; /* Force a path end to work around a bug in AquaTerm 1.0.0 */
[adapter setLineCapStyle:AQTButtLineCapStyle]; /* Reset line capstyle */
}
/* after one plot of multiplot */
TERM_PUBLIC void
AQUA_suspend()
{
[adapter renderPlot];
}
/* before subsequent plot of multiplot */
TERM_PUBLIC void
AQUA_resume()
{
}
/* clear part of multiplot */
TERM_PUBLIC void
AQUA_boxfill(int style, unsigned int x1, unsigned int y1, unsigned int width, unsigned int height)
{
float r,g,b,a;
LOG(@"\nstyle=%d\nstyle & 0xf = %d\nfillpar=%d\n", style, style & 0xf, style >> 4);
/* Save current color */
if (AQUA_hasAlphaSupport)
[adapter getColorRed:&r green:&g blue:&b alpha:&a];
else
[adapter getColorRed:&r green:&g blue:&b];
/* fillpar:
* - solid : 0 - 100
* - pattern : 0 - 100
*/
int fillpar = style >> 4;
style &= 0xf;
switch (style) {
case 0: /* fill with background color */
{
float rb, gb, bb;
[adapter getBackgroundColorRed:&rb green:&gb blue:&bb];
[adapter setColorRed:rb green:gb blue:bb];
}
break;
case FS_TRANSPARENT_SOLID:
if (AQUA_hasAlphaSupport) {
float alpha = fillpar * 0.01;
[adapter setColorRed:r green:g blue:b alpha:alpha];
break;
} else
/* fall through */
case FS_SOLID: /* solid fill */
if (fillpar < 100) {
float density = (100 - fillpar)*0.01;
[adapter setColorRed:r*(1-density) + density
green:g*(1-density) + density
blue:b*(1-density) + density];
}
break;
case FS_PATTERN: /* pattern fill */
case FS_TRANSPARENT_PATTERN:
/* Can't do pattern easily, using colors. */
[adapter takeColorFromColormapEntry:(fillpar%CYCLIC_COLORS)+SPECIAL_COLORS];
break;
default:
break;
}
NSRect scaledRect = NSMakeRect(x1/AQUA_RESOLUTION, y1/AQUA_RESOLUTION, width/AQUA_RESOLUTION, height/AQUA_RESOLUTION);
/* FIXME: Aquaterm eraseRect scales very badly with the total number of rectangles.
* It is probably fixable, but is the erase operation necessary at all?
*/
[adapter eraseRect:scaledRect];
[adapter addFilledRect:scaledRect];
/* Restore color */
if (AQUA_hasAlphaSupport)
[adapter setColorRed:r green:g blue:b alpha:a];
else
[adapter setColorRed:r green:g blue:b];
}
TERM_PUBLIC void
AQUA_linewidth(double linewidth)
{
linewidth *= AQUA_LineWidth;
[adapter setLinewidth:linewidth];
}
TERM_PUBLIC void
AQUA_pointsize(double pointsize)
{
LOG(@"AQUA_pointsize(%f)", pointsize);
term_pointsize = pointsize;
}
TERM_PUBLIC int
AQUA_make_palette(t_sm_palette *palette)
{
if (palette == NULL) {
/* AquaTerm can do continuous colors */
return 0;
}
return 0;
}
TERM_PUBLIC void
AQUA_set_color(t_colorspec *colorspec)
{
rgb_color color;
double alpha;
switch (colorspec->type) {
case TC_FRAC:
rgb1maxcolors_from_gray(colorspec->value, &color);
[adapter setColorRed:color.r green:color.g blue:color.b];
break;
case TC_RGB:
color.r = (double)((colorspec->lt >> 16) & 255) / 255.;
color.g = (double)((colorspec->lt >> 8 ) & 255) / 255.;
color.b = (double)(colorspec->lt & 255) / 255.;
alpha = (double)((colorspec->lt >> 24) & 255) / 255.;
if (AQUA_hasAlphaSupport && (alpha > 0)) {
alpha = 1.0 - alpha;
[adapter setColorRed:color.r green:color.g blue:color.b alpha:alpha];
} else {
[adapter setColorRed:color.r green:color.g blue:color.b];
}
break;
case TC_LT:
[adapter takeColorFromColormapEntry:((colorspec->lt)%CYCLIC_COLORS)+SPECIAL_COLORS];
break;
default:
break;
}
AQUA_LineType = LT_UNDEFINED;
}
TERM_PUBLIC void
AQUA_filled_polygon(int pc, gpiPoint *corners)
{
int i;
int fillpar = corners->style >> 4;
float r,g,b,a;
/* Save current color */
if (AQUA_hasAlphaSupport)
[adapter getColorRed:&r green:&g blue:&b alpha:&a];
else
[adapter getColorRed:&r green:&g blue:&b];
/* This switch is a clone of the one in AQUA_boxfill() */
switch (corners->style & 0xf) {
case 0: /* fill with background color */
{
float rb, gb, bb;
[adapter getBackgroundColorRed:&rb green:&gb blue:&bb];
[adapter setColorRed:rb green:gb blue:bb];
}
break;
case FS_TRANSPARENT_SOLID:
if (AQUA_hasAlphaSupport) {
float alpha = fillpar * 0.01;
[adapter setColorRed:r green:g blue:b alpha:alpha];
break;
} else
/* fall through */
case FS_SOLID: /* solid fill */
if (fillpar < 100) {
float density = (100 - fillpar)*0.01;
[adapter setColorRed:r*(1-density) + density
green:g*(1-density) + density
blue:b*(1-density) + density];
}
break;
case FS_PATTERN: /* pattern fill */
case FS_TRANSPARENT_PATTERN:
/* Can't do pattern easily, using colors. */
[adapter takeColorFromColormapEntry:(fillpar%CYCLIC_COLORS)+SPECIAL_COLORS];
break;
default:
break;
}
[adapter moveToVertexPoint:NSMakePoint(corners[0].x/AQUA_RESOLUTION,
corners[0].y/AQUA_RESOLUTION)];
for (i=1; i<pc; i++) {
[adapter addEdgeToVertexPoint:NSMakePoint(corners[i].x/AQUA_RESOLUTION,
corners[i].y/AQUA_RESOLUTION)];
}
/* Restore color */
if (AQUA_hasAlphaSupport)
[adapter setColorRed:r green:g blue:b alpha:a];
else
[adapter setColorRed:r green:g blue:b];
}
TERM_PUBLIC void
AQUA_previous_palette()
{
}
TERM_PUBLIC void
AQUA_image (unsigned int M, unsigned int N, coordval *image, gpiPoint *corner, t_imagecolor color_mode)
{
float width = (corner[1].x - corner[0].x)/AQUA_RESOLUTION;
float height = (corner[0].y - corner[1].y)/AQUA_RESOLUTION;
float xPos = corner[0].x/AQUA_RESOLUTION;
float yPos = corner[1].y/AQUA_RESOLUTION;
int bitmapSize = M*N;
int targetSize = 3 * bitmapSize;
int srcSize;
unsigned char *bitmap;
int i;
bitmap = malloc(targetSize*sizeof(unsigned char));
if (bitmap != nil) {
if (color_mode == IC_RGB) {
srcSize = targetSize;
for (i=0;i<srcSize;i++) {
bitmap[i] = (unsigned char)(255*image[i]);
}
} else if (color_mode == IC_PALETTE) {
rgb_color color;
unsigned char *bitmapPtr = bitmap;
srcSize = bitmapSize;
for (i=0;i<srcSize;i++) {
rgb1maxcolors_from_gray(image[i], &color);
*bitmapPtr = (unsigned char)(255*color.r);
bitmapPtr++;
*bitmapPtr = (unsigned char)(255*color.g);
bitmapPtr++;
*bitmapPtr = (unsigned char)(255*color.b);
bitmapPtr++;
}
} else {
NSLog(@"Unknown bitmap format");
}
[adapter addImageWithBitmap:bitmap
size:NSMakeSize(M, N)
bounds:NSMakeRect(xPos, yPos, width, height)];
free(bitmap);
}
return;
}
/*
* Per Persson 20041019
* Support for enhanced text mode
*
* Known issues:
* - Overprinting not implemented
* - The sub/superscript level is determined from relative fontsize,
* it may break if fontsize is changed for individual characters.
*/
static NSMutableAttributedString *enhString;
static NSMutableDictionary *attributes;
TERM_PUBLIC void
ENHAQUA_put_text(unsigned int x, unsigned int y, const char str[])
{
if (!strlen(str))
return;
if (ignore_enhanced_text || !strpbrk(str, "{}^_@&~")) {
AQUA_put_text(x,y,str);
return;
}
/* set up the global variables needed by enhanced_recursion() */
enhanced_fontscale = 1;
strncpy(enhanced_escape_format,"\\%o",sizeof(enhanced_escape_format));
/* Clear the attributed string */
[enhString release];
enhString = [[NSMutableAttributedString alloc] init];
[enhString setAttributedString:[[NSAttributedString alloc] initWithString:@""]];
while (*(str = enhanced_recursion((char *)str, TRUE, AQUA_fontNameCur,
(double)(AQUA_fontSizeCur), 0.0, TRUE, TRUE, 0))) {
/* I think we can only get here if *str == '}' */
enh_err_check(str);
if (!*++str)
break; /* end of string */
/* else carry on and process the rest of the string */
}
/* Now, send the attributed string to the adapter */
[adapter addLabel:enhString
atPoint:NSMakePoint(x/AQUA_RESOLUTION, y/AQUA_RESOLUTION)
angle:AQUA_TextAngle
align:(AQUA_TextJust | AQTAlignMiddle)];
}
TERM_PUBLIC void
ENHAQUA_open(char * fontname, double fontsize,
double base, TBOOLEAN widthflag, TBOOLEAN showflag,
int overprint)
{
LOG(@"%s %.1f %.1f %s %s %d", fontname, fontsize, base,
widthflag ? "true" : "false",
showflag ? "true" : "false",
overprint);
if (overprint != 0)
return;
[attributes release];
attributes = [[NSMutableDictionary alloc] initWithCapacity:16];
[attributes setObject:AQUA_convert_using_encoding(fontname) forKey:@"AQTFontname"];
if (fabs(base)>0.01) {
/* consider this as super/subscript, and compute subscript level */
int n = (int)round(log(fontsize/AQUA_fontSizeCur)/log(0.8));
[attributes setObject:[NSNumber numberWithInt:(base > 0)?n:-n]
forKey:@"NSSuperScript"];
} else if (fabs(fontsize - AQUA_fontSizeCur)>0.01) {
/* Fontsize was set explicitly */
[attributes setObject:[NSNumber numberWithFloat:fontsize] forKey:@"AQTFontsize"];
}
if (!showflag)
[attributes setObject:[NSNumber numberWithInt:1]
forKey:@"AQTNonPrintingChar"];
}
/* Local buffer used in encoding conversion */
#define ENHAQUA_CSTRBUFLEN 1023
static char cStrBuf[ENHAQUA_CSTRBUFLEN + 1];
static unsigned int cStrBufIndex = 0;
TERM_PUBLIC void
ENHAQUA_flush(void)
{
/* Convert cStrBuf UTF8 according to encoding, use convert_using_encoding()
and apply attributes before adding to enhString
*/
NSAttributedString *aStr;
cStrBuf[cStrBufIndex] = '\0';
cStrBufIndex = 0;
aStr = [[NSAttributedString alloc] initWithString:AQUA_convert_using_encoding(cStrBuf) attributes:attributes];
[enhString appendAttributedString:aStr];
[aStr release];
}
TERM_PUBLIC void
ENHAQUA_writec(int c)
{
/* Buffer byte sequence into cStrBuf */
LOG(@"int c = 0x%04x", c);
cStrBuf[cStrBufIndex] = (char)(c+0x100) & 0xFF; /* FIXME: Sometimes c is overflowed */
if (cStrBufIndex < ENHAQUA_CSTRBUFLEN)
cStrBufIndex++;
}
#endif /* TERM_BODY */
#ifdef TERM_TABLE
TERM_TABLE_START(aqua_driver)
"aqua",
"Interface to graphics terminal server for Mac OS X",
0 /* xmax */ , 0 /* ymax */ , 0 /* vchar */ , 0 /* hchar */ ,
0 /* vtic */ , 0 /* htic */ ,
AQUA_options, AQUA_init, AQUA_reset,
AQUA_text, null_scale, AQUA_graphics, AQUA_move, AQUA_vector,
AQUA_linetype, AQUA_put_text,
/* optionals */
AQUA_text_angle,
AQUA_justify_text, AQUA_point, do_arrow, AQUA_set_font,
AQUA_pointsize,
TERM_CAN_MULTIPLOT|TERM_NO_OUTPUTFILE|TERM_CAN_DASH|TERM_POLYGON_PIXELS|TERM_LINEWIDTH,
AQUA_suspend, AQUA_resume,
AQUA_boxfill, AQUA_linewidth
#ifdef USE_MOUSE
, 0, 0, 0, 0, 0
#endif /* USE_MOUSE */
, AQUA_make_palette,
AQUA_previous_palette,
AQUA_set_color,
AQUA_filled_polygon,
AQUA_image,
ENHAQUA_open, ENHAQUA_flush, ENHAQUA_writec,
0 /* layer */ , 0 /* path */ , 0.0 /* tscale */ , 0 /* hypertext */,
0 /* boxed_text */ , 0 /* modify_plots */,
AQUA_dashtype
TERM_TABLE_END(aqua_driver)
#undef LAST_TERM
#define LAST_TERM aqua_driver
#endif /* TERM_TABLE */
#endif /* TERM_PROTO_ONLY */
#ifdef TERM_HELP
START_HELP(aqua)
"1 aqua",
"?commands set terminal aqua",
"?set terminal aqua",
"?set term aqua",
"?terminal aqua",
"?term aqua",
"?aqua",
"?Aqua",
" This terminal relies on AquaTerm.app for display on Mac OS X.",
"",
" Syntax:",
" set terminal aqua {<n>} {title \"<wintitle>\"} {size <x> <y>}",
" {font \"<fontname>{,<fontsize>}\"}",
" {linewidth <lw>}\"}",
" {{no}enhanced} {solid|dashed} {dl <dashlength>}}",
"",
" where <n> is the number of the window to draw in (default is 0),",
" <wintitle> is the name shown in the title bar (default \"Figure <n>\"),",
" <x> <y> is the size of the plot (default is 846x594 pt = 11.75x8.25 in).",
"",
" Use <fontname> to specify the font (default is \"Times-Roman\"),",
" and <fontsize> to specify the font size (default is 14.0 pt).",
"",
" The aqua terminal supports enhanced text mode (see `enhanced`), except for",
" overprint. Font support is limited to the fonts available on the system.",
" Character encoding can be selected by `set encoding` and currently supports",
" iso_latin_1, iso_latin_2, cp1250, and UTF8 (default).",
"",
" Lines can be drawn either solid or dashed, (default is solid) and the dash",
" spacing can be modified by <dashlength> which is a multiplier > 0.",
""
END_HELP(aqua)
#endif /* TERM_HELP */