Panda3D

pnmPainter.cxx

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 }
 All Classes Functions Variables Enumerations