summaryrefslogtreecommitdiff
path: root/graphics/epix/samples/std_F.cc
blob: 9ccd7b90c6b1df40666ad95721b7ec787192e935 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* 
 * std_F.cc -- The std_F class definitions
 *
 * Last Change: September 23, 2007
 */
// Include only the headers we need; burdensome, but generally more
// efficient for larger projects with many dependencies.
#ifdef MINIMAL
#include "epix/affine.h"
#include "epix/Color.h"
#include "epix/curves.h"
#include "epix/pairs.h"
#include "epix/path.h"
#include "epix/state.h"
#include "epix/triples.h"

#else
#include "epix.h"
#endif

#include "epix/paint_style.h"
#include "std_F.h"

namespace ePiX {

  // The constructor initializes the class data, ensuring objects are
  // well-formed. For efficiency, we use "initialization" instead of
  // assignment (the "=" operator); this way, data members get their
  // actual values immediately. The constructor body is empty, since
  // this class requires no further initialization.

  // All class member function definitions must be qualified with the
  // class name, here "std_F::"
  std_F::std_F()
    : m_loc(0,0), m_e1(1,0), m_e2(0,1),
      m_fore(Black()), m_back(White()),
      m_edge(Black()), m_edge_width(0.4) { }

  // Apply the affine map af; return a reference to this object so
  // calls can be daisy-chained. Note the efficiency of storing only
  // the bare minimum data to specify an affine map rather than
  // holding and manipulating the shape of an F.
  std_F& std_F::map_by(const affine& af)
  {
    m_loc = af(m_loc); // affines map locations, so this works
    m_e1 = af(m_e1);
    m_e2 = af(m_e2);

    return *this;
  }

  // Set the background and foreground colors. Arguments' names chosen
  // to indicate their purpose.
  std_F& std_F::backing(const Color& back)
  {
    m_back = back;
    return *this;
  }

  std_F& std_F::fill(const Color& fore)
  {
    m_fore = fore;
    return *this;
  }

  // Set outline parameters.
  std_F& std_F::border(const Color& edge, double wid)
  {
    m_edge = edge;
    m_edge_width = wid;
    return *this;
  }

  // Draw in the active screen. Most of the "real work" is done here.
  void std_F::draw() const
  {
    // Get global drawing state, so we can restore before returning.
    // Not particularly elegant, but it's what we have to work with.
    Color old_fill(the_paint_style().fill_color());
    bool old_flag(the_paint_style().fill_flag());

    Color old_line(the_paint_style().line_color());
    length old_line_width(the_paint_style().line_width());

    // now we can draw
    const double r(1.0/6.0);

    path F;

    // pr converts coords in [0,1] x [0,1] to our coords
    F .pt(pr(r,   0.75*r)).pt(pr(2*r, 0.75*r)).pt(pr(2*r, 2.25*r))
      .pt(pr(4*r, 2.25*r)).pt(pr(4*r, 3.25*r)).pt(pr(2*r, 3.25*r))
      .pt(pr(2*r, 4.25*r)).pt(pr(5*r, 4.25*r)).pt(pr(5*r, 5.25*r))
      .pt(pr(  r, 5.25*r));

    F.close().fill();

    // Set global drawing state. We have a member function named fill,
    // so the call must be explicitly qualified with "ePiX::".
    ePiX::fill(m_back);
    ePiX::pen(m_edge, m_edge_width);

    // Bounding parallelogram
    ePiX::quad(pr(0,0), pr(1,0), pr(1,1), pr(0,1));

    ePiX::fill(m_fore);
    F.draw();
    // Restore global fill state.
    the_paint_style().fill_color(old_fill);
    the_paint_style().fill_flag(old_flag);

    the_paint_style().line_color(old_line);
    the_paint_style().line_width(old_line_width);
  }

  // private; convert (x,y) to a location usable in path construction
  // "Privacy" is enforced by the compiler from reading the header;
  // the definition requires no special syntax.
  P std_F::pr(double x, double y) const
  {
    pair loc((1 - x -y)*m_loc + x*m_e1 + y*m_e2);
    return P(loc.x1(), loc.x2());
  }
} // end of namespace