BaseMargin.h (5501B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MOZILLA_GFX_BASEMARGIN_H_ 8 #define MOZILLA_GFX_BASEMARGIN_H_ 9 10 #include <ostream> 11 12 #include "Types.h" 13 14 namespace mozilla { 15 16 /** 17 * Sides represents a set of physical sides. 18 */ 19 struct Sides final { 20 Sides() : mBits(SideBits::eNone) {} 21 explicit Sides(SideBits aSideBits) { 22 MOZ_ASSERT((aSideBits & ~SideBits::eAll) == SideBits::eNone, 23 "illegal side bits"); 24 mBits = aSideBits; 25 } 26 bool IsEmpty() const { return mBits == SideBits::eNone; } 27 bool Intersects(SideBits aSideBits) const { return bool(mBits & aSideBits); } 28 bool Top() const { return Intersects(SideBits::eTop); } 29 bool Right() const { return Intersects(SideBits::eRight); } 30 bool Bottom() const { return Intersects(SideBits::eBottom); } 31 bool Left() const { return Intersects(SideBits::eLeft); } 32 bool Contains(SideBits aSideBits) const { 33 MOZ_ASSERT(!(aSideBits & ~SideBits::eAll), "illegal side bits"); 34 return (mBits & aSideBits) == aSideBits; 35 } 36 Sides operator|(Sides aOther) const { 37 return Sides(SideBits(mBits | aOther.mBits)); 38 } 39 Sides operator|(SideBits aSideBits) const { return *this | Sides(aSideBits); } 40 Sides& operator|=(Sides aOther) { 41 mBits |= aOther.mBits; 42 return *this; 43 } 44 Sides& operator|=(SideBits aSideBits) { return *this |= Sides(aSideBits); } 45 bool operator==(Sides aOther) const { return mBits == aOther.mBits; } 46 bool operator!=(Sides aOther) const { return !(*this == aOther); } 47 48 private: 49 SideBits mBits; 50 }; 51 52 namespace gfx { 53 54 /** 55 * Do not use this class directly. Subclass it, pass that subclass as the 56 * Sub parameter, and only use that subclass. 57 */ 58 template <class T, class Sub, class Coord = T> 59 struct BaseMargin { 60 typedef mozilla::Side SideT; // because we have a method named Side 61 62 // Do not change the layout of these members; the Side() methods below 63 // depend on this order. 64 Coord top, right, bottom, left; 65 66 // Constructors 67 constexpr BaseMargin() : top(0), right(0), bottom(0), left(0) {} 68 constexpr BaseMargin(Coord aTop, Coord aRight, Coord aBottom, Coord aLeft) 69 : top(aTop), right(aRight), bottom(aBottom), left(aLeft) {} 70 71 void SizeTo(Coord aTop, Coord aRight, Coord aBottom, Coord aLeft) { 72 top = aTop; 73 right = aRight; 74 bottom = aBottom; 75 left = aLeft; 76 } 77 78 Coord LeftRight() const { return left + right; } 79 Coord TopBottom() const { return top + bottom; } 80 81 Coord& Side(SideT aSide) { 82 // This is ugly! 83 return *(&top + int(aSide)); 84 } 85 Coord Side(SideT aSide) const { 86 // This is ugly! 87 return *(&top + int(aSide)); 88 } 89 90 Sub& ApplySkipSides(Sides aSkipSides) { 91 if (aSkipSides.Top()) { 92 top = 0; 93 } 94 if (aSkipSides.Right()) { 95 right = 0; 96 } 97 if (aSkipSides.Bottom()) { 98 bottom = 0; 99 } 100 if (aSkipSides.Left()) { 101 left = 0; 102 } 103 return *static_cast<Sub*>(this); 104 } 105 106 // Ensures that all our sides are at least as big as the argument. 107 void EnsureAtLeast(const BaseMargin& aMargin) { 108 top = std::max(top, aMargin.top); 109 right = std::max(right, aMargin.right); 110 bottom = std::max(bottom, aMargin.bottom); 111 left = std::max(left, aMargin.left); 112 } 113 114 // Ensures that all our sides are at most as big as the argument. 115 void EnsureAtMost(const BaseMargin& aMargin) { 116 top = std::min(top, aMargin.top); 117 right = std::min(right, aMargin.right); 118 bottom = std::min(bottom, aMargin.bottom); 119 left = std::min(left, aMargin.left); 120 } 121 122 bool IsAll(Coord aCoord) const { 123 return left == aCoord && top == aCoord && right == aCoord && 124 bottom == aCoord; 125 } 126 127 bool IsAllZero() const { return IsAll(0); } 128 bool IsAllEqual() const { return IsAll(top); } 129 130 // Overloaded operators. Note that '=' isn't defined so we'll get the 131 // compiler generated default assignment operator 132 bool operator==(const Sub& aMargin) const { 133 return top == aMargin.top && right == aMargin.right && 134 bottom == aMargin.bottom && left == aMargin.left; 135 } 136 bool operator!=(const Sub& aMargin) const { return !(*this == aMargin); } 137 Sub operator+(const Sub& aMargin) const { 138 return Sub(top + aMargin.top, right + aMargin.right, 139 bottom + aMargin.bottom, left + aMargin.left); 140 } 141 Sub operator-(const Sub& aMargin) const { 142 return Sub(top - aMargin.top, right - aMargin.right, 143 bottom - aMargin.bottom, left - aMargin.left); 144 } 145 Sub operator-() const { return Sub(-top, -right, -bottom, -left); } 146 Sub& operator+=(const Sub& aMargin) { 147 top += aMargin.top; 148 right += aMargin.right; 149 bottom += aMargin.bottom; 150 left += aMargin.left; 151 return *static_cast<Sub*>(this); 152 } 153 Sub& operator-=(const Sub& aMargin) { 154 top -= aMargin.top; 155 right -= aMargin.right; 156 bottom -= aMargin.bottom; 157 left -= aMargin.left; 158 return *static_cast<Sub*>(this); 159 } 160 161 friend std::ostream& operator<<(std::ostream& aStream, 162 const BaseMargin& aMargin) { 163 return aStream << "(t=" << aMargin.top << ", r=" << aMargin.right 164 << ", b=" << aMargin.bottom << ", l=" << aMargin.left << ')'; 165 } 166 }; 167 168 } // namespace gfx 169 } // namespace mozilla 170 171 #endif /* MOZILLA_GFX_BASEMARGIN_H_ */