Home | History | Annotate | Download | only in gfx
      1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/gfx/rect.h"
      6 
      7 #if defined(OS_WIN)
      8 #include <windows.h>
      9 #elif defined(OS_MACOSX)
     10 #include <CoreGraphics/CGGeometry.h>
     11 #elif defined(OS_POSIX)
     12 #include <gdk/gdk.h>
     13 #endif
     14 
     15 #include <iostream>
     16 
     17 #include "base/logging.h"
     18 
     19 namespace {
     20 
     21 void AdjustAlongAxis(int dst_origin, int dst_size, int* origin, int* size) {
     22   if (*origin < dst_origin) {
     23     *origin = dst_origin;
     24     *size = std::min(dst_size, *size);
     25   } else {
     26     *size = std::min(dst_size, *size);
     27     *origin = std::min(dst_origin + dst_size, *origin + *size) - *size;
     28   }
     29 }
     30 
     31 } // namespace
     32 
     33 namespace gfx {
     34 
     35 Rect::Rect() {
     36 }
     37 
     38 Rect::Rect(int width, int height) {
     39   set_width(width);
     40   set_height(height);
     41 }
     42 
     43 Rect::Rect(int x, int y, int width, int height)
     44     : origin_(x, y) {
     45   set_width(width);
     46   set_height(height);
     47 }
     48 
     49 Rect::Rect(const gfx::Point& origin, const gfx::Size& size)
     50     : origin_(origin), size_(size) {
     51 }
     52 
     53 #if defined(OS_WIN)
     54 Rect::Rect(const RECT& r)
     55     : origin_(r.left, r.top) {
     56   set_width(r.right - r.left);
     57   set_height(r.bottom - r.top);
     58 }
     59 
     60 Rect& Rect::operator=(const RECT& r) {
     61   origin_.SetPoint(r.left, r.top);
     62   set_width(r.right - r.left);
     63   set_height(r.bottom - r.top);
     64   return *this;
     65 }
     66 #elif defined(OS_MACOSX)
     67 Rect::Rect(const CGRect& r)
     68     : origin_(r.origin.x, r.origin.y) {
     69   set_width(r.size.width);
     70   set_height(r.size.height);
     71 }
     72 
     73 Rect& Rect::operator=(const CGRect& r) {
     74   origin_.SetPoint(r.origin.x, r.origin.y);
     75   set_width(r.size.width);
     76   set_height(r.size.height);
     77   return *this;
     78 }
     79 #elif defined(OS_POSIX)
     80 Rect::Rect(const GdkRectangle& r)
     81     : origin_(r.x, r.y) {
     82   set_width(r.width);
     83   set_height(r.height);
     84 }
     85 
     86 Rect& Rect::operator=(const GdkRectangle& r) {
     87   origin_.SetPoint(r.x, r.y);
     88   set_width(r.width);
     89   set_height(r.height);
     90   return *this;
     91 }
     92 #endif
     93 
     94 void Rect::set_width(int width) {
     95   size_.set_width(width);
     96 }
     97 void Rect::set_height(int height) {
     98   size_.set_height(height);
     99 }
    100 
    101 void Rect::SetRect(int x, int y, int width, int height) {
    102   origin_.SetPoint(x, y);
    103   set_width(width);
    104   set_height(height);
    105 }
    106 
    107 void Rect::Inset(int left, int top, int right, int bottom) {
    108   Offset(left, top);
    109   set_width(std::max(width() - left - right, 0));
    110   set_height(std::max(height() - top - bottom, 0));
    111 }
    112 
    113 void Rect::Offset(int horizontal, int vertical) {
    114   set_x(x() + horizontal);
    115   set_y(y() + vertical);
    116 }
    117 
    118 bool Rect::operator==(const Rect& other) const {
    119   return origin_ == other.origin_ && size_ == other.size_;
    120 }
    121 
    122 #if defined(OS_WIN)
    123 RECT Rect::ToRECT() const {
    124   RECT r;
    125   r.left = x();
    126   r.right = right();
    127   r.top = y();
    128   r.bottom = bottom();
    129   return r;
    130 }
    131 #elif defined(OS_MACOSX)
    132 CGRect Rect::ToCGRect() const {
    133   return CGRectMake(x(), y(), width(), height());
    134 }
    135 #elif defined(OS_POSIX)
    136 GdkRectangle Rect::ToGdkRectangle() const {
    137   GdkRectangle r = {x(), y(), width(), height()};
    138   return r;
    139 }
    140 #endif
    141 
    142 bool Rect::Contains(int point_x, int point_y) const {
    143   return (point_x >= x()) && (point_x < right()) &&
    144          (point_y >= y()) && (point_y < bottom());
    145 }
    146 
    147 bool Rect::Contains(const Rect& rect) const {
    148   return (rect.x() >= x() && rect.right() <= right() &&
    149           rect.y() >= y() && rect.bottom() <= bottom());
    150 }
    151 
    152 bool Rect::Intersects(const Rect& rect) const {
    153   return !(rect.x() >= right() || rect.right() <= x() ||
    154            rect.y() >= bottom() || rect.bottom() <= y());
    155 }
    156 
    157 Rect Rect::Intersect(const Rect& rect) const {
    158   int rx = std::max(x(), rect.x());
    159   int ry = std::max(y(), rect.y());
    160   int rr = std::min(right(), rect.right());
    161   int rb = std::min(bottom(), rect.bottom());
    162 
    163   if (rx >= rr || ry >= rb)
    164     rx = ry = rr = rb = 0;  // non-intersecting
    165 
    166   return Rect(rx, ry, rr - rx, rb - ry);
    167 }
    168 
    169 Rect Rect::Union(const Rect& rect) const {
    170   // special case empty rects...
    171   if (IsEmpty())
    172     return rect;
    173   if (rect.IsEmpty())
    174     return *this;
    175 
    176   int rx = std::min(x(), rect.x());
    177   int ry = std::min(y(), rect.y());
    178   int rr = std::max(right(), rect.right());
    179   int rb = std::max(bottom(), rect.bottom());
    180 
    181   return Rect(rx, ry, rr - rx, rb - ry);
    182 }
    183 
    184 Rect Rect::Subtract(const Rect& rect) const {
    185   // boundary cases:
    186   if (!Intersects(rect))
    187     return *this;
    188   if (rect.Contains(*this))
    189     return Rect();
    190 
    191   int rx = x();
    192   int ry = y();
    193   int rr = right();
    194   int rb = bottom();
    195 
    196   if (rect.y() <= y() && rect.bottom() >= bottom()) {
    197     // complete intersection in the y-direction
    198     if (rect.x() <= x()) {
    199       rx = rect.right();
    200     } else {
    201       rr = rect.x();
    202     }
    203   } else if (rect.x() <= x() && rect.right() >= right()) {
    204     // complete intersection in the x-direction
    205     if (rect.y() <= y()) {
    206       ry = rect.bottom();
    207     } else {
    208       rb = rect.y();
    209     }
    210   }
    211   return Rect(rx, ry, rr - rx, rb - ry);
    212 }
    213 
    214 Rect Rect::AdjustToFit(const Rect& rect) const {
    215   int new_x = x();
    216   int new_y = y();
    217   int new_width = width();
    218   int new_height = height();
    219   AdjustAlongAxis(rect.x(), rect.width(), &new_x, &new_width);
    220   AdjustAlongAxis(rect.y(), rect.height(), &new_y, &new_height);
    221   return Rect(new_x, new_y, new_width, new_height);
    222 }
    223 
    224 Point Rect::CenterPoint() const {
    225   return Point(x() + (width() + 1) / 2, y() + (height() + 1) / 2);
    226 }
    227 
    228 bool Rect::SharesEdgeWith(const gfx::Rect& rect) const {
    229   return (y() == rect.y() && height() == rect.height() &&
    230              (x() == rect.right() || right() == rect.x())) ||
    231          (x() == rect.x() && width() == rect.width() &&
    232              (y() == rect.bottom() || bottom() == rect.y()));
    233 }
    234 
    235 }  // namespace gfx
    236 
    237 std::ostream& operator<<(std::ostream& out, const gfx::Rect& r) {
    238   return out << r.origin() << " " << r.size();
    239 }
    240