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 / docsup / IdrawImage.c < prev    next >
C/C++ Source or Header  |  1992-12-08  |  15KB  |  529 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.  * IdrawImage - read an idraw drawing from a file
  27.  */
  28.  
  29. #include "IdrawImage.h"
  30.  
  31. #include "Figure.h"
  32.  
  33. #include <InterViews/box.h>
  34. #include <InterViews/brush.h>
  35. #include <InterViews/character.h>
  36. #include <InterViews/color.h>
  37. #include <InterViews/fixedspan.h>
  38. #include <InterViews/font.h>
  39. #include <InterViews/psfont.h>
  40. #include <InterViews/shapeof.h>
  41. #include <InterViews/strut.h>
  42. #include <InterViews/tformsetter.h>
  43. #include <InterViews/transformer.h>
  44. #include <InterViews/world.h>
  45.  
  46. #include <string.h>
  47. #include <ctype.h>
  48.  
  49. static boolean _idraw_font_metrics;
  50.  
  51. char buffer[1000];
  52.  
  53. void skip (FILE* f) {
  54.     while (fscanf(f, "%s ", buffer) && strcmp(buffer, "%I") != 0) { }
  55. }
  56.  
  57. Brush* no_brush = (Brush*)-1;
  58.  
  59. class BrushInfo {
  60. public:
  61.     const Brush* _brush;
  62.     int _width;
  63.     int _pattern;
  64.     BrushInfo* _next;
  65. };
  66.  
  67. BrushInfo* _brushes;
  68. int _brush_count;
  69.  
  70. const Brush* read_brush (FILE* f) {
  71.     skip(f);
  72.     fscanf(f, "%s %s", buffer, buffer);
  73.     if (strcmp(buffer, "u") == 0) {
  74.         return nil;
  75.     } else if (strcmp(buffer, "n") == 0) {
  76.         return no_brush;
  77.     } else {
  78.         int pattern;
  79.         int width;
  80.         sscanf(buffer, "%d", &pattern);
  81.         fscanf(f, "%d", &width);
  82.  
  83.         BrushInfo* brush = _brushes;
  84.         while (
  85.             brush != nil
  86.             && (brush->_width != width || brush->_pattern != pattern)
  87.         ) {
  88.             brush = brush->_next;
  89.         }
  90.         if (brush == nil) {
  91.             brush = new BrushInfo;
  92.             brush->_brush = new Brush(pattern, Coord(width));
  93.             brush->_brush->ref();
  94.             brush->_width = width;
  95.             brush->_pattern = pattern;
  96.             brush->_next = _brushes;
  97.             _brushes = brush;
  98.             _brush_count += 1;
  99.         }
  100.         return brush->_brush;
  101.     }
  102. }
  103.  
  104. class ColorInfo {
  105. public:
  106.     const Color* _color;
  107.     float _r;
  108.     float _g;
  109.     float _b;
  110.     ColorInfo* _next;
  111. };
  112.  
  113. ColorInfo* _colors;
  114. int _color_count;
  115.  
  116. const Color* read_color (FILE* f) {
  117.     skip(f);
  118.     fscanf(f, "%s %s", buffer, buffer);
  119.     if (strcmp(buffer, "u") == 0) {
  120.         return nil;
  121.     } else {
  122.         float r, g, b;
  123.         fscanf(f, "%g %g %g", &r, &g, &b);
  124.  
  125.         ColorInfo* color = _colors;
  126.         while (
  127.             color != nil
  128.             && (color->_r != r || color->_g != g || color->_b != b)
  129.         ) {
  130.             color = color->_next;
  131.         }
  132.         if (color == nil) {
  133.             color = new ColorInfo;
  134.             color->_color = new Color(r, g, b);
  135.             color->_color->ref();
  136.             color->_r = r;
  137.             color->_g = g;
  138.             color->_b = b;
  139.             color->_next = _colors;
  140.             _colors = color;
  141.             _color_count += 1;
  142.         }
  143.         return color->_color;
  144.     }
  145. }
  146.  
  147. const Color* dither_color (const Color* f, const Color* b, float dither) {
  148.     float fr, fg, fb;
  149.     float br, bg, bb;
  150.     f->intensities(fr, fg, fb);
  151.     b->intensities(br, bg, bb);
  152.     float red = (1 - dither) * fr + dither * br;
  153.     float green = (1 - dither) * fg + dither * bg;
  154.     float blue = (1 - dither) * fb + dither * bb;
  155.  
  156.     ColorInfo* color = _colors;
  157.     while (
  158.         color != nil
  159.         && (color->_r != red || color->_g != green || color->_b != blue)
  160.     ) {
  161.         color = color->_next;
  162.     }
  163.     if (color == nil) {
  164.         color = new ColorInfo;
  165.         color->_color = new Color(red, green, blue);
  166.         color->_color->ref();
  167.         color->_r = red;
  168.         color->_g = green;
  169.         color->_b = blue;
  170.         color->_next = _colors;
  171.         _colors = color;
  172.         _color_count += 1;
  173.     }
  174.     return color->_color;
  175. }
  176.  
  177. class FontInfo {
  178. public:
  179.     const Font* _font;
  180.     const char* _screenname;
  181.     const char* _psname;
  182.     float _pointsize;
  183.     FontInfo* _next;
  184. };
  185.  
  186. FontInfo* _fonts;
  187. int _font_count;
  188.  
  189. const Font* read_font (FILE* f) {
  190.     skip(f);
  191.     fscanf(f, "%s %s", buffer, buffer);
  192.     if (strcmp(buffer, "u") == 0) {
  193.         return nil;
  194.     } else {
  195.         char psname[256];
  196.         float pointsize;
  197.         fscanf(f, "%s %g", psname, &pointsize);
  198.         FontInfo* font = _fonts;
  199.         while (font != nil && (strcmp(font->_screenname, buffer) != 0)) {
  200.             font = font->_next;
  201.         }
  202.         if (font == nil) {
  203.         World* w = World::current();
  204.             font = new FontInfo;
  205.             if (_idraw_font_metrics) {
  206.         if (Font::exists(w->display(), buffer)) {
  207.                     font->_font = new Font(buffer);
  208.                 } else {
  209.                     font->_font = w->font();
  210.                 }
  211.             } else {
  212.         if (PSFont::exists(psname)) {
  213.                     font->_font = new PSFont(psname, pointsize, buffer, 1.0);
  214.                 } else {
  215.             font->_font = w->font();
  216.                 }
  217.             }
  218.             font->_font->ref();
  219.             font->_screenname = strcpy(new char[strlen(buffer) + 1], buffer);
  220.             font->_psname = strcpy(new char[strlen(psname) + 1], psname);
  221.             font->_pointsize = pointsize;
  222.             font->_next = _fonts;
  223.             _fonts = font;
  224.             _font_count += 1;
  225.         }
  226.         return font->_font;
  227.     }
  228. }
  229.  
  230. float pointsize (const Font* f) {
  231.     FontInfo* font = _fonts;
  232.     while (font != nil && font->_font != f) {
  233.         font = font->_next;
  234.     }
  235.     if (font != nil) {
  236.         return font->_pointsize;
  237.     } else {
  238.         return 0;
  239.     }
  240. }
  241.  
  242. class Stipple : public Resource {
  243. public:
  244.     Stipple (float dither);
  245.  
  246.     float _dither;
  247. protected:
  248.     virtual ~Stipple ();
  249. };
  250.  
  251. Stipple::Stipple (float dither) {
  252.     _dither = dither;
  253. }
  254.  
  255. Stipple::~Stipple () { }
  256.  
  257. class StippleInfo {
  258. public:
  259.     Stipple* _stipple;
  260.     StippleInfo* _next;
  261. };
  262.  
  263. StippleInfo* _stipples;
  264. int _stipple_count;
  265.  
  266. Stipple* no_stipple = (Stipple*) -1;
  267.  
  268. Stipple* read_stipple (FILE* file) {
  269.     skip(file);
  270.     fscanf(file, "%s %s", buffer, buffer);
  271.     if (strcmp(buffer, "u") == 0) {
  272.         return nil;
  273.     } else if (strcmp(buffer, "n") == 0) {
  274.         return no_stipple;
  275.     } else {
  276.         float dither;
  277.         sscanf(buffer, "%f", &dither);
  278.         StippleInfo* stipple = _stipples;
  279.         while (
  280.             stipple != nil
  281.             && stipple->_stipple->_dither != dither
  282.         ) {
  283.             stipple = stipple->_next;
  284.         }
  285.         if (stipple == nil) {
  286.             stipple = new StippleInfo;
  287.             stipple->_stipple = new Stipple(dither);
  288.             stipple->_stipple->ref();
  289.             stipple->_next = _stipples;
  290.             _stipples = stipple;
  291.             _stipple_count += 1;
  292.         }
  293.         return stipple->_stipple;
  294.     }
  295. }
  296.  
  297. void read_transformer (FILE* f, Transformer& t) {
  298.     skip(f);
  299.     fscanf(f, "%s %s", buffer, buffer);
  300.     if (strcmp(buffer, "u") != 0) {
  301.         float a00, a01, a10, a11, a20, a21;
  302.         fscanf(
  303.             f, "%f %f %f %f %f %f",
  304.             &a00, &a01, &a10, &a11, &a20, &a21
  305.         );
  306.         Transformer tt(a00, a01, a10, a11, a20, a21);
  307.         t = tt;
  308.     }
  309. }
  310.  
  311. struct figure {
  312.     const char* name;
  313.     boolean brush;
  314.     boolean foreground;
  315.     boolean background;
  316.     boolean font;
  317.     boolean pattern;
  318.     boolean transformer;
  319.     int coords;
  320.     int skip;
  321. };
  322.     
  323. figure early_version_figures[] = {
  324.     {"Idraw", 1, 1, 1, 1, 1, 1, 0, 0},
  325.     {"BSpl",  1, 1, 1, 0, 1, 1, -1, 0},
  326.     {"Circ",  1, 1, 1, 0, 1, 1, 1, 0},
  327.     {"CBSpl", 1, 1, 1, 0, 1, 1, -1, 0},
  328.     {"Elli",  1, 1, 1, 0, 1, 1, 1, 0},
  329.     {"Line",  1, 1, 1, 0, 1, 1, 2, 0},
  330.     {"MLine", 1, 1, 1, 0, 1, 1, -1, 0},
  331.     {"Pict",  1, 1, 1, 1, 1, 1, 0, 0},
  332.     {"Poly",  1, 1, 1, 0, 1, 1, -1, 0},
  333.     {"Rect",  1, 1, 1, 0, 1, 1, 2, 0},
  334.     {"Text", 0, 1, 0, 1, 0, 1, 0, 0},
  335.     {"eop",  0, 0, 0, 0, 0, 0, 0, 0},
  336.     {nil, 0, 0, 0, 0, 0, 0, 0}
  337. };
  338.  
  339. figure version_10_figures[] = {
  340.     {"Idraw", 1, 1, 1, 1, 1, 1, 0, 0},
  341.     {"BSpl",  1, 1, 1, 0, 1, 1, -1, 1},
  342.     {"Circ",  1, 1, 1, 0, 1, 1, 1, 0},
  343.     {"CBSpl", 1, 1, 1, 0, 1, 1, -1, 0},
  344.     {"Elli",  1, 1, 1, 0, 1, 1, 1, 0},
  345.     {"Line",  1, 1, 1, 0, 1, 1, 2, 1},
  346.     {"MLine", 1, 1, 1, 0, 1, 1, -1, 1},
  347.     {"Pict",  1, 1, 1, 1, 1, 1, 0, 0},
  348.     {"Poly",  1, 1, 1, 0, 1, 1, -1, 0},
  349.     {"Rect",  1, 1, 1, 0, 1, 1, 2, 0},
  350.     {"Text", 0, 1, 0, 1, 0, 1, 0, 0},
  351.     {"eop",  0, 0, 0, 0, 0, 0, 0, 0},
  352.     {nil, 0, 0, 0, 0, 0, 0, 0, 0}
  353. };
  354.  
  355. static int drawing_version;
  356.  
  357. figure* versions[] = {
  358.     early_version_figures,
  359.     early_version_figures,
  360.     early_version_figures,
  361.     early_version_figures,
  362.     early_version_figures,
  363.     early_version_figures,
  364.     early_version_figures,
  365.     early_version_figures,
  366.     early_version_figures,
  367.     early_version_figures,
  368.     version_10_figures,
  369.     nil
  370. };
  371.  
  372. static figure* figures = versions[0];
  373.  
  374. int which (figure* figures, const char* name) {
  375.     int i = 0;
  376.     while (figures[i].name != nil && strcmp(figures[i].name, name) != 0) {
  377.         ++i;
  378.     }
  379.     return i;
  380. }
  381.  
  382. const float fixtextscale = 75.0 / 72.0;
  383.  
  384. Glyph* read_idraw_graphic (
  385.     FILE* file, const Brush* pb, const Color* pfg, const Color* pbg,
  386.     const Font* pf, Stipple* ps
  387. ) {
  388.     skip(file);
  389.     Transformer tx;
  390.     Glyph* glyph = nil;
  391.     if (fscanf(file, "%s", buffer) != EOF) {
  392.         figure& fig = figures[which(figures, buffer)];
  393.  
  394.         if (strcmp(fig.name, "Idraw") == 0) {
  395.             fscanf(file, "%d", &drawing_version);
  396.             figures = versions[drawing_version];
  397.         }
  398.         const Brush* b = (fig.brush) ? read_brush(file) : nil;
  399.         const Color* fg = (fig.foreground) ? read_color(file) : nil;
  400.         const Color* bg = (fig.background) ? read_color(file) : nil;
  401.         const Font* f = (fig.font) ? read_font(file) : nil;
  402.         Stipple* s = (fig.pattern) ? read_stipple(file) : nil;
  403.         if (fig.transformer) {
  404.             read_transformer(file, tx);
  405.         }
  406.  
  407.         if (pb) b = pb;
  408.         if (pfg) fg = pfg;
  409.         if (pbg) bg = pbg;
  410.         if (pf) f = pf;
  411.         if (ps) s = ps;
  412.  
  413.         if (fig.name == nil) {
  414.             ; // error
  415.         } else if (
  416.             strcmp(fig.name, "Idraw") == 0 || strcmp(fig.name, "Pict") == 0
  417.         ) {
  418.             Glyph* pic = new Overlay();
  419.             Glyph* g;
  420.             do {
  421.                 g = read_idraw_graphic(file, b, fg, bg, f, s);
  422.                 if (g != nil) {
  423.                     pic->append(g);
  424.                 }
  425.             } while (g != nil);
  426.             glyph = pic;
  427.         } else if (strcmp(fig.name, "eop") == 0) {
  428.             glyph = nil;
  429.         } else if (strcmp(fig.name, "Text") == 0) {
  430.             skip(file);
  431.             fscanf(file, "%s", buffer);
  432.             getc(file);
  433.             TBBox* col = new TBBox();
  434.             LRBox* line = new LRBox();
  435.             Coord lineheight = pointsize(f);
  436.             if (_idraw_font_metrics) {
  437.                 lineheight = lineheight/fixtextscale;
  438.             }
  439.             int c;
  440.             while ((c = getc(file)) != ']') {
  441.                 if (c == '\n') {
  442.                     line->append(new Strut(f));
  443.                     col->append(new FixedSpan(line, Dimension_Y, lineheight));
  444.                     line = new LRBox();
  445.                 } else if (c == ' ') {
  446.                     if (_idraw_font_metrics) {
  447.                         line->append(new ShapeOf(new Character(' ', f, fg)));
  448.                     } else {
  449.                         line->append(new Character(' ', f, fg));
  450.                     }
  451.                 } else if (c != ')' && c != '(') {
  452.                     if (c == '\\') {
  453.                         c = getc(file);
  454.             if (isdigit(c)) {
  455.                 c -= '0';
  456.                 c = (c * 8) + getc(file) - '0';
  457.                 c = (c * 8) + getc(file) - '0';
  458.             }
  459.                     }
  460.                     line->append(new Character(c, f, fg));
  461.                 }
  462.             }
  463.             Transformer fixtext;
  464.             if (_idraw_font_metrics) {
  465.                 fixtext.scale(fixtextscale, fixtextscale);
  466.             }
  467.             fixtext.translate(0, f->descent() - lineheight);
  468.             glyph = new TransformSetter(col, fixtext);
  469.         } else {
  470.             skip(file);
  471.             int c = fig.coords;
  472.             if (c == -1) { 
  473.                 fscanf(file, "%d", &c);
  474.             }
  475.             Coord xx, yy;
  476.             Coord* x = new Coord[c];
  477.             Coord* y = new Coord[c];
  478.             for (int i = 0; i < c; ++i) {
  479.                 fscanf(file, "%g %g", &xx, &yy);
  480.                 x[i] = xx;
  481.                 y[i] = yy;
  482.             }
  483.  
  484.             const Brush* brush = (b != no_brush) ? b : nil;
  485.             const Color* stroke = fg;
  486.             const Color* fill = (
  487.                 (s != no_stipple) ? dither_color(fg, bg, s->_dither) : nil
  488.             );
  489.             if (strcmp(fig.name, "Line") == 0) {
  490.                 glyph = new Line(brush, stroke, fill, x[0], y[0], x[1], y[1]);
  491.             } else if (strcmp(fig.name, "BSpl") == 0) {
  492.                 glyph = new Open_BSpline(brush, stroke, fill, x, y, c);
  493.             } else if (strcmp(fig.name, "CBSpl") == 0) {
  494.                 glyph = new Closed_BSpline(brush, stroke, fill, x, y, c);
  495.             } else if (strcmp(fig.name, "MLine") == 0) {
  496.                 glyph = new Polyline(brush, stroke, fill, x, y, c);
  497.             } else if (strcmp(fig.name, "Poly") == 0) {
  498.                 glyph = new Polygon(brush, stroke, fill, x, y, c);
  499.             } else if (strcmp(fig.name, "Rect") == 0) {
  500.                 glyph = new Rectangle(brush, stroke, fill,x[0],y[0],x[1],y[1]);
  501.             } else if (strcmp(fig.name, "Circ") == 0) {
  502.                 fscanf(file, "%f", &xx);
  503.                 glyph = new Circle(brush, stroke, fill, x[0], y[0], xx);
  504.             } else if (strcmp(fig.name, "Elli") == 0) {
  505.                 fscanf(file, "%f %f", &xx, &yy);
  506.                 glyph = new Ellipse(brush, stroke, fill, x[0], y[0], xx, yy);
  507.             } else {
  508.                 glyph = nil;
  509.             }
  510.             delete x;
  511.             delete y;
  512.         }
  513.         for (int extra = fig.skip; extra > 0; --extra) {
  514.             skip(file);
  515.         }
  516.     }
  517.     if (glyph != nil && !tx.identity()) {
  518.         glyph = new TransformSetter(glyph, tx);
  519.     }
  520.     return glyph;
  521. }
  522.  
  523. IdrawImage::IdrawImage(FILE* file, boolean idraw_font_metrics) {
  524.     _idraw_font_metrics = idraw_font_metrics;
  525.     body(read_idraw_graphic(file, nil, nil, nil, nil, nil));
  526. }
  527.  
  528. IdrawImage::~IdrawImage() { }
  529.