/* drvFIG.c : This file is part of pstoedit Based on the skeleton for the implementation of new backends Copyright (C) 1993,1994,1995,1996 Wolfgang Glunz, Wolfgang.Glunz@zfe.siemens.de This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* FIG 3.1 driver by Ian MacPhedran (Ian_MacPhedran@engr.usask.ca) April 1995 Color support and conversion to use C++ streams done by Wolfgang Glunz Object depth support by Gerhard Kircher March 1996 */ #include "drvfig.h" #include #include // for sprintf #include // for free #include static const char * colorstring(float r, float g, float b) { static char buffer[10]; sprintf(buffer,"%s%.2x%.2x%.2x","#", (int) (r * 255), (int) ( g * 255) , (int) (b * 255)); return buffer; } static const char * fig_default_colors[] = { "#000000", "#0000ff", "#00ff00", "#00ffff", "#ff0000", "#ff00ff", "#ffff00", "#ffffff", "#000090", "#0000b0", "#0000d0", "#87ceff", "#009000", "#00b000", "#00d000", "#009090", "#00b0b0", "#00d0d0", "#900000", "#b00000", "#d00000", "#900090", "#b000b0", "#d000d0", "#803000", "#a04000", "#c06000", "#ff8080", "#ffa0a0", "#ffc0c0", "#ffe0e0", "#ffd700" }; const int defaults = sizeof(fig_default_colors)/sizeof(char*); static ColorTable colorTable(fig_default_colors,defaults,colorstring); #if 0 // I know we could make a class here const int maxcolors = 1000; int currentcolor = 0; static char * newcolors[maxcolors]; static void initnewcolors() { for (int i = 0 ; i< maxcolors; i++) newcolors[i] = 0; } static void freenewcolors() { int current= 0; while (newcolors[current] != 0) { free(newcolors[current]); // need free instead of delete, because strdup calls malloc current++; } } static int registercolor(float r, float g, float b) { // returns the index under which the color was registered const char * cmp = colorstring(r,g,b); for (int i = 0; i < defaults ; i++ ) { if (strcmp(cmp,fig_default_colors[i]) == 0) { return i; } } // look in new colors for (int j = 0; j < currentcolor ; j++ ) { if (strcmp(cmp,newcolors[j]) == 0) { return j+defaults; } } // not found so far // add a copy to newcolors if (currentcolor < maxcolors) { newcolors[currentcolor] = strdup(cmp); currentcolor++; return currentcolor+defaults-1; } else { cerr << "running out of colors in drvFIG.c" << endl; return 0; } } #endif static int registercolor(float r, float g, float b) { return colorTable.getColorIndex(r,g,b); } static void dumpnewcolors(ostream & theoutStream) { int current= defaults; const char * colstring; while ((colstring = colorTable.getColorString(current)) != 0) { theoutStream << "0 " << current << " " << colstring << endl; current++; } } drvFIG::drvFIG(ostream & theoutStream): drvbase(theoutStream,0,0,0), buffer(tempFile.asOutput()) { // driver specific initializations // set FIG specific values scale = 1; currentDeviceHeight = 13200.0 * scale; // We use objectId as depth value. // We need this because editing will reorder objects of equal depth, // which has an undesireable effect if objects overlap. // Depth must be in the range 0..999 (FIG 3.1). // If we have more than 1000 objects this will get negative and // xfig will set negative depth values to zero. // This feature will thus become useless if we have more // than 1000 objects. This is an xfig limitation. objectId = 999; x_offset = 0.0; y_offset = currentDeviceHeight; // output buffer, needed because // color entries must be written at // top of output file, but are known // only after processing the full input // print the header part outf << "#FIG 3.1\nPortrait\nFlush Left\nInches\n1200 2\n"; } drvFIG::~drvFIG() { dumpnewcolors(outf); // now we can copy the buffer the output ifstream & inbuffer = tempFile.asInput(); copy_file(inbuffer,outf); } void drvFIG::print_coords() { int j; float PntFig = 1200.0 / 72.0; j = 0; for (unsigned int n = 0; n < numberOfElementsInPath(); n++) { const Point & p = pathElement(n).getPoint(0); if (j == 0) { buffer << "\t"; } buffer << (int)(PntFig * p.x_) << " " << (int)(y_offset - (PntFig * p.y_)) << " "; j++; if (j == 5) { j=0; buffer << "\n"; } } if (j != 0) { buffer << "\n"; } } void drvFIG::close_page() { // Well, since FIG doesn't support multipage output, we'll move down // 11 inches and start again. y_offset += currentDeviceHeight; // reset depth counter objectId = 999; } void drvFIG::open_page() { } // // FIG 3.1 uses an index for the popular fonts: // // (we cannot make this array local to drvFIG::show_textstring // because some CCs don't support that yet. const char *FigFonts[] = { "Times-Roman","Times-Italic", "Times-Bold", "Times-BoldItalic", "AvantGarde-Book", "AvantGarde-BookOblique", "AvantGarde-Demi", "AvantGarde-DemiOblique", "Bookman-Light", "Bookman-LightItalic", "Bookman-Demi", "Bookman-DemiItalic", "Courier", "Courier-Oblique", "Courier-Bold","Courier-BoldOblique","Helvetica","Helvetica-Oblique", "Helvetica-Bold", "Helvetica-BoldOblique", "Helvetica-Narrow", "Helvetica-Narrow-Oblique", "Helvetica-Narrow-Bold", "Helvetica-Narrow-BoldOblique", "NewCenturySchlbk-Roman", "NewCenturySchlbk-Italic", "NewCenturySchlbk-Bold", "NewCenturySchlbk-BoldItalic", "Palatino-Roman", "Palatino-Italic", "Palatino-Bold", "Palatino-BoldItalic", "Symbol", "ZapfChancery-MediumItalic", "ZapfDingbats"}; void drvFIG::show_text(const TextInfo & textinfo) { unsigned int MAXFNTNUM, fntlength; int FigFontNum; float FigHeight,FigLength; float PntFig = 1200.0 / 72.0; float toRadians = 3.14159265359 / 180.0; MAXFNTNUM = sizeof(FigFonts)/(sizeof(char *)) - 1; FigFontNum = -1; fntlength = strlen(textinfo.currentFontName); for (unsigned int i=0; i<=MAXFNTNUM; i++) { if (fntlength == strlen(FigFonts[i])) { if (strncmp(textinfo.currentFontName,FigFonts[i],fntlength) == 0) FigFontNum = i; } } if (FigFontNum == -1) { cerr << "Warning, unsupported font " << textinfo.currentFontName << ", using Courier instead" << endl; FigFontNum = 12; // Courier } int color = registercolor(textinfo.currentR,textinfo.currentG,textinfo.currentB); float localFontSize = textinfo.currentFontSize; if (localFontSize <= 0.1) { localFontSize = 9; } localFontSize++; // There appears to be a reduction for some reason FigHeight = 1200.0 * localFontSize / 72.0; FigLength = FigHeight * strlen(textinfo.thetext); buffer << "4 0 "; buffer << color; buffer << " " << objectId-- << " -1 " << FigFontNum << " " << (int) localFontSize << " " << textinfo.currentFontAngle*toRadians << " 4 " << FigHeight << " " << FigLength << " " << (int)(PntFig * textinfo.x) << " " << (int)(y_offset - (PntFig * textinfo.y)) << " " << textinfo.thetext << "\\001\n"; } void drvFIG::show_path() { float localLineWidth = currentLineWidth(); if ((localLineWidth < 0.0) || ((localLineWidth > 0.0) && (localLineWidth <= 1.0))) { localLineWidth = 1.0; } buffer << "2 1 0 " << (int)localLineWidth << " " ; const int color = registercolor(currentR(),currentG(),currentB()); const int fill_or_nofill = (currentShowType() == drvbase::stroke) ? -1 : 20; buffer << color << " " << color << " " << objectId-- << " 0 " << fill_or_nofill << " 0.00 0 0 0 0 0 "; buffer << (int)(numberOfElementsInPath()) << "\n"; print_coords(); }; void drvFIG::show_rectangle(const float llx, const float lly, const float urx, const float ury) { // just do show_polyline for a first guess show_path(); }