summaryrefslogtreecommitdiffstats
path: root/tksao/colorbar/colorbarbase.C
diff options
context:
space:
mode:
Diffstat (limited to 'tksao/colorbar/colorbarbase.C')
-rw-r--r--tksao/colorbar/colorbarbase.C1103
1 files changed, 1103 insertions, 0 deletions
diff --git a/tksao/colorbar/colorbarbase.C b/tksao/colorbar/colorbarbase.C
new file mode 100644
index 0000000..e454468
--- /dev/null
+++ b/tksao/colorbar/colorbarbase.C
@@ -0,0 +1,1103 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include <tkInt.h>
+
+#include "colorbarbase.h"
+#include "util.h"
+#include "cbgrid.h"
+#include "ps.h"
+
+#define TICKLEN 3
+#define TICKGAP 7
+
+// Parser Stuff
+#undef yyFlexLexer
+#define yyFlexLexer cbFlexLexer
+#include <FlexLexer.h>
+
+void* cblval;
+extern int cbparse(ColorbarBase*, cbFlexLexer*);
+
+int cblex(void* vval, cbFlexLexer* ll)
+{
+ cblval = vval;
+ return ll ? ll->yylex() : 0;
+}
+
+void cberror(ColorbarBase* cb, cbFlexLexer* ll, const char* m)
+{
+ cb->error(m);
+ const char* cmd = ll ? ll->YYText() : (const char*)NULL;
+ if (cmd && cmd[0] != '\n') {
+ cb->error(": ");
+ cb->error(cmd);
+ }
+}
+
+// Public Member Functions
+
+ColorbarBase::ColorbarBase(Tcl_Interp* i, Tk_Canvas c, Tk_Item* item)
+ : Widget(i,c,item)
+{
+ // this is needed because of a problem with Tk_ConfigureWidget
+ ((ColorbarBaseOptions*)options)->font = NULL;
+ ((ColorbarBaseOptions*)options)->fontWeight = NULL;
+ ((ColorbarBaseOptions*)options)->fontSlant = NULL;
+
+ xmap = NULL;
+ colorCells = NULL;
+ colorCount = 0;
+
+ grid = NULL;
+
+ cnt = 0;
+ lut = NULL;
+
+ invert = 0;
+
+ ticktxt = NULL;
+ tickcnt =0;
+ skipcnt =0;
+}
+
+ColorbarBase::~ColorbarBase()
+{
+ if (xmap)
+ XDestroyImage(xmap);
+
+ if (colorCells)
+ delete [] colorCells;
+
+ if (grid)
+ delete grid;
+
+ if (lut)
+ delete [] lut;
+
+ if (ticktxt) {
+ for (int ii=0; ii<tickcnt; ii++)
+ if (ticktxt[ii])
+ delete [] ticktxt[ii];
+ delete [] ticktxt;
+ }
+}
+
+int ColorbarBase::configure(int argc, const char* argv[], int flags)
+{
+ if (Widget::configure(argc, argv, flags) == TCL_ERROR)
+ return TCL_ERROR;
+
+ // only valid for the initial configuration call
+ if (flags != TK_CONFIG_ARGV_ONLY)
+ return initColormap();
+ else {
+ if ((configSpecs[CONFIGORIENTATION].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGNUMERICS].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGSIZE].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGFONT].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGFONTSTYLE].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGFONTSIZE].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGSPACE].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGTICKS].specFlags & TK_CONFIG_OPTION_SPECIFIED)) {
+ updateBBox();
+
+ invalidPixmap();
+ redraw();
+ }
+ }
+ return TCL_OK;
+}
+
+void ColorbarBase::invalidPixmap()
+{
+ Widget::invalidPixmap();
+
+ if (xmap)
+ XDestroyImage(xmap);
+ xmap = NULL;
+}
+
+int ColorbarBase::parse(istringstream& istr)
+{
+ result = TCL_OK;
+ cbFlexLexer* ll = new cbFlexLexer(&istr);
+ cbparse(this, ll);
+ delete ll;
+
+ return result;
+}
+
+Tk_Font ColorbarBase::getFont()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ ostringstream fstr;
+#ifdef MAC_OSX_TK
+ int fz = int(opts->fontSize*getDisplayRatio());
+#else
+ int fz = opts->fontSize;
+#endif
+
+ if (!strncmp(opts->font,"helvetica",4))
+ fstr << '{' << opts->helvetica << '}' << ' ' << fz << ' '
+ << opts->fontWeight << ' ' << opts->fontSlant << ends;
+ else if (!strncmp(opts->font,"courier",4))
+ fstr << '{' << opts->courier << '}' << ' ' << fz << ' '
+ << opts->fontWeight << ' ' << opts->fontSlant << ends;
+ else if (!strncmp(opts->font,"times",4))
+ fstr << '{' << opts->times << '}' << ' ' << fz << ' '
+ << opts->fontWeight << ' ' << opts->fontSlant << ends;
+ else
+ fstr << '{' << opts->helvetica << '}' << ' ' << fz << ' '
+ << opts->fontWeight << ' ' << opts->fontSlant << ends;
+
+ return Tk_GetFont(interp, tkwin, fstr.str().c_str());
+}
+
+void ColorbarBase::lutToText(Tk_Font font)
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ // init
+ if (ticktxt)
+ for (int ii=0; ii<tickcnt; ii++)
+ delete [] ticktxt[ii];
+ delete [] ticktxt;
+ tickcnt = opts->ticks;
+ ticktxt = new char*[opts->ticks];
+ for (int ii=0; ii<opts->ticks; ii++)
+ ticktxt[ii] = NULL;
+ skipcnt =0;
+
+ // first estimate of prec
+ int prec;
+ {
+ int aa = (int)(log10(fabs(lut[0])));
+ int bb = (int)(log10(fabs(lut[cnt-1])));
+ if (aa != bb)
+ prec = aa>bb ? aa : bb;
+ else
+ prec = 1;
+ }
+
+ // up to three tries
+ for (int jj=0; jj<3; jj++) {
+ // render text
+ for (int ii=0; ii<opts->ticks; ii++) {
+ int id = ii/double(opts->ticks-1)*cnt;
+ // the last one will be one over
+ if (id>=cnt)
+ id = cnt-1;
+
+ ostringstream str;
+ if (prec < -2)
+ str << scientific << setprecision(2+jj) << lut[id] << ends;
+ else if (prec < 0)
+ str << fixed << setprecision(abs(prec)+3+jj) << lut[id] << ends;
+ else if (prec < 2)
+ str << setprecision(2+jj) << lut[id] << ends;
+ else if (prec < 5)
+ str << fixed << setprecision(0+jj) << lut[id] << ends;
+ else
+ str << scientific << setprecision(2+jj) << lut[id] << ends;
+
+ if (ticktxt[ii])
+ delete [] ticktxt[ii];
+ ticktxt[ii] = new char[strlen(str.str().c_str())+1];
+ strcpy(ticktxt[ii],str.str().c_str());
+ }
+
+ // now see if all is unique
+ int ok=1;
+ for (int ii=1; ii<opts->ticks; ii++) {
+ if (!strcmp(ticktxt[ii-1],ticktxt[ii]))
+ ok=0;
+ }
+
+ if (ok)
+ break;
+ }
+
+ // determine skipcnt
+ Tk_FontMetrics metrics;
+ Tk_GetFontMetrics(font, &metrics);
+
+ if (!opts->orientation) {
+ // horizontal
+ int ww =0;
+ for (int ii=0; ii<opts->ticks; ii++) {
+ if (ticktxt[ii]) {
+ int aa = Tk_TextWidth(font, ticktxt[ii], strlen(ticktxt[ii]));
+ if (aa>ww)
+ ww = aa;
+ }
+ }
+ skipcnt = (ww+2)*opts->ticks/opts->width;
+ }
+ else {
+ // vertical
+ int total = (metrics.linespace+1)*opts->ticks;
+ skipcnt = total/opts->height;
+ }
+}
+
+int ColorbarBase::initColormap()
+{
+ colorCount = (((ColorbarBaseOptions*)options)->colors);
+ colorCells = new unsigned char[colorCount*3];
+
+ // needed to initialize colorCells
+ reset();
+
+ return TCL_OK;
+}
+
+void ColorbarBase::updateColors()
+{
+ updateColorCells();
+
+ // fill in xmap
+ // make sure we have a pixmap
+ if (!pixmap || !xmap)
+ return;
+
+ if (!((ColorbarBaseOptions*)options)->orientation) {
+ updateColorsHorz();
+ TkPutImage(NULL,0,display, pixmap, widgetGC, xmap, 0, 0, 1, 1,
+ options->width-2, ((ColorbarBaseOptions*)options)->size-2);
+ }
+ else {
+ updateColorsVert();
+ TkPutImage(NULL,0,display, pixmap, widgetGC, xmap, 0, 0, 1, 1,
+ ((ColorbarBaseOptions*)options)->size-2, options->height-2);
+ }
+
+ redraw();
+}
+
+// X11
+
+int ColorbarBase::updatePixmap(const BBox& bb)
+{
+ if (!widgetGC)
+ widgetGC = XCreateGC(display, Tk_WindowId(tkwin), 0, NULL);
+
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ if (pixmap)
+ return TCL_OK;
+
+ // create a valid pixmap
+ // assume if no pixmap, no xmap
+ // bb is in canvas coords
+
+ if (!(pixmap = Tk_GetPixmap(display, Tk_WindowId(tkwin), options->width,
+ options->height, depth))) {
+ internalError("Colorbar: Unable to Create Pixmap");
+ return TCL_OK;
+ }
+
+ XSetForeground(display, widgetGC, getColor("white"));
+ XFillRectangle(display, pixmap, widgetGC, 0, 0, options->width,options->height);
+
+ if (!opts->orientation) {
+ if (!(xmap = XGetImage(display, pixmap, 1, 1,
+ options->width-2,
+ opts->size-2,
+ AllPlanes, ZPixmap))){
+ internalError("Colorbar: Unable to Create XImage");
+ return TCL_OK;
+ }
+ }
+ else {
+ if (!(xmap = XGetImage(display, pixmap, 1, 1,
+ opts->size-2,
+ options->height-2,
+ AllPlanes, ZPixmap))){
+ internalError("Colorbar: Unable to Create XImage");
+ return TCL_OK;
+ }
+ }
+
+ updateColors();
+
+ if (opts->numerics && opts->space) {
+ renderGridAST();
+ return TCL_OK;
+ }
+
+ // we want a border, even with no numerics
+ renderGrid();
+ return TCL_OK;
+}
+
+void ColorbarBase::renderGrid()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ // box
+ XSetForeground(display, widgetGC, getColor("black"));
+ if (!opts->orientation)
+ XDrawRectangle(display, pixmap, widgetGC, 0, 0,
+ options->width-1, opts->size-1);
+ else
+ XDrawRectangle(display, pixmap, widgetGC, 0, 0,
+ opts->size-1, options->height-1);
+
+ if (opts->numerics && lut)
+ renderGridNumerics();
+}
+
+void ColorbarBase::renderGridNumerics()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ // font
+ Tk_Font font = getFont();
+ if (!font)
+ return; // bad font, we're done
+ Tk_FontMetrics metrics;
+ Tk_GetFontMetrics(font, &metrics);
+
+ // set font
+ XSetFont(display, widgetGC, Tk_FontId(font));
+
+ // generate text
+ lutToText(font);
+
+ // tick marks
+ int incrcnt=0;
+ for (int ii=1; ii<opts->ticks-1; ii++) {
+ if (!opts->orientation) {
+ // horizontal
+ int ww = (int)(ii/double(opts->ticks-1)*opts->width);
+ int h = opts->size-1;
+ int hh = opts->size-1 + TICKLEN;
+ XDrawLine(display, pixmap, widgetGC, ww, h, ww, hh);
+
+ if (!incrcnt) {
+ int txtwidth = Tk_TextWidth(font, ticktxt[ii], strlen(ticktxt[ii]));
+ int www = ww - txtwidth/2.;
+ int hhh = hh + TICKGAP + metrics.ascent;
+ Tk_DrawChars(display, pixmap, widgetGC, font, ticktxt[ii],
+ strlen(ticktxt[ii]), www, hhh);
+ }
+ }
+ else {
+ // vertical
+ int w = opts->size-1;
+ int ww = opts->size-1 + TICKLEN;
+ int hh = opts->height - (int)(ii/double(opts->ticks-1)*opts->height);
+ XDrawLine(display, pixmap, widgetGC, w, hh, ww, hh);
+
+ if (!incrcnt) {
+ int www = ww + TICKGAP;
+ int hhh = hh + (metrics.ascent-metrics.descent)/2.;
+ Tk_DrawChars(display, pixmap, widgetGC, font, ticktxt[ii],
+ strlen(ticktxt[ii]), www, hhh);
+ }
+ }
+
+ if (incrcnt<skipcnt)
+ incrcnt++;
+ else
+ incrcnt=0;
+ }
+
+ Tk_FreeFont(font);
+}
+
+void ColorbarBase::renderGridAST()
+{
+ if (grid)
+ delete grid;
+ grid = NULL;
+
+ if (cnt>1 && lut) {
+ grid = new CBGrid(this, cnt, lut);
+ if (grid)
+ grid->render();
+ }
+}
+
+// PS
+
+int ColorbarBase::postscriptProc(int prepass)
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ if (!visible)
+ return TCL_OK;
+
+ if (prepass)
+ return TCL_OK;
+
+ // bar
+ Tcl_AppendResult(interp, "gsave\n", NULL);
+ ps();
+ Tcl_AppendResult(interp, "grestore\n", NULL);
+
+ // numerics
+ Tcl_AppendResult(interp, "gsave\n", NULL);
+
+ if (opts->numerics && opts->space && grid) {
+ psGridAST();
+ Tcl_AppendResult(interp, "grestore\n", NULL);
+ return TCL_OK;
+ }
+
+ // we want a border, even if no numerics
+ psGrid();
+ Tcl_AppendResult(interp, "grestore\n", NULL);
+ return TCL_OK;
+}
+
+void ColorbarBase::ps()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ int& width = options->width;
+ int& height = options->height;
+ int& size = opts->size;
+
+ // image
+ int ww = !opts->orientation ? width : size;
+ int hh = !opts->orientation ? size : height;
+ Vector org = psOrigin();
+ if (!opts->orientation)
+ org += Vector(0,height-size);
+
+ ostringstream str;
+ str << org << " translate " << 1 << ' ' << 1 << " scale" << endl;
+
+ switch (psLevel) {
+ case 1:
+ {
+ psHead1(str, ww, hh);
+ NoCompressAsciiHex filter(psLevel);
+ psHV(str, filter, ww, hh);
+ }
+ break;
+ case 2:
+ {
+ psHead2(str, ww, hh, "RunLength", "ASCII85");
+ RLEAscii85 filter(psLevel);
+ psHV(str, filter, ww, hh);
+ }
+ break;
+ case 3:
+ {
+ psHead2(str, ww, hh, "Flate", "ASCII85");
+ GZIPAscii85 filter(psLevel);
+ psHV(str, filter, ww, hh);
+ }
+ break;
+ }
+
+ str << ends;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+}
+
+void ColorbarBase::psHV(ostream& str, Filter& filter, int width, int height)
+{
+ if (!((ColorbarBaseOptions*)options)->orientation)
+ psHorz(str, filter, width, height);
+ else
+ psVert(str, filter, width, height);
+
+ filter.flush(str);
+}
+
+void ColorbarBase::psGrid()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ int& width = options->width;
+ int& height = options->height;
+ int& size = opts->size;
+
+ // box
+ int ww,hh;
+ Vector org = psOrigin();
+ if (!opts->orientation) {
+ ww = width;
+ hh = size;
+ org += Vector(0,height-size);
+ }
+ else {
+ ww = size;
+ hh = height;
+ }
+
+ Vector ll = Vector(0,0);
+ Vector lr = Vector(ww,0);
+ Vector ur = Vector(ww,hh);
+ Vector ul = Vector(0,hh);
+
+ ostringstream str;
+ str << org << " translate " << endl
+ << "newpath " << endl
+ << ll << " moveto" << endl
+ << lr << " lineto" << endl
+ << ur << " lineto" << endl
+ << ul << " lineto" << endl
+ << ll << " lineto" << endl
+ << "closepath" << endl
+ << .5 << " setlinewidth" << endl
+ << "stroke" << endl << ends;
+
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+
+ // numerics
+ if (opts->numerics && lut)
+ psGridNumerics();
+}
+
+void ColorbarBase::psGridNumerics()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ // font
+ Tk_Font font = NULL;
+ {
+ ostringstream fstr;
+ fstr << opts->font << ' ' << opts->fontSize << ' '
+ << opts->fontWeight << ' ' << opts->fontSlant << ends;
+ font = Tk_GetFont(interp, tkwin, fstr.str().c_str());
+ if (!font)
+ return; // bad font, we're done
+ }
+
+ // set font
+ {
+ ostringstream str;
+ str << '/' << psFontName(opts->font, opts->fontWeight, opts->fontSlant)
+ << " findfont " << int(opts->fontSize*getDisplayRatio())
+ << " scalefont setfont" << endl;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+ }
+
+ // generate text
+ lutToText(font);
+
+ // tick marks
+ int incrcnt=0;
+ for (int ii=0; ii<opts->ticks; ii++) {
+ if (!opts->orientation) {
+ // horizontal
+ int ww = (int)(ii/double(opts->ticks-1)*opts->width);
+ int h = 0;
+ int hh = h-TICKLEN;
+
+ ostringstream str;
+ str << "newpath " << endl
+ << Vector(ww,h) << " moveto " << endl
+ << Vector(ww,hh) << " lineto " << endl
+ << "closepath " << endl
+ << .5 << " setlinewidth" << endl
+ << "stroke" << endl << ends;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+
+ if (!incrcnt) {
+ ostringstream str;
+ Vector tt = Vector(ww,hh-TICKGAP);
+ str << "newpath " << endl
+ << tt << " moveto" << endl
+ << '(' << psQuote(ticktxt[ii]) << ')'
+ << "dup true charpath pathbbox " << endl
+ << "closepath " << endl
+ << "3 -1 roll sub 1.2 mul neg " << endl
+ << "3 1 roll sub 2 div exch " << endl
+ << tt << " moveto rmoveto show " << endl;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+ }
+ }
+ else {
+ // vertical
+ int w = opts->size;
+ int ww = opts->size + TICKLEN;
+ int hh = (int)(ii/double(opts->ticks-1)*opts->height);
+
+ ostringstream str;
+ str << "newpath " << endl
+ << Vector(w,hh) << " moveto " << endl
+ << Vector(ww,hh) << " lineto " << endl
+ << "closepath " << endl
+ << .5 << " setlinewidth" << endl
+ << "stroke" << endl << ends;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+
+ if (!incrcnt) {
+ ostringstream str;
+ Vector tt = Vector(ww+TICKGAP,hh);
+ str << "newpath " << endl
+ << tt << " moveto" << endl
+ << '(' << psQuote(ticktxt[ii]) << ')'
+ << "dup true charpath pathbbox " << endl
+ << "closepath " << endl
+ << "3 -1 roll sub 2 div neg " << endl
+ << "3 1 roll pop pop 0 exch " << endl
+ << tt << " moveto rmoveto show " << endl;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+ }
+ }
+
+ if (incrcnt<skipcnt)
+ incrcnt++;
+ else
+ incrcnt=0;
+ }
+
+ Tk_FreeFont(font);
+}
+
+void ColorbarBase::psGridAST()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ Vector oo;
+ Vector uu(options->width, options->height);
+ float delta = 4*opts->fontSize;
+
+ // clip rect (to remove ticks on inside)
+ if (!opts->orientation) {
+ oo += Vector(-delta,-.5);
+ uu += Vector(2*delta,-.75);
+ }
+ else {
+ oo += Vector(-.25,-delta);
+ uu += Vector(0,2*delta);
+ }
+
+ Matrix mm = Translate(psOrigin());
+ Vector ll = oo*mm;
+ Vector lr = Vector(uu[0],oo[1])*mm;
+ Vector ur = uu*mm;
+ Vector ul = Vector(oo[0],uu[1])*mm;
+
+ ostringstream str;
+ str << "newpath " << endl
+ << ll << " moveto " << endl
+ << lr << " lineto " << endl
+ << ur << " lineto " << endl
+ << ul << " lineto " << endl
+ << ll << " lineto " << endl
+ << "closepath clip" << endl << ends;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+
+ // grid
+ if (grid)
+ grid->ps(psColorSpace, originX, originY);
+}
+
+// Commands
+
+void ColorbarBase::getInvertCmd()
+{
+ if (invert)
+ Tcl_AppendResult(interp, "1", NULL);
+ else
+ Tcl_AppendResult(interp, "0", NULL);
+}
+
+void ColorbarBase::getValueCmd(int x, int y)
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ if (lut && cnt) {
+ int id =0;
+ ostringstream str;
+ if (!opts->orientation) {
+ // horizontal
+ id = (int)(x/float(options->width) * cnt);
+ }
+ else {
+ // vertical
+ id = (int)((options->height -y)/float(options->height) * cnt);
+ }
+
+ if (id<0)
+ id = 0;
+ if (id>=cnt)
+ id = cnt-1;
+
+ str << lut[id] << ends;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+ }
+ else
+ Tcl_AppendResult(interp, NULL);
+}
+
+void ColorbarBase::invertCmd(int ii)
+{
+ invert = ii ? 1 : 0;
+ updateColors();
+}
+
+void ColorbarBase::setColormapLevelCmd()
+{
+ if (lut)
+ delete [] lut;
+ lut = NULL;
+ cnt = 0;
+
+ invalidPixmap();
+ redraw();
+}
+
+void ColorbarBase::setColormapLevelCmd(int cc, double* ff)
+{
+ // check for the same
+ if (cnt == cc) {
+ int same = 1;
+ for (int ii=0; ii<cc; ii++)
+ same &= (lut[ii] == ff[ii]);
+ if (same)
+ return;
+ }
+
+ // remove the old
+ if (lut)
+ delete [] lut;
+ cnt = cc;
+ lut = new double[cc];
+ for (int ii=0; ii<cc; ii++)
+ lut[ii] = ff[ii];
+
+ invalidPixmap();
+ redraw();
+}
+
+// MacOSX
+
+#ifdef MAC_OSX_TK
+void ColorbarBase::macosxPrintCmd()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ if (!visible)
+ return;
+
+ // init
+ macosxBegin();
+
+ int ww,hh;
+ if (!opts->orientation) {
+ ww = options->width;
+ hh = opts->size;
+ }
+ else {
+ ww = opts->size;
+ hh = options->height;
+ }
+
+ // image
+ macosx(1, ww, hh, Vector(originX,originY), Vector(ww,hh));
+
+ // grid
+ if (opts->numerics && opts->space && grid) {
+ macosxGridAST();
+ macosxEnd();
+ return;
+ }
+
+ // we want a border, even if no numerics
+ macosxGrid();
+ macosxEnd();
+}
+
+void ColorbarBase::macosxGrid()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ int& width = options->width;
+ int& height = options->height;
+ int& size = opts->size;
+
+ Matrix mm = Translate(originX, originY);
+
+ macosxColor(getXColor("black"));
+ macosxDash(NULL,0);
+ macosxWidth(.5);
+
+ // Box
+ int ww,hh;
+ if (!opts->orientation) {
+ ww = width;
+ hh = size;
+ }
+ else {
+ ww = size;
+ hh = height;
+ }
+
+ Vector v[5];
+ v[0] = Vector(0,0) * mm;
+ v[1] = Vector(ww,0) * mm;
+ v[2] = Vector(ww,hh) * mm;
+ v[3] = Vector(0,hh) * mm;
+ v[4] = Vector(0,0) * mm;
+ macosxDrawLines(v,5);
+
+ // numerics
+ if (opts->numerics && lut)
+ macosxGridNumerics();
+}
+
+void ColorbarBase::macosxGridNumerics()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+ Matrix mm = Translate(originX, originY);
+
+ // font
+ Tk_Font font = getFont();
+ if (!font)
+ return; // bad font, we're done
+ Tk_FontMetrics metrics;
+ Tk_GetFontMetrics(font, &metrics);
+
+ // set font
+ Tcl_DString psFont;
+ Tcl_DStringInit(&psFont);
+ int psSize = Tk_PostscriptFontName(font, &psFont);
+ macosxFont(Tcl_DStringValue(&psFont), psSize);
+ Tcl_DStringFree(&psFont);
+
+ // generate text
+ lutToText(font);
+
+ // tick marks
+ int incrcnt=0;
+ for (int ii=0; ii<opts->ticks; ii++) {
+ if (!opts->orientation) {
+ // horizontal
+ int ww = (int)(ii/double(opts->ticks-1)*opts->width);
+ int h = opts->size;
+ int hh = opts->size + TICKLEN;
+ Vector vv[2];
+ vv[0] = Vector(ww,h)*mm;
+ vv[1] = Vector(ww,hh)*mm;
+ macosxDrawLines(vv,2);
+
+ if (!incrcnt) {
+ int txtwidth = Tk_TextWidth(font, ticktxt[ii], strlen(ticktxt[ii]));
+ int www = ww - txtwidth/2.;
+ int hhh = hh + TICKGAP + metrics.ascent;
+ macosxDrawText(Vector(www,hhh)*mm, 0, ticktxt[ii]);
+ }
+ }
+ else {
+ // vertical
+ int w = opts->size;
+ int ww = opts->size + TICKLEN;
+ int hh = opts->height - (int)(ii/double(opts->ticks-1)*opts->height);
+ Vector vv[2];
+ vv[0] = Vector(w,hh)*mm;
+ vv[1] = Vector(ww,hh)*mm;
+ macosxDrawLines(vv,2);
+
+ if (!incrcnt) {
+ int www = ww + TICKGAP;
+ int hhh = hh + (metrics.ascent-metrics.descent)/2.;
+ macosxDrawText(Vector(www,hhh)*mm, 0, ticktxt[ii]);
+ }
+ }
+
+ if (incrcnt<skipcnt)
+ incrcnt++;
+ else
+ incrcnt=0;
+ }
+
+ Tk_FreeFont(font);
+}
+
+void ColorbarBase::macosxGridAST()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ Vector oo(originX, originY);
+ Vector uu(options->width, options->height);
+ float delta = 4*opts->fontSize;
+
+ if (!opts->orientation) {
+ oo += Vector(-delta,-.2);
+ uu += Vector(2*delta,-.2);
+ }
+ else {
+ oo += Vector(-.2,-delta);
+ uu += Vector(0,2*delta);
+ }
+ macosxClip(oo,uu);
+
+ if (grid)
+ grid->macosx(originX, originY);
+}
+
+#endif
+
+// WIN32
+
+#ifdef __WIN32
+void ColorbarBase::win32PrintCmd()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ if (!visible)
+ return;
+
+ // init
+ win32Begin();
+
+ int ww,hh;
+ if (!opts->orientation) {
+ ww = options->width;
+ hh = opts->size;
+ }
+ else {
+ ww = opts->size;
+ hh = options->height;
+ }
+
+ // image
+ win32(1, ww, hh, Vector(originX,originY), Vector(ww,hh));
+
+ // grid
+ if (opts->numerics && opts->space && grid) {
+ win32GridAST();
+ win32End();
+ }
+
+ // we want a border, even if no numerics
+ win32Grid();
+ win32End();
+}
+
+void ColorbarBase::win32Grid()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ int& width = options->width;
+ int& height = options->height;
+ int& size = opts->size;
+
+ Matrix mm = Translate(originX, originY);
+
+ win32Color(getXColor("black"));
+ win32Dash(NULL,0);
+ win32Width(.5);
+
+ // box
+ int ww,hh;
+ if (!opts->orientation) {
+ ww = width;
+ hh = size;
+ }
+ else {
+ ww = size;
+ hh = height;
+ }
+
+ Vector v[5];
+ v[0] = Vector(0,0) * mm;
+ v[1] = Vector(ww,0) * mm;
+ v[2] = Vector(ww,hh) * mm;
+ v[3] = Vector(0,hh) * mm;
+ v[4] = Vector(0,0) * mm;
+ win32DrawLines(v,5);
+
+ // numerics
+ if (opts->numerics && lut)
+ win32GridNumerics();
+}
+
+void ColorbarBase::win32GridNumerics()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+ Matrix mm = Translate(originX, originY);
+
+ // font
+ Tk_Font font = getFont();
+ if (!font)
+ return; // bad font, we're done
+ Tk_FontMetrics metrics;
+ Tk_GetFontMetrics(font, &metrics);
+
+ win32Font(font);
+
+ // generate text
+ lutToText(font);
+
+ // tick marks
+ int incrcnt=0;
+ for (int ii=0; ii<opts->ticks; ii++) {
+ if (!opts->orientation) {
+ // horizontal
+ int ww = ii/double(opts->ticks-1)*opts->width;
+ int h = opts->size;
+ int hh = opts->size + TICKLEN;
+ Vector vv[2];
+ vv[0] = Vector(ww,h)*mm;
+ vv[1] = Vector(ww,hh)*mm;
+ win32DrawLines(vv,2);
+
+ if (!incrcnt) {
+ int txtwidth = Tk_TextWidth(font, ticktxt[ii], strlen(ticktxt[ii]));
+ int www = ww - txtwidth/2.;
+ int hhh = hh + TICKGAP + metrics.ascent;
+ win32DrawText(Vector(www,hhh)*mm, 0, ticktxt[ii]);
+ }
+ }
+ else {
+ // vertical
+ int w = opts->size;
+ int ww = opts->size + TICKLEN;
+ int hh = opts->height - (int)(ii/double(opts->ticks-1)*opts->height);
+ Vector vv[2];
+ vv[0] = Vector(w,hh)*mm;
+ vv[1] = Vector(ww,hh)*mm;
+ win32DrawLines(vv,2);
+
+ if (!incrcnt) {
+ int www = ww + TICKGAP;
+ int hhh = hh + (metrics.ascent-metrics.descent)/2.;
+ win32DrawText(Vector(www,hhh)*mm, 0, ticktxt[ii]);
+ }
+ }
+
+ if (incrcnt<skipcnt)
+ incrcnt++;
+ else
+ incrcnt=0;
+ }
+
+ Tk_FreeFont(font);
+}
+
+void ColorbarBase::win32GridAST()
+{
+ ColorbarBaseOptions* opts = (ColorbarBaseOptions*)options;
+
+ Vector oo(originX, originY);
+ Vector uu(options->width, options->height);
+ float delta = 4*opts->fontSize;
+
+ if (!opts->orientation) {
+ oo += Vector(-delta,-.2);
+ uu += Vector(2*delta,-.2);
+ }
+ else {
+ oo += Vector(-.2,-delta);
+ uu += Vector(0,2*delta);
+ }
+ win32Clip(oo,uu);
+
+ if (grid)
+ grid->win32(originX, originY);
+}
+
+#endif
+
+