home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xhyper10.zip / XHyper_v1.0 / src / printer.c < prev    next >
C/C++ Source or Header  |  1992-12-08  |  12KB  |  467 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989, 1990, 1991 Stanford University
  3.  * Copyright (c) 1991 Silicon Graphics, Inc.
  4.  *
  5.  * Permission to use, copy, modify, distribute, and sell this software and 
  6.  * its documentation for any purpose is hereby granted without fee, provided
  7.  * that (i) the above copyright notices and this permission notice appear in
  8.  * all copies of the software and related documentation, and (ii) the names of
  9.  * Stanford and Silicon Graphics may not be used in any advertising or
  10.  * publicity relating to the software without the specific, prior written
  11.  * permission of Stanford and Silicon Graphics.
  12.  * 
  13.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  14.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  15.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  16.  *
  17.  * IN NO EVENT SHALL STANFORD OR SILICON GRAPHICS BE LIABLE FOR
  18.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  19.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  20.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  21.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  22.  * OF THIS SOFTWARE.
  23.  */
  24.  
  25. /*
  26.  * Printer - draw for PostScript printer
  27.  */
  28.  
  29. #include <InterViews/bitmap.h>
  30. #include <InterViews/brush.h>
  31. #include <InterViews/color.h>
  32. #include <InterViews/font.h>
  33. #include <InterViews/printer.h>
  34. #include <InterViews/raster.h>
  35. #include <InterViews/transformer.h>
  36. #include <OS/list.h>
  37. #include <OS/math.h>
  38. #include <stream.h>
  39. #include <string.h>
  40.  
  41. static const float PAGE_WIDTH = 8.5 * 72;
  42. static const float PAGE_HEIGHT = 11 * 72;
  43. static const float epsilon = 0.01;
  44.  
  45. static const char* ps_prolog = "\
  46. save 20 dict begin\n\
  47. \n\
  48. /sf {   % scale /fontName => -  (set current font)\n\
  49.     {findfont} stopped {pop /Courier findfont} if\n\
  50.     exch scalefont setfont\n\
  51. } def\n\
  52. \n\
  53. /ws {\n\
  54.     4 index 6 4 roll moveto sub\n\
  55.     2 index stringwidth pop sub\n\
  56.     exch div 0 8#40 4 3 roll\n\
  57.     widthshow\n\
  58. } def\n\
  59. \n\
  60. /as {\n\
  61.     4 index 6 4 roll moveto sub\n\
  62.     2 index stringwidth pop sub\n\
  63.     exch div 0 3 2 roll\n\
  64.     ashow\n\
  65. } def\n\
  66. \n\
  67. ";
  68.  
  69. static const char* ps_epilog = "\
  70. end restore\n\
  71. ";
  72.  
  73. class PrinterInfo {
  74. public:
  75.     const Color* color_;
  76.     const Brush* brush_;
  77.     const Font* font_;
  78. };
  79.  
  80. class PrinterRep {
  81. public:
  82.     ostream* out_;
  83.     int page_;
  84.     class PrinterInfoList* info_;
  85.  
  86.     float x_;
  87.     float y_;
  88.     Coord text_curx_;
  89.     Coord text_cury_;
  90.     int text_chars_;
  91.     int text_spaces_;
  92. };
  93.  
  94. declareList(PrinterInfoList,PrinterInfo);
  95. implementList(PrinterInfoList,PrinterInfo);
  96.  
  97. static void do_color(ostream& out, const Color* color) {
  98.     float r, g, b;
  99.     color->intensities(r, g, b);
  100.     out << r << " " << g << " " << b << " setrgbcolor\n";
  101. }
  102.  
  103. static void do_brush(ostream& out, const Brush* brush) {
  104.     Coord linewidth = brush->width();
  105.     out << linewidth << " setlinewidth\n";
  106. }
  107.  
  108. static void do_font(ostream& out, const Font* font) 
  109.     {
  110.     out << font->size() << " /";
  111.  
  112.     const char* p = font->name();
  113. /*** JJH Addition *****/
  114.     char   buf[100];
  115.     
  116.     if (strstr(p, "times") != NULL)
  117.        strcpy(buf, "Times-");    
  118.     else
  119.        strcpy(buf, "Courier-");    
  120.  
  121.     if (strstr(p, "bold") != NULL)
  122.        strcat(buf, "Bold");
  123.     else 
  124.        strcat(buf, "Roman");
  125.  
  126.     out << buf;
  127.     //JJH while (*p != '\0') {
  128.     //JJH     out << char(*p == ' ' ? '-' : *p);
  129.     //JJH     ++p;
  130.     //JJH }
  131.     out << " sf\n";
  132. }
  133.  
  134. Printer::Printer(ostream* out) {
  135.     PrinterRep* p = new PrinterRep;
  136.     rep_ = p;
  137.     p->out_ = out;
  138.     p->page_ = 1;
  139.     p->x_ = 0;
  140.     p->y_ = 0;
  141.     p->text_curx_ = 0;
  142.     p->text_cury_ = 0;
  143.     p->text_chars_ = 0;
  144.     p->text_spaces_ = 0;
  145.  
  146.     PrinterInfo info;
  147.     info.color_ = nil;
  148.     info.brush_ = nil;
  149.     info.font_ = nil;
  150.  
  151.     p->info_ = new PrinterInfoList();
  152.     p->info_->append(info);
  153. }
  154.  
  155. Printer::~Printer() {
  156.     flush();
  157.     delete rep_->info_;
  158.     delete rep_;
  159. }
  160.  
  161. void Printer::resize(Coord left, Coord bottom, Coord right, Coord top) {
  162.     PrinterRep* p = rep_;
  163.     ostream& out = *p->out_;
  164.     p->x_ = (float(left + right) - PAGE_WIDTH)/2;
  165.     p->y_ = (float(top + bottom) - PAGE_HEIGHT)/2;
  166.     flush();
  167.     size(right - left, top - bottom);
  168.     damage(left, bottom, right, top);
  169. }
  170.  
  171. void Printer::prolog(const char* creator) {
  172.     ostream& out = *rep_->out_;
  173.     out << "%!PS-Adobe-2.0\n";
  174.     out << "%%Creator: " << creator << "\n";
  175.     out << "%%Pages: atend\n";
  176.     out << "%%EndComments\n";
  177.     out << ps_prolog;
  178.     out << "%%EndProlog\n";
  179. }
  180.  
  181. void Printer::epilog () {
  182.     PrinterRep* p = rep_;
  183.     ostream& out = *p->out_;
  184.     flush();
  185.     out << "showpage\n";
  186.     out << "%%Trailer\n";
  187.     out << ps_epilog;
  188.     out << "%%Pages: " << p->page_ - 1 << "\n";
  189. }
  190.  
  191. void Printer::comment(const char* text) {
  192.     ostream& out = *rep_->out_;
  193.     flush();
  194.     out << "%% " << text << "\n";
  195. }
  196.  
  197. void Printer::page(const char* label) {
  198.     PrinterRep* p = rep_;
  199.     flush();
  200.     if (p->page_ > 1) {
  201.         *p->out_ << "showpage\n";
  202.     }
  203.     *p->out_ << "%%Page: " << label << " " << p->page_ << "\n";
  204.     *p->out_ << -(p->x_) << " " << -(p->y_) << " translate\n";
  205.     PrinterInfo& info = p->info_->item(p->info_->count() - 1);
  206.     info.font_ = nil;
  207.     info.color_ = nil;
  208.     info.brush_ = nil;
  209.     p->page_ += 1;
  210. }
  211.  
  212. void Printer::push_transform() {
  213.     Canvas::push_transform();
  214.     PrinterRep* p = rep_;
  215.     flush();
  216.     long depth = p->info_->count();
  217.     PrinterInfo info = p->info_->item(depth - 1);
  218.     p->info_->insert(depth, info);
  219.     *p->out_ << "gsave\n";
  220. }
  221.  
  222. void Printer::pop_transform() {
  223.     PrinterRep* p = rep_;
  224.     flush();
  225.     long depth = p->info_->count();
  226.     p->info_->remove(depth - 1);
  227.     *p->out_ << "grestore\n";
  228.     Canvas::pop_transform();
  229. }
  230.  
  231. void Printer::transform(const Transformer& t) {
  232.     Canvas::transform(t);
  233.     PrinterRep* p = rep_;
  234.     flush();
  235.     float a00, a01, a10, a11, a20, a21;
  236.     t.matrix(a00, a01, a10, a11, a20, a21);
  237.     *p->out_ << "[" << a00 << " " << a01;
  238.     *p->out_ << " " << a10 << " " << a11;
  239.     *p->out_ << " " << a20 << " " << a21 << "] concat\n";
  240. }
  241.  
  242. /*
  243.  * The current transform push/pop just saves and restores state,
  244.  * so we can use it for clipping as well.
  245.  */
  246.  
  247. void Printer::push_clipping() {
  248.     PrinterRep* p = rep_;
  249.     flush();
  250.     long depth = p->info_->count();
  251.     PrinterInfo info = p->info_->item(depth - 1);
  252.     p->info_->insert(depth, info);
  253.     *p->out_ << "gsave\n";
  254. }
  255.  
  256. void Printer::pop_clipping() {
  257.     PrinterRep* p = rep_;
  258.     flush();
  259.     long depth = p->info_->count();
  260.     p->info_->remove(depth - 1);
  261.     *p->out_ << "grestore\n";
  262. }
  263.  
  264. void Printer::new_path() {
  265.     ostream& out = *rep_->out_;
  266.     flush();
  267.     out << "newpath\n";
  268. }
  269.  
  270. void Printer::move_to(Coord x, Coord y) {
  271.     ostream& out = *rep_->out_;
  272.     flush();
  273.     out << x << " " << y << " moveto\n";
  274. }
  275.  
  276. void Printer::line_to(Coord x, Coord y) {
  277.     ostream& out = *rep_->out_;
  278.     flush();
  279.     out << x << " " << y << " lineto\n";
  280. }
  281.  
  282. void Printer::curve_to(
  283.     Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2
  284. ) {
  285.     ostream& out = *rep_->out_;
  286.     flush();
  287.     out << x1 << " " << y1 << " " << x2 << " " << y2 << " ";
  288.     out << x << " " << y << " curveto\n";
  289. }
  290.  
  291. void Printer::close_path() {
  292.     ostream& out = *rep_->out_;
  293.     flush();
  294.     out << "closepath\n";
  295. }
  296.  
  297. void Printer::stroke(const Color* color, const Brush* brush) {
  298.     PrinterRep* p = rep_;
  299.     ostream& out = *p->out_;
  300.     flush();
  301.     PrinterInfo& info = p->info_->item(p->info_->count() - 1);
  302.     if (info.color_ != color) {
  303.         do_color(out, color);
  304.         info.color_ = color;
  305.     }
  306.     if (info.brush_ != brush) {
  307.         do_brush(out, brush);
  308.         info.brush_ = brush;
  309.     }
  310.     out << "gsave stroke grestore\n";
  311. }
  312.  
  313. void Printer::fill(const Color* color) {
  314.     PrinterRep* p = rep_;
  315.     ostream& out = *p->out_;
  316.     flush();
  317.     PrinterInfo& info = p->info_->item(p->info_->count() - 1);
  318.     if (info.color_ != color) {
  319.         do_color(out, color);
  320.         info.color_ = color;
  321.     }
  322.     out << "gsave eofill grestore\n";
  323. }
  324.  
  325. void Printer::clip() {
  326.     ostream& out = *rep_->out_;
  327.     flush();
  328.     out << "gsave eoclip grestore\n";
  329. }
  330.  
  331. void Printer::character(
  332.     const Font* font, long c, Coord width, const Color* color, Coord x, Coord y
  333. ) {
  334.     PrinterRep* p = rep_;
  335.     ostream& out = *p->out_;
  336.     PrinterInfo& info = p->info_->item(p->info_->count() - 1);
  337.     if (info.color_ != color) {
  338.         flush();
  339.         do_color(out, color);
  340.         info.color_ = color;
  341.     }
  342.     if (!Math::equal(y, p->text_cury_, epsilon)) {
  343.         flush();
  344.     }
  345.     if (!Math::equal(x, p->text_curx_, epsilon)) {
  346.         flush();
  347.     }
  348.     if (info.font_ != font) {
  349.         flush();
  350.         do_font(out, font);
  351.         info.font_ = font;
  352.     }
  353.     if (p->text_chars_ == 0) {
  354.         out << x << " " << y << "(";
  355.     }
  356.     p->text_curx_ = x + width;
  357.     p->text_cury_ = y;
  358.     if (c == '\\' || c == ')' || c == '(') {
  359.         out << "\\" << char(c);
  360.     } else if (c > 127) {
  361.     out << "\\";
  362.         int old_width = out.width(3);
  363.         char old_fill = out.fill('0');
  364.         out << oct << c << dec;
  365.         out.width(old_width);
  366.         out.fill(old_fill);
  367.     } else {
  368.         out << char(c);
  369.     }
  370.     p->text_chars_ += 1;
  371.     if (c == ' ') {
  372.         p->text_spaces_ += 1;
  373.     }
  374. }
  375.  
  376. void Printer::flush() {
  377.     PrinterRep* p = rep_;
  378.     ostream& out = *p->out_;
  379.     if (p->text_chars_ > 0) {
  380.         out << ") ";
  381.         if (p->text_spaces_ > 0) {
  382.             out << p->text_spaces_ << " " << p->text_curx_ << " ws\n";
  383.         } else {
  384.             out << p->text_chars_ << " " << p->text_curx_ << " as\n";
  385.         }
  386.         p->text_chars_ = 0;
  387.         p->text_spaces_ = 0;
  388.     }
  389. }
  390.  
  391. void Printer::stencil(
  392.     const Bitmap* mask, const Color* color, Coord x, Coord y
  393. ) {
  394.     PrinterRep* p = rep_;
  395.     ostream& out = *p->out_;
  396.     flush();
  397.     PrinterInfo& info = p->info_->item(p->info_->count() - 1);
  398.     if (info.color_ != color) {
  399.         do_color(out, color);
  400.         info.color_ = color;
  401.     }
  402.     unsigned long width = mask->pwidth();
  403.     unsigned long height = mask->pheight();
  404.     unsigned long bytes = (width-1)/8 + 1;
  405.     Coord left = x - mask->left_bearing();
  406.     Coord right = x + mask->right_bearing();
  407.     Coord bottom = y - mask->descent();
  408.     Coord top = y + mask->ascent();
  409.     out << "gsave\n";
  410.     out << "/picstr " << bytes << " string def\n";
  411.     out << left << " " << bottom << "  translate\n";
  412.     out << right - left << " " << top - bottom << " scale\n";
  413.     out << width << " " << height << " true\n";
  414.     out << "[" << width << " 0 0 " << height << " 0 0]\n";
  415.     out << "{currentfile picstr readhexstring pop} imagemask\n";
  416.     int old_width = out.width(1);
  417.     out << hex;
  418.     for (int y = 0; y < height; ++y) {
  419.         for (int x = 0; x < bytes; ++x) {
  420.             int byte = 0;
  421.             for (int bit = 0; bit < 8; ++bit) {
  422.                 if (mask->peek(x*8 + bit, y)) {
  423.                     byte |= 0x80 >> bit;
  424.                 }
  425.             }
  426.             out << ((byte>>4) & 0x0f) <<  (byte & 0x0f);
  427.         }
  428.         out << "\n";
  429.     }
  430.     out << dec;
  431.     out.width(old_width);
  432.     out << "grestore\n";
  433. }
  434.  
  435. void Printer::image(const Raster* raster, Coord x, Coord y) {
  436.     PrinterRep* p = rep_;
  437.     ostream& out = *p->out_;
  438.     flush();
  439.     unsigned long width = raster->pwidth();
  440.     unsigned long height = raster->pheight();
  441.     float left = float(x) - raster->left_bearing();
  442.     float right = float(x) + raster->right_bearing();
  443.     float bottom = float(y) - raster->descent();
  444.     float top = float(y) + raster->ascent();
  445.     out << "gsave\n";
  446.     out << "/picstr " << width << " string def\n";
  447.     out << left << " " << bottom << "  translate\n";
  448.     out << right - left << " " << top - bottom << " scale\n";
  449.     out << width << " " << height << " 8\n";
  450.     out << "[" << width << " 0 0 " << height << " 0 0]\n";
  451.     out << "{currentfile picstr readhexstring pop} image\n";
  452.     int old_width = out.width(1);
  453.     out << hex;
  454.     for (int y = 0; y < height; ++y) {
  455.         for (int x = 0; x < width; ++x) {
  456.             float r, g, b, alpha;
  457.             raster->peek(x, y, r, g, b, alpha);
  458.             int byte = int(0xff * (r + g + b) / 3);
  459.             out << ((byte>>4) & 0x0f) <<  (byte & 0x0f);
  460.         }
  461.         out << "\n";
  462.     }
  463.     out << dec;
  464.     out.width(old_width);
  465.     out << "grestore\n";
  466. }
  467.