/work/obj-fuzz/dist/include/mozilla/WritingModes.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 WritingModes_h_ |
8 | | #define WritingModes_h_ |
9 | | |
10 | | #include "mozilla/ComputedStyle.h" |
11 | | #include "mozilla/ComputedStyleInlines.h" |
12 | | |
13 | | #include "nsRect.h" |
14 | | #include "nsBidiUtils.h" |
15 | | |
16 | | // It is the caller's responsibility to operate on logical-coordinate objects |
17 | | // with matched writing modes. Failure to do so will be a runtime bug; the |
18 | | // compiler can't catch it, but in debug mode, we'll throw an assertion. |
19 | | // NOTE that in non-debug builds, a writing mode mismatch error will NOT be |
20 | | // detected, yet the results will be nonsense (and may lead to further layout |
21 | | // failures). Therefore, it is important to test (and fuzz-test) writing-mode |
22 | | // support using debug builds. |
23 | | |
24 | | // Methods in logical-coordinate classes that take another logical-coordinate |
25 | | // object as a parameter should call CHECK_WRITING_MODE on it to verify that |
26 | | // the writing modes match. |
27 | | // (In some cases, there are internal (private) methods that don't do this; |
28 | | // such methods should only be used by other methods that have already checked |
29 | | // the writing modes.) |
30 | | // The check ignores the eSidewaysMask bit of writing mode, because this does |
31 | | // not affect the interpretation of logical coordinates. |
32 | | |
33 | | #define CHECK_WRITING_MODE(param) \ |
34 | 0 | NS_ASSERTION(param.IgnoreSideways() == GetWritingMode().IgnoreSideways(), \ |
35 | 0 | "writing-mode mismatch") |
36 | | |
37 | | namespace mozilla { |
38 | | |
39 | | namespace widget { |
40 | | struct IMENotification; |
41 | | } // namespace widget |
42 | | |
43 | | // Physical axis constants. |
44 | | enum PhysicalAxis { |
45 | | eAxisVertical = 0x0, |
46 | | eAxisHorizontal = 0x1 |
47 | | }; |
48 | | |
49 | | inline LogicalAxis GetOrthogonalAxis(LogicalAxis aAxis) |
50 | | { |
51 | | return aAxis == eLogicalAxisBlock ? eLogicalAxisInline : eLogicalAxisBlock; |
52 | | } |
53 | | |
54 | 0 | inline bool IsInline(LogicalSide aSide) { return aSide & 0x2; } |
55 | 0 | inline bool IsBlock(LogicalSide aSide) { return !IsInline(aSide); } |
56 | 0 | inline bool IsEnd(LogicalSide aSide) { return aSide & 0x1; } |
57 | 0 | inline bool IsStart(LogicalSide aSide) { return !IsEnd(aSide); } |
58 | | |
59 | | inline LogicalAxis GetAxis(LogicalSide aSide) |
60 | | { |
61 | | return IsInline(aSide) ? eLogicalAxisInline : eLogicalAxisBlock; |
62 | | } |
63 | | |
64 | | inline LogicalEdge GetEdge(LogicalSide aSide) |
65 | 0 | { |
66 | 0 | return IsEnd(aSide) ? eLogicalEdgeEnd : eLogicalEdgeStart; |
67 | 0 | } |
68 | | |
69 | | inline LogicalEdge GetOppositeEdge(LogicalEdge aEdge) |
70 | | { |
71 | | // This relies on the only two LogicalEdge enum values being 0 and 1. |
72 | | return LogicalEdge(1 - aEdge); |
73 | | } |
74 | | |
75 | | inline LogicalSide |
76 | | MakeLogicalSide(LogicalAxis aAxis, LogicalEdge aEdge) |
77 | 0 | { |
78 | 0 | return LogicalSide((aAxis << 1) | aEdge); |
79 | 0 | } |
80 | | |
81 | | inline LogicalSide GetOppositeSide(LogicalSide aSide) |
82 | | { |
83 | | return MakeLogicalSide(GetAxis(aSide), GetOppositeEdge(GetEdge(aSide))); |
84 | | } |
85 | | |
86 | | enum LogicalSideBits { |
87 | | eLogicalSideBitsNone = 0, |
88 | | eLogicalSideBitsBStart = 1 << eLogicalSideBStart, |
89 | | eLogicalSideBitsBEnd = 1 << eLogicalSideBEnd, |
90 | | eLogicalSideBitsIEnd = 1 << eLogicalSideIEnd, |
91 | | eLogicalSideBitsIStart = 1 << eLogicalSideIStart, |
92 | | eLogicalSideBitsBBoth = eLogicalSideBitsBStart | eLogicalSideBitsBEnd, |
93 | | eLogicalSideBitsIBoth = eLogicalSideBitsIStart | eLogicalSideBitsIEnd, |
94 | | eLogicalSideBitsAll = eLogicalSideBitsBBoth | eLogicalSideBitsIBoth |
95 | | }; |
96 | | |
97 | | enum LineRelativeDir { |
98 | | eLineRelativeDirOver = eLogicalSideBStart, |
99 | | eLineRelativeDirUnder = eLogicalSideBEnd, |
100 | | eLineRelativeDirLeft = eLogicalSideIStart, |
101 | | eLineRelativeDirRight = eLogicalSideIEnd |
102 | | }; |
103 | | |
104 | | /** |
105 | | * LogicalSides represents a set of logical sides. |
106 | | */ |
107 | | struct LogicalSides final { |
108 | 0 | LogicalSides() : mBits(0) {} |
109 | | explicit LogicalSides(LogicalSideBits aSideBits) |
110 | | { |
111 | | MOZ_ASSERT((aSideBits & ~eLogicalSideBitsAll) == 0, "illegal side bits"); |
112 | | mBits = aSideBits; |
113 | | } |
114 | 0 | bool IsEmpty() const { return mBits == 0; } |
115 | 0 | bool BStart() const { return mBits & eLogicalSideBitsBStart; } |
116 | 0 | bool BEnd() const { return mBits & eLogicalSideBitsBEnd; } |
117 | 0 | bool IStart() const { return mBits & eLogicalSideBitsIStart; } |
118 | 0 | bool IEnd() const { return mBits & eLogicalSideBitsIEnd; } |
119 | | bool Contains(LogicalSideBits aSideBits) const |
120 | 0 | { |
121 | 0 | MOZ_ASSERT((aSideBits & ~eLogicalSideBitsAll) == 0, "illegal side bits"); |
122 | 0 | return (mBits & aSideBits) == aSideBits; |
123 | 0 | } |
124 | | LogicalSides operator|(LogicalSides aOther) const |
125 | | { |
126 | | return LogicalSides(LogicalSideBits(mBits | aOther.mBits)); |
127 | | } |
128 | | LogicalSides operator|(LogicalSideBits aSideBits) const |
129 | 0 | { |
130 | 0 | return *this | LogicalSides(aSideBits); |
131 | 0 | } |
132 | | LogicalSides& operator|=(LogicalSides aOther) |
133 | 0 | { |
134 | 0 | mBits |= aOther.mBits; |
135 | 0 | return *this; |
136 | 0 | } |
137 | | LogicalSides& operator|=(LogicalSideBits aSideBits) |
138 | 0 | { |
139 | 0 | return *this |= LogicalSides(aSideBits); |
140 | 0 | } |
141 | | bool operator==(LogicalSides aOther) const |
142 | 0 | { |
143 | 0 | return mBits == aOther.mBits; |
144 | 0 | } |
145 | | bool operator!=(LogicalSides aOther) const |
146 | 0 | { |
147 | 0 | return !(*this == aOther); |
148 | 0 | } |
149 | | |
150 | | private: |
151 | | uint8_t mBits; |
152 | | }; |
153 | | |
154 | | /** |
155 | | * mozilla::WritingMode is an immutable class representing a |
156 | | * writing mode. |
157 | | * |
158 | | * It efficiently stores the writing mode and can rapidly compute |
159 | | * interesting things about it for use in layout. |
160 | | * |
161 | | * Writing modes are computed from the CSS 'direction', |
162 | | * 'writing-mode', and 'text-orientation' properties. |
163 | | * See CSS3 Writing Modes for more information |
164 | | * http://www.w3.org/TR/css3-writing-modes/ |
165 | | */ |
166 | | class WritingMode { |
167 | | public: |
168 | | /** |
169 | | * Absolute inline flow direction |
170 | | */ |
171 | | enum InlineDir { |
172 | | eInlineLTR = 0x00, // text flows horizontally left to right |
173 | | eInlineRTL = 0x02, // text flows horizontally right to left |
174 | | eInlineTTB = 0x01, // text flows vertically top to bottom |
175 | | eInlineBTT = 0x03, // text flows vertically bottom to top |
176 | | }; |
177 | | |
178 | | /** |
179 | | * Absolute block flow direction |
180 | | */ |
181 | | enum BlockDir { |
182 | | eBlockTB = 0x00, // horizontal lines stack top to bottom |
183 | | eBlockRL = 0x01, // vertical lines stack right to left |
184 | | eBlockLR = 0x05, // vertical lines stack left to right |
185 | | }; |
186 | | |
187 | | /** |
188 | | * Line-relative (bidi-relative) inline flow direction |
189 | | */ |
190 | | enum BidiDir { |
191 | | eBidiLTR = 0x00, // inline flow matches bidi LTR text |
192 | | eBidiRTL = 0x10, // inline flow matches bidi RTL text |
193 | | }; |
194 | | |
195 | | /** |
196 | | * Unknown writing mode (should never actually be stored or used anywhere). |
197 | | */ |
198 | | enum { |
199 | | eUnknownWritingMode = 0xff |
200 | | }; |
201 | | |
202 | | /** |
203 | | * Return the absolute inline flow direction as an InlineDir |
204 | | */ |
205 | 0 | InlineDir GetInlineDir() const { return InlineDir(mWritingMode & eInlineMask); } |
206 | | |
207 | | /** |
208 | | * Return the absolute block flow direction as a BlockDir |
209 | | */ |
210 | 0 | BlockDir GetBlockDir() const { return BlockDir(mWritingMode & eBlockMask); } |
211 | | |
212 | | /** |
213 | | * Return the line-relative inline flow direction as a BidiDir |
214 | | */ |
215 | 0 | BidiDir GetBidiDir() const { return BidiDir(mWritingMode & eBidiMask); } |
216 | | |
217 | | /** |
218 | | * Return true if the inline flow direction is against physical direction |
219 | | * (i.e. right-to-left or bottom-to-top). |
220 | | * This occurs when writing-mode is sideways-lr OR direction is rtl (but not |
221 | | * if both of those are true). |
222 | | */ |
223 | 0 | bool IsInlineReversed() const { return !!(mWritingMode & eInlineFlowMask); } |
224 | | |
225 | | /** |
226 | | * Return true if bidi direction is LTR. (Convenience method) |
227 | | */ |
228 | 0 | bool IsBidiLTR() const { return eBidiLTR == GetBidiDir(); } |
229 | | |
230 | | /** |
231 | | * True if vertical-mode block direction is LR (convenience method). |
232 | | */ |
233 | 0 | bool IsVerticalLR() const { return eBlockLR == GetBlockDir(); } |
234 | | |
235 | | /** |
236 | | * True if vertical-mode block direction is RL (convenience method). |
237 | | */ |
238 | | bool IsVerticalRL() const { return eBlockRL == GetBlockDir(); } |
239 | | |
240 | | /** |
241 | | * True if vertical writing mode, i.e. when |
242 | | * writing-mode: vertical-lr | vertical-rl. |
243 | | */ |
244 | 0 | bool IsVertical() const { return !!(mWritingMode & eOrientationMask); } |
245 | | |
246 | | /** |
247 | | * True if line-over/line-under are inverted from block-start/block-end. |
248 | | * This is true only when writing-mode is vertical-lr. |
249 | | */ |
250 | 0 | bool IsLineInverted() const { return !!(mWritingMode & eLineOrientMask); } |
251 | | |
252 | | /** |
253 | | * Block-axis flow-relative to line-relative factor. |
254 | | * May be used as a multiplication factor for block-axis coordinates |
255 | | * to convert between flow- and line-relative coordinate systems (e.g. |
256 | | * positioning an over- or under-line decoration). |
257 | | */ |
258 | | int FlowRelativeToLineRelativeFactor() const |
259 | 0 | { |
260 | 0 | return IsLineInverted() ? -1 : 1; |
261 | 0 | } |
262 | | |
263 | | /** |
264 | | * True if the text-orientation will force all text to be rendered sideways |
265 | | * in vertical lines, in which case we should prefer an alphabetic baseline; |
266 | | * otherwise, the default is centered. |
267 | | * Note that some glyph runs may be rendered sideways even if this is false, |
268 | | * due to text-orientation:mixed resolution, but in that case the dominant |
269 | | * baseline remains centered. |
270 | | */ |
271 | 0 | bool IsSideways() const { return !!(mWritingMode & eSidewaysMask); } |
272 | | |
273 | | #ifdef DEBUG // Used by CHECK_WRITING_MODE to compare modes without regard |
274 | | // for the eSidewaysMask flag. |
275 | | WritingMode IgnoreSideways() const { |
276 | | return WritingMode(mWritingMode & ~eSidewaysMask); |
277 | | } |
278 | | #endif |
279 | | |
280 | | /** |
281 | | * Return true if boxes with this writing mode should use central baselines. |
282 | | */ |
283 | 0 | bool IsCentralBaseline() const { return IsVertical() && !IsSideways(); } |
284 | | |
285 | | /** |
286 | | * Return true if boxes with this writing mode should use alphabetical |
287 | | * baselines. |
288 | | */ |
289 | 0 | bool IsAlphabeticalBaseline() const { return !IsCentralBaseline(); } |
290 | | |
291 | | |
292 | | static mozilla::PhysicalAxis PhysicalAxisForLogicalAxis( |
293 | | uint8_t aWritingModeValue, |
294 | | LogicalAxis aAxis) |
295 | 0 | { |
296 | 0 | // This relies on bit 0 of a writing-value mode indicating vertical |
297 | 0 | // orientation and bit 0 of a LogicalAxis value indicating the inline axis, |
298 | 0 | // so that it can correctly form mozilla::PhysicalAxis values using bit |
299 | 0 | // manipulation. |
300 | 0 | static_assert(NS_STYLE_WRITING_MODE_HORIZONTAL_TB == 0 && |
301 | 0 | NS_STYLE_WRITING_MODE_VERTICAL_RL == 1 && |
302 | 0 | NS_STYLE_WRITING_MODE_VERTICAL_LR == 3 && |
303 | 0 | eLogicalAxisBlock == 0 && |
304 | 0 | eLogicalAxisInline == 1 && |
305 | 0 | eAxisVertical == 0 && |
306 | 0 | eAxisHorizontal == 1, |
307 | 0 | "unexpected writing-mode, logical axis or physical axis " |
308 | 0 | "constant values"); |
309 | 0 | return mozilla::PhysicalAxis((aWritingModeValue ^ aAxis) & 0x1); |
310 | 0 | } |
311 | | |
312 | | mozilla::PhysicalAxis PhysicalAxis(LogicalAxis aAxis) const |
313 | 0 | { |
314 | 0 | // This will set wm to either NS_STYLE_WRITING_MODE_HORIZONTAL_TB or |
315 | 0 | // NS_STYLE_WRITING_MODE_VERTICAL_RL, and not the other two (real |
316 | 0 | // and hypothetical) values. But this is fine; we only need to |
317 | 0 | // distinguish between vertical and horizontal in |
318 | 0 | // PhysicalAxisForLogicalAxis. |
319 | 0 | int wm = mWritingMode & eOrientationMask; |
320 | 0 | return PhysicalAxisForLogicalAxis(wm, aAxis); |
321 | 0 | } |
322 | | |
323 | | static mozilla::Side PhysicalSideForBlockAxis(uint8_t aWritingModeValue, |
324 | | LogicalEdge aEdge) |
325 | 0 | { |
326 | 0 | // indexes are NS_STYLE_WRITING_MODE_* values, which are the same as these |
327 | 0 | // two-bit values: |
328 | 0 | // bit 0 = the eOrientationMask value |
329 | 0 | // bit 1 = the eBlockFlowMask value |
330 | 0 | static const mozilla::Side kLogicalBlockSides[][2] = { |
331 | 0 | { eSideTop, eSideBottom }, // horizontal-tb |
332 | 0 | { eSideRight, eSideLeft }, // vertical-rl |
333 | 0 | { eSideBottom, eSideTop }, // (horizontal-bt) |
334 | 0 | { eSideLeft, eSideRight }, // vertical-lr |
335 | 0 | }; |
336 | 0 |
|
337 | 0 | // Ignore the SIDEWAYS_MASK bit of the writing-mode value, as this has no |
338 | 0 | // effect on the side mappings. |
339 | 0 | aWritingModeValue &= ~NS_STYLE_WRITING_MODE_SIDEWAYS_MASK; |
340 | 0 |
|
341 | 0 | // What's left of the writing-mode should be in the range 0-3: |
342 | 0 | NS_ASSERTION(aWritingModeValue < 4, "invalid aWritingModeValue value"); |
343 | 0 |
|
344 | 0 | return kLogicalBlockSides[aWritingModeValue][aEdge]; |
345 | 0 | } |
346 | | |
347 | | mozilla::Side PhysicalSideForInlineAxis(LogicalEdge aEdge) const |
348 | 0 | { |
349 | 0 | // indexes are four-bit values: |
350 | 0 | // bit 0 = the eOrientationMask value |
351 | 0 | // bit 1 = the eInlineFlowMask value |
352 | 0 | // bit 2 = the eBlockFlowMask value |
353 | 0 | // bit 3 = the eLineOrientMask value |
354 | 0 | // Not all of these combinations can actually be specified via CSS: there |
355 | 0 | // is no horizontal-bt writing-mode, and no text-orientation value that |
356 | 0 | // produces "inverted" text. (The former 'sideways-left' value, no longer |
357 | 0 | // in the spec, would have produced this in vertical-rl mode.) |
358 | 0 | static const mozilla::Side kLogicalInlineSides[][2] = { |
359 | 0 | { eSideLeft, eSideRight }, // horizontal-tb ltr |
360 | 0 | { eSideTop, eSideBottom }, // vertical-rl ltr |
361 | 0 | { eSideRight, eSideLeft }, // horizontal-tb rtl |
362 | 0 | { eSideBottom, eSideTop }, // vertical-rl rtl |
363 | 0 | { eSideRight, eSideLeft }, // (horizontal-bt) (inverted) ltr |
364 | 0 | { eSideTop, eSideBottom }, // sideways-lr rtl |
365 | 0 | { eSideLeft, eSideRight }, // (horizontal-bt) (inverted) rtl |
366 | 0 | { eSideBottom, eSideTop }, // sideways-lr ltr |
367 | 0 | { eSideLeft, eSideRight }, // horizontal-tb (inverted) rtl |
368 | 0 | { eSideTop, eSideBottom }, // vertical-rl (inverted) rtl |
369 | 0 | { eSideRight, eSideLeft }, // horizontal-tb (inverted) ltr |
370 | 0 | { eSideBottom, eSideTop }, // vertical-rl (inverted) ltr |
371 | 0 | { eSideLeft, eSideRight }, // (horizontal-bt) ltr |
372 | 0 | { eSideTop, eSideBottom }, // vertical-lr ltr |
373 | 0 | { eSideRight, eSideLeft }, // (horizontal-bt) rtl |
374 | 0 | { eSideBottom, eSideTop }, // vertical-lr rtl |
375 | 0 | }; |
376 | 0 |
|
377 | 0 | // Inline axis sides depend on all three of writing-mode, text-orientation |
378 | 0 | // and direction, which are encoded in the eOrientationMask, |
379 | 0 | // eInlineFlowMask, eBlockFlowMask and eLineOrientMask bits. Use these four |
380 | 0 | // bits to index into kLogicalInlineSides. |
381 | 0 | static_assert(eOrientationMask == 0x01 && eInlineFlowMask == 0x02 && |
382 | 0 | eBlockFlowMask == 0x04 && eLineOrientMask == 0x08, |
383 | 0 | "unexpected mask values"); |
384 | 0 | int index = mWritingMode & 0x0F; |
385 | 0 | return kLogicalInlineSides[index][aEdge]; |
386 | 0 | } |
387 | | |
388 | | /** |
389 | | * Returns the physical side corresponding to the specified logical side, |
390 | | * given the current writing mode. |
391 | | */ |
392 | | mozilla::Side PhysicalSide(LogicalSide aSide) const |
393 | 0 | { |
394 | 0 | if (IsBlock(aSide)) { |
395 | 0 | static_assert(eOrientationMask == 0x01 && eBlockFlowMask == 0x04, |
396 | 0 | "unexpected mask values"); |
397 | 0 | int wm = ((mWritingMode & eBlockFlowMask) >> 1) | |
398 | 0 | (mWritingMode & eOrientationMask); |
399 | 0 | return PhysicalSideForBlockAxis(wm, GetEdge(aSide)); |
400 | 0 | } |
401 | 0 | |
402 | 0 | return PhysicalSideForInlineAxis(GetEdge(aSide)); |
403 | 0 | } |
404 | | |
405 | | /** |
406 | | * Returns the logical side corresponding to the specified physical side, |
407 | | * given the current writing mode. |
408 | | * (This is the inverse of the PhysicalSide() method above.) |
409 | | */ |
410 | | LogicalSide LogicalSideForPhysicalSide(mozilla::Side aSide) const |
411 | 0 | { |
412 | 0 | // indexes are four-bit values: |
413 | 0 | // bit 0 = the eOrientationMask value |
414 | 0 | // bit 1 = the eInlineFlowMask value |
415 | 0 | // bit 2 = the eBlockFlowMask value |
416 | 0 | // bit 3 = the eLineOrientMask value |
417 | 0 | static const LogicalSide kPhysicalToLogicalSides[][4] = { |
418 | 0 | // top right |
419 | 0 | // bottom left |
420 | 0 | { eLogicalSideBStart, eLogicalSideIEnd, |
421 | 0 | eLogicalSideBEnd, eLogicalSideIStart }, // horizontal-tb ltr |
422 | 0 | { eLogicalSideIStart, eLogicalSideBStart, |
423 | 0 | eLogicalSideIEnd, eLogicalSideBEnd }, // vertical-rl ltr |
424 | 0 | { eLogicalSideBStart, eLogicalSideIStart, |
425 | 0 | eLogicalSideBEnd, eLogicalSideIEnd }, // horizontal-tb rtl |
426 | 0 | { eLogicalSideIEnd, eLogicalSideBStart, |
427 | 0 | eLogicalSideIStart, eLogicalSideBEnd }, // vertical-rl rtl |
428 | 0 | { eLogicalSideBEnd, eLogicalSideIStart, |
429 | 0 | eLogicalSideBStart, eLogicalSideIEnd }, // (horizontal-bt) (inv) ltr |
430 | 0 | { eLogicalSideIStart, eLogicalSideBEnd, |
431 | 0 | eLogicalSideIEnd, eLogicalSideBStart }, // vertical-lr sw-left rtl |
432 | 0 | { eLogicalSideBEnd, eLogicalSideIEnd, |
433 | 0 | eLogicalSideBStart, eLogicalSideIStart }, // (horizontal-bt) (inv) rtl |
434 | 0 | { eLogicalSideIEnd, eLogicalSideBEnd, |
435 | 0 | eLogicalSideIStart, eLogicalSideBStart }, // vertical-lr sw-left ltr |
436 | 0 | { eLogicalSideBStart, eLogicalSideIEnd, |
437 | 0 | eLogicalSideBEnd, eLogicalSideIStart }, // horizontal-tb (inv) rtl |
438 | 0 | { eLogicalSideIStart, eLogicalSideBStart, |
439 | 0 | eLogicalSideIEnd, eLogicalSideBEnd }, // vertical-rl sw-left rtl |
440 | 0 | { eLogicalSideBStart, eLogicalSideIStart, |
441 | 0 | eLogicalSideBEnd, eLogicalSideIEnd }, // horizontal-tb (inv) ltr |
442 | 0 | { eLogicalSideIEnd, eLogicalSideBStart, |
443 | 0 | eLogicalSideIStart, eLogicalSideBEnd }, // vertical-rl sw-left ltr |
444 | 0 | { eLogicalSideBEnd, eLogicalSideIEnd, |
445 | 0 | eLogicalSideBStart, eLogicalSideIStart }, // (horizontal-bt) ltr |
446 | 0 | { eLogicalSideIStart, eLogicalSideBEnd, |
447 | 0 | eLogicalSideIEnd, eLogicalSideBStart }, // vertical-lr ltr |
448 | 0 | { eLogicalSideBEnd, eLogicalSideIStart, |
449 | 0 | eLogicalSideBStart, eLogicalSideIEnd }, // (horizontal-bt) rtl |
450 | 0 | { eLogicalSideIEnd, eLogicalSideBEnd, |
451 | 0 | eLogicalSideIStart, eLogicalSideBStart }, // vertical-lr rtl |
452 | 0 | }; |
453 | 0 |
|
454 | 0 | static_assert(eOrientationMask == 0x01 && eInlineFlowMask == 0x02 && |
455 | 0 | eBlockFlowMask == 0x04 && eLineOrientMask == 0x08, |
456 | 0 | "unexpected mask values"); |
457 | 0 | int index = mWritingMode & 0x0F; |
458 | 0 | return kPhysicalToLogicalSides[index][aSide]; |
459 | 0 | } |
460 | | |
461 | | /** |
462 | | * Returns the logical side corresponding to the specified |
463 | | * line-relative direction, given the current writing mode. |
464 | | */ |
465 | | LogicalSide LogicalSideForLineRelativeDir(LineRelativeDir aDir) const |
466 | | { |
467 | | auto side = static_cast<LogicalSide>(aDir); |
468 | | if (IsInline(side)) { |
469 | | return IsBidiLTR() ? side : GetOppositeSide(side); |
470 | | } |
471 | | return !IsLineInverted() ? side : GetOppositeSide(side); |
472 | | } |
473 | | |
474 | | /** |
475 | | * Default constructor gives us a horizontal, LTR writing mode. |
476 | | * XXX We will probably eliminate this and require explicit initialization |
477 | | * in all cases once transition is complete. |
478 | | */ |
479 | | WritingMode() |
480 | | : mWritingMode(0) |
481 | 0 | { } |
482 | | |
483 | | /** |
484 | | * Construct writing mode based on a ComputedStyle. |
485 | | */ |
486 | | explicit WritingMode(ComputedStyle* aComputedStyle) |
487 | 0 | { |
488 | 0 | NS_ASSERTION(aComputedStyle, "we need an ComputedStyle here"); |
489 | 0 | InitFromStyleVisibility(aComputedStyle->StyleVisibility()); |
490 | 0 | } |
491 | | |
492 | | explicit WritingMode(const nsStyleVisibility* aStyleVisibility) |
493 | 0 | { |
494 | 0 | NS_ASSERTION(aStyleVisibility, "we need an nsStyleVisibility here"); |
495 | 0 | InitFromStyleVisibility(aStyleVisibility); |
496 | 0 | } |
497 | | |
498 | | private: |
499 | | void InitFromStyleVisibility(const nsStyleVisibility* aStyleVisibility) |
500 | 0 | { |
501 | 0 | switch (aStyleVisibility->mWritingMode) { |
502 | 0 | case NS_STYLE_WRITING_MODE_HORIZONTAL_TB: |
503 | 0 | mWritingMode = 0; |
504 | 0 | break; |
505 | 0 |
|
506 | 0 | case NS_STYLE_WRITING_MODE_VERTICAL_LR: |
507 | 0 | { |
508 | 0 | mWritingMode = eBlockFlowMask | |
509 | 0 | eLineOrientMask | |
510 | 0 | eOrientationMask; |
511 | 0 | uint8_t textOrientation = aStyleVisibility->mTextOrientation; |
512 | 0 | if (textOrientation == NS_STYLE_TEXT_ORIENTATION_SIDEWAYS) { |
513 | 0 | mWritingMode |= eSidewaysMask; |
514 | 0 | } |
515 | 0 | break; |
516 | 0 | } |
517 | 0 |
|
518 | 0 | case NS_STYLE_WRITING_MODE_VERTICAL_RL: |
519 | 0 | { |
520 | 0 | mWritingMode = eOrientationMask; |
521 | 0 | uint8_t textOrientation = aStyleVisibility->mTextOrientation; |
522 | 0 | if (textOrientation == NS_STYLE_TEXT_ORIENTATION_SIDEWAYS) { |
523 | 0 | mWritingMode |= eSidewaysMask; |
524 | 0 | } |
525 | 0 | break; |
526 | 0 | } |
527 | 0 |
|
528 | 0 | case NS_STYLE_WRITING_MODE_SIDEWAYS_LR: |
529 | 0 | mWritingMode = eBlockFlowMask | |
530 | 0 | eInlineFlowMask | |
531 | 0 | eOrientationMask | |
532 | 0 | eSidewaysMask; |
533 | 0 | break; |
534 | 0 |
|
535 | 0 | case NS_STYLE_WRITING_MODE_SIDEWAYS_RL: |
536 | 0 | mWritingMode = eOrientationMask | |
537 | 0 | eSidewaysMask; |
538 | 0 | break; |
539 | 0 |
|
540 | 0 | default: |
541 | 0 | MOZ_ASSERT_UNREACHABLE("unknown writing mode!"); |
542 | 0 | mWritingMode = 0; |
543 | 0 | break; |
544 | 0 | } |
545 | 0 |
|
546 | 0 | if (NS_STYLE_DIRECTION_RTL == aStyleVisibility->mDirection) { |
547 | 0 | mWritingMode ^= eInlineFlowMask | eBidiMask; |
548 | 0 | } |
549 | 0 | } |
550 | | public: |
551 | | |
552 | | /** |
553 | | * This function performs fixup for elements with 'unicode-bidi: plaintext', |
554 | | * where inline directionality is derived from the Unicode bidi categories |
555 | | * of the element's content, and not the CSS 'direction' property. |
556 | | * |
557 | | * The WritingMode constructor will have already incorporated the 'direction' |
558 | | * property into our flag bits, so such elements need to use this method |
559 | | * (after resolving the bidi level of their content) to update the direction |
560 | | * bits as needed. |
561 | | * |
562 | | * If it turns out that our bidi direction already matches what plaintext |
563 | | * resolution determined, there's nothing to do here. If it didn't (i.e. if |
564 | | * the rtl-ness doesn't match), then we correct the direction by flipping the |
565 | | * same bits that get flipped in the constructor's CSS 'direction'-based |
566 | | * chunk. |
567 | | * |
568 | | * XXX change uint8_t to UBiDiLevel after bug 924851 |
569 | | */ |
570 | | void SetDirectionFromBidiLevel(uint8_t level) |
571 | 0 | { |
572 | 0 | if (IS_LEVEL_RTL(level) == IsBidiLTR()) { |
573 | 0 | mWritingMode ^= eBidiMask | eInlineFlowMask; |
574 | 0 | } |
575 | 0 | } |
576 | | |
577 | | /** |
578 | | * Compare two WritingModes for equality. |
579 | | */ |
580 | | bool operator==(const WritingMode& aOther) const |
581 | | { |
582 | | return mWritingMode == aOther.mWritingMode; |
583 | | } |
584 | | |
585 | | bool operator!=(const WritingMode& aOther) const |
586 | 0 | { |
587 | 0 | return mWritingMode != aOther.mWritingMode; |
588 | 0 | } |
589 | | |
590 | | /** |
591 | | * Check whether two modes are orthogonal to each other. |
592 | | */ |
593 | | bool IsOrthogonalTo(const WritingMode& aOther) const |
594 | 0 | { |
595 | 0 | return IsVertical() != aOther.IsVertical(); |
596 | 0 | } |
597 | | |
598 | | /** |
599 | | * Returns true if this WritingMode's aLogicalAxis has the same physical |
600 | | * start side as the parallel axis of WritingMode |aOther|. |
601 | | * |
602 | | * @param aLogicalAxis The axis to compare from this WritingMode. |
603 | | * @param aOther The other WritingMode (from which we'll choose the axis |
604 | | * that's parallel to this WritingMode's aLogicalAxis, for |
605 | | * comparison). |
606 | | */ |
607 | | bool ParallelAxisStartsOnSameSide(LogicalAxis aLogicalAxis, |
608 | | const WritingMode& aOther) const |
609 | | { |
610 | | mozilla::Side myStartSide = |
611 | | this->PhysicalSide(MakeLogicalSide(aLogicalAxis, |
612 | | eLogicalEdgeStart)); |
613 | | |
614 | | // Figure out which of aOther's axes is parallel to |this| WritingMode's |
615 | | // aLogicalAxis, and get its physical start side as well. |
616 | | LogicalAxis otherWMAxis = aOther.IsOrthogonalTo(*this) ? |
617 | | GetOrthogonalAxis(aLogicalAxis) : aLogicalAxis; |
618 | | mozilla::Side otherWMStartSide = |
619 | | aOther.PhysicalSide(MakeLogicalSide(otherWMAxis, |
620 | | eLogicalEdgeStart)); |
621 | | |
622 | | NS_ASSERTION(myStartSide % 2 == otherWMStartSide % 2, |
623 | | "Should end up with sides in the same physical axis"); |
624 | | return myStartSide == otherWMStartSide; |
625 | | } |
626 | | |
627 | 0 | uint8_t GetBits() const { return mWritingMode; } |
628 | | |
629 | 0 | const char* DebugString() const { |
630 | 0 | return IsVertical() |
631 | 0 | ? IsVerticalLR() |
632 | 0 | ? IsBidiLTR() |
633 | 0 | ? IsSideways() ? "sw-lr-ltr" : "v-lr-ltr" |
634 | 0 | : IsSideways() ? "sw-lr-rtl" : "v-lr-rtl" |
635 | 0 | : IsBidiLTR() |
636 | 0 | ? IsSideways() ? "sw-rl-ltr" : "v-rl-ltr" |
637 | 0 | : IsSideways() ? "sw-rl-rtl" : "v-rl-rtl" |
638 | 0 | : IsBidiLTR() ? "h-ltr" : "h-rtl" |
639 | 0 | ; |
640 | 0 | } |
641 | | |
642 | | private: |
643 | | friend class LogicalPoint; |
644 | | friend class LogicalSize; |
645 | | friend class LogicalMargin; |
646 | | friend class LogicalRect; |
647 | | |
648 | | friend struct IPC::ParamTraits<WritingMode>; |
649 | | // IMENotification cannot store this class directly since this has some |
650 | | // constructors. Therefore, it stores mWritingMode and recreate the |
651 | | // instance from it. |
652 | | friend struct widget::IMENotification; |
653 | | |
654 | | /** |
655 | | * Return a WritingMode representing an unknown value. |
656 | | */ |
657 | | static inline WritingMode Unknown() |
658 | 0 | { |
659 | 0 | return WritingMode(eUnknownWritingMode); |
660 | 0 | } |
661 | | |
662 | | /** |
663 | | * Constructing a WritingMode with an arbitrary value is a private operation |
664 | | * currently only used by the Unknown() static method. |
665 | | */ |
666 | | explicit WritingMode(uint8_t aValue) |
667 | | : mWritingMode(aValue) |
668 | | { } |
669 | | |
670 | | uint8_t mWritingMode; |
671 | | |
672 | | enum Masks { |
673 | | // Masks for our bits; true chosen as opposite of commonest case |
674 | | eOrientationMask = 0x01, // true means vertical text |
675 | | eInlineFlowMask = 0x02, // true means absolute RTL/BTT (against physical coords) |
676 | | eBlockFlowMask = 0x04, // true means vertical-LR (or horizontal-BT if added) |
677 | | eLineOrientMask = 0x08, // true means over != block-start |
678 | | eBidiMask = 0x10, // true means line-relative RTL (bidi RTL) |
679 | | // Note: We have one excess bit of info; WritingMode can pack into 4 bits. |
680 | | // But since we have space, we're caching interesting things for fast access. |
681 | | |
682 | | eSidewaysMask = 0x20, // true means text is being rendered vertically |
683 | | // using rotated glyphs (i.e. writing-mode is |
684 | | // sideways-*, or writing-mode is vertical-* AND |
685 | | // text-orientation is sideways), |
686 | | // which means we'll use alphabetic instead of |
687 | | // centered default baseline for vertical text |
688 | | |
689 | | // Masks for output enums |
690 | | eInlineMask = 0x03, |
691 | | eBlockMask = 0x05 |
692 | | }; |
693 | | }; |
694 | | |
695 | | |
696 | | /** |
697 | | * Logical-coordinate classes: |
698 | | * |
699 | | * There are three sets of coordinate space: |
700 | | * - physical (top, left, bottom, right) |
701 | | * relative to graphics coord system |
702 | | * - flow-relative (block-start, inline-start, block-end, inline-end) |
703 | | * relative to block/inline flow directions |
704 | | * - line-relative (line-over, line-left, line-under, line-right) |
705 | | * relative to glyph orientation / inline bidi directions |
706 | | * See CSS3 Writing Modes for more information |
707 | | * http://www.w3.org/TR/css3-writing-modes/#abstract-box |
708 | | * |
709 | | * For shorthand, B represents the block-axis |
710 | | * I represents the inline-axis |
711 | | * |
712 | | * The flow-relative geometric classes store coords in flow-relative space. |
713 | | * They use a private ns{Point,Size,Rect,Margin} member to store the actual |
714 | | * coordinate values, but reinterpret them as logical instead of physical. |
715 | | * This allows us to easily perform calculations in logical space (provided |
716 | | * writing modes of the operands match), by simply mapping to nsPoint (etc) |
717 | | * methods. |
718 | | * |
719 | | * Physical-coordinate accessors/setters are responsible to translate these |
720 | | * internal logical values as necessary. |
721 | | * |
722 | | * In DEBUG builds, the logical types store their WritingMode and check |
723 | | * that the same WritingMode is passed whenever callers ask them to do a |
724 | | * writing-mode-dependent operation. Non-DEBUG builds do NOT check this, |
725 | | * to avoid the overhead of storing WritingMode fields. |
726 | | * |
727 | | * Open question: do we need a different set optimized for line-relative |
728 | | * math, for use in nsLineLayout and the like? Or is multiplying values |
729 | | * by FlowRelativeToLineRelativeFactor() enough? |
730 | | */ |
731 | | |
732 | | /** |
733 | | * Flow-relative point |
734 | | */ |
735 | | class LogicalPoint { |
736 | | public: |
737 | | explicit LogicalPoint(WritingMode aWritingMode) |
738 | | : |
739 | | #ifdef DEBUG |
740 | | mWritingMode(aWritingMode), |
741 | | #endif |
742 | | mPoint(0, 0) |
743 | 0 | { } |
744 | | |
745 | | // Construct from a writing mode and individual coordinates (which MUST be |
746 | | // values in that writing mode, NOT physical coordinates!) |
747 | | LogicalPoint(WritingMode aWritingMode, nscoord aI, nscoord aB) |
748 | | : |
749 | | #ifdef DEBUG |
750 | | mWritingMode(aWritingMode), |
751 | | #endif |
752 | | mPoint(aI, aB) |
753 | 0 | { } |
754 | | |
755 | | // Construct from a writing mode and a physical point, within a given |
756 | | // containing rectangle's size (defining the conversion between LTR |
757 | | // and RTL coordinates, and between TTB and BTT coordinates). |
758 | | LogicalPoint(WritingMode aWritingMode, |
759 | | const nsPoint& aPoint, |
760 | | const nsSize& aContainerSize) |
761 | | #ifdef DEBUG |
762 | | : mWritingMode(aWritingMode) |
763 | | #endif |
764 | 0 | { |
765 | 0 | if (aWritingMode.IsVertical()) { |
766 | 0 | I() = aWritingMode.IsInlineReversed() ? aContainerSize.height - aPoint.y |
767 | 0 | : aPoint.y; |
768 | 0 | B() = aWritingMode.IsVerticalLR() ? aPoint.x |
769 | 0 | : aContainerSize.width - aPoint.x; |
770 | 0 | } else { |
771 | 0 | I() = aWritingMode.IsInlineReversed() ? aContainerSize.width - aPoint.x |
772 | 0 | : aPoint.x; |
773 | 0 | B() = aPoint.y; |
774 | 0 | } |
775 | 0 | } |
776 | | |
777 | | /** |
778 | | * Read-only (const) access to the logical coordinates. |
779 | | */ |
780 | | nscoord I(WritingMode aWritingMode) const // inline-axis |
781 | 0 | { |
782 | 0 | CHECK_WRITING_MODE(aWritingMode); |
783 | 0 | return mPoint.x; |
784 | 0 | } |
785 | | nscoord B(WritingMode aWritingMode) const // block-axis |
786 | 0 | { |
787 | 0 | CHECK_WRITING_MODE(aWritingMode); |
788 | 0 | return mPoint.y; |
789 | 0 | } |
790 | | nscoord LineRelative(WritingMode aWritingMode, |
791 | | const nsSize& aContainerSize) const // line-axis |
792 | | { |
793 | | CHECK_WRITING_MODE(aWritingMode); |
794 | | if (aWritingMode.IsBidiLTR()) { |
795 | | return I(); |
796 | | } |
797 | | return (aWritingMode.IsVertical() ? aContainerSize.height |
798 | | : aContainerSize.width) - I(); |
799 | | } |
800 | | |
801 | | /** |
802 | | * These non-const accessors return a reference (lvalue) that can be |
803 | | * assigned to by callers. |
804 | | */ |
805 | | nscoord& I(WritingMode aWritingMode) // inline-axis |
806 | 0 | { |
807 | 0 | CHECK_WRITING_MODE(aWritingMode); |
808 | 0 | return mPoint.x; |
809 | 0 | } |
810 | | nscoord& B(WritingMode aWritingMode) // block-axis |
811 | 0 | { |
812 | 0 | CHECK_WRITING_MODE(aWritingMode); |
813 | 0 | return mPoint.y; |
814 | 0 | } |
815 | | |
816 | | /** |
817 | | * Return a physical point corresponding to our logical coordinates, |
818 | | * converted according to our writing mode. |
819 | | */ |
820 | | nsPoint GetPhysicalPoint(WritingMode aWritingMode, |
821 | | const nsSize& aContainerSize) const |
822 | 0 | { |
823 | 0 | CHECK_WRITING_MODE(aWritingMode); |
824 | 0 | if (aWritingMode.IsVertical()) { |
825 | 0 | return nsPoint(aWritingMode.IsVerticalLR() |
826 | 0 | ? B() : aContainerSize.width - B(), |
827 | 0 | aWritingMode.IsInlineReversed() |
828 | 0 | ? aContainerSize.height - I() : I()); |
829 | 0 | } else { |
830 | 0 | return nsPoint(aWritingMode.IsInlineReversed() |
831 | 0 | ? aContainerSize.width - I() : I(), |
832 | 0 | B()); |
833 | 0 | } |
834 | 0 | } |
835 | | |
836 | | /** |
837 | | * Return the equivalent point in a different writing mode. |
838 | | */ |
839 | | LogicalPoint ConvertTo(WritingMode aToMode, WritingMode aFromMode, |
840 | | const nsSize& aContainerSize) const |
841 | 0 | { |
842 | 0 | CHECK_WRITING_MODE(aFromMode); |
843 | 0 | return aToMode == aFromMode ? |
844 | 0 | *this : LogicalPoint(aToMode, |
845 | 0 | GetPhysicalPoint(aFromMode, aContainerSize), |
846 | 0 | aContainerSize); |
847 | 0 | } |
848 | | |
849 | | bool operator==(const LogicalPoint& aOther) const |
850 | | { |
851 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
852 | | return mPoint == aOther.mPoint; |
853 | | } |
854 | | |
855 | | bool operator!=(const LogicalPoint& aOther) const |
856 | 0 | { |
857 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
858 | 0 | return mPoint != aOther.mPoint; |
859 | 0 | } |
860 | | |
861 | | LogicalPoint operator+(const LogicalPoint& aOther) const |
862 | 0 | { |
863 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
864 | 0 | // In non-debug builds, LogicalPoint does not store the WritingMode, |
865 | 0 | // so the first parameter here (which will always be eUnknownWritingMode) |
866 | 0 | // is ignored. |
867 | 0 | return LogicalPoint(GetWritingMode(), |
868 | 0 | mPoint.x + aOther.mPoint.x, |
869 | 0 | mPoint.y + aOther.mPoint.y); |
870 | 0 | } |
871 | | |
872 | | LogicalPoint& operator+=(const LogicalPoint& aOther) |
873 | | { |
874 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
875 | | I() += aOther.I(); |
876 | | B() += aOther.B(); |
877 | | return *this; |
878 | | } |
879 | | |
880 | | LogicalPoint operator-(const LogicalPoint& aOther) const |
881 | 0 | { |
882 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
883 | 0 | // In non-debug builds, LogicalPoint does not store the WritingMode, |
884 | 0 | // so the first parameter here (which will always be eUnknownWritingMode) |
885 | 0 | // is ignored. |
886 | 0 | return LogicalPoint(GetWritingMode(), |
887 | 0 | mPoint.x - aOther.mPoint.x, |
888 | 0 | mPoint.y - aOther.mPoint.y); |
889 | 0 | } |
890 | | |
891 | | LogicalPoint& operator-=(const LogicalPoint& aOther) |
892 | 0 | { |
893 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
894 | 0 | I() -= aOther.I(); |
895 | 0 | B() -= aOther.B(); |
896 | 0 | return *this; |
897 | 0 | } |
898 | | |
899 | | private: |
900 | | friend class LogicalRect; |
901 | | |
902 | | /** |
903 | | * NOTE that in non-DEBUG builds, GetWritingMode() always returns |
904 | | * eUnknownWritingMode, as the current mode is not stored in the logical- |
905 | | * geometry classes. Therefore, this method is private; it is used ONLY |
906 | | * by the DEBUG-mode checking macros in this class and its friends; |
907 | | * other code is not allowed to ask a logical point for its writing mode, |
908 | | * as this info will simply not be available in non-DEBUG builds. |
909 | | * |
910 | | * Also, in non-DEBUG builds, CHECK_WRITING_MODE does nothing, and the |
911 | | * WritingMode parameter to logical methods will generally be optimized |
912 | | * away altogether. |
913 | | */ |
914 | | #ifdef DEBUG |
915 | | WritingMode GetWritingMode() const { return mWritingMode; } |
916 | | #else |
917 | 0 | WritingMode GetWritingMode() const { return WritingMode::Unknown(); } |
918 | | #endif |
919 | | |
920 | | // We don't allow construction of a LogicalPoint with no writing mode. |
921 | | LogicalPoint() = delete; |
922 | | |
923 | | // Accessors that don't take or check a WritingMode value. |
924 | | // These are for internal use only; they are called by methods that have |
925 | | // themselves already checked the WritingMode passed by the caller. |
926 | | nscoord I() const // inline-axis |
927 | 0 | { |
928 | 0 | return mPoint.x; |
929 | 0 | } |
930 | | nscoord B() const // block-axis |
931 | 0 | { |
932 | 0 | return mPoint.y; |
933 | 0 | } |
934 | | |
935 | | nscoord& I() // inline-axis |
936 | 0 | { |
937 | 0 | return mPoint.x; |
938 | 0 | } |
939 | | nscoord& B() // block-axis |
940 | 0 | { |
941 | 0 | return mPoint.y; |
942 | 0 | } |
943 | | |
944 | | #ifdef DEBUG |
945 | | WritingMode mWritingMode; |
946 | | #endif |
947 | | |
948 | | // We use an nsPoint to hold the coordinates, but reinterpret its .x and .y |
949 | | // fields as the inline and block directions. Hence, this is not exposed |
950 | | // directly, but only through accessors that will map them according to the |
951 | | // writing mode. |
952 | | nsPoint mPoint; |
953 | | }; |
954 | | |
955 | | /** |
956 | | * Flow-relative size |
957 | | */ |
958 | | class LogicalSize { |
959 | | public: |
960 | | explicit LogicalSize(WritingMode aWritingMode) |
961 | | : |
962 | | #ifdef DEBUG |
963 | | mWritingMode(aWritingMode), |
964 | | #endif |
965 | | mSize(0, 0) |
966 | 0 | { } |
967 | | |
968 | | LogicalSize(WritingMode aWritingMode, nscoord aISize, nscoord aBSize) |
969 | | : |
970 | | #ifdef DEBUG |
971 | | mWritingMode(aWritingMode), |
972 | | #endif |
973 | | mSize(aISize, aBSize) |
974 | 0 | { } |
975 | | |
976 | | LogicalSize(WritingMode aWritingMode, const nsSize& aPhysicalSize) |
977 | | #ifdef DEBUG |
978 | | : mWritingMode(aWritingMode) |
979 | | #endif |
980 | 0 | { |
981 | 0 | if (aWritingMode.IsVertical()) { |
982 | 0 | ISize() = aPhysicalSize.height; |
983 | 0 | BSize() = aPhysicalSize.width; |
984 | 0 | } else { |
985 | 0 | ISize() = aPhysicalSize.width; |
986 | 0 | BSize() = aPhysicalSize.height; |
987 | 0 | } |
988 | 0 | } |
989 | | |
990 | | void SizeTo(WritingMode aWritingMode, nscoord aISize, nscoord aBSize) |
991 | | { |
992 | | CHECK_WRITING_MODE(aWritingMode); |
993 | | mSize.SizeTo(aISize, aBSize); |
994 | | } |
995 | | |
996 | | /** |
997 | | * Dimensions in logical and physical terms |
998 | | */ |
999 | | nscoord ISize(WritingMode aWritingMode) const // inline-size |
1000 | 0 | { |
1001 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1002 | 0 | return mSize.width; |
1003 | 0 | } |
1004 | | nscoord BSize(WritingMode aWritingMode) const // block-size |
1005 | 0 | { |
1006 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1007 | 0 | return mSize.height; |
1008 | 0 | } |
1009 | | nscoord Size(LogicalAxis aAxis, WritingMode aWM) const |
1010 | 0 | { |
1011 | 0 | return aAxis == eLogicalAxisInline ? ISize(aWM) : BSize(aWM); |
1012 | 0 | } |
1013 | | |
1014 | | nscoord Width(WritingMode aWritingMode) const |
1015 | | { |
1016 | | CHECK_WRITING_MODE(aWritingMode); |
1017 | | return aWritingMode.IsVertical() ? BSize() : ISize(); |
1018 | | } |
1019 | | nscoord Height(WritingMode aWritingMode) const |
1020 | | { |
1021 | | CHECK_WRITING_MODE(aWritingMode); |
1022 | | return aWritingMode.IsVertical() ? ISize() : BSize(); |
1023 | | } |
1024 | | |
1025 | | /** |
1026 | | * Writable references to the logical dimensions |
1027 | | */ |
1028 | | nscoord& ISize(WritingMode aWritingMode) // inline-size |
1029 | 0 | { |
1030 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1031 | 0 | return mSize.width; |
1032 | 0 | } |
1033 | | nscoord& BSize(WritingMode aWritingMode) // block-size |
1034 | 0 | { |
1035 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1036 | 0 | return mSize.height; |
1037 | 0 | } |
1038 | | nscoord& Size(LogicalAxis aAxis, WritingMode aWM) |
1039 | 0 | { |
1040 | 0 | return aAxis == eLogicalAxisInline ? ISize(aWM) : BSize(aWM); |
1041 | 0 | } |
1042 | | |
1043 | | /** |
1044 | | * Return an nsSize containing our physical dimensions |
1045 | | */ |
1046 | | nsSize GetPhysicalSize(WritingMode aWritingMode) const |
1047 | 0 | { |
1048 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1049 | 0 | return aWritingMode.IsVertical() ? |
1050 | 0 | nsSize(BSize(), ISize()) : nsSize(ISize(), BSize()); |
1051 | 0 | } |
1052 | | |
1053 | | /** |
1054 | | * Return a LogicalSize representing this size in a different writing mode |
1055 | | */ |
1056 | | LogicalSize ConvertTo(WritingMode aToMode, WritingMode aFromMode) const |
1057 | 0 | { |
1058 | | #ifdef DEBUG |
1059 | | // In DEBUG builds make sure to return a LogicalSize with the |
1060 | | // expected writing mode |
1061 | | CHECK_WRITING_MODE(aFromMode); |
1062 | | return aToMode == aFromMode ? |
1063 | | *this : LogicalSize(aToMode, GetPhysicalSize(aFromMode)); |
1064 | | #else |
1065 | | // optimization for non-DEBUG builds where LogicalSize doesn't store |
1066 | 0 | // the writing mode |
1067 | 0 | return (aToMode == aFromMode || !aToMode.IsOrthogonalTo(aFromMode)) |
1068 | 0 | ? *this : LogicalSize(aToMode, BSize(), ISize()); |
1069 | 0 | #endif |
1070 | 0 | } |
1071 | | |
1072 | | /** |
1073 | | * Test if a size is (0, 0). |
1074 | | */ |
1075 | | bool IsAllZero() const |
1076 | 0 | { |
1077 | 0 | return ISize() == 0 && BSize() == 0; |
1078 | 0 | } |
1079 | | |
1080 | | /** |
1081 | | * Various binary operators on LogicalSize. These are valid ONLY for operands |
1082 | | * that share the same writing mode. |
1083 | | */ |
1084 | | bool operator==(const LogicalSize& aOther) const |
1085 | 0 | { |
1086 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1087 | 0 | return mSize == aOther.mSize; |
1088 | 0 | } |
1089 | | |
1090 | | bool operator!=(const LogicalSize& aOther) const |
1091 | | { |
1092 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1093 | | return mSize != aOther.mSize; |
1094 | | } |
1095 | | |
1096 | | LogicalSize operator+(const LogicalSize& aOther) const |
1097 | 0 | { |
1098 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1099 | 0 | return LogicalSize(GetWritingMode(), ISize() + aOther.ISize(), |
1100 | 0 | BSize() + aOther.BSize()); |
1101 | 0 | } |
1102 | | LogicalSize& operator+=(const LogicalSize& aOther) |
1103 | | { |
1104 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1105 | | ISize() += aOther.ISize(); |
1106 | | BSize() += aOther.BSize(); |
1107 | | return *this; |
1108 | | } |
1109 | | |
1110 | | LogicalSize operator-(const LogicalSize& aOther) const |
1111 | 0 | { |
1112 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1113 | 0 | return LogicalSize(GetWritingMode(), ISize() - aOther.ISize(), |
1114 | 0 | BSize() - aOther.BSize()); |
1115 | 0 | } |
1116 | | LogicalSize& operator-=(const LogicalSize& aOther) |
1117 | 0 | { |
1118 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1119 | 0 | ISize() -= aOther.ISize(); |
1120 | 0 | BSize() -= aOther.BSize(); |
1121 | 0 | return *this; |
1122 | 0 | } |
1123 | | |
1124 | | private: |
1125 | | friend class LogicalRect; |
1126 | | |
1127 | | LogicalSize() = delete; |
1128 | | |
1129 | | #ifdef DEBUG |
1130 | | WritingMode GetWritingMode() const { return mWritingMode; } |
1131 | | #else |
1132 | 0 | WritingMode GetWritingMode() const { return WritingMode::Unknown(); } |
1133 | | #endif |
1134 | | |
1135 | | nscoord ISize() const // inline-size |
1136 | 0 | { |
1137 | 0 | return mSize.width; |
1138 | 0 | } |
1139 | | nscoord BSize() const // block-size |
1140 | 0 | { |
1141 | 0 | return mSize.height; |
1142 | 0 | } |
1143 | | |
1144 | | nscoord& ISize() // inline-size |
1145 | 0 | { |
1146 | 0 | return mSize.width; |
1147 | 0 | } |
1148 | | nscoord& BSize() // block-size |
1149 | 0 | { |
1150 | 0 | return mSize.height; |
1151 | 0 | } |
1152 | | |
1153 | | #ifdef DEBUG |
1154 | | WritingMode mWritingMode; |
1155 | | #endif |
1156 | | nsSize mSize; |
1157 | | }; |
1158 | | |
1159 | | /** |
1160 | | * Flow-relative margin |
1161 | | */ |
1162 | | class LogicalMargin { |
1163 | | public: |
1164 | | explicit LogicalMargin(WritingMode aWritingMode) |
1165 | | : |
1166 | | #ifdef DEBUG |
1167 | | mWritingMode(aWritingMode), |
1168 | | #endif |
1169 | | mMargin(0, 0, 0, 0) |
1170 | 0 | { } |
1171 | | |
1172 | | LogicalMargin(WritingMode aWritingMode, |
1173 | | nscoord aBStart, nscoord aIEnd, |
1174 | | nscoord aBEnd, nscoord aIStart) |
1175 | | : |
1176 | | #ifdef DEBUG |
1177 | | mWritingMode(aWritingMode), |
1178 | | #endif |
1179 | | mMargin(aBStart, aIEnd, aBEnd, aIStart) |
1180 | 0 | { } |
1181 | | |
1182 | | LogicalMargin(WritingMode aWritingMode, const nsMargin& aPhysicalMargin) |
1183 | | #ifdef DEBUG |
1184 | | : mWritingMode(aWritingMode) |
1185 | | #endif |
1186 | 0 | { |
1187 | 0 | if (aWritingMode.IsVertical()) { |
1188 | 0 | if (aWritingMode.IsVerticalLR()) { |
1189 | 0 | mMargin.top = aPhysicalMargin.left; |
1190 | 0 | mMargin.bottom = aPhysicalMargin.right; |
1191 | 0 | } else { |
1192 | 0 | mMargin.top = aPhysicalMargin.right; |
1193 | 0 | mMargin.bottom = aPhysicalMargin.left; |
1194 | 0 | } |
1195 | 0 | if (aWritingMode.IsInlineReversed()) { |
1196 | 0 | mMargin.left = aPhysicalMargin.bottom; |
1197 | 0 | mMargin.right = aPhysicalMargin.top; |
1198 | 0 | } else { |
1199 | 0 | mMargin.left = aPhysicalMargin.top; |
1200 | 0 | mMargin.right = aPhysicalMargin.bottom; |
1201 | 0 | } |
1202 | 0 | } else { |
1203 | 0 | mMargin.top = aPhysicalMargin.top; |
1204 | 0 | mMargin.bottom = aPhysicalMargin.bottom; |
1205 | 0 | if (aWritingMode.IsInlineReversed()) { |
1206 | 0 | mMargin.left = aPhysicalMargin.right; |
1207 | 0 | mMargin.right = aPhysicalMargin.left; |
1208 | 0 | } else { |
1209 | 0 | mMargin.left = aPhysicalMargin.left; |
1210 | 0 | mMargin.right = aPhysicalMargin.right; |
1211 | 0 | } |
1212 | 0 | } |
1213 | 0 | } |
1214 | | |
1215 | | nscoord IStart(WritingMode aWritingMode) const // inline-start margin |
1216 | 0 | { |
1217 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1218 | 0 | return mMargin.left; |
1219 | 0 | } |
1220 | | nscoord IEnd(WritingMode aWritingMode) const // inline-end margin |
1221 | 0 | { |
1222 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1223 | 0 | return mMargin.right; |
1224 | 0 | } |
1225 | | nscoord BStart(WritingMode aWritingMode) const // block-start margin |
1226 | 0 | { |
1227 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1228 | 0 | return mMargin.top; |
1229 | 0 | } |
1230 | | nscoord BEnd(WritingMode aWritingMode) const // block-end margin |
1231 | 0 | { |
1232 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1233 | 0 | return mMargin.bottom; |
1234 | 0 | } |
1235 | | nscoord Start(LogicalAxis aAxis, WritingMode aWM) const |
1236 | 0 | { |
1237 | 0 | return aAxis == eLogicalAxisInline ? IStart(aWM) : BStart(aWM); |
1238 | 0 | } |
1239 | | nscoord End(LogicalAxis aAxis, WritingMode aWM) const |
1240 | 0 | { |
1241 | 0 | return aAxis == eLogicalAxisInline ? IEnd(aWM) : BEnd(aWM); |
1242 | 0 | } |
1243 | | |
1244 | | nscoord& IStart(WritingMode aWritingMode) // inline-start margin |
1245 | 0 | { |
1246 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1247 | 0 | return mMargin.left; |
1248 | 0 | } |
1249 | | nscoord& IEnd(WritingMode aWritingMode) // inline-end margin |
1250 | 0 | { |
1251 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1252 | 0 | return mMargin.right; |
1253 | 0 | } |
1254 | | nscoord& BStart(WritingMode aWritingMode) // block-start margin |
1255 | 0 | { |
1256 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1257 | 0 | return mMargin.top; |
1258 | 0 | } |
1259 | | nscoord& BEnd(WritingMode aWritingMode) // block-end margin |
1260 | 0 | { |
1261 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1262 | 0 | return mMargin.bottom; |
1263 | 0 | } |
1264 | | nscoord& Start(LogicalAxis aAxis, WritingMode aWM) |
1265 | 0 | { |
1266 | 0 | return aAxis == eLogicalAxisInline ? IStart(aWM) : BStart(aWM); |
1267 | 0 | } |
1268 | | nscoord& End(LogicalAxis aAxis, WritingMode aWM) |
1269 | 0 | { |
1270 | 0 | return aAxis == eLogicalAxisInline ? IEnd(aWM) : BEnd(aWM); |
1271 | 0 | } |
1272 | | |
1273 | | nscoord IStartEnd(WritingMode aWritingMode) const // inline margins |
1274 | 0 | { |
1275 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1276 | 0 | return mMargin.LeftRight(); |
1277 | 0 | } |
1278 | | nscoord BStartEnd(WritingMode aWritingMode) const // block margins |
1279 | 0 | { |
1280 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1281 | 0 | return mMargin.TopBottom(); |
1282 | 0 | } |
1283 | | nscoord StartEnd(LogicalAxis aAxis, WritingMode aWM) const |
1284 | 0 | { |
1285 | 0 | return aAxis == eLogicalAxisInline ? IStartEnd(aWM) : BStartEnd(aWM); |
1286 | 0 | } |
1287 | | |
1288 | | /* |
1289 | | * Return margin values for line-relative sides, as defined in |
1290 | | * http://www.w3.org/TR/css-writing-modes-3/#line-directions: |
1291 | | * |
1292 | | * line-left |
1293 | | * Nominally the side from which LTR text would start. |
1294 | | * line-right |
1295 | | * Nominally the side from which RTL text would start. (Opposite of |
1296 | | * line-left.) |
1297 | | */ |
1298 | | nscoord LineLeft(WritingMode aWritingMode) const |
1299 | 0 | { |
1300 | 0 | // We don't need to CHECK_WRITING_MODE here because the IStart or IEnd |
1301 | 0 | // accessor that we call will do it. |
1302 | 0 | return aWritingMode.IsBidiLTR() |
1303 | 0 | ? IStart(aWritingMode) : IEnd(aWritingMode); |
1304 | 0 | } |
1305 | | nscoord LineRight(WritingMode aWritingMode) const |
1306 | 0 | { |
1307 | 0 | return aWritingMode.IsBidiLTR() |
1308 | 0 | ? IEnd(aWritingMode) : IStart(aWritingMode); |
1309 | 0 | } |
1310 | | |
1311 | | /** |
1312 | | * Return a LogicalSize representing the total size of the inline- |
1313 | | * and block-dimension margins. |
1314 | | */ |
1315 | | LogicalSize Size(WritingMode aWritingMode) const |
1316 | 0 | { |
1317 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1318 | 0 | return LogicalSize(aWritingMode, IStartEnd(), BStartEnd()); |
1319 | 0 | } |
1320 | | |
1321 | | /** |
1322 | | * Accessors for physical margins, using our writing mode to convert from |
1323 | | * logical values. |
1324 | | */ |
1325 | | nscoord Top(WritingMode aWritingMode) const |
1326 | | { |
1327 | | CHECK_WRITING_MODE(aWritingMode); |
1328 | | return aWritingMode.IsVertical() ? |
1329 | | (aWritingMode.IsInlineReversed() ? IEnd() : IStart()) : BStart(); |
1330 | | } |
1331 | | |
1332 | | nscoord Bottom(WritingMode aWritingMode) const |
1333 | 0 | { |
1334 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1335 | 0 | return aWritingMode.IsVertical() ? |
1336 | 0 | (aWritingMode.IsInlineReversed() ? IStart() : IEnd()) : BEnd(); |
1337 | 0 | } |
1338 | | |
1339 | | nscoord Left(WritingMode aWritingMode) const |
1340 | | { |
1341 | | CHECK_WRITING_MODE(aWritingMode); |
1342 | | return aWritingMode.IsVertical() ? |
1343 | | (aWritingMode.IsVerticalLR() ? BStart() : BEnd()) : |
1344 | | (aWritingMode.IsInlineReversed() ? IEnd() : IStart()); |
1345 | | } |
1346 | | |
1347 | | nscoord Right(WritingMode aWritingMode) const |
1348 | 0 | { |
1349 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1350 | 0 | return aWritingMode.IsVertical() ? |
1351 | 0 | (aWritingMode.IsVerticalLR() ? BEnd() : BStart()) : |
1352 | 0 | (aWritingMode.IsInlineReversed() ? IStart() : IEnd()); |
1353 | 0 | } |
1354 | | |
1355 | | nscoord LeftRight(WritingMode aWritingMode) const |
1356 | 0 | { |
1357 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1358 | 0 | return aWritingMode.IsVertical() ? BStartEnd() : IStartEnd(); |
1359 | 0 | } |
1360 | | |
1361 | | nscoord TopBottom(WritingMode aWritingMode) const |
1362 | 0 | { |
1363 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1364 | 0 | return aWritingMode.IsVertical() ? IStartEnd() : BStartEnd(); |
1365 | 0 | } |
1366 | | |
1367 | | void SizeTo(WritingMode aWritingMode, |
1368 | | nscoord aBStart, nscoord aIEnd, nscoord aBEnd, nscoord aIStart) |
1369 | | { |
1370 | | CHECK_WRITING_MODE(aWritingMode); |
1371 | | mMargin.SizeTo(aBStart, aIEnd, aBEnd, aIStart); |
1372 | | } |
1373 | | |
1374 | | /** |
1375 | | * Return an nsMargin containing our physical coordinates |
1376 | | */ |
1377 | | nsMargin GetPhysicalMargin(WritingMode aWritingMode) const |
1378 | 0 | { |
1379 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1380 | 0 | return aWritingMode.IsVertical() |
1381 | 0 | ? (aWritingMode.IsVerticalLR() |
1382 | 0 | ? (aWritingMode.IsInlineReversed() |
1383 | 0 | ? nsMargin(IEnd(), BEnd(), IStart(), BStart()) |
1384 | 0 | : nsMargin(IStart(), BEnd(), IEnd(), BStart())) |
1385 | 0 | : (aWritingMode.IsInlineReversed() |
1386 | 0 | ? nsMargin(IEnd(), BStart(), IStart(), BEnd()) |
1387 | 0 | : nsMargin(IStart(), BStart(), IEnd(), BEnd()))) |
1388 | 0 | : (aWritingMode.IsInlineReversed() |
1389 | 0 | ? nsMargin(BStart(), IStart(), BEnd(), IEnd()) |
1390 | 0 | : nsMargin(BStart(), IEnd(), BEnd(), IStart())); |
1391 | 0 | } |
1392 | | |
1393 | | /** |
1394 | | * Return a LogicalMargin representing this margin in a different |
1395 | | * writing mode |
1396 | | */ |
1397 | | LogicalMargin ConvertTo(WritingMode aToMode, WritingMode aFromMode) const |
1398 | 0 | { |
1399 | 0 | CHECK_WRITING_MODE(aFromMode); |
1400 | 0 | return aToMode == aFromMode ? |
1401 | 0 | *this : LogicalMargin(aToMode, GetPhysicalMargin(aFromMode)); |
1402 | 0 | } |
1403 | | |
1404 | | void ApplySkipSides(LogicalSides aSkipSides) |
1405 | 0 | { |
1406 | 0 | if (aSkipSides.BStart()) { |
1407 | 0 | BStart() = 0; |
1408 | 0 | } |
1409 | 0 | if (aSkipSides.BEnd()) { |
1410 | 0 | BEnd() = 0; |
1411 | 0 | } |
1412 | 0 | if (aSkipSides.IStart()) { |
1413 | 0 | IStart() = 0; |
1414 | 0 | } |
1415 | 0 | if (aSkipSides.IEnd()) { |
1416 | 0 | IEnd() = 0; |
1417 | 0 | } |
1418 | 0 | } |
1419 | | |
1420 | | bool IsAllZero() const |
1421 | 0 | { |
1422 | 0 | return (mMargin.left == 0 && mMargin.top == 0 && |
1423 | 0 | mMargin.right == 0 && mMargin.bottom == 0); |
1424 | 0 | } |
1425 | | |
1426 | 0 | LogicalMargin operator+(const LogicalMargin& aMargin) const { |
1427 | 0 | CHECK_WRITING_MODE(aMargin.GetWritingMode()); |
1428 | 0 | return LogicalMargin(GetWritingMode(), |
1429 | 0 | BStart() + aMargin.BStart(), |
1430 | 0 | IEnd() + aMargin.IEnd(), |
1431 | 0 | BEnd() + aMargin.BEnd(), |
1432 | 0 | IStart() + aMargin.IStart()); |
1433 | 0 | } |
1434 | | |
1435 | | LogicalMargin operator+=(const LogicalMargin& aMargin) |
1436 | 0 | { |
1437 | 0 | CHECK_WRITING_MODE(aMargin.GetWritingMode()); |
1438 | 0 | mMargin += aMargin.mMargin; |
1439 | 0 | return *this; |
1440 | 0 | } |
1441 | | |
1442 | 0 | LogicalMargin operator-(const LogicalMargin& aMargin) const { |
1443 | 0 | CHECK_WRITING_MODE(aMargin.GetWritingMode()); |
1444 | 0 | return LogicalMargin(GetWritingMode(), |
1445 | 0 | BStart() - aMargin.BStart(), |
1446 | 0 | IEnd() - aMargin.IEnd(), |
1447 | 0 | BEnd() - aMargin.BEnd(), |
1448 | 0 | IStart() - aMargin.IStart()); |
1449 | 0 | } |
1450 | | |
1451 | | private: |
1452 | | friend class LogicalRect; |
1453 | | |
1454 | | LogicalMargin() = delete; |
1455 | | |
1456 | | #ifdef DEBUG |
1457 | | WritingMode GetWritingMode() const { return mWritingMode; } |
1458 | | #else |
1459 | 0 | WritingMode GetWritingMode() const { return WritingMode::Unknown(); } |
1460 | | #endif |
1461 | | |
1462 | | nscoord IStart() const // inline-start margin |
1463 | 0 | { |
1464 | 0 | return mMargin.left; |
1465 | 0 | } |
1466 | | nscoord IEnd() const // inline-end margin |
1467 | 0 | { |
1468 | 0 | return mMargin.right; |
1469 | 0 | } |
1470 | | nscoord BStart() const // block-start margin |
1471 | 0 | { |
1472 | 0 | return mMargin.top; |
1473 | 0 | } |
1474 | | nscoord BEnd() const // block-end margin |
1475 | 0 | { |
1476 | 0 | return mMargin.bottom; |
1477 | 0 | } |
1478 | | |
1479 | | nscoord& IStart() // inline-start margin |
1480 | 0 | { |
1481 | 0 | return mMargin.left; |
1482 | 0 | } |
1483 | | nscoord& IEnd() // inline-end margin |
1484 | 0 | { |
1485 | 0 | return mMargin.right; |
1486 | 0 | } |
1487 | | nscoord& BStart() // block-start margin |
1488 | 0 | { |
1489 | 0 | return mMargin.top; |
1490 | 0 | } |
1491 | | nscoord& BEnd() // block-end margin |
1492 | 0 | { |
1493 | 0 | return mMargin.bottom; |
1494 | 0 | } |
1495 | | |
1496 | | nscoord IStartEnd() const // inline margins |
1497 | 0 | { |
1498 | 0 | return mMargin.LeftRight(); |
1499 | 0 | } |
1500 | | nscoord BStartEnd() const // block margins |
1501 | 0 | { |
1502 | 0 | return mMargin.TopBottom(); |
1503 | 0 | } |
1504 | | |
1505 | | #ifdef DEBUG |
1506 | | WritingMode mWritingMode; |
1507 | | #endif |
1508 | | nsMargin mMargin; |
1509 | | }; |
1510 | | |
1511 | | /** |
1512 | | * Flow-relative rectangle |
1513 | | */ |
1514 | | class LogicalRect { |
1515 | | public: |
1516 | | explicit LogicalRect(WritingMode aWritingMode) |
1517 | | : |
1518 | | #ifdef DEBUG |
1519 | | mWritingMode(aWritingMode), |
1520 | | #endif |
1521 | | mIStart(0), |
1522 | | mBStart(0), |
1523 | | mISize(0), |
1524 | | mBSize(0) |
1525 | 0 | { } |
1526 | | |
1527 | | LogicalRect(WritingMode aWritingMode, |
1528 | | nscoord aIStart, nscoord aBStart, |
1529 | | nscoord aISize, nscoord aBSize) |
1530 | | : |
1531 | | #ifdef DEBUG |
1532 | | mWritingMode(aWritingMode), |
1533 | | #endif |
1534 | | mIStart(aIStart), |
1535 | | mBStart(aBStart), |
1536 | | mISize(aISize), |
1537 | | mBSize(aBSize) |
1538 | 0 | { } |
1539 | | |
1540 | | LogicalRect(WritingMode aWritingMode, |
1541 | | const LogicalPoint& aOrigin, |
1542 | | const LogicalSize& aSize) |
1543 | | : |
1544 | | #ifdef DEBUG |
1545 | | mWritingMode(aWritingMode), |
1546 | | #endif |
1547 | | mIStart(aOrigin.mPoint.x), |
1548 | | mBStart(aOrigin.mPoint.y), |
1549 | | mISize(aSize.mSize.width), |
1550 | | mBSize(aSize.mSize.height) |
1551 | | { |
1552 | | CHECK_WRITING_MODE(aOrigin.GetWritingMode()); |
1553 | | CHECK_WRITING_MODE(aSize.GetWritingMode()); |
1554 | | } |
1555 | | |
1556 | | LogicalRect(WritingMode aWritingMode, |
1557 | | const nsRect& aRect, |
1558 | | const nsSize& aContainerSize) |
1559 | | #ifdef DEBUG |
1560 | | : mWritingMode(aWritingMode) |
1561 | | #endif |
1562 | 0 | { |
1563 | 0 | if (aWritingMode.IsVertical()) { |
1564 | 0 | mBStart = aWritingMode.IsVerticalLR() |
1565 | 0 | ? aRect.X() : aContainerSize.width - aRect.XMost(); |
1566 | 0 | mIStart = aWritingMode.IsInlineReversed() |
1567 | 0 | ? aContainerSize.height - aRect.YMost() : aRect.Y(); |
1568 | 0 | mBSize = aRect.Width(); |
1569 | 0 | mISize = aRect.Height(); |
1570 | 0 | } else { |
1571 | 0 | mIStart = aWritingMode.IsInlineReversed() |
1572 | 0 | ? aContainerSize.width - aRect.XMost() : aRect.X(); |
1573 | 0 | mBStart = aRect.Y(); |
1574 | 0 | mISize = aRect.Width(); |
1575 | 0 | mBSize = aRect.Height(); |
1576 | 0 | } |
1577 | 0 | } |
1578 | | |
1579 | | /** |
1580 | | * Inline- and block-dimension geometry. |
1581 | | */ |
1582 | | nscoord IStart(WritingMode aWritingMode) const // inline-start edge |
1583 | 0 | { |
1584 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1585 | 0 | return mIStart; |
1586 | 0 | } |
1587 | | nscoord IEnd(WritingMode aWritingMode) const // inline-end edge |
1588 | 0 | { |
1589 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1590 | 0 | return mIStart + mISize; |
1591 | 0 | } |
1592 | | nscoord ISize(WritingMode aWritingMode) const // inline-size |
1593 | 0 | { |
1594 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1595 | 0 | return mISize; |
1596 | 0 | } |
1597 | | |
1598 | | nscoord BStart(WritingMode aWritingMode) const // block-start edge |
1599 | 0 | { |
1600 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1601 | 0 | return mBStart; |
1602 | 0 | } |
1603 | | nscoord BEnd(WritingMode aWritingMode) const // block-end edge |
1604 | 0 | { |
1605 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1606 | 0 | return mBStart + mBSize; |
1607 | 0 | } |
1608 | | nscoord BSize(WritingMode aWritingMode) const // block-size |
1609 | 0 | { |
1610 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1611 | 0 | return mBSize; |
1612 | 0 | } |
1613 | | |
1614 | | /** |
1615 | | * Writable (reference) accessors are only available for the basic logical |
1616 | | * fields (Start and Size), not derivatives like End. |
1617 | | */ |
1618 | | nscoord& IStart(WritingMode aWritingMode) // inline-start edge |
1619 | 0 | { |
1620 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1621 | 0 | return mIStart; |
1622 | 0 | } |
1623 | | nscoord& ISize(WritingMode aWritingMode) // inline-size |
1624 | 0 | { |
1625 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1626 | 0 | return mISize; |
1627 | 0 | } |
1628 | | nscoord& BStart(WritingMode aWritingMode) // block-start edge |
1629 | 0 | { |
1630 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1631 | 0 | return mBStart; |
1632 | 0 | } |
1633 | | nscoord& BSize(WritingMode aWritingMode) // block-size |
1634 | 0 | { |
1635 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1636 | 0 | return mBSize; |
1637 | 0 | } |
1638 | | |
1639 | | /** |
1640 | | * Accessors for line-relative coordinates |
1641 | | */ |
1642 | | nscoord LineLeft(WritingMode aWritingMode, |
1643 | | const nsSize& aContainerSize) const |
1644 | | { |
1645 | | CHECK_WRITING_MODE(aWritingMode); |
1646 | | if (aWritingMode.IsBidiLTR()) { |
1647 | | return IStart(); |
1648 | | } |
1649 | | nscoord containerISize = |
1650 | | aWritingMode.IsVertical() ? aContainerSize.height : aContainerSize.width; |
1651 | | return containerISize - IEnd(); |
1652 | | } |
1653 | | nscoord LineRight(WritingMode aWritingMode, |
1654 | | const nsSize& aContainerSize) const |
1655 | | { |
1656 | | CHECK_WRITING_MODE(aWritingMode); |
1657 | | if (aWritingMode.IsBidiLTR()) { |
1658 | | return IEnd(); |
1659 | | } |
1660 | | nscoord containerISize = |
1661 | | aWritingMode.IsVertical() ? aContainerSize.height : aContainerSize.width; |
1662 | | return containerISize - IStart(); |
1663 | | } |
1664 | | |
1665 | | /** |
1666 | | * Physical coordinates of the rect. |
1667 | | */ |
1668 | | nscoord X(WritingMode aWritingMode, nscoord aContainerWidth) const |
1669 | 0 | { |
1670 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1671 | 0 | if (aWritingMode.IsVertical()) { |
1672 | 0 | return aWritingMode.IsVerticalLR() ? |
1673 | 0 | mBStart : aContainerWidth - BEnd(); |
1674 | 0 | } else { |
1675 | 0 | return aWritingMode.IsInlineReversed() ? |
1676 | 0 | aContainerWidth - IEnd() : mIStart; |
1677 | 0 | } |
1678 | 0 | } |
1679 | | |
1680 | | nscoord Y(WritingMode aWritingMode, nscoord aContainerHeight) const |
1681 | 0 | { |
1682 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1683 | 0 | if (aWritingMode.IsVertical()) { |
1684 | 0 | return aWritingMode.IsInlineReversed() ? aContainerHeight - IEnd() |
1685 | 0 | : mIStart; |
1686 | 0 | } else { |
1687 | 0 | return mBStart; |
1688 | 0 | } |
1689 | 0 | } |
1690 | | |
1691 | | nscoord Width(WritingMode aWritingMode) const |
1692 | 0 | { |
1693 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1694 | 0 | return aWritingMode.IsVertical() ? mBSize : mISize; |
1695 | 0 | } |
1696 | | |
1697 | | nscoord Height(WritingMode aWritingMode) const |
1698 | 0 | { |
1699 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1700 | 0 | return aWritingMode.IsVertical() ? mISize : mBSize; |
1701 | 0 | } |
1702 | | |
1703 | | nscoord XMost(WritingMode aWritingMode, nscoord aContainerWidth) const |
1704 | 0 | { |
1705 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1706 | 0 | if (aWritingMode.IsVertical()) { |
1707 | 0 | return aWritingMode.IsVerticalLR() ? |
1708 | 0 | BEnd() : aContainerWidth - mBStart; |
1709 | 0 | } else { |
1710 | 0 | return aWritingMode.IsInlineReversed() ? |
1711 | 0 | aContainerWidth - mIStart : IEnd(); |
1712 | 0 | } |
1713 | 0 | } |
1714 | | |
1715 | | nscoord YMost(WritingMode aWritingMode, nscoord aContainerHeight) const |
1716 | 0 | { |
1717 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1718 | 0 | if (aWritingMode.IsVertical()) { |
1719 | 0 | return aWritingMode.IsInlineReversed() ? aContainerHeight - mIStart |
1720 | 0 | : IEnd(); |
1721 | 0 | } else { |
1722 | 0 | return mBStart; |
1723 | 0 | } |
1724 | 0 | } |
1725 | | |
1726 | | bool IsEmpty() const |
1727 | 0 | { |
1728 | 0 | return mISize <= 0 || mBSize <= 0; |
1729 | 0 | } |
1730 | | |
1731 | | bool IsAllZero() const |
1732 | | { |
1733 | | return (mIStart == 0 && mBStart == 0 && |
1734 | | mISize == 0 && mBSize == 0); |
1735 | | } |
1736 | | |
1737 | | bool IsZeroSize() const |
1738 | 0 | { |
1739 | 0 | return (mISize == 0 && mBSize == 0); |
1740 | 0 | } |
1741 | | |
1742 | 0 | void SetEmpty() { mISize = mBSize = 0; } |
1743 | | |
1744 | | bool IsEqualEdges(const LogicalRect aOther) const |
1745 | 0 | { |
1746 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1747 | 0 | bool result = mIStart == aOther.mIStart && mBStart == aOther.mBStart && |
1748 | 0 | mISize == aOther.mISize && mBSize == aOther.mBSize; |
1749 | 0 |
|
1750 | 0 | // We want the same result as nsRect, so assert we get it. |
1751 | 0 | MOZ_ASSERT(result == nsRect(mIStart, mBStart, mISize, mBSize). |
1752 | 0 | IsEqualEdges(nsRect(aOther.mIStart, aOther.mBStart, |
1753 | 0 | aOther.mISize, aOther.mBSize))); |
1754 | 0 | return result; |
1755 | 0 | } |
1756 | | |
1757 | | LogicalPoint Origin(WritingMode aWritingMode) const |
1758 | 0 | { |
1759 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1760 | 0 | return LogicalPoint(aWritingMode, IStart(), BStart()); |
1761 | 0 | } |
1762 | | void SetOrigin(WritingMode aWritingMode, const LogicalPoint& aPoint) |
1763 | 0 | { |
1764 | 0 | IStart(aWritingMode) = aPoint.I(aWritingMode); |
1765 | 0 | BStart(aWritingMode) = aPoint.B(aWritingMode); |
1766 | 0 | } |
1767 | | |
1768 | | LogicalSize Size(WritingMode aWritingMode) const |
1769 | | { |
1770 | | CHECK_WRITING_MODE(aWritingMode); |
1771 | | return LogicalSize(aWritingMode, ISize(), BSize()); |
1772 | | } |
1773 | | |
1774 | | LogicalRect operator+(const LogicalPoint& aPoint) const |
1775 | 0 | { |
1776 | 0 | CHECK_WRITING_MODE(aPoint.GetWritingMode()); |
1777 | 0 | return LogicalRect(GetWritingMode(), |
1778 | 0 | IStart() + aPoint.I(), BStart() + aPoint.B(), |
1779 | 0 | ISize(), BSize()); |
1780 | 0 | } |
1781 | | |
1782 | | LogicalRect& operator+=(const LogicalPoint& aPoint) |
1783 | 0 | { |
1784 | 0 | CHECK_WRITING_MODE(aPoint.GetWritingMode()); |
1785 | 0 | mIStart += aPoint.mPoint.x; |
1786 | 0 | mBStart += aPoint.mPoint.y; |
1787 | 0 | return *this; |
1788 | 0 | } |
1789 | | |
1790 | | LogicalRect operator-(const LogicalPoint& aPoint) const |
1791 | 0 | { |
1792 | 0 | CHECK_WRITING_MODE(aPoint.GetWritingMode()); |
1793 | 0 | return LogicalRect(GetWritingMode(), |
1794 | 0 | IStart() - aPoint.I(), BStart() - aPoint.B(), |
1795 | 0 | ISize(), BSize()); |
1796 | 0 | } |
1797 | | |
1798 | | LogicalRect& operator-=(const LogicalPoint& aPoint) |
1799 | 0 | { |
1800 | 0 | CHECK_WRITING_MODE(aPoint.GetWritingMode()); |
1801 | 0 | mIStart -= aPoint.mPoint.x; |
1802 | 0 | mBStart -= aPoint.mPoint.y; |
1803 | 0 | return *this; |
1804 | 0 | } |
1805 | | |
1806 | | void MoveBy(WritingMode aWritingMode, const LogicalPoint& aDelta) |
1807 | | { |
1808 | | CHECK_WRITING_MODE(aWritingMode); |
1809 | | CHECK_WRITING_MODE(aDelta.GetWritingMode()); |
1810 | | IStart() += aDelta.I(); |
1811 | | BStart() += aDelta.B(); |
1812 | | } |
1813 | | |
1814 | | void Inflate(nscoord aD) |
1815 | 0 | { |
1816 | 0 | #ifdef DEBUG |
1817 | 0 | // Compute using nsRect and assert the results match |
1818 | 0 | nsRect rectDebug(mIStart, mBStart, mISize, mBSize); |
1819 | 0 | rectDebug.Inflate(aD); |
1820 | 0 | #endif |
1821 | 0 | mIStart -= aD; |
1822 | 0 | mBStart -= aD; |
1823 | 0 | mISize += 2 * aD; |
1824 | 0 | mBSize += 2 * aD; |
1825 | 0 | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1826 | 0 | } |
1827 | | void Inflate(nscoord aDI, nscoord aDB) |
1828 | 0 | { |
1829 | 0 | #ifdef DEBUG |
1830 | 0 | // Compute using nsRect and assert the results match |
1831 | 0 | nsRect rectDebug(mIStart, mBStart, mISize, mBSize); |
1832 | 0 | rectDebug.Inflate(aDI, aDB); |
1833 | 0 | #endif |
1834 | 0 | mIStart -= aDI; |
1835 | 0 | mBStart -= aDB; |
1836 | 0 | mISize += 2 * aDI; |
1837 | 0 | mBSize += 2 * aDB; |
1838 | 0 | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1839 | 0 | } |
1840 | | void Inflate(WritingMode aWritingMode, const LogicalMargin& aMargin) |
1841 | | { |
1842 | | CHECK_WRITING_MODE(aWritingMode); |
1843 | | CHECK_WRITING_MODE(aMargin.GetWritingMode()); |
1844 | | #ifdef DEBUG |
1845 | | // Compute using nsRect and assert the results match |
1846 | | nsRect rectDebug(mIStart, mBStart, mISize, mBSize); |
1847 | | rectDebug.Inflate(aMargin.mMargin); |
1848 | | #endif |
1849 | | mIStart -= aMargin.mMargin.left; |
1850 | | mBStart -= aMargin.mMargin.top; |
1851 | | mISize += aMargin.mMargin.LeftRight(); |
1852 | | mBSize += aMargin.mMargin.TopBottom(); |
1853 | | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1854 | | } |
1855 | | |
1856 | | void Deflate(nscoord aD) |
1857 | 0 | { |
1858 | 0 | #ifdef DEBUG |
1859 | 0 | // Compute using nsRect and assert the results match |
1860 | 0 | nsRect rectDebug(mIStart, mBStart, mISize, mBSize); |
1861 | 0 | rectDebug.Deflate(aD); |
1862 | 0 | #endif |
1863 | 0 | mIStart += aD; |
1864 | 0 | mBStart += aD; |
1865 | 0 | mISize = std::max(0, mISize - 2 * aD); |
1866 | 0 | mBSize = std::max(0, mBSize - 2 * aD); |
1867 | 0 | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1868 | 0 | } |
1869 | | void Deflate(nscoord aDI, nscoord aDB) |
1870 | 0 | { |
1871 | 0 | #ifdef DEBUG |
1872 | 0 | // Compute using nsRect and assert the results match |
1873 | 0 | nsRect rectDebug(mIStart, mBStart, mISize, mBSize); |
1874 | 0 | rectDebug.Deflate(aDI, aDB); |
1875 | 0 | #endif |
1876 | 0 | mIStart += aDI; |
1877 | 0 | mBStart += aDB; |
1878 | 0 | mISize = std::max(0, mISize - 2 * aDI); |
1879 | 0 | mBSize = std::max(0, mBSize - 2 * aDB); |
1880 | 0 | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1881 | 0 | } |
1882 | | void Deflate(WritingMode aWritingMode, const LogicalMargin& aMargin) |
1883 | | { |
1884 | | CHECK_WRITING_MODE(aWritingMode); |
1885 | | CHECK_WRITING_MODE(aMargin.GetWritingMode()); |
1886 | | #ifdef DEBUG |
1887 | | // Compute using nsRect and assert the results match |
1888 | | nsRect rectDebug(mIStart, mBStart, mISize, mBSize); |
1889 | | rectDebug.Deflate(aMargin.mMargin); |
1890 | | #endif |
1891 | | mIStart += aMargin.mMargin.left; |
1892 | | mBStart += aMargin.mMargin.top; |
1893 | | mISize = std::max(0, mISize - aMargin.mMargin.LeftRight()); |
1894 | | mBSize = std::max(0, mBSize - aMargin.mMargin.TopBottom()); |
1895 | | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1896 | | } |
1897 | | |
1898 | | /** |
1899 | | * Return an nsRect containing our physical coordinates within the given |
1900 | | * container size. |
1901 | | */ |
1902 | | nsRect GetPhysicalRect(WritingMode aWritingMode, |
1903 | | const nsSize& aContainerSize) const |
1904 | 0 | { |
1905 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1906 | 0 | if (aWritingMode.IsVertical()) { |
1907 | 0 | return nsRect(aWritingMode.IsVerticalLR() |
1908 | 0 | ? BStart() : aContainerSize.width - BEnd(), |
1909 | 0 | aWritingMode.IsInlineReversed() |
1910 | 0 | ? aContainerSize.height - IEnd() : IStart(), |
1911 | 0 | BSize(), ISize()); |
1912 | 0 | } else { |
1913 | 0 | return nsRect(aWritingMode.IsInlineReversed() |
1914 | 0 | ? aContainerSize.width - IEnd() : IStart(), |
1915 | 0 | BStart(), ISize(), BSize()); |
1916 | 0 | } |
1917 | 0 | } |
1918 | | |
1919 | | /** |
1920 | | * Return a LogicalRect representing this rect in a different writing mode |
1921 | | */ |
1922 | | LogicalRect ConvertTo(WritingMode aToMode, WritingMode aFromMode, |
1923 | | const nsSize& aContainerSize) const |
1924 | 0 | { |
1925 | 0 | CHECK_WRITING_MODE(aFromMode); |
1926 | 0 | return aToMode == aFromMode ? |
1927 | 0 | *this : LogicalRect(aToMode, GetPhysicalRect(aFromMode, aContainerSize), |
1928 | 0 | aContainerSize); |
1929 | 0 | } |
1930 | | |
1931 | | /** |
1932 | | * Set *this to be the rectangle containing the intersection of aRect1 |
1933 | | * and aRect2, return whether the intersection is non-empty. |
1934 | | */ |
1935 | | bool IntersectRect(const LogicalRect& aRect1, const LogicalRect& aRect2) |
1936 | | { |
1937 | | CHECK_WRITING_MODE(aRect1.mWritingMode); |
1938 | | CHECK_WRITING_MODE(aRect2.mWritingMode); |
1939 | | #ifdef DEBUG |
1940 | | // Compute using nsRect and assert the results match |
1941 | | nsRect rectDebug; |
1942 | | rectDebug.IntersectRect(nsRect(aRect1.mIStart, aRect1.mBStart, |
1943 | | aRect1.mISize, aRect1.mBSize), |
1944 | | nsRect(aRect2.mIStart, aRect2.mBStart, |
1945 | | aRect2.mISize, aRect2.mBSize)); |
1946 | | #endif |
1947 | | |
1948 | | nscoord iEnd = std::min(aRect1.IEnd(), aRect2.IEnd()); |
1949 | | mIStart = std::max(aRect1.mIStart, aRect2.mIStart); |
1950 | | mISize = iEnd - mIStart; |
1951 | | |
1952 | | nscoord bEnd = std::min(aRect1.BEnd(), aRect2.BEnd()); |
1953 | | mBStart = std::max(aRect1.mBStart, aRect2.mBStart); |
1954 | | mBSize = bEnd - mBStart; |
1955 | | |
1956 | | if (mISize < 0 || mBSize < 0) { |
1957 | | mISize = 0; |
1958 | | mBSize = 0; |
1959 | | } |
1960 | | |
1961 | | MOZ_ASSERT((rectDebug.IsEmpty() && (mISize == 0 || mBSize == 0)) || rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1962 | | return mISize > 0 && mBSize > 0; |
1963 | | } |
1964 | | |
1965 | | private: |
1966 | | LogicalRect() = delete; |
1967 | | |
1968 | | #ifdef DEBUG |
1969 | | WritingMode GetWritingMode() const { return mWritingMode; } |
1970 | | #else |
1971 | 0 | WritingMode GetWritingMode() const { return WritingMode::Unknown(); } |
1972 | | #endif |
1973 | | |
1974 | | nscoord IStart() const // inline-start edge |
1975 | 0 | { |
1976 | 0 | return mIStart; |
1977 | 0 | } |
1978 | | nscoord IEnd() const // inline-end edge |
1979 | 0 | { |
1980 | 0 | return mIStart + mISize; |
1981 | 0 | } |
1982 | | nscoord ISize() const // inline-size |
1983 | 0 | { |
1984 | 0 | return mISize; |
1985 | 0 | } |
1986 | | |
1987 | | nscoord BStart() const // block-start edge |
1988 | 0 | { |
1989 | 0 | return mBStart; |
1990 | 0 | } |
1991 | | nscoord BEnd() const // block-end edge |
1992 | 0 | { |
1993 | 0 | return mBStart + mBSize; |
1994 | 0 | } |
1995 | | nscoord BSize() const // block-size |
1996 | 0 | { |
1997 | 0 | return mBSize; |
1998 | 0 | } |
1999 | | |
2000 | | nscoord& IStart() // inline-start edge |
2001 | | { |
2002 | | return mIStart; |
2003 | | } |
2004 | | nscoord& ISize() // inline-size |
2005 | 0 | { |
2006 | 0 | return mISize; |
2007 | 0 | } |
2008 | | nscoord& BStart() // block-start edge |
2009 | | { |
2010 | | return mBStart; |
2011 | | } |
2012 | | nscoord& BSize() // block-size |
2013 | 0 | { |
2014 | 0 | return mBSize; |
2015 | 0 | } |
2016 | | |
2017 | | #ifdef DEBUG |
2018 | | WritingMode mWritingMode; |
2019 | | #endif |
2020 | | // Inline- and block-geometry dimension |
2021 | | nscoord mIStart; // inline-start edge |
2022 | | nscoord mBStart; // block-start edge |
2023 | | nscoord mISize; // inline-size |
2024 | | nscoord mBSize; // block-size |
2025 | | }; |
2026 | | |
2027 | | } // namespace mozilla |
2028 | | |
2029 | | // Definitions of inline methods for nsStyleSides, declared in nsStyleCoord.h |
2030 | | // but not defined there because they need WritingMode. |
2031 | | inline nsStyleUnit nsStyleSides::GetUnit(mozilla::WritingMode aWM, |
2032 | | mozilla::LogicalSide aSide) const |
2033 | 0 | { |
2034 | 0 | return GetUnit(aWM.PhysicalSide(aSide)); |
2035 | 0 | } |
2036 | | |
2037 | | inline nsStyleUnit nsStyleSides::GetIStartUnit(mozilla::WritingMode aWM) const |
2038 | 0 | { |
2039 | 0 | return GetUnit(aWM, mozilla::eLogicalSideIStart); |
2040 | 0 | } |
2041 | | |
2042 | | inline nsStyleUnit nsStyleSides::GetBStartUnit(mozilla::WritingMode aWM) const |
2043 | 0 | { |
2044 | 0 | return GetUnit(aWM, mozilla::eLogicalSideBStart); |
2045 | 0 | } |
2046 | | |
2047 | | inline nsStyleUnit nsStyleSides::GetIEndUnit(mozilla::WritingMode aWM) const |
2048 | 0 | { |
2049 | 0 | return GetUnit(aWM, mozilla::eLogicalSideIEnd); |
2050 | 0 | } |
2051 | | |
2052 | | inline nsStyleUnit nsStyleSides::GetBEndUnit(mozilla::WritingMode aWM) const |
2053 | 0 | { |
2054 | 0 | return GetUnit(aWM, mozilla::eLogicalSideBEnd); |
2055 | 0 | } |
2056 | | |
2057 | | inline bool nsStyleSides::HasBlockAxisAuto(mozilla::WritingMode aWM) const |
2058 | | { |
2059 | | return GetBStartUnit(aWM) == eStyleUnit_Auto || |
2060 | | GetBEndUnit(aWM) == eStyleUnit_Auto; |
2061 | | } |
2062 | | |
2063 | | inline bool nsStyleSides::HasInlineAxisAuto(mozilla::WritingMode aWM) const |
2064 | | { |
2065 | | return GetIStartUnit(aWM) == eStyleUnit_Auto || |
2066 | | GetIEndUnit(aWM) == eStyleUnit_Auto; |
2067 | | } |
2068 | | |
2069 | | inline nsStyleCoord nsStyleSides::Get(mozilla::WritingMode aWM, |
2070 | | mozilla::LogicalSide aSide) const |
2071 | 0 | { |
2072 | 0 | return Get(aWM.PhysicalSide(aSide)); |
2073 | 0 | } |
2074 | | |
2075 | | inline nsStyleCoord nsStyleSides::GetIStart(mozilla::WritingMode aWM) const |
2076 | 0 | { |
2077 | 0 | return Get(aWM, mozilla::eLogicalSideIStart); |
2078 | 0 | } |
2079 | | |
2080 | | inline nsStyleCoord nsStyleSides::GetBStart(mozilla::WritingMode aWM) const |
2081 | 0 | { |
2082 | 0 | return Get(aWM, mozilla::eLogicalSideBStart); |
2083 | 0 | } |
2084 | | |
2085 | | inline nsStyleCoord nsStyleSides::GetIEnd(mozilla::WritingMode aWM) const |
2086 | 0 | { |
2087 | 0 | return Get(aWM, mozilla::eLogicalSideIEnd); |
2088 | 0 | } |
2089 | | |
2090 | | inline nsStyleCoord nsStyleSides::GetBEnd(mozilla::WritingMode aWM) const |
2091 | 0 | { |
2092 | 0 | return Get(aWM, mozilla::eLogicalSideBEnd); |
2093 | 0 | } |
2094 | | |
2095 | | // Definitions of inline methods for nsStylePosition, declared in |
2096 | | // nsStyleStruct.h but not defined there because they need WritingMode. |
2097 | | inline nsStyleCoord& nsStylePosition::ISize(mozilla::WritingMode aWM) |
2098 | 0 | { |
2099 | 0 | return aWM.IsVertical() ? mHeight : mWidth; |
2100 | 0 | } |
2101 | | inline nsStyleCoord& nsStylePosition::MinISize(mozilla::WritingMode aWM) |
2102 | 0 | { |
2103 | 0 | return aWM.IsVertical() ? mMinHeight : mMinWidth; |
2104 | 0 | } |
2105 | | inline nsStyleCoord& nsStylePosition::MaxISize(mozilla::WritingMode aWM) |
2106 | 0 | { |
2107 | 0 | return aWM.IsVertical() ? mMaxHeight : mMaxWidth; |
2108 | 0 | } |
2109 | | inline nsStyleCoord& nsStylePosition::BSize(mozilla::WritingMode aWM) |
2110 | 0 | { |
2111 | 0 | return aWM.IsVertical() ? mWidth : mHeight; |
2112 | 0 | } |
2113 | | inline nsStyleCoord& nsStylePosition::MinBSize(mozilla::WritingMode aWM) |
2114 | 0 | { |
2115 | 0 | return aWM.IsVertical() ? mMinWidth : mMinHeight; |
2116 | 0 | } |
2117 | | inline nsStyleCoord& nsStylePosition::MaxBSize(mozilla::WritingMode aWM) |
2118 | 0 | { |
2119 | 0 | return aWM.IsVertical() ? mMaxWidth : mMaxHeight; |
2120 | 0 | } |
2121 | | |
2122 | | inline const nsStyleCoord& |
2123 | | nsStylePosition::ISize(mozilla::WritingMode aWM) const |
2124 | 0 | { |
2125 | 0 | return aWM.IsVertical() ? mHeight : mWidth; |
2126 | 0 | } |
2127 | | inline const nsStyleCoord& |
2128 | | nsStylePosition::MinISize(mozilla::WritingMode aWM) const |
2129 | 0 | { |
2130 | 0 | return aWM.IsVertical() ? mMinHeight : mMinWidth; |
2131 | 0 | } |
2132 | | inline const nsStyleCoord& |
2133 | | nsStylePosition::MaxISize(mozilla::WritingMode aWM) const |
2134 | 0 | { |
2135 | 0 | return aWM.IsVertical() ? mMaxHeight : mMaxWidth; |
2136 | 0 | } |
2137 | | inline const nsStyleCoord& |
2138 | | nsStylePosition::BSize(mozilla::WritingMode aWM) const |
2139 | 0 | { |
2140 | 0 | return aWM.IsVertical() ? mWidth : mHeight; |
2141 | 0 | } |
2142 | | inline const nsStyleCoord& |
2143 | | nsStylePosition::MinBSize(mozilla::WritingMode aWM) const |
2144 | 0 | { |
2145 | 0 | return aWM.IsVertical() ? mMinWidth : mMinHeight; |
2146 | 0 | } |
2147 | | inline const nsStyleCoord& |
2148 | | nsStylePosition::MaxBSize(mozilla::WritingMode aWM) const |
2149 | 0 | { |
2150 | 0 | return aWM.IsVertical() ? mMaxWidth : mMaxHeight; |
2151 | 0 | } |
2152 | | |
2153 | | inline bool |
2154 | | nsStylePosition::ISizeDependsOnContainer(mozilla::WritingMode aWM) const |
2155 | | { |
2156 | | return aWM.IsVertical() ? HeightDependsOnContainer() |
2157 | | : WidthDependsOnContainer(); |
2158 | | } |
2159 | | inline bool |
2160 | | nsStylePosition::MinISizeDependsOnContainer(mozilla::WritingMode aWM) const |
2161 | | { |
2162 | | return aWM.IsVertical() ? MinHeightDependsOnContainer() |
2163 | | : MinWidthDependsOnContainer(); |
2164 | | } |
2165 | | inline bool |
2166 | | nsStylePosition::MaxISizeDependsOnContainer(mozilla::WritingMode aWM) const |
2167 | | { |
2168 | | return aWM.IsVertical() ? MaxHeightDependsOnContainer() |
2169 | | : MaxWidthDependsOnContainer(); |
2170 | | } |
2171 | | inline bool |
2172 | | nsStylePosition::BSizeDependsOnContainer(mozilla::WritingMode aWM) const |
2173 | 0 | { |
2174 | 0 | return aWM.IsVertical() ? WidthDependsOnContainer() |
2175 | 0 | : HeightDependsOnContainer(); |
2176 | 0 | } |
2177 | | inline bool |
2178 | | nsStylePosition::MinBSizeDependsOnContainer(mozilla::WritingMode aWM) const |
2179 | 0 | { |
2180 | 0 | return aWM.IsVertical() ? MinWidthDependsOnContainer() |
2181 | 0 | : MinHeightDependsOnContainer(); |
2182 | 0 | } |
2183 | | inline bool |
2184 | | nsStylePosition::MaxBSizeDependsOnContainer(mozilla::WritingMode aWM) const |
2185 | 0 | { |
2186 | 0 | return aWM.IsVertical() ? MaxWidthDependsOnContainer() |
2187 | 0 | : MaxHeightDependsOnContainer(); |
2188 | 0 | } |
2189 | | |
2190 | | inline bool |
2191 | | nsStyleMargin::HasBlockAxisAuto(mozilla::WritingMode aWM) const |
2192 | | { |
2193 | | return mMargin.HasBlockAxisAuto(aWM); |
2194 | | } |
2195 | | inline bool |
2196 | | nsStyleMargin::HasInlineAxisAuto(mozilla::WritingMode aWM) const |
2197 | | { |
2198 | | return mMargin.HasInlineAxisAuto(aWM); |
2199 | | } |
2200 | | |
2201 | | #endif // WritingModes_h_ |