Panda3D
pnmPainter.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pnmPainter.cxx
10  * @author drose
11  * @date 2007-02-02
12  */
13 
14 #include "pnmPainter.h"
15 
16 /**
17  * The constructor stores a pointer to the PNMImage you pass it, but it does
18  * not take ownership of the object; you are responsible for ensuring that the
19  * PNMImage does not destruct during the lifetime of the PNMPainter object.
20  *
21  * The xo, yo coordinates specify an optional offset for fill coordinates. If
22  * you are painting with a pattern fill, these specify the virtual coordinates
23  * of the upper-left corner of the image, which can allow you to adjust the
24  * pattern to line up with nested images, if necessary.
25  */
27 PNMPainter(PNMImage &image, int xo, int yo) :
28  _image(image),
29  _xo(xo), _yo(yo)
30 {
31  _pen = PNMBrush::make_pixel(LColorf(0, 0, 0, 1));
32  _fill = PNMBrush::make_pixel(LColorf(1, 1, 1, 1));
33 }
34 
35 /**
36  * Draws an antialiased line on the PNMImage, using the current pen.
37  */
38 void PNMPainter::
39 draw_line(float xa, float ya, float xb, float yb) {
40  // Shift the line coordinates to position the center of the pen on the line.
41  xa -= (_pen->get_xc() - 0.5);
42  xb -= (_pen->get_xc() - 0.5);
43  ya -= (_pen->get_yc() - 0.5);
44  yb -= (_pen->get_yc() - 0.5);
45 
46  // Compute the line delta.
47  float xd = xb - xa;
48  float yd = yb - ya;
49 
50  if (xa == xb && ya == yb) {
51  // Just a single point. Treat it as a very short horizontal line.
52  xd = 1.0;
53  }
54 
55  if (cabs(xd) > cabs(yd)) {
56  // This line is more horizontal than vertical.
57  if (xa < xb) {
58  // Draw the line from left to right.
59  int x_min = (int)cfloor(xa);
60  int x_max = (int)cceil(xb);
61 
62  // The first point.
63  draw_hline_point(x_min, xa, ya, xd, yd, 1.0 - (xa - x_min));
64 
65  // The middle points.
66  for (int x = x_min + 1; x < x_max; ++x) {
67  draw_hline_point(x, xa, ya, xd, yd, 1.0);
68  }
69 
70  if (x_max != x_min) {
71  // The last point.
72  draw_hline_point(x_max, xa, ya, xd, yd, 1.0 - (x_max - xb));
73  }
74 
75  } else {
76  // Draw the line from right to left.
77  int x_min = (int)cfloor(xb);
78  int x_max = (int)cceil(xa);
79 
80  // The first point.
81  draw_hline_point(x_max, xa, ya, xd, yd, 1.0 - (x_max - xa));
82 
83  // The middle points.
84  for (int x = x_max - 1; x > x_min; --x) {
85  draw_hline_point(x, xa, ya, xd, yd, 1.0);
86  }
87 
88  if (x_max != x_min) {
89  // The last point.
90  draw_hline_point(x_min, xa, ya, xd, yd, 1.0 - (xb - x_min));
91  }
92  }
93 
94  } else {
95  // This line is more vertical than horizontal.
96  if (ya < yb) {
97  // Draw the line from top to bottom.
98  int y_min = (int)cfloor(ya);
99  int y_max = (int)cceil(yb);
100 
101  // The first point.
102  draw_vline_point(y_min, xa, ya, xd, yd, 1.0 - (ya - y_min));
103 
104  // The middle points.
105  for (int y = y_min + 1; y < y_max; ++y) {
106  draw_vline_point(y, xa, ya, xd, yd, 1.0);
107  }
108 
109  if (y_max != y_min) {
110  // The last point.
111  draw_vline_point(y_max, xa, ya, xd, yd, 1.0 - (y_max - yb));
112  }
113 
114  } else {
115  // Draw the line from bottom to top.
116  int y_min = (int)cfloor(yb);
117  int y_max = (int)cceil(ya);
118 
119  // The first point.
120  draw_vline_point(y_max, xa, ya, xd, yd, 1.0 - (y_max - ya));
121 
122  // The middle points.
123  for (int y = y_max - 1; y > y_min; --y) {
124  draw_vline_point(y, xa, ya, xd, yd, 1.0);
125  }
126 
127  if (y_max != y_min) {
128  // The last point.
129  draw_vline_point(y_min, xa, ya, xd, yd, 1.0 - (yb - y_min));
130  }
131  }
132  }
133 }
134 
135 /**
136  * Draws a filled rectangule on the PNMImage, using the current pen for the
137  * outline, and the current fill brush for the interior.
138  *
139  * The two coordinates specify any two diagonally opposite corners.
140  */
141 void PNMPainter::
142 draw_rectangle(float xa, float ya, float xb, float yb) {
143  // Make (xa, ya) be the upper-left corner, and (xb, yb) the lower-right.
144  if (xa > xb) {
145  float t = xa;
146  xa = xb;
147  xb = t;
148  }
149  if (ya > yb) {
150  float t = ya;
151  ya = yb;
152  yb = t;
153  }
154 
155  // First, fill the interior.
156  int x_min = (int)cceil(xa);
157  int x_max = (int)cfloor(xb);
158  int y_min = (int)cceil(ya);
159  int y_max = (int)cfloor(yb);
160  for (int y = y_min; y <= y_max; ++y) {
161  _fill->fill(_image, x_min, x_max, y, _xo, _yo);
162  }
163 
164  // Then, draw the outline.
165  draw_line(xa, ya, xa, yb);
166  draw_line(xa, yb, xb, yb);
167  draw_line(xb, yb, xb, ya);
168  draw_line(xb, ya, xa, ya);
169 }
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
Definition: pnmImage.h:58
PNMPainter(PNMImage &image, int xo=0, int yo=0)
The constructor stores a pointer to the PNMImage you pass it, but it does not take ownership of the o...
Definition: pnmPainter.cxx:27
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void draw_line(float xa, float ya, float xb, float yb)
Draws an antialiased line on the PNMImage, using the current pen.
Definition: pnmPainter.cxx:39
void draw_rectangle(float xa, float ya, float xb, float yb)
Draws a filled rectangule on the PNMImage, using the current pen for the outline, and the current fil...
Definition: pnmPainter.cxx:142