00001 /* 00002 libwt - Vassilis Virvilis Toolkit - a widget library 00003 Copyright (C) 2006 Vassilis Virvilis <vasvir2@fastmail.fm> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public 00007 License as published by the Free Software Foundation; either 00008 version 2.1 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public 00016 License along with this library; if not, write to the 00017 Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, SA. 00019 */ 00020 00021 #include <iostream> 00022 00023 #include <wt/rect.h> 00024 00025 namespace Wt { 00026 00027 Rect Rect::invalid = Rect(0, 0, -1, -1); 00028 Rect Rect::empty = Rect(0, 0, 0, 0); 00029 00030 Rect Rect::unite(const Rect &r) const { 00031 if(!isValid() || !r.isValid()) 00032 return invalid; 00033 00034 int min_x = std::min(left(), r.left()); 00035 int min_y = std::min(top(), r.top()); 00036 int max_x = std::max(right(), r.right()) + 1; 00037 int max_y = std::max(bottom(), r.bottom()) + 1; 00038 00039 assert(min_x <= max_x); 00040 assert(min_y <= max_y); 00041 00042 return Rect(min_x, min_y, max_x - min_x, max_y - min_y); 00043 } 00044 00045 /** 00046 * Returns an invalid rectangle if *this and r don't intersect 00047 **/ 00048 Rect Rect::intersect(const Rect &r) const { 00049 if(!isValid() || !r.isValid()) 00050 return invalid; 00051 00052 int min_x = std::max(left(), r.left()); 00053 int min_y = std::max(top(), r.top()); 00054 int max_x = std::min(right(), r.right()) + 1; 00055 int max_y = std::min(bottom(), r.bottom()) + 1; 00056 00057 if(min_x > max_x || min_y > max_y) 00058 return invalid; 00059 00060 return Rect(min_x, min_y, max_x - min_x, max_y - min_y); 00061 } 00062 00063 int Rect::borderCross(int x, int y) const { 00064 int border_cross = 0; 00065 00066 border_cross |= (x < left()) ? Left : 0; 00067 border_cross |= (x > right()) ? Right : 0; 00068 border_cross |= (y < top()) ? Top : 0; 00069 border_cross |= (y > bottom()) ? Bottom : 0; 00070 00071 return border_cross; 00072 } 00073 00074 bool Rect::clipLine(int& x1, int& y1, int& x2, int& y2) const { 00075 00076 int b1 = borderCross(x1, y1); 00077 int b2 = borderCross(x2, y2); 00078 00079 while (b1 || b2) { 00080 int b; 00081 int x, y; 00082 00083 if (b1 & b2) { 00084 // trivially reject 00085 return false; 00086 } else { 00087 b = (b1) ? b1 : b2; 00088 } 00089 00090 if (b & Left) { 00091 x = left(); 00092 y = y1 + (y2 - y1) * (x - x1) / (x2 - x1); 00093 } else if (b & Right) { 00094 x = right(); 00095 y = y1 + (y2 - y1) * (x - x1) / (x2 - x1); 00096 } else if (b & Top) { 00097 y = top(); 00098 x = x1 + (x2 - x1) * (y - y1) / (y2 - y1); 00099 } else { // if (b & Bottom) { 00100 y = bottom(); 00101 x = x1 + (x2 - x1) * (y - y1) / (y2 - y1); 00102 } 00103 00104 if (b == b1) { 00105 x1 = x; 00106 y1 = y; 00107 b1 = borderCross(x1, y1); 00108 } else { 00109 x2 = x; 00110 y2 = y; 00111 b2 = borderCross(x2, y2); 00112 } 00113 }; 00114 00115 return true; 00116 } 00117 00118 bool Rect::clipLine(Point& p1, Point& p2) const { 00119 int x1 = p1.x(); 00120 int y1 = p1.y(); 00121 int x2 = p2.x(); 00122 int y2 = p2.y(); 00123 bool clip = clipLine(x1, y1, x2, y2); 00124 p1.setX(x1); 00125 p1.setY(y1); 00126 p2.setX(x2); 00127 p2.setY(y2); 00128 return clip; 00129 } 00130 00131 Rect Rect::align(const Rect& container, const Size& size, int alignment) { 00132 int xc = 0, yc = 0; 00133 00134 if (alignment == AlignAuto) 00135 alignment = AlignCenter; 00136 else if (! (alignment & AlignHorizontal_Mask) ) 00137 alignment |= AlignHCenter; 00138 else if (! (alignment & AlignVertical_Mask) ) 00139 alignment |= AlignVCenter; 00140 00141 switch (alignment & AlignHorizontal_Mask) { 00142 case AlignLeft: 00143 xc = container.x(); 00144 break; 00145 case AlignRight: 00146 xc = container.x() + container.width() - size.width(); 00147 break; 00148 case AlignHCenter: 00149 xc = container.x() + ((container.width() - size.width()) >> 1); 00150 break; 00151 case AlignJustify: 00152 default: 00153 //Error("Unimplemented Alignment flag %d\n", alignment); 00154 return invalid; 00155 break; 00156 } 00157 00158 switch (alignment & AlignVertical_Mask) { 00159 case AlignTop: 00160 yc = container.y(); 00161 break; 00162 case AlignBottom: 00163 yc = container.y() + container.height() - size.height(); 00164 break; 00165 case AlignVCenter: 00166 yc = container.y() + ((container.height() - size.height()) >> 1); 00167 break; 00168 default: 00169 //Error("Unimplemented Alignment flag %d\n", alignment); 00170 return invalid; 00171 break; 00172 } 00173 00174 return Rect(xc, yc, size.width(), size.height()); 00175 } 00176 00177 std::ostream& operator<<(std::ostream& s, const Point& p) { 00178 s << "[" << p.x() << ", " << p.y() << "]"; 00179 return s; 00180 } 00181 00182 std::ostream& operator<<(std::ostream& s, const Size& size) { 00183 s << "[ " << size.width() << " x " << size.height() << " ]"; 00184 return s; 00185 } 00186 00187 std::ostream& operator<<(std::ostream& s, const Rect& r) { 00188 s << "(" << r.x() << "," << r.y() << "," << r.width() << "," << r.height() << ")"; 00189 return s; 00190 } 00191 00192 } // namespace Wt
This document is licensed under the terms of the GNU Free Documentation License and may be freely distributed under the conditions given by this license.