Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/painting/DashedCornerFinder.h
Line
Count
Source (jump to first uncovered line)
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
{
86
  typedef mozilla::gfx::Bezier Bezier;
87
  typedef mozilla::gfx::Float Float;
88
  typedef mozilla::gfx::Point Point;
89
  typedef mozilla::gfx::Size Size;
90
91
public:
92
  struct Result
93
  {
94
    // Control points for the outer curve and the inner curve.
95
    //
96
    //   outerSectionBezier
97
    //        |
98
    //        v     _+ 3
99
    //        ___---#|
100
    //  0 +---#######|
101
    //    |###########|
102
    //     |###########|
103
    //      |##########|
104
    //       |##########|
105
    //        |#########|
106
    //         |#####____+ 3
107
    //        0 +----
108
    //              ^
109
    //              |
110
    //   innerSectionBezier
111
    Bezier outerSectionBezier;
112
    Bezier innerSectionBezier;
113
114
    Result(const Bezier& aOuterSectionBezier, const Bezier& aInnerSectionBezier)
115
      : outerSectionBezier(aOuterSectionBezier)
116
      , innerSectionBezier(aInnerSectionBezier)
117
0
    {
118
0
    }
119
  };
120
121
  //                       aCornerDim.width
122
  //                     |<----------------->|
123
  //                     |                   |
124
  //                   --+-------------___---+--
125
  //                   ^ |         __--      | ^
126
  //                   | |       _-          | |
127
  //                   | |     /             | | aBorderWidthH
128
  //                   | |   /               | |
129
  //                   | |  |                | v
130
  //                   | | |             __--+--
131
  // aCornerDim.height | ||            _-
132
  //                   | ||           /
133
  //                   | |           /
134
  //                   | |          |
135
  //                   | |          |
136
  //                   | |         |
137
  //                   | |         |
138
  //                   v |         |
139
  //                   --+---------+
140
  //                     |         |
141
  //                     |<------->|
142
  //                     aBorderWidthV
143
  DashedCornerFinder(const Bezier& aOuterBezier,
144
                     const Bezier& aInnerBezier,
145
                     Float aBorderWidthH,
146
                     Float aBorderWidthV,
147
                     const Size& aCornerDim);
148
149
  bool HasMore(void) const;
150
  Result Next(void);
151
152
private:
153
  static const size_t MAX_LOOP = 32;
154
155
  // Bezier control points for the outer curve and the inner curve.
156
  //
157
  //               ___---+ outer curve
158
  //           __--      |
159
  //         _-          |
160
  //       /             |
161
  //     /               |
162
  //    |                |
163
  //   |             __--+ inner curve
164
  //  |            _-
165
  //  |           /
166
  // |           /
167
  // |          |
168
  // |          |
169
  // |         |
170
  // |         |
171
  // |         |
172
  // +---------+
173
  Bezier mOuterBezier;
174
  Bezier mInnerBezier;
175
176
  Point mLastOuterP;
177
  Point mLastInnerP;
178
  Float mLastOuterT;
179
  Float mLastInnerT;
180
181
  // Length for each segment, ratio of the border width at that point.
182
  Float mBestDashLength;
183
184
  // If one of border-widths is 0, do not calculate mBestDashLength, and draw
185
  // segments until it reaches the other side or exceeds mMaxCount.
186
  bool mHasZeroBorderWidth;
187
  bool mHasMore;
188
189
  // The maximum number of segments.
190
  size_t mMaxCount;
191
192
  enum
193
  {
194
    //                      radius.width
195
    //                 |<----------------->|
196
    //                 |                   |
197
    //               --+-------------___---+--
198
    //               ^ |         __--      | ^
199
    //               | |       _-          | |
200
    //               | |     /             + | top-width
201
    //               | |   /               | |
202
    //               | |  |                | v
203
    //               | | |             __--+--
204
    // radius.height | ||            _-
205
    //               | ||           /
206
    //               | |           /
207
    //               | |          |
208
    //               | |          |
209
    //               | |         |
210
    //               | |         |
211
    //               v |         |
212
    //               --+----+----+
213
    //                 |         |
214
    //                 |<------->|
215
    //                  left-width
216
217
    // * top-width == left-width
218
    // * radius.width == radius.height
219
    // * top-width < radius.width * 2
220
    //
221
    // Split the perfect circle's arc into 2n segments, each segment's length is
222
    // top-width * dashLength. Then split the inner curve and the outer curve
223
    // with same angles.
224
    //
225
    //                        radius.width
226
    //                 |<---------------------->|
227
    //                 |                        | v
228
    //               --+------------------------+--
229
    //               ^ |                        | | top-width / 2
230
    //               | | perfect                | |
231
    //               | | circle's         ___---+--
232
    //               | | arc          __-+      | ^
233
    //               | |  |         _-   |      |
234
    // radius.height | |  |       +       |     +--
235
    //               | |  |     /  \      |     |
236
    //               | |  |    |     \     |    |
237
    //               | |  |   |       \     |   |
238
    //               | |  +->|          \   |   |
239
    //               | |    +---__       \   |  |
240
    //               | |    |     --__     \  | |
241
    //               | |    |         ---__ \ | |
242
    //               v |    |              --_\||
243
    //               --+----+----+--------------+
244
    //                 |    |    |
245
    //                 |<-->|    |
246
    //               left-width / 2
247
    PERFECT,
248
249
    // Other cases.
250
    //
251
    // Split the outer curve and the inner curve into 2n segments, each segment
252
    // satisfies following:
253
    //   (OuterL_i + InnerL_i) / 2 == dashLength * (W_i + W_{i-1}) / 2
254
    OTHER
255
  } mType;
256
257
  size_t mI;
258
  size_t mCount;
259
260
  // Determine mType from parameters.
261
  void DetermineType(Float aBorderWidthH, Float aBorderWidthV);
262
263
  // Reset calculation.
264
  void Reset(void);
265
266
  // Find next segment.
267
  Float FindNext(Float dashLength);
268
269
  // Find mBestDashLength for parameters.
270
  void FindBestDashLength(Float aMinBorderWidth,
271
                          Float aMaxBorderWidth,
272
                          Float aMinBorderRadius,
273
                          Float aMaxBorderRadius);
274
275
  // Fill corner with dashes with given dash length, and return the number of
276
  // segments and last segment's dash length.
277
  bool GetCountAndLastDashLength(Float aDashLength,
278
                                 size_t* aCount,
279
                                 Float* aActualDashLength);
280
};
281
282
} // namespace mozilla
283
284
#endif /* mozilla_DashedCornerFinder_h_ */