PSImageBase.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: PSImageBase.cpp 3140 2012-06-18 15:03:02Z susancummins $"
00002 
00004 
00005 //============================================================================
00006 //
00007 //  This file is part of GPSTk, the GPS Toolkit.
00008 //
00009 //  The GPSTk is free software; you can redistribute it and/or modify
00010 //  it under the terms of the GNU Lesser General Public License as published
00011 //  by the Free Software Foundation; either version 2.1 of the License, or
00012 //  any later version.
00013 //
00014 //  The GPSTk is distributed in the hope that it will be useful,
00015 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 //  GNU Lesser General Public License for more details.
00018 //
00019 //  You should have received a copy of the GNU Lesser General Public
00020 //  License along with GPSTk; if not, write to the Free Software Foundation,
00021 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
00022 //  
00023 //  Copyright 2004, The University of Texas at Austin
00024 //
00025 //============================================================================
00026 
00027 #include <iostream>
00028 #include <iomanip>
00029 #include <stdlib.h>
00030 #include <sstream>
00031 #include "PSImageBase.hpp"
00032 
00033 namespace vdraw
00034 {
00035 
00039   PSImageBase::PSImageBase(std::ostream& stream, 
00040       double width, 
00041       double height,
00042       ORIGIN_LOCATION iloc):
00043     VGImage(width, height, iloc), 
00044     ostr(stream), strokeStylePrinted(false),
00045     textStylePrinted(false),centerDefined(false),
00046     rightDefined(false)
00047   {
00048   }
00049 
00050 
00051   PSImageBase::PSImageBase(const char* fname, double width,
00052       double height,
00053       ORIGIN_LOCATION iloc):
00054     VGImage(width, height, iloc), 
00055     myfstream(fname), ostr(myfstream), filename(fname),
00056     strokeStylePrinted(false),textStylePrinted(false),
00057     centerDefined(false), rightDefined(false)
00058   {
00059   }
00060 
00061 
00062 
00063   PSImageBase::~PSImageBase(void)
00064   {}
00065 
00066 
00071   void PSImageBase::updateStrokeStyle(StrokeStyle& ss)
00072   {
00073     if (!strokeStylePrinted || lastUsedStrokeStyle!=ss)
00074       printStrokeStyle(ss);
00075   }
00076 
00077   void PSImageBase::comment(const Comment& comment)
00078   {
00079     using namespace std;
00080 
00081     string::size_type loc = 0, lastloc = 0;
00082     while( (loc = comment.str.find("\n",lastloc)) != string::npos )
00083     {
00084       ostr << "% " << comment.str.substr(lastloc,loc-lastloc+1);
00085       lastloc = loc + 1;
00086     }
00087     if( lastloc < (comment.str.length()) )
00088       ostr << "% " << comment.str.substr(lastloc) << endl;
00089 
00090   }
00091 
00092   void PSImageBase::printStrokeStyle(const StrokeStyle& style)
00093   {
00094     using namespace std;
00095 
00096     // Color
00097     double red, blue, green;
00098     style.getColor().getRGBTripletFractional(red, green, blue);
00099     ostr << setprecision(5) << red << " " << green << " " << blue;
00100     ostr << " setrgbcolor " << endl;
00101 
00102     // Width
00103     ostr << style.getWidth() << " setlinewidth" << endl;
00104 
00105     // Dashing - write out length, space delimited
00106     ostr << "[ ";
00107 
00108     StrokeStyle::dashLengthList dll=style.getDashList();
00109     StrokeStyle::dashLengthList::iterator i;
00110     for (i=dll.begin(); i!=dll.end(); i++) 
00111       ostr  << (*i) << " ";
00112 
00113     ostr << "] 0 setdash " << endl;
00114 
00115     lastUsedStrokeStyle = style;
00116     strokeStylePrinted = true;
00117   }
00118 
00119   void PSImageBase::outputPath(const Path& path)
00120   {
00121     using namespace std;
00122 
00123     auto_ptr<Path> abspath = path.asAbsolute();
00124     Path::const_iterator i;
00125     bool first=true;
00126 
00127     // Step through each point
00128     for (i=abspath->begin(); i!=abspath->end(); i++)
00129     {
00130       if (first)
00131       {
00132         ostr << i->first << " " << ((ll)?i->second:(canvasHeight-i->second)) << " moveto" << endl;
00133         first=false;
00134       }
00135       else
00136         ostr << i->first << " " << ((ll)?i->second:(canvasHeight-i->second)) << " lineto" << endl;
00137     } // Step through points in the path
00138 
00139     return;
00140   }
00141 
00142   void PSImageBase::markPath(const Path& path, const char * name)
00143   {
00144     using namespace std;
00145 
00146     auto_ptr<Path> abspath = path.asAbsolute();    
00147     Path::const_iterator i;
00148 
00149     // Step through each point
00150     for (i=abspath->begin(); i!=abspath->end(); i++)
00151       ostr << i->first << " " << ((ll)?i->second:(canvasHeight-i->second)) << " " << name << endl;
00152 
00153     return;
00154   }
00155 
00156 
00157   void PSImageBase::line (const Line& line)
00158   {
00159     using namespace std;
00160 
00161     if ( extraComments )
00162       ostr << "% Line" << endl;
00163 
00164     Marker cmarker;
00165     StyleType tmarker = getCorrectMarker(&cmarker,line);
00166     if( tmarker == SHAPE )
00167     {
00168       if ( !markerDefined || (lastMarker != line.getMarker()) )
00169       {
00170         defineMarker( line.getMarker() );
00171       }
00172     }
00173 
00174     StrokeStyle ss;
00175     StyleType tss = getCorrectStrokeStyle(&ss,line);
00176 
00177     if( tmarker != NONE && tmarker != CLEAR )
00178     {
00179       ostr << "% This is the marker run through...\n";
00180 
00181       // Color
00182       double red, blue, green;
00183       cmarker.getColor().getRGBTripletFractional(red, green, blue);
00184       ostr << setprecision(5) << red << " " << green << " " << blue;
00185       ostr << " setrgbcolor " << endl;
00186       ostr << ".2 setlinewidth " << endl;
00187 
00188       if( tmarker == SHAPE ) markPath(line);
00189       else if( tmarker == DEFAULT ) markPath(line,"dflt");
00190     }
00191 
00192     // The marker messed with color and stuff...so force rewrite...
00193     if( tmarker != NONE && tmarker != CLEAR ) 
00194       printStrokeStyle(ss);
00195     else  
00196       updateStrokeStyle(ss);
00197 
00198     // If there is neither a line or general stroke style and there is a marker
00199     // then just leave it at rendering points, not lines.
00200     if( !(tss == CLEAR) || (tss == NONE && (tmarker == SHAPE || tmarker == DEFAULT)) )
00201     {
00202       ostr << "newpath" << endl;
00203       outputPath(line);
00204       ostr << "stroke" << endl;
00205     }
00206   }
00207 
00208   void PSImageBase::defineMarker (const Marker& marker, const char * markername)
00209   {
00210     using namespace std;
00211 
00212     bool dflt = true;
00213     if( !markername )
00214     {
00215       dflt = false;
00216       markername = "mark";
00217     }
00218 
00219     if( extraComments )
00220       ostr << "%   Marker defintion\n";
00221 
00222     ostr << "/" << markername << " { ";
00223 
00224     double r = marker.getRange();
00225     double r2 = r*2;
00226 
00227     if (marker.hasDefaultMark())
00228     {
00229       Marker::Mark mark = marker.getMark();
00230       switch(mark)
00231       {
00232         case Marker::DOT:
00233           ostr << "newpath " << r << " 0 360 arc fill";
00234           break;
00235         case Marker::PLUS:
00236           ostr << "moveto " 
00237             << r << " 0 rmoveto "
00238             << -r2  << " 0 rlineto "
00239             << r << " " << r << " rmoveto "
00240             << "0 " << -r2 << " rlineto stroke";
00241           break;
00242         case Marker::X:
00243           ostr << "moveto "
00244             << r << " " << r << " rmoveto "
00245             << -r2 << " " << -r2 << " rlineto "
00246             << r2 << " 0 rmoveto "
00247             << -r2 << " " << r2 << " rlineto stroke";
00248           break;
00249       }
00250     }
00251     else
00252     {
00253       //Not implemented...see SVG file for more info in same place...
00254     }
00255 
00256     ostr << " } def\n";
00257 
00258     if( !dflt )
00259     {
00260       markerDefined = true;
00261       lastMarker = marker;
00262     }
00263   }
00264 
00265   void PSImageBase::rectangle (const Rectangle& rect)
00266   {
00267     using namespace std;
00268 
00269     StrokeStyle ss;
00270     StyleType tss = getCorrectStrokeStyle(&ss,rect);
00271     Color fc;
00272     StyleType tfc = getCorrectFillColor(&fc,rect);
00273 
00274     if( (tss == NONE || tss == CLEAR) && (tfc == NONE || tfc == CLEAR) )
00275       comment("invisible rectangle ignored...");
00276 
00277 
00278     if ( extraComments )
00279       ostr << "% Rectangle" << endl;
00280 
00281     ostr << "newpath" << endl;
00282 
00283     ostr << rect.x1 << " " << ((ll)?rect.y1:(canvasHeight-rect.y1)) << " moveto\n"
00284       << rect.x2 << " " << ((ll)?rect.y1:(canvasHeight-rect.y1))  << " lineto\n"
00285       << rect.x2 << " " << ((ll)?rect.y2:(canvasHeight-rect.y2))  << " lineto\n"
00286       << rect.x1 << " " << ((ll)?rect.y2:(canvasHeight-rect.y2))  << " lineto\n"
00287       << "closepath" << endl;
00288 
00289     if( tfc != CLEAR && tfc != NONE )
00290       ostr << fillWithColor(fc);
00291 
00292     // If the line is clear then don't bother to stroke
00293     if(!(tss == CLEAR))
00294     {
00295       updateStrokeStyle(ss);
00296       ostr << "stroke" << endl;
00297     }
00298   }
00299 
00300   void PSImageBase::circle (const Circle& circle)
00301   {
00302     using namespace std;
00303 
00304     StrokeStyle ss;
00305     StyleType tss = getCorrectStrokeStyle(&ss,circle);
00306     Color fc;
00307     StyleType tfc = getCorrectFillColor(&fc,circle);
00308 
00309     if( (tss == NONE || tss == CLEAR) && (tfc == NONE || tfc == CLEAR) )
00310       comment("invisible circle ignored...");
00311 
00312     if ( extraComments )
00313       ostr << "% Circle" << endl;
00314 
00315     ostr << "newpath" << endl;
00316 
00317     ostr << circle.xc << " " << ((ll)?circle.yc:(canvasHeight-circle.yc)) << " "
00318       << circle.radius << " 0 360 arc\n"
00319       << "closepath" << endl;
00320 
00321 
00322     if( tfc != CLEAR && tfc != NONE )
00323       ostr << fillWithColor(fc);
00324 
00325     // If the line is clear then don't bother to stroke
00326     if(!(tss == CLEAR))
00327     {
00328       updateStrokeStyle(ss);
00329       ostr << "stroke" << endl;
00330     }
00331   }
00332 
00333 
00334   void PSImageBase::polygon(const Polygon& polygon)
00335   {
00336     using namespace std;
00337 
00338     StrokeStyle ss;
00339     StyleType tss = getCorrectStrokeStyle(&ss,polygon);
00340     Color fc;
00341     StyleType tfc = getCorrectFillColor(&fc,polygon);
00342 
00343     if( (tss == NONE || tss == CLEAR) && (tfc == NONE || tfc == CLEAR) )
00344       comment("invisible polygon ignored...");
00345 
00346     if ( extraComments )
00347       ostr << "% Polygon" << endl;
00348 
00349     ostr << "newpath" << endl;
00350     outputPath(polygon);
00351     ostr << "closepath" << endl;
00352 
00353     if( tfc != CLEAR && tfc != NONE )
00354       ostr << fillWithColor(fc);
00355 
00356     // If the line is clear then don't bother to stroke
00357     if(!(tss == CLEAR))
00358     {
00359       updateStrokeStyle(ss);
00360       ostr << "stroke" << endl;
00361     }
00362   }
00363 
00364   void PSImageBase::bitmap (const Bitmap& bitmap) 
00365   {
00366     using namespace std;
00367 
00368     if(bitmap.boxes)
00369     {
00370       comment("Bitmap boxes");
00371       rectangles(bitmap);
00372     }
00373     else
00374     {
00375       comment("Bitmap Image");
00376       ostr << "gsave" << endl;
00377 
00378       double bw=bitmap.x2-bitmap.x1;
00379       double bh=(ll?1:-1)*(bitmap.y2-bitmap.y1);
00380 
00381       //ostr << bitmap.x1 << " " << bitmap.y1 << " translate" << endl
00382       ostr << bitmap.x1 << " " << ((ll)?bitmap.y1:(canvasHeight-bitmap.y1)) << " translate" << endl
00383         << bw << " " << bh << " scale" << endl;
00384 
00385       Bitmap::CMType which;
00386       int w, h, osw, osh;
00387       InterpolatedColorMap icm;
00388       ColorMap cm;
00389 
00390       if(bitmap.getICM(&icm))
00391       {
00392         which = Bitmap::ICM;
00393         w = icm.getCols();
00394         h = icm.getRows();
00395       }
00396       else if(bitmap.getCM(&cm))
00397       {
00398         which = Bitmap::CM;
00399         w = cm.getCols();
00400         h = cm.getRows();
00401       }
00402       osw = w*bitmap.osc;
00403       osh = h*bitmap.osr;
00404 
00405       // width height bits/comp matrix datasrc0 … datasrcncomp-1 multi ncomp colorimag
00406       // matrix = [width 0 0 -height 0 height]
00407       ostr << osw  << " " << osh << " 8 ["  << osw << " 0 0 " << -osh << " 0 " << osh 
00408         << "]\n{currentfile " << 3*osw << " string readhexstring pop} bind"
00409         << "\nfalse 3 colorimage";
00410       //for(int r=h-1; r>=0; r--) // For ll
00411       //for(int r=0  ; r<h ; r++) // For !ll
00412       int count=0;
00413       for(int r=(ll?h-1:0);(ll?r>=0:r<h);r+=(ll?-1:1))        
00414       {
00415         for(int rr=0;rr<bitmap.osr;rr++)
00416         {
00417           for(int c=0; c<w; c++)
00418           {
00419             stringstream ss;
00420             ss << hex << noshowbase << setfill('0') << setw(6);
00421             if(which==Bitmap::CM)
00422               ss << cm.get(r,c).getRGB();
00423             else
00424               ss << icm.get(r,c).getRGB();
00425             string sss = ss.str();
00426             for(int cc=0;cc<bitmap.osc;cc++)
00427             {
00428               if((count%12)==0) ostr << endl;
00429               ostr << sss;
00430               count++;
00431             }
00432           }
00433         }
00434       }
00435     }
00436     ostr << endl << "grestore" << endl;
00437   }
00438 
00439   void PSImageBase::text(const Text& text)
00440   {
00441     using namespace std;
00442     TextStyle ts;
00443     StyleType tts = getCorrectTextStyle(&ts,text);
00444 
00445     /*
00446      * This is to be safe since other things rely upon the last stroke
00447      * style to see if they need to redefine the style.  Since text changes
00448      * color this could screw up lines to be this color since the stroke
00449      * style has not changed.
00450      */
00451     StrokeStyle ss(ts.getColor());
00452     updateStrokeStyle(ss);
00453 
00454     if( tts == CLEAR )
00455     {
00456       comment("Text with clear font ignored:%s",text.getString().c_str());
00457       return;
00458     }
00459 
00460     if ( extraComments )
00461       ostr << "% Text" << endl;
00462 
00463     if (text.isCenter() && !centerDefined)
00464     {
00465       ostr << "/center { dup stringwidth pop 2 div neg 0 rmoveto } def" << endl;
00466       centerDefined = true;
00467     }
00468 
00469     if (text.isRight() && !rightDefined)
00470     {
00471       ostr << "/right { dup stringwidth pop neg 0 rmoveto } def" << endl;
00472       rightDefined = true;
00473     }
00474 
00475     if( !textStylePrinted || ts != lastUsedTextStyle )
00476     {
00477       printTextStyle(ts);
00478       lastUsedTextStyle = ts;
00479     }
00480 
00481     double red, blue, green;
00482     ts.getColor().getRGBTripletFractional(red, green, blue);
00483     ostr << setprecision(5) << red << " " << green << " " << blue;
00484     ostr << " setrgbcolor " << endl;
00485 
00486     bool hasAngle = text.getAngle()!=0;
00487 
00488     if( hasAngle )
00489     {
00490       ostr << "newpath" << endl
00491         << "gsave" << endl
00492         << text.x << " " << ((ll)?text.y:(canvasHeight-text.y)) 
00493         << " translate" << endl
00494         << text.getAngle() << " rotate" << endl
00495         << "0 0 moveto" << endl;
00496     }
00497     else
00498     {
00499       ostr << "newpath" << endl
00500         << text.x << " " << ((ll)?text.y:(canvasHeight-text.y)) 
00501         << " moveto" << endl;
00502     }
00503 
00504     ostr << "(" << text.getString() << ") " 
00505       << (text.isRight()?"right":(text.isCenter()?"center":"")) <<" show" << endl;
00506 
00507     if( hasAngle )
00508       ostr << "grestore" << endl;
00509   }
00510 
00511   void PSImageBase::printTextStyle(const TextStyle& ts)
00512   {
00513     using namespace std;
00514 
00515     if( ts.isMonospace() )
00516       ostr << "/Courier";
00517     else if( ts.isSerif() )
00518       ostr << "/Times";
00519     else //if( ts.isSansSerif() )
00520       ostr << "/Helvetica";
00521 
00522     if( ts.isBold() )
00523       ostr << "-Bold";
00524     if( ts.isItalic() )
00525     {
00526       if( !ts.isBold() ) 
00527         ostr << "-";
00528       if( ts.isMonospace() | ts.isSansSerif() )
00529         ostr << "Oblique";
00530       else
00531         ostr << "Italic";
00532     }
00533 
00534     ostr << " findfont" << endl;
00535 
00536     ostr << ts.getPointSize() << " scalefont setfont" << endl; 
00537 
00538     textStylePrinted = true;
00539   }
00540 
00541   std::string PSImageBase::fillWithColor(const Color& color) const
00542   {
00543     using namespace std;
00544 
00545     if( color.isClear() )
00546       return "";
00547 
00548     stringstream ostr(stringstream::in | stringstream::out); 
00549 
00550     ostr << "gsave" << endl;
00551     // Use the fill color
00552     double red, blue, green;
00553     color.getRGBTripletFractional(red, green, blue);
00554     ostr << setprecision(5) << red << " " << green << " " << blue;
00555     ostr << " setrgbcolor " << endl;
00556     ostr << "fill" << endl;
00557     ostr << "grestore" << endl;   
00558 
00559     return string(ostr.str());
00560   }
00561 
00562 } // namespace vdraw
00563 

Generated on Sun May 19 03:31:12 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1