00001 #pragma ident "$Id: PSImageBase.cpp 3140 2012-06-18 15:03:02Z susancummins $"
00002
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
00103 ostr << style.getWidth() << " setlinewidth" << endl;
00104
00105
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
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 }
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
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
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
00193 if( tmarker != NONE && tmarker != CLEAR )
00194 printStrokeStyle(ss);
00195 else
00196 updateStrokeStyle(ss);
00197
00198
00199
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
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
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
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
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
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
00406
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
00411
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
00447
00448
00449
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
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
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 }
00563