/* Changes by luberth dijkman http://www.Sticker.Tk strange speed / scale code drvHPGL.cpp : This file is part of pstoedit HPGL / HPGL2 Device driver supporting text commands Copyright (C) 1993 - 2001 Peter Katzmann p.katzmann_AT_thiesen.com Copyright (C) 2000 - 2006 Katzmann & Glunz (fill stuff) Copyright (C) 2001 Peter Kuhlemann kuhlemannp_AT_genrad.com Copyright (C) 2002 - 2003 Peter Kuhlemann peter.kuhlemann_AT_teradyne.com 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. Aug 21, 2001: Donald Arseneau (asnd_AT_triumf.ca) adds pen changes when color changes. Changed sections are delimited by: // Start DA hpgl color addition // End DA hpgl color addition */ #define USESPRINTF 1 #include "drvhpgl.h" #include #include I_stdio static const float HPGLScale = 14.0f; void drvHPGL::rot(double &x, double &y, int angle) { double tmp; switch (angle) { case 90: tmp = x; x = -y; y = tmp; break; case 180: x = -x; y = -y; break; case 270: tmp = x; x = y; y = -tmp; break; default: break; } } drvHPGL::derivedConstructor(drvHPGL): constructBase, // Start DA hpgl color addition prevColor(5555), maxPen(0), penColors(0) // End DA hpgl color addition { // driver specific initializations // and writing of header to output file // bool show_usage_line = false; //NN savedtextinfo.thetext = ""; if (options->rot90) rotation = 90; else if (options->rot180) rotation = 180; else if (options->rot270) rotation = 270; else rotation = 0; //NN merge = 0; #if 0 for (unsigned int i = 0; i < d_argc; i++) { assert(d_argv && d_argv[i]); //lint !e796 if (Verbose()) outf << "% " << d_argv[i] << endl; if (strcmp(d_argv[i], "-pen") == 0) { penplotter = true; } else if (strcmp(d_argv[i], "-VS") == 0) { i++; if (i >= d_argc) { errf << "-VS requires a numeric argument " << endl; show_usage_line = true; } else { speed = atoi(d_argv[i]); } } else if (strcmp(d_argv[i], "-fill") == 0) { i++; if (i >= d_argc) { errf << "-fill requires a string argument " << endl; show_usage_line = true; } else { fillinstruction = d_argv[i]; } /* Fill Type (FT) Command ========================================= This command selects the shading pattern used to fill polygons ( FP ), rectangles ( RA or RR ), wedges ( WG ), or characters ( CF ). The Fill Type command ( FT ), can use solid, shading, parallel lines (hatching), cross hatching, patterned (raster) fill, or PCL user-defined patterns. For more information see the PCL 5 Printer Language Technical Reference Manual. The syntax for this command is as follows: FT fill type,[option1,[option2]]; or FT; */ // known fill types: // FT 1 - solid black // FT 3 - parallel lines FT 3[,delta,angle] // FT 4 - cross hatching FT 4[,delta,angle] // FT 10 - shading FT 10,[percentage] } else if (strcmp(d_argv[i], "-rot90") == 0) { rotation = 90; } else if (strcmp(d_argv[i], "-rot180") == 0) { rotation = 180; } else if (strcmp(d_argv[i], "-rot270") == 0) { rotation = 270; //NN } else if (strcmp(d_argv[i], "-merge") == 0) { //NN merge = 1; } else { errf << "Unknown fig driver option: " << d_argv[i] << endl; show_usage_line = true; } } if (show_usage_line) { errf << "Usage -f 'HPGL: [-fill fillstring] [-pen] [-pencolors number] [-rot90 | -rot180 | -rot270] '" << endl; } #endif // if (0) { // const char esc = (char) 27; // outf << esc << ".(;"; // } errf << "Info: This HPGL driver is not very elaborated - consider using -f plot-hpgl instead." << endl; outf << "IN;VL0;PA;PU;SP0;VS5;TP180;\n"; penColors = new unsigned int[options->maxPenColors + 1 + 1]; // 1 offset - 0 is not used // one more for flint ;-) for (unsigned int p = 0; p <= (unsigned int) options->maxPenColors + 1; p++) { penColors[p] = 0; } // float x_offset; // float y_offset; } drvHPGL::~drvHPGL() { // driver specific deallocations // and writing of trailer to output file outf << "PU0,0\n"; // fillinstruction = NIL; delete [] penColors; penColors = NIL; options= NIL; } void drvHPGL::print_coords() { const unsigned int elems = numberOfElementsInPath(); if (elems) { for (unsigned int n = 0; n < elems; n++) { const basedrawingelement & elem = pathElement(n); switch (elem.getType()) { case moveto: { const Point & p = elem.getPoint(0); double x = (p.x_ + x_offset) * HPGLScale; double y = (p.y_ + y_offset) * HPGLScale; rot(x, y, rotation); #if USESPRINTF char str[256]; sprintf_s(TARGETWITHLEN(str,256), "PU%i,%i;", (int) x, (int) y); outf << str; #else outf << "PU" << (int) x << "," << (int) y << ";"; #endif } break; case lineto: { { const Point & p = elem.getPoint(0); double x = (p.x_ + x_offset) * HPGLScale; double y = (p.y_ + y_offset) * HPGLScale; rot(x, y, rotation); #if USESPRINTF char str[256]; sprintf_s(TARGETWITHLEN(str,256), "PD%i,%i;", (int) x, (int) y); outf << str; #else outf << "PD" << (int) x << "," << (int) y << ";"; #endif } if (isPolygon() && (n == elems)) { const basedrawingelement & elemnull = pathElement(0); const Point & pnull = elemnull.getPoint(0); double x = (pnull.x_ + x_offset) * HPGLScale; double y = (pnull.y_ + y_offset) * HPGLScale; rot(x, y, rotation); #if USESPRINTF char str[256]; sprintf_s(TARGETWITHLEN(str,256), "PD%i,%i;", (int) x, (int) y); outf << str; #else outf << "PD" << (int) x << "," << (int) y << ";"; #endif } } break; case closepath: { const Point & p = pathElement(0).getPoint(0); double x = (p.x_ + x_offset) * HPGLScale; double y = (p.y_ + y_offset) * HPGLScale; rot(x, y, rotation); #if USESPRINTF char str[256]; sprintf_s(TARGETWITHLEN(str,256), "PD%i,%i;", (int) x, (int) y); outf << str; #else outf << "PD" << (int) x << "," << (int) y << ";"; #endif } break; case curveto: errf << "\t\tFatal: unexpected case curveto in drvHPGL " << endl; abort(); break; default: errf << "\t\tFatal: unexpected case default in drvHPGL " << endl; abort(); break; } } } } void drvHPGL::open_page() { // Start DA hpgl color addition prevColor = 5555; maxPen = 0; // End DA hpgl color addition //removed luberth http://www.sticker.tk outf << "IN;SC;PU;PU;SP1;LT;VS" << (int) HPGLScale << "\n"; } void drvHPGL::close_page() { //removed luberth http://www.sticker.tk outf << "PU;SP;EC;PG1;EC1;OE\n"; } #if 0 void drvHPGL::endtext() { if (merge) { flush_text(savedtextinfo); savedtextinfo.thetext = ""; } } #endif void drvHPGL::show_text(const TextInfo & textinfo) { #if 0 // this is now handled by drvbase if (merge) { if (savedtextinfo.thetext == "") { savedtextinfo = textinfo; } else if ((textinfo.currentFontAngle == savedtextinfo.currentFontAngle) && (textinfo.currentFontSize == savedtextinfo.currentFontSize) && (fabs(textinfo.x - savedtextinfo.x_end) < textinfo.currentFontSize / HPGLScale) && (fabs(textinfo.y - savedtextinfo.y_end) < textinfo.currentFontSize / HPGLScale)) { savedtextinfo.thetext += textinfo.thetext; savedtextinfo.x_end = textinfo.x_end; savedtextinfo.y_end = textinfo.y_end; } else { flush_text(savedtextinfo); savedtextinfo = textinfo; } } else #endif const double pi = 3.1415926535; const double angleofs = rotation * pi / 180; const double dix = 100.0 * cos(textinfo.currentFontAngle * pi / 180.0 + angleofs); const double diy = 100.0 * sin(textinfo.currentFontAngle * pi / 180.0 + angleofs); double x = (textinfo.x + x_offset) * HPGLScale; double y = (textinfo.y + y_offset) * HPGLScale; rot(x, y, rotation); /* drvhpgl.cpp:316: warning: ISO C++ does not support the `%lg' printf format drvhpgl.cpp:316: warning: ISO C++ does not support the `%lg' printf format drvhpgl.cpp:318: warning: ISO C++ does not support the `%lg' printf format drvhpgl.cpp:318: warning: ISO C++ does not support the `%lg' printf format */ #if USESPRINTF char str[256]; sprintf_s(TARGETWITHLEN(str,256), "DI%g,%g;", dix, diy); outf << str; sprintf_s(TARGETWITHLEN(str,256), "SI%g,%g;", textinfo.currentFontSize / 1000 * HPGLScale, textinfo.currentFontSize / 1000 * HPGLScale); outf << str; sprintf_s(TARGETWITHLEN(str,256), "PU%i,%i;", (int) x, (int) y); outf << str; #else outf << "DI" << dix << "," << diy << ";"; outf << "SI" << textinfo.currentFontSize / 1000 * HPGLScale << "," << textinfo.currentFontSize / 1000 * HPGLScale << ";"; outf << "PU" << (int) x << "," << (int) y << ";"; #endif outf << "LB" << textinfo.thetext.value() << "\003;" << endl; } void drvHPGL::show_path() { // Start DA hpgl color addition /* * This block should be a separate subroutine, called by each of * the hpgl subroutines. * * The object is to generate pen switching commands when the color * changes. We keep a list of pen colors, which approximate the * desired rgb colors. Choose an existing pen number when the * rgb color approximates that color, and add a new color to the * list when the rgb color is distinctly new. */ if (numberOfElementsInPath()) { if (options->maxPenColors > 0) { const unsigned int reducedColor = 256 * (unsigned int) (currentR() * 16) + 16 * (unsigned int) (currentG() * 16) + (unsigned int) (currentB() * 16); if (prevColor != reducedColor) { // If color changed, see if color has been used before unsigned int npen = 0; if (maxPen > 0) { for (unsigned int j = 1; j <= maxPen; j++) { // 0th element is never used - 0 indicates "new" color if (penColors[j] == reducedColor) { npen = j; } } } // If color is new, add it to list, if room if (npen == 0) { if (maxPen < (unsigned int)options->maxPenColors) { maxPen++; } npen = maxPen; //cout << "npen : " << npen << " maxPenColors" << maxPenColors << endl; penColors[npen] = reducedColor; } // Select new pen prevColor = reducedColor; outf << "PU; \nSP" << npen << ";\n"; } // End DA hpgl color addition } switch (currentShowType()) { case drvbase::stroke: break; case drvbase::eofill: // Probably Wrong, but treat eoffil like fill case drvbase::fill: { const Point & p = pathElement(0).getPoint(0); double x = (p.x_ + x_offset) * HPGLScale; double y = (p.y_ + y_offset) * HPGLScale; rot(x, y, rotation); #if USESPRINTF char str[256]; sprintf_s(TARGETWITHLEN(str,256), "PU%i,%i;", (int) x, (int) y); outf << str; #else outf << "PU" << (int) x << "," << (int) y << ";"; #endif outf << options->fillinstruction.value << ";PM0;"; } break; default: // cannot happen errf << "unexpected ShowType " << (int) currentShowType(); break; } if (!options->penplotter) { #if USESPRINTF char str[256]; sprintf_s(TARGETWITHLEN(str,256), "PW%lg;", currentLineWidth()); outf << str; #else //outf << "PW" << currentLineWidth() << ";"; #endif } print_coords(); switch (currentShowType()) { // To check which endsequenz we need case drvbase::stroke: break; case drvbase::eofill: // Probably Wrong, but treat eoffil like fill case drvbase::fill: outf << "PM2;FP;EP;"; // EP also draws path break; default: // cannot happen outf << "unexpected ShowType " << (int) currentShowType(); break; } outf << endl; } } #if 0 // not needed anymore - at least not as long the default is acceptable. void drvHPGL::show_rectangle(const float llx, const float lly, const float urx, const float ury) { unused(&llx); unused(&lly); unused(&urx); unused(&ury); // just do show_path for a first guess show_path(); } #endif static DriverDescriptionT < drvHPGL > D_HPGL("hpgl", "HPGL code", "","hpgl", false, // backend supports subpathes // if subpathes are supported, the backend must deal with // sequences of the following form // moveto (start of subpath) // lineto (a line segment) // lineto // moveto (start of a new subpath) // lineto (a line segment) // lineto // // If this argument is set to false each subpath is drawn // individually which might not necessarily represent // the original drawing. false, // backend supports curves false, // backend supports elements which are filled and have edges true, // backend supports text DriverDescription::noimage, // no support for PNG file images DriverDescription::normalopen, false, // backend support multiple pages false /*clipping */ );