rect.cpp

Go to the documentation of this file.
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

Generated Fri Jul 28 19:23:00 2006.
Copyright © 1998-2003 by the respective authors.

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.