DashedCornerFinder.h (9710B)
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_DashedCornerFinder_h_ 8 #define mozilla_DashedCornerFinder_h_ 9 10 #include "mozilla/gfx/2D.h" 11 #include "mozilla/gfx/BezierUtils.h" 12 13 namespace mozilla { 14 15 // Calculate {OuterT_i, InnerT_i} for each 1 < i < n, that 16 // (OuterL_i + InnerL_i) / 2 == dashLength * (W_i + W_{i-1}) / 2 17 // where 18 // OuterP_i: OuterCurve(OuterT_i) 19 // InnerP_i: InnerCurve(OuterT_i) 20 // OuterL_i: Elliptic arc length between OuterP_i - OuterP_{i-1} 21 // InnerL_i: Elliptic arc length between InnerP_i - InnerP_{i-1} 22 // W_i = |OuterP_i - InnerP_i| 23 // 1.0 < dashLength < 3.0 24 // 25 // OuterP_1 OuterP_0 26 // _+__-----------+ OuterCurve 27 // OuterP_2 __---- | OuterL_1 | 28 // __+--- | | 29 // __--- | OuterL_2 | | 30 // OuterP_3 _-- | | W_1 | W_0 31 // _+ | | | 32 // / \ W_2 | | | 33 // / \ | | InnerL_1 | 34 // | \ | InnerL_2|____-------+ InnerCurve 35 // | \ |____----+ InnerP_0 36 // | . \ __---+ InnerP_1 37 // | \ / InnerP_2 38 // | . /+ InnerP_3 39 // | | 40 // | . | 41 // | | 42 // | | 43 // | | 44 // OuterP_{n-1} +--------+ InnerP_{n-1} 45 // | | 46 // | | 47 // | | 48 // | | 49 // | | 50 // OuterP_n +--------+ InnerP_n 51 // 52 // Returns region with [OuterCurve((OuterT_{2j} + OuterT_{2j-1}) / 2), 53 // OuterCurve((OuterT_{2j} + OuterT_{2j-1}) / 2), 54 // InnerCurve((OuterT_{2j} + OuterT_{2j+1}) / 2), 55 // InnerCurve((OuterT_{2j} + OuterT_{2j+1}) / 2)], 56 // to start and end with half segment. 57 // 58 // _+__----+------+ OuterCurve 59 // _+---- | |######| 60 // __+---#| | |######| 61 // _+---##|####| | |######| 62 // _-- |#####|#####| | |#####| 63 // _+ |#####|#####| | |#####| 64 // / \ |#####|####| | |#####| 65 // / \ |####|#####| | |#####| 66 // | \ |####|####| |____-+-----+ InnerCurve 67 // | \ |####|____+---+ 68 // | . \ __+---+ 69 // | \ / 70 // | . /+ 71 // | | 72 // | . | 73 // | | 74 // | | 75 // | | 76 // +--------+ 77 // | | 78 // | | 79 // +--------+ 80 // |########| 81 // |########| 82 // +--------+ 83 84 class DashedCornerFinder { 85 typedef mozilla::gfx::Bezier Bezier; 86 typedef mozilla::gfx::Float Float; 87 typedef mozilla::gfx::Point Point; 88 typedef mozilla::gfx::Size Size; 89 90 public: 91 struct Result { 92 // Control points for the outer curve and the inner curve. 93 // 94 // outerSectionBezier 95 // | 96 // v _+ 3 97 // ___---#| 98 // 0 +---#######| 99 // |###########| 100 // |###########| 101 // |##########| 102 // |##########| 103 // |#########| 104 // |#####____+ 3 105 // 0 +---- 106 // ^ 107 // | 108 // innerSectionBezier 109 Bezier outerSectionBezier; 110 Bezier innerSectionBezier; 111 112 Result(const Bezier& aOuterSectionBezier, const Bezier& aInnerSectionBezier) 113 : outerSectionBezier(aOuterSectionBezier), 114 innerSectionBezier(aInnerSectionBezier) {} 115 }; 116 117 // aCornerDim.width 118 // |<----------------->| 119 // | | 120 // --+-------------___---+-- 121 // ^ | __-- | ^ 122 // | | _- | | 123 // | | / | | aBorderWidthH 124 // | | / | | 125 // | | | | v 126 // | | | __--+-- 127 // aCornerDim.height | || _- 128 // | || / 129 // | | / 130 // | | | 131 // | | | 132 // | | | 133 // | | | 134 // v | | 135 // --+---------+ 136 // | | 137 // |<------->| 138 // aBorderWidthV 139 DashedCornerFinder(const Bezier& aOuterBezier, const Bezier& aInnerBezier, 140 Float aBorderWidthH, Float aBorderWidthV, 141 const Size& aCornerDim); 142 143 bool HasMore(void) const; 144 Result Next(void); 145 146 private: 147 static const size_t MAX_LOOP = 32; 148 149 // Bezier control points for the outer curve and the inner curve. 150 // 151 // ___---+ outer curve 152 // __-- | 153 // _- | 154 // / | 155 // / | 156 // | | 157 // | __--+ inner curve 158 // | _- 159 // | / 160 // | / 161 // | | 162 // | | 163 // | | 164 // | | 165 // | | 166 // +---------+ 167 Bezier mOuterBezier; 168 Bezier mInnerBezier; 169 170 Point mLastOuterP; 171 Point mLastInnerP; 172 Float mLastOuterT; 173 Float mLastInnerT; 174 175 // Length for each segment, ratio of the border width at that point. 176 Float mBestDashLength; 177 178 // If one of border-widths is 0, do not calculate mBestDashLength, and draw 179 // segments until it reaches the other side or exceeds mMaxCount. 180 bool mHasZeroBorderWidth; 181 bool mHasMore; 182 183 // The maximum number of segments. 184 size_t mMaxCount; 185 186 enum { 187 // radius.width 188 // |<----------------->| 189 // | | 190 // --+-------------___---+-- 191 // ^ | __-- | ^ 192 // | | _- | | 193 // | | / + | top-width 194 // | | / | | 195 // | | | | v 196 // | | | __--+-- 197 // radius.height | || _- 198 // | || / 199 // | | / 200 // | | | 201 // | | | 202 // | | | 203 // | | | 204 // v | | 205 // --+----+----+ 206 // | | 207 // |<------->| 208 // left-width 209 210 // * top-width == left-width 211 // * radius.width == radius.height 212 // * top-width < radius.width * 2 213 // 214 // Split the perfect circle's arc into 2n segments, each segment's length is 215 // top-width * dashLength. Then split the inner curve and the outer curve 216 // with same angles. 217 // 218 // radius.width 219 // |<---------------------->| 220 // | | v 221 // --+------------------------+-- 222 // ^ | | | top-width / 2 223 // | | perfect | | 224 // | | circle's ___---+-- 225 // | | arc __-+ | ^ 226 // | | | _- | | 227 // radius.height | | | + | +-- 228 // | | | / \ | | 229 // | | | | \ | | 230 // | | | | \ | | 231 // | | +->| \ | | 232 // | | +---__ \ | | 233 // | | | --__ \ | | 234 // | | | ---__ \ | | 235 // v | | --_\|| 236 // --+----+----+--------------+ 237 // | | | 238 // |<-->| | 239 // left-width / 2 240 PERFECT, 241 242 // Other cases. 243 // 244 // Split the outer curve and the inner curve into 2n segments, each segment 245 // satisfies following: 246 // (OuterL_i + InnerL_i) / 2 == dashLength * (W_i + W_{i-1}) / 2 247 OTHER 248 } mType; 249 250 size_t mI; 251 size_t mCount; 252 253 // Determine mType from parameters. 254 void DetermineType(Float aBorderWidthH, Float aBorderWidthV); 255 256 // Reset calculation. 257 void Reset(void); 258 259 // Find next segment. 260 Float FindNext(Float dashLength); 261 262 // Find mBestDashLength for parameters. 263 void FindBestDashLength(Float aMinBorderWidth, Float aMaxBorderWidth, 264 Float aMinBorderRadius, Float aMaxBorderRadius); 265 266 // Fill corner with dashes with given dash length, and return the number of 267 // segments and last segment's dash length. 268 bool GetCountAndLastDashLength(Float aDashLength, size_t* aCount, 269 Float* aActualDashLength); 270 }; 271 272 } // namespace mozilla 273 274 #endif /* mozilla_DashedCornerFinder_h_ */