Panda3D
|
00001 // Filename: pnmPainter.cxx 00002 // Created by: drose (02Feb07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "pnmPainter.h" 00016 #include "pnmBrush.h" 00017 00018 //////////////////////////////////////////////////////////////////// 00019 // Function: PNMPainter::Constructor 00020 // Access: Published 00021 // Description: The constructor stores a pointer to the PNMImage you 00022 // pass it, but it does not take ownership of the 00023 // object; you are responsible for ensuring that the 00024 // PNMImage does not destruct during the lifetime of the 00025 // PNMPainter object. 00026 // 00027 // The xo, yo coordinates specify an optional offset for 00028 // fill coordinates. If you are painting with a pattern 00029 // fill, these specify the virtual coordinates of the 00030 // upper-left corner of the image, which can allow you 00031 // to adjust the pattern to line up with nested images, 00032 // if necessary. 00033 //////////////////////////////////////////////////////////////////// 00034 PNMPainter:: 00035 PNMPainter(PNMImage &image, int xo, int yo) : 00036 _image(image), 00037 _xo(xo), _yo(yo) 00038 { 00039 _pen = PNMBrush::make_pixel(LColord(0, 0, 0, 1)); 00040 _fill = PNMBrush::make_pixel(LColord(1, 1, 1, 1)); 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: PNMPainter::draw_line 00045 // Access: Published 00046 // Description: Draws an antialiased line on the PNMImage, using the 00047 // current pen. 00048 //////////////////////////////////////////////////////////////////// 00049 void PNMPainter:: 00050 draw_line(double xa, double ya, double xb, double yb) { 00051 // Shift the line coordinates to position the center of the pen on 00052 // the line. 00053 xa -= (_pen->get_xc() - 0.5); 00054 xb -= (_pen->get_xc() - 0.5); 00055 ya -= (_pen->get_yc() - 0.5); 00056 yb -= (_pen->get_yc() - 0.5); 00057 00058 // Compute the line delta. 00059 double xd = xb - xa; 00060 double yd = yb - ya; 00061 00062 if (xa == xb && ya == yb) { 00063 // Just a single point. Treat it as a very short horizontal line. 00064 xd = 1.0; 00065 } 00066 00067 if (cabs(xd) > cabs(yd)) { 00068 // This line is more horizontal than vertical. 00069 if (xa < xb) { 00070 // Draw the line from left to right. 00071 int x_min = (int)cfloor(xa); 00072 int x_max = (int)cceil(xb); 00073 00074 // The first point. 00075 draw_hline_point(x_min, xa, ya, xd, yd, 1.0 - (xa - x_min)); 00076 00077 // The middle points. 00078 for (int x = x_min + 1; x < x_max; ++x) { 00079 draw_hline_point(x, xa, ya, xd, yd, 1.0); 00080 } 00081 00082 if (x_max != x_min) { 00083 // The last point. 00084 draw_hline_point(x_max, xa, ya, xd, yd, 1.0 - (x_max - xb)); 00085 } 00086 00087 } else { 00088 // Draw the line from right to left. 00089 int x_min = (int)cfloor(xb); 00090 int x_max = (int)cceil(xa); 00091 00092 // The first point. 00093 draw_hline_point(x_max, xa, ya, xd, yd, 1.0 - (x_max - xa)); 00094 00095 // The middle points. 00096 for (int x = x_max - 1; x > x_min; --x) { 00097 draw_hline_point(x, xa, ya, xd, yd, 1.0); 00098 } 00099 00100 if (x_max != x_min) { 00101 // The last point. 00102 draw_hline_point(x_min, xa, ya, xd, yd, 1.0 - (xb - x_min)); 00103 } 00104 } 00105 00106 } else { 00107 // This line is more vertical than horizontal. 00108 if (ya < yb) { 00109 // Draw the line from top to bottom. 00110 int y_min = (int)cfloor(ya); 00111 int y_max = (int)cceil(yb); 00112 00113 // The first point. 00114 draw_vline_point(y_min, xa, ya, xd, yd, 1.0 - (ya - y_min)); 00115 00116 // The middle points. 00117 for (int y = y_min + 1; y < y_max; ++y) { 00118 draw_vline_point(y, xa, ya, xd, yd, 1.0); 00119 } 00120 00121 if (y_max != y_min) { 00122 // The last point. 00123 draw_vline_point(y_max, xa, ya, xd, yd, 1.0 - (y_max - yb)); 00124 } 00125 00126 } else { 00127 // Draw the line from bottom to top. 00128 int y_min = (int)cfloor(yb); 00129 int y_max = (int)cceil(ya); 00130 00131 // The first point. 00132 draw_vline_point(y_max, xa, ya, xd, yd, 1.0 - (y_max - ya)); 00133 00134 // The middle points. 00135 for (int y = y_max - 1; y > y_min; --y) { 00136 draw_vline_point(y, xa, ya, xd, yd, 1.0); 00137 } 00138 00139 if (y_max != y_min) { 00140 // The last point. 00141 draw_vline_point(y_min, xa, ya, xd, yd, 1.0 - (yb - y_min)); 00142 } 00143 } 00144 } 00145 } 00146 00147 //////////////////////////////////////////////////////////////////// 00148 // Function: PNMPainter::draw_rectangle 00149 // Access: Published 00150 // Description: Draws a filled rectangule on the PNMImage, using the 00151 // current pen for the outline, and the current fill 00152 // brush for the interior. 00153 // 00154 // The two coordinates specify any two diagonally 00155 // opposite corners. 00156 //////////////////////////////////////////////////////////////////// 00157 void PNMPainter:: 00158 draw_rectangle(double xa, double ya, double xb, double yb) { 00159 // Make (xa, ya) be the upper-left corner, and (xb, yb) the 00160 // lower-right. 00161 if (xa > xb) { 00162 double t = xa; 00163 xa = xb; 00164 xb = t; 00165 } 00166 if (ya > yb) { 00167 double t = ya; 00168 ya = yb; 00169 yb = t; 00170 } 00171 00172 // First, fill the interior. 00173 int x_min = (int)cceil(xa); 00174 int x_max = (int)cfloor(xb); 00175 int y_min = (int)cceil(ya); 00176 int y_max = (int)cfloor(yb); 00177 for (int y = y_min; y <= y_max; ++y) { 00178 _fill->fill(_image, x_min, x_max, y, _xo, _yo); 00179 } 00180 00181 // Then, draw the outline. 00182 draw_line(xa, ya, xa, yb); 00183 draw_line(xa, yb, xb, yb); 00184 draw_line(xb, yb, xb, ya); 00185 draw_line(xb, ya, xa, ya); 00186 }