/src/mozilla-central/layout/generic/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 | 0 | { |
51 | 0 | return aAxis == eLogicalAxisBlock ? eLogicalAxisInline : eLogicalAxisBlock; |
52 | 0 | } |
53 | | |
54 | | inline bool IsInline(LogicalSide aSide) { return aSide & 0x2; } |
55 | | inline bool IsBlock(LogicalSide aSide) { return !IsInline(aSide); } |
56 | | inline bool IsEnd(LogicalSide aSide) { return aSide & 0x1; } |
57 | | inline bool IsStart(LogicalSide aSide) { return !IsEnd(aSide); } |
58 | | |
59 | | inline LogicalAxis GetAxis(LogicalSide aSide) |
60 | 0 | { |
61 | 0 | return IsInline(aSide) ? eLogicalAxisInline : eLogicalAxisBlock; |
62 | 0 | } |
63 | | |
64 | | inline LogicalEdge GetEdge(LogicalSide aSide) |
65 | | { |
66 | | return IsEnd(aSide) ? eLogicalEdgeEnd : eLogicalEdgeStart; |
67 | | } |
68 | | |
69 | | inline LogicalEdge GetOppositeEdge(LogicalEdge aEdge) |
70 | 0 | { |
71 | 0 | // This relies on the only two LogicalEdge enum values being 0 and 1. |
72 | 0 | return LogicalEdge(1 - aEdge); |
73 | 0 | } |
74 | | |
75 | | inline LogicalSide |
76 | | MakeLogicalSide(LogicalAxis aAxis, LogicalEdge aEdge) |
77 | | { |
78 | | return LogicalSide((aAxis << 1) | aEdge); |
79 | | } |
80 | | |
81 | | inline LogicalSide GetOppositeSide(LogicalSide aSide) |
82 | 0 | { |
83 | 0 | return MakeLogicalSide(GetAxis(aSide), GetOppositeEdge(GetEdge(aSide))); |
84 | 0 | } |
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 | | LogicalSides() : mBits(0) {} |
109 | | explicit LogicalSides(LogicalSideBits aSideBits) |
110 | 0 | { |
111 | 0 | MOZ_ASSERT((aSideBits & ~eLogicalSideBitsAll) == 0, "illegal side bits"); |
112 | 0 | mBits = aSideBits; |
113 | 0 | } |
114 | | bool IsEmpty() const { return mBits == 0; } |
115 | | bool BStart() const { return mBits & eLogicalSideBitsBStart; } |
116 | | bool BEnd() const { return mBits & eLogicalSideBitsBEnd; } |
117 | | bool IStart() const { return mBits & eLogicalSideBitsIStart; } |
118 | | bool IEnd() const { return mBits & eLogicalSideBitsIEnd; } |
119 | | bool Contains(LogicalSideBits aSideBits) const |
120 | | { |
121 | | MOZ_ASSERT((aSideBits & ~eLogicalSideBitsAll) == 0, "illegal side bits"); |
122 | | return (mBits & aSideBits) == aSideBits; |
123 | | } |
124 | | LogicalSides operator|(LogicalSides aOther) const |
125 | 0 | { |
126 | 0 | return LogicalSides(LogicalSideBits(mBits | aOther.mBits)); |
127 | 0 | } |
128 | | LogicalSides operator|(LogicalSideBits aSideBits) const |
129 | | { |
130 | | return *this | LogicalSides(aSideBits); |
131 | | } |
132 | | LogicalSides& operator|=(LogicalSides aOther) |
133 | | { |
134 | | mBits |= aOther.mBits; |
135 | | return *this; |
136 | | } |
137 | | LogicalSides& operator|=(LogicalSideBits aSideBits) |
138 | | { |
139 | | return *this |= LogicalSides(aSideBits); |
140 | | } |
141 | | bool operator==(LogicalSides aOther) const |
142 | | { |
143 | | return mBits == aOther.mBits; |
144 | | } |
145 | | bool operator!=(LogicalSides aOther) const |
146 | | { |
147 | | return !(*this == aOther); |
148 | | } |
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 | | InlineDir GetInlineDir() const { return InlineDir(mWritingMode & eInlineMask); } |
206 | | |
207 | | /** |
208 | | * Return the absolute block flow direction as a BlockDir |
209 | | */ |
210 | | BlockDir GetBlockDir() const { return BlockDir(mWritingMode & eBlockMask); } |
211 | | |
212 | | /** |
213 | | * Return the line-relative inline flow direction as a BidiDir |
214 | | */ |
215 | | 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 | | bool IsInlineReversed() const { return !!(mWritingMode & eInlineFlowMask); } |
224 | | |
225 | | /** |
226 | | * Return true if bidi direction is LTR. (Convenience method) |
227 | | */ |
228 | | bool IsBidiLTR() const { return eBidiLTR == GetBidiDir(); } |
229 | | |
230 | | /** |
231 | | * True if vertical-mode block direction is LR (convenience method). |
232 | | */ |
233 | | bool IsVerticalLR() const { return eBlockLR == GetBlockDir(); } |
234 | | |
235 | | /** |
236 | | * True if vertical-mode block direction is RL (convenience method). |
237 | | */ |
238 | 0 | 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 | | 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 | | 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 | | { |
260 | | return IsLineInverted() ? -1 : 1; |
261 | | } |
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 | | 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 | | bool IsCentralBaseline() const { return IsVertical() && !IsSideways(); } |
284 | | |
285 | | /** |
286 | | * Return true if boxes with this writing mode should use alphabetical |
287 | | * baselines. |
288 | | */ |
289 | | bool IsAlphabeticalBaseline() const { return !IsCentralBaseline(); } |
290 | | |
291 | | |
292 | | static mozilla::PhysicalAxis PhysicalAxisForLogicalAxis( |
293 | | uint8_t aWritingModeValue, |
294 | | LogicalAxis aAxis) |
295 | | { |
296 | | // This relies on bit 0 of a writing-value mode indicating vertical |
297 | | // orientation and bit 0 of a LogicalAxis value indicating the inline axis, |
298 | | // so that it can correctly form mozilla::PhysicalAxis values using bit |
299 | | // manipulation. |
300 | | static_assert(NS_STYLE_WRITING_MODE_HORIZONTAL_TB == 0 && |
301 | | NS_STYLE_WRITING_MODE_VERTICAL_RL == 1 && |
302 | | NS_STYLE_WRITING_MODE_VERTICAL_LR == 3 && |
303 | | eLogicalAxisBlock == 0 && |
304 | | eLogicalAxisInline == 1 && |
305 | | eAxisVertical == 0 && |
306 | | eAxisHorizontal == 1, |
307 | | "unexpected writing-mode, logical axis or physical axis " |
308 | | "constant values"); |
309 | | return mozilla::PhysicalAxis((aWritingModeValue ^ aAxis) & 0x1); |
310 | | } |
311 | | |
312 | | mozilla::PhysicalAxis PhysicalAxis(LogicalAxis aAxis) const |
313 | | { |
314 | | // This will set wm to either NS_STYLE_WRITING_MODE_HORIZONTAL_TB or |
315 | | // NS_STYLE_WRITING_MODE_VERTICAL_RL, and not the other two (real |
316 | | // and hypothetical) values. But this is fine; we only need to |
317 | | // distinguish between vertical and horizontal in |
318 | | // PhysicalAxisForLogicalAxis. |
319 | | int wm = mWritingMode & eOrientationMask; |
320 | | return PhysicalAxisForLogicalAxis(wm, aAxis); |
321 | | } |
322 | | |
323 | | static mozilla::Side PhysicalSideForBlockAxis(uint8_t aWritingModeValue, |
324 | | LogicalEdge aEdge) |
325 | | { |
326 | | // indexes are NS_STYLE_WRITING_MODE_* values, which are the same as these |
327 | | // two-bit values: |
328 | | // bit 0 = the eOrientationMask value |
329 | | // bit 1 = the eBlockFlowMask value |
330 | | static const mozilla::Side kLogicalBlockSides[][2] = { |
331 | | { eSideTop, eSideBottom }, // horizontal-tb |
332 | | { eSideRight, eSideLeft }, // vertical-rl |
333 | | { eSideBottom, eSideTop }, // (horizontal-bt) |
334 | | { eSideLeft, eSideRight }, // vertical-lr |
335 | | }; |
336 | | |
337 | | // Ignore the SIDEWAYS_MASK bit of the writing-mode value, as this has no |
338 | | // effect on the side mappings. |
339 | | aWritingModeValue &= ~NS_STYLE_WRITING_MODE_SIDEWAYS_MASK; |
340 | | |
341 | | // What's left of the writing-mode should be in the range 0-3: |
342 | | NS_ASSERTION(aWritingModeValue < 4, "invalid aWritingModeValue value"); |
343 | | |
344 | | return kLogicalBlockSides[aWritingModeValue][aEdge]; |
345 | | } |
346 | | |
347 | | mozilla::Side PhysicalSideForInlineAxis(LogicalEdge aEdge) const |
348 | | { |
349 | | // indexes are four-bit values: |
350 | | // bit 0 = the eOrientationMask value |
351 | | // bit 1 = the eInlineFlowMask value |
352 | | // bit 2 = the eBlockFlowMask value |
353 | | // bit 3 = the eLineOrientMask value |
354 | | // Not all of these combinations can actually be specified via CSS: there |
355 | | // is no horizontal-bt writing-mode, and no text-orientation value that |
356 | | // produces "inverted" text. (The former 'sideways-left' value, no longer |
357 | | // in the spec, would have produced this in vertical-rl mode.) |
358 | | static const mozilla::Side kLogicalInlineSides[][2] = { |
359 | | { eSideLeft, eSideRight }, // horizontal-tb ltr |
360 | | { eSideTop, eSideBottom }, // vertical-rl ltr |
361 | | { eSideRight, eSideLeft }, // horizontal-tb rtl |
362 | | { eSideBottom, eSideTop }, // vertical-rl rtl |
363 | | { eSideRight, eSideLeft }, // (horizontal-bt) (inverted) ltr |
364 | | { eSideTop, eSideBottom }, // sideways-lr rtl |
365 | | { eSideLeft, eSideRight }, // (horizontal-bt) (inverted) rtl |
366 | | { eSideBottom, eSideTop }, // sideways-lr ltr |
367 | | { eSideLeft, eSideRight }, // horizontal-tb (inverted) rtl |
368 | | { eSideTop, eSideBottom }, // vertical-rl (inverted) rtl |
369 | | { eSideRight, eSideLeft }, // horizontal-tb (inverted) ltr |
370 | | { eSideBottom, eSideTop }, // vertical-rl (inverted) ltr |
371 | | { eSideLeft, eSideRight }, // (horizontal-bt) ltr |
372 | | { eSideTop, eSideBottom }, // vertical-lr ltr |
373 | | { eSideRight, eSideLeft }, // (horizontal-bt) rtl |
374 | | { eSideBottom, eSideTop }, // vertical-lr rtl |
375 | | }; |
376 | | |
377 | | // Inline axis sides depend on all three of writing-mode, text-orientation |
378 | | // and direction, which are encoded in the eOrientationMask, |
379 | | // eInlineFlowMask, eBlockFlowMask and eLineOrientMask bits. Use these four |
380 | | // bits to index into kLogicalInlineSides. |
381 | | static_assert(eOrientationMask == 0x01 && eInlineFlowMask == 0x02 && |
382 | | eBlockFlowMask == 0x04 && eLineOrientMask == 0x08, |
383 | | "unexpected mask values"); |
384 | | int index = mWritingMode & 0x0F; |
385 | | return kLogicalInlineSides[index][aEdge]; |
386 | | } |
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 | | { |
394 | | if (IsBlock(aSide)) { |
395 | | static_assert(eOrientationMask == 0x01 && eBlockFlowMask == 0x04, |
396 | | "unexpected mask values"); |
397 | | int wm = ((mWritingMode & eBlockFlowMask) >> 1) | |
398 | | (mWritingMode & eOrientationMask); |
399 | | return PhysicalSideForBlockAxis(wm, GetEdge(aSide)); |
400 | | } |
401 | | |
402 | | return PhysicalSideForInlineAxis(GetEdge(aSide)); |
403 | | } |
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 | | { |
412 | | // indexes are four-bit values: |
413 | | // bit 0 = the eOrientationMask value |
414 | | // bit 1 = the eInlineFlowMask value |
415 | | // bit 2 = the eBlockFlowMask value |
416 | | // bit 3 = the eLineOrientMask value |
417 | | static const LogicalSide kPhysicalToLogicalSides[][4] = { |
418 | | // top right |
419 | | // bottom left |
420 | | { eLogicalSideBStart, eLogicalSideIEnd, |
421 | | eLogicalSideBEnd, eLogicalSideIStart }, // horizontal-tb ltr |
422 | | { eLogicalSideIStart, eLogicalSideBStart, |
423 | | eLogicalSideIEnd, eLogicalSideBEnd }, // vertical-rl ltr |
424 | | { eLogicalSideBStart, eLogicalSideIStart, |
425 | | eLogicalSideBEnd, eLogicalSideIEnd }, // horizontal-tb rtl |
426 | | { eLogicalSideIEnd, eLogicalSideBStart, |
427 | | eLogicalSideIStart, eLogicalSideBEnd }, // vertical-rl rtl |
428 | | { eLogicalSideBEnd, eLogicalSideIStart, |
429 | | eLogicalSideBStart, eLogicalSideIEnd }, // (horizontal-bt) (inv) ltr |
430 | | { eLogicalSideIStart, eLogicalSideBEnd, |
431 | | eLogicalSideIEnd, eLogicalSideBStart }, // vertical-lr sw-left rtl |
432 | | { eLogicalSideBEnd, eLogicalSideIEnd, |
433 | | eLogicalSideBStart, eLogicalSideIStart }, // (horizontal-bt) (inv) rtl |
434 | | { eLogicalSideIEnd, eLogicalSideBEnd, |
435 | | eLogicalSideIStart, eLogicalSideBStart }, // vertical-lr sw-left ltr |
436 | | { eLogicalSideBStart, eLogicalSideIEnd, |
437 | | eLogicalSideBEnd, eLogicalSideIStart }, // horizontal-tb (inv) rtl |
438 | | { eLogicalSideIStart, eLogicalSideBStart, |
439 | | eLogicalSideIEnd, eLogicalSideBEnd }, // vertical-rl sw-left rtl |
440 | | { eLogicalSideBStart, eLogicalSideIStart, |
441 | | eLogicalSideBEnd, eLogicalSideIEnd }, // horizontal-tb (inv) ltr |
442 | | { eLogicalSideIEnd, eLogicalSideBStart, |
443 | | eLogicalSideIStart, eLogicalSideBEnd }, // vertical-rl sw-left ltr |
444 | | { eLogicalSideBEnd, eLogicalSideIEnd, |
445 | | eLogicalSideBStart, eLogicalSideIStart }, // (horizontal-bt) ltr |
446 | | { eLogicalSideIStart, eLogicalSideBEnd, |
447 | | eLogicalSideIEnd, eLogicalSideBStart }, // vertical-lr ltr |
448 | | { eLogicalSideBEnd, eLogicalSideIStart, |
449 | | eLogicalSideBStart, eLogicalSideIEnd }, // (horizontal-bt) rtl |
450 | | { eLogicalSideIEnd, eLogicalSideBEnd, |
451 | | eLogicalSideIStart, eLogicalSideBStart }, // vertical-lr rtl |
452 | | }; |
453 | | |
454 | | static_assert(eOrientationMask == 0x01 && eInlineFlowMask == 0x02 && |
455 | | eBlockFlowMask == 0x04 && eLineOrientMask == 0x08, |
456 | | "unexpected mask values"); |
457 | | int index = mWritingMode & 0x0F; |
458 | | return kPhysicalToLogicalSides[index][aSide]; |
459 | | } |
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 | 0 | { |
467 | 0 | auto side = static_cast<LogicalSide>(aDir); |
468 | 0 | if (IsInline(side)) { |
469 | 0 | return IsBidiLTR() ? side : GetOppositeSide(side); |
470 | 0 | } |
471 | 0 | return !IsLineInverted() ? side : GetOppositeSide(side); |
472 | 0 | } |
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 | | { } |
482 | | |
483 | | /** |
484 | | * Construct writing mode based on a ComputedStyle. |
485 | | */ |
486 | | explicit WritingMode(ComputedStyle* aComputedStyle) |
487 | | { |
488 | | NS_ASSERTION(aComputedStyle, "we need an ComputedStyle here"); |
489 | | InitFromStyleVisibility(aComputedStyle->StyleVisibility()); |
490 | | } |
491 | | |
492 | | explicit WritingMode(const nsStyleVisibility* aStyleVisibility) |
493 | | { |
494 | | NS_ASSERTION(aStyleVisibility, "we need an nsStyleVisibility here"); |
495 | | InitFromStyleVisibility(aStyleVisibility); |
496 | | } |
497 | | |
498 | | private: |
499 | | void InitFromStyleVisibility(const nsStyleVisibility* aStyleVisibility) |
500 | | { |
501 | | switch (aStyleVisibility->mWritingMode) { |
502 | | case NS_STYLE_WRITING_MODE_HORIZONTAL_TB: |
503 | | mWritingMode = 0; |
504 | | break; |
505 | | |
506 | | case NS_STYLE_WRITING_MODE_VERTICAL_LR: |
507 | | { |
508 | | mWritingMode = eBlockFlowMask | |
509 | | eLineOrientMask | |
510 | | eOrientationMask; |
511 | | uint8_t textOrientation = aStyleVisibility->mTextOrientation; |
512 | | if (textOrientation == NS_STYLE_TEXT_ORIENTATION_SIDEWAYS) { |
513 | | mWritingMode |= eSidewaysMask; |
514 | | } |
515 | | break; |
516 | | } |
517 | | |
518 | | case NS_STYLE_WRITING_MODE_VERTICAL_RL: |
519 | | { |
520 | | mWritingMode = eOrientationMask; |
521 | | uint8_t textOrientation = aStyleVisibility->mTextOrientation; |
522 | | if (textOrientation == NS_STYLE_TEXT_ORIENTATION_SIDEWAYS) { |
523 | | mWritingMode |= eSidewaysMask; |
524 | | } |
525 | | break; |
526 | | } |
527 | | |
528 | | case NS_STYLE_WRITING_MODE_SIDEWAYS_LR: |
529 | | mWritingMode = eBlockFlowMask | |
530 | | eInlineFlowMask | |
531 | | eOrientationMask | |
532 | | eSidewaysMask; |
533 | | break; |
534 | | |
535 | | case NS_STYLE_WRITING_MODE_SIDEWAYS_RL: |
536 | | mWritingMode = eOrientationMask | |
537 | | eSidewaysMask; |
538 | | break; |
539 | | |
540 | | default: |
541 | | MOZ_ASSERT_UNREACHABLE("unknown writing mode!"); |
542 | | mWritingMode = 0; |
543 | | break; |
544 | | } |
545 | | |
546 | | if (NS_STYLE_DIRECTION_RTL == aStyleVisibility->mDirection) { |
547 | | mWritingMode ^= eInlineFlowMask | eBidiMask; |
548 | | } |
549 | | } |
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 | | { |
572 | | if (IS_LEVEL_RTL(level) == IsBidiLTR()) { |
573 | | mWritingMode ^= eBidiMask | eInlineFlowMask; |
574 | | } |
575 | | } |
576 | | |
577 | | /** |
578 | | * Compare two WritingModes for equality. |
579 | | */ |
580 | | bool operator==(const WritingMode& aOther) const |
581 | 0 | { |
582 | 0 | return mWritingMode == aOther.mWritingMode; |
583 | 0 | } |
584 | | |
585 | | bool operator!=(const WritingMode& aOther) const |
586 | | { |
587 | | return mWritingMode != aOther.mWritingMode; |
588 | | } |
589 | | |
590 | | /** |
591 | | * Check whether two modes are orthogonal to each other. |
592 | | */ |
593 | | bool IsOrthogonalTo(const WritingMode& aOther) const |
594 | | { |
595 | | return IsVertical() != aOther.IsVertical(); |
596 | | } |
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 | 0 | { |
610 | 0 | mozilla::Side myStartSide = |
611 | 0 | this->PhysicalSide(MakeLogicalSide(aLogicalAxis, |
612 | 0 | eLogicalEdgeStart)); |
613 | 0 |
|
614 | 0 | // Figure out which of aOther's axes is parallel to |this| WritingMode's |
615 | 0 | // aLogicalAxis, and get its physical start side as well. |
616 | 0 | LogicalAxis otherWMAxis = aOther.IsOrthogonalTo(*this) ? |
617 | 0 | GetOrthogonalAxis(aLogicalAxis) : aLogicalAxis; |
618 | 0 | mozilla::Side otherWMStartSide = |
619 | 0 | aOther.PhysicalSide(MakeLogicalSide(otherWMAxis, |
620 | 0 | eLogicalEdgeStart)); |
621 | 0 |
|
622 | 0 | NS_ASSERTION(myStartSide % 2 == otherWMStartSide % 2, |
623 | 0 | "Should end up with sides in the same physical axis"); |
624 | 0 | return myStartSide == otherWMStartSide; |
625 | 0 | } |
626 | | |
627 | | uint8_t GetBits() const { return mWritingMode; } |
628 | | |
629 | | const char* DebugString() const { |
630 | | return IsVertical() |
631 | | ? IsVerticalLR() |
632 | | ? IsBidiLTR() |
633 | | ? IsSideways() ? "sw-lr-ltr" : "v-lr-ltr" |
634 | | : IsSideways() ? "sw-lr-rtl" : "v-lr-rtl" |
635 | | : IsBidiLTR() |
636 | | ? IsSideways() ? "sw-rl-ltr" : "v-rl-ltr" |
637 | | : IsSideways() ? "sw-rl-rtl" : "v-rl-rtl" |
638 | | : IsBidiLTR() ? "h-ltr" : "h-rtl" |
639 | | ; |
640 | | } |
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 | | { |
659 | | return WritingMode(eUnknownWritingMode); |
660 | | } |
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 | 0 | { } |
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 | | { } |
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 | | { } |
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 | | { |
765 | | if (aWritingMode.IsVertical()) { |
766 | | I() = aWritingMode.IsInlineReversed() ? aContainerSize.height - aPoint.y |
767 | | : aPoint.y; |
768 | | B() = aWritingMode.IsVerticalLR() ? aPoint.x |
769 | | : aContainerSize.width - aPoint.x; |
770 | | } else { |
771 | | I() = aWritingMode.IsInlineReversed() ? aContainerSize.width - aPoint.x |
772 | | : aPoint.x; |
773 | | B() = aPoint.y; |
774 | | } |
775 | | } |
776 | | |
777 | | /** |
778 | | * Read-only (const) access to the logical coordinates. |
779 | | */ |
780 | | nscoord I(WritingMode aWritingMode) const // inline-axis |
781 | | { |
782 | | CHECK_WRITING_MODE(aWritingMode); |
783 | | return mPoint.x; |
784 | | } |
785 | | nscoord B(WritingMode aWritingMode) const // block-axis |
786 | | { |
787 | | CHECK_WRITING_MODE(aWritingMode); |
788 | | return mPoint.y; |
789 | | } |
790 | | nscoord LineRelative(WritingMode aWritingMode, |
791 | | const nsSize& aContainerSize) const // line-axis |
792 | 0 | { |
793 | 0 | CHECK_WRITING_MODE(aWritingMode); |
794 | 0 | if (aWritingMode.IsBidiLTR()) { |
795 | 0 | return I(); |
796 | 0 | } |
797 | 0 | return (aWritingMode.IsVertical() ? aContainerSize.height |
798 | 0 | : aContainerSize.width) - I(); |
799 | 0 | } |
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 | | { |
807 | | CHECK_WRITING_MODE(aWritingMode); |
808 | | return mPoint.x; |
809 | | } |
810 | | nscoord& B(WritingMode aWritingMode) // block-axis |
811 | | { |
812 | | CHECK_WRITING_MODE(aWritingMode); |
813 | | return mPoint.y; |
814 | | } |
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 | | { |
823 | | CHECK_WRITING_MODE(aWritingMode); |
824 | | if (aWritingMode.IsVertical()) { |
825 | | return nsPoint(aWritingMode.IsVerticalLR() |
826 | | ? B() : aContainerSize.width - B(), |
827 | | aWritingMode.IsInlineReversed() |
828 | | ? aContainerSize.height - I() : I()); |
829 | | } else { |
830 | | return nsPoint(aWritingMode.IsInlineReversed() |
831 | | ? aContainerSize.width - I() : I(), |
832 | | B()); |
833 | | } |
834 | | } |
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 | | { |
842 | | CHECK_WRITING_MODE(aFromMode); |
843 | | return aToMode == aFromMode ? |
844 | | *this : LogicalPoint(aToMode, |
845 | | GetPhysicalPoint(aFromMode, aContainerSize), |
846 | | aContainerSize); |
847 | | } |
848 | | |
849 | | bool operator==(const LogicalPoint& aOther) const |
850 | 0 | { |
851 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
852 | 0 | return mPoint == aOther.mPoint; |
853 | 0 | } |
854 | | |
855 | | bool operator!=(const LogicalPoint& aOther) const |
856 | | { |
857 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
858 | | return mPoint != aOther.mPoint; |
859 | | } |
860 | | |
861 | | LogicalPoint operator+(const LogicalPoint& aOther) const |
862 | | { |
863 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
864 | | // In non-debug builds, LogicalPoint does not store the WritingMode, |
865 | | // so the first parameter here (which will always be eUnknownWritingMode) |
866 | | // is ignored. |
867 | | return LogicalPoint(GetWritingMode(), |
868 | | mPoint.x + aOther.mPoint.x, |
869 | | mPoint.y + aOther.mPoint.y); |
870 | | } |
871 | | |
872 | | LogicalPoint& operator+=(const LogicalPoint& aOther) |
873 | 0 | { |
874 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
875 | 0 | I() += aOther.I(); |
876 | 0 | B() += aOther.B(); |
877 | 0 | return *this; |
878 | 0 | } |
879 | | |
880 | | LogicalPoint operator-(const LogicalPoint& aOther) const |
881 | | { |
882 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
883 | | // In non-debug builds, LogicalPoint does not store the WritingMode, |
884 | | // so the first parameter here (which will always be eUnknownWritingMode) |
885 | | // is ignored. |
886 | | return LogicalPoint(GetWritingMode(), |
887 | | mPoint.x - aOther.mPoint.x, |
888 | | mPoint.y - aOther.mPoint.y); |
889 | | } |
890 | | |
891 | | LogicalPoint& operator-=(const LogicalPoint& aOther) |
892 | | { |
893 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
894 | | I() -= aOther.I(); |
895 | | B() -= aOther.B(); |
896 | | return *this; |
897 | | } |
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 | | 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 | | { |
928 | | return mPoint.x; |
929 | | } |
930 | | nscoord B() const // block-axis |
931 | | { |
932 | | return mPoint.y; |
933 | | } |
934 | | |
935 | | nscoord& I() // inline-axis |
936 | | { |
937 | | return mPoint.x; |
938 | | } |
939 | | nscoord& B() // block-axis |
940 | | { |
941 | | return mPoint.y; |
942 | | } |
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 | | { } |
967 | | |
968 | | LogicalSize(WritingMode aWritingMode, nscoord aISize, nscoord aBSize) |
969 | | : |
970 | | #ifdef DEBUG |
971 | | mWritingMode(aWritingMode), |
972 | | #endif |
973 | | mSize(aISize, aBSize) |
974 | | { } |
975 | | |
976 | | LogicalSize(WritingMode aWritingMode, const nsSize& aPhysicalSize) |
977 | | #ifdef DEBUG |
978 | | : mWritingMode(aWritingMode) |
979 | | #endif |
980 | | { |
981 | | if (aWritingMode.IsVertical()) { |
982 | | ISize() = aPhysicalSize.height; |
983 | | BSize() = aPhysicalSize.width; |
984 | | } else { |
985 | | ISize() = aPhysicalSize.width; |
986 | | BSize() = aPhysicalSize.height; |
987 | | } |
988 | | } |
989 | | |
990 | | void SizeTo(WritingMode aWritingMode, nscoord aISize, nscoord aBSize) |
991 | 0 | { |
992 | 0 | CHECK_WRITING_MODE(aWritingMode); |
993 | 0 | mSize.SizeTo(aISize, aBSize); |
994 | 0 | } |
995 | | |
996 | | /** |
997 | | * Dimensions in logical and physical terms |
998 | | */ |
999 | | nscoord ISize(WritingMode aWritingMode) const // inline-size |
1000 | | { |
1001 | | CHECK_WRITING_MODE(aWritingMode); |
1002 | | return mSize.width; |
1003 | | } |
1004 | | nscoord BSize(WritingMode aWritingMode) const // block-size |
1005 | | { |
1006 | | CHECK_WRITING_MODE(aWritingMode); |
1007 | | return mSize.height; |
1008 | | } |
1009 | | nscoord Size(LogicalAxis aAxis, WritingMode aWM) const |
1010 | | { |
1011 | | return aAxis == eLogicalAxisInline ? ISize(aWM) : BSize(aWM); |
1012 | | } |
1013 | | |
1014 | | nscoord Width(WritingMode aWritingMode) const |
1015 | 0 | { |
1016 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1017 | 0 | return aWritingMode.IsVertical() ? BSize() : ISize(); |
1018 | 0 | } |
1019 | | nscoord Height(WritingMode aWritingMode) const |
1020 | 0 | { |
1021 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1022 | 0 | return aWritingMode.IsVertical() ? ISize() : BSize(); |
1023 | 0 | } |
1024 | | |
1025 | | /** |
1026 | | * Writable references to the logical dimensions |
1027 | | */ |
1028 | | nscoord& ISize(WritingMode aWritingMode) // inline-size |
1029 | | { |
1030 | | CHECK_WRITING_MODE(aWritingMode); |
1031 | | return mSize.width; |
1032 | | } |
1033 | | nscoord& BSize(WritingMode aWritingMode) // block-size |
1034 | | { |
1035 | | CHECK_WRITING_MODE(aWritingMode); |
1036 | | return mSize.height; |
1037 | | } |
1038 | | nscoord& Size(LogicalAxis aAxis, WritingMode aWM) |
1039 | | { |
1040 | | return aAxis == eLogicalAxisInline ? ISize(aWM) : BSize(aWM); |
1041 | | } |
1042 | | |
1043 | | /** |
1044 | | * Return an nsSize containing our physical dimensions |
1045 | | */ |
1046 | | nsSize GetPhysicalSize(WritingMode aWritingMode) const |
1047 | | { |
1048 | | CHECK_WRITING_MODE(aWritingMode); |
1049 | | return aWritingMode.IsVertical() ? |
1050 | | nsSize(BSize(), ISize()) : nsSize(ISize(), BSize()); |
1051 | | } |
1052 | | |
1053 | | /** |
1054 | | * Return a LogicalSize representing this size in a different writing mode |
1055 | | */ |
1056 | | LogicalSize ConvertTo(WritingMode aToMode, WritingMode aFromMode) const |
1057 | | { |
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 | | // the writing mode |
1067 | | return (aToMode == aFromMode || !aToMode.IsOrthogonalTo(aFromMode)) |
1068 | | ? *this : LogicalSize(aToMode, BSize(), ISize()); |
1069 | | #endif |
1070 | | } |
1071 | | |
1072 | | /** |
1073 | | * Test if a size is (0, 0). |
1074 | | */ |
1075 | | bool IsAllZero() const |
1076 | | { |
1077 | | return ISize() == 0 && BSize() == 0; |
1078 | | } |
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 | | { |
1086 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1087 | | return mSize == aOther.mSize; |
1088 | | } |
1089 | | |
1090 | | bool operator!=(const LogicalSize& aOther) const |
1091 | 0 | { |
1092 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1093 | 0 | return mSize != aOther.mSize; |
1094 | 0 | } |
1095 | | |
1096 | | LogicalSize operator+(const LogicalSize& aOther) const |
1097 | | { |
1098 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1099 | | return LogicalSize(GetWritingMode(), ISize() + aOther.ISize(), |
1100 | | BSize() + aOther.BSize()); |
1101 | | } |
1102 | | LogicalSize& operator+=(const LogicalSize& aOther) |
1103 | 0 | { |
1104 | 0 | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1105 | 0 | ISize() += aOther.ISize(); |
1106 | 0 | BSize() += aOther.BSize(); |
1107 | 0 | return *this; |
1108 | 0 | } |
1109 | | |
1110 | | LogicalSize operator-(const LogicalSize& aOther) const |
1111 | | { |
1112 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1113 | | return LogicalSize(GetWritingMode(), ISize() - aOther.ISize(), |
1114 | | BSize() - aOther.BSize()); |
1115 | | } |
1116 | | LogicalSize& operator-=(const LogicalSize& aOther) |
1117 | | { |
1118 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1119 | | ISize() -= aOther.ISize(); |
1120 | | BSize() -= aOther.BSize(); |
1121 | | return *this; |
1122 | | } |
1123 | | |
1124 | | private: |
1125 | | friend class LogicalRect; |
1126 | | |
1127 | | LogicalSize() = delete; |
1128 | | |
1129 | | #ifdef DEBUG |
1130 | | WritingMode GetWritingMode() const { return mWritingMode; } |
1131 | | #else |
1132 | | WritingMode GetWritingMode() const { return WritingMode::Unknown(); } |
1133 | | #endif |
1134 | | |
1135 | | nscoord ISize() const // inline-size |
1136 | | { |
1137 | | return mSize.width; |
1138 | | } |
1139 | | nscoord BSize() const // block-size |
1140 | | { |
1141 | | return mSize.height; |
1142 | | } |
1143 | | |
1144 | | nscoord& ISize() // inline-size |
1145 | | { |
1146 | | return mSize.width; |
1147 | | } |
1148 | | nscoord& BSize() // block-size |
1149 | | { |
1150 | | return mSize.height; |
1151 | | } |
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 | | { } |
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 | | { } |
1181 | | |
1182 | | LogicalMargin(WritingMode aWritingMode, const nsMargin& aPhysicalMargin) |
1183 | | #ifdef DEBUG |
1184 | | : mWritingMode(aWritingMode) |
1185 | | #endif |
1186 | | { |
1187 | | if (aWritingMode.IsVertical()) { |
1188 | | if (aWritingMode.IsVerticalLR()) { |
1189 | | mMargin.top = aPhysicalMargin.left; |
1190 | | mMargin.bottom = aPhysicalMargin.right; |
1191 | | } else { |
1192 | | mMargin.top = aPhysicalMargin.right; |
1193 | | mMargin.bottom = aPhysicalMargin.left; |
1194 | | } |
1195 | | if (aWritingMode.IsInlineReversed()) { |
1196 | | mMargin.left = aPhysicalMargin.bottom; |
1197 | | mMargin.right = aPhysicalMargin.top; |
1198 | | } else { |
1199 | | mMargin.left = aPhysicalMargin.top; |
1200 | | mMargin.right = aPhysicalMargin.bottom; |
1201 | | } |
1202 | | } else { |
1203 | | mMargin.top = aPhysicalMargin.top; |
1204 | | mMargin.bottom = aPhysicalMargin.bottom; |
1205 | | if (aWritingMode.IsInlineReversed()) { |
1206 | | mMargin.left = aPhysicalMargin.right; |
1207 | | mMargin.right = aPhysicalMargin.left; |
1208 | | } else { |
1209 | | mMargin.left = aPhysicalMargin.left; |
1210 | | mMargin.right = aPhysicalMargin.right; |
1211 | | } |
1212 | | } |
1213 | | } |
1214 | | |
1215 | | nscoord IStart(WritingMode aWritingMode) const // inline-start margin |
1216 | | { |
1217 | | CHECK_WRITING_MODE(aWritingMode); |
1218 | | return mMargin.left; |
1219 | | } |
1220 | | nscoord IEnd(WritingMode aWritingMode) const // inline-end margin |
1221 | | { |
1222 | | CHECK_WRITING_MODE(aWritingMode); |
1223 | | return mMargin.right; |
1224 | | } |
1225 | | nscoord BStart(WritingMode aWritingMode) const // block-start margin |
1226 | | { |
1227 | | CHECK_WRITING_MODE(aWritingMode); |
1228 | | return mMargin.top; |
1229 | | } |
1230 | | nscoord BEnd(WritingMode aWritingMode) const // block-end margin |
1231 | | { |
1232 | | CHECK_WRITING_MODE(aWritingMode); |
1233 | | return mMargin.bottom; |
1234 | | } |
1235 | | nscoord Start(LogicalAxis aAxis, WritingMode aWM) const |
1236 | | { |
1237 | | return aAxis == eLogicalAxisInline ? IStart(aWM) : BStart(aWM); |
1238 | | } |
1239 | | nscoord End(LogicalAxis aAxis, WritingMode aWM) const |
1240 | | { |
1241 | | return aAxis == eLogicalAxisInline ? IEnd(aWM) : BEnd(aWM); |
1242 | | } |
1243 | | |
1244 | | nscoord& IStart(WritingMode aWritingMode) // inline-start margin |
1245 | | { |
1246 | | CHECK_WRITING_MODE(aWritingMode); |
1247 | | return mMargin.left; |
1248 | | } |
1249 | | nscoord& IEnd(WritingMode aWritingMode) // inline-end margin |
1250 | | { |
1251 | | CHECK_WRITING_MODE(aWritingMode); |
1252 | | return mMargin.right; |
1253 | | } |
1254 | | nscoord& BStart(WritingMode aWritingMode) // block-start margin |
1255 | | { |
1256 | | CHECK_WRITING_MODE(aWritingMode); |
1257 | | return mMargin.top; |
1258 | | } |
1259 | | nscoord& BEnd(WritingMode aWritingMode) // block-end margin |
1260 | | { |
1261 | | CHECK_WRITING_MODE(aWritingMode); |
1262 | | return mMargin.bottom; |
1263 | | } |
1264 | | nscoord& Start(LogicalAxis aAxis, WritingMode aWM) |
1265 | | { |
1266 | | return aAxis == eLogicalAxisInline ? IStart(aWM) : BStart(aWM); |
1267 | | } |
1268 | | nscoord& End(LogicalAxis aAxis, WritingMode aWM) |
1269 | | { |
1270 | | return aAxis == eLogicalAxisInline ? IEnd(aWM) : BEnd(aWM); |
1271 | | } |
1272 | | |
1273 | | nscoord IStartEnd(WritingMode aWritingMode) const // inline margins |
1274 | | { |
1275 | | CHECK_WRITING_MODE(aWritingMode); |
1276 | | return mMargin.LeftRight(); |
1277 | | } |
1278 | | nscoord BStartEnd(WritingMode aWritingMode) const // block margins |
1279 | | { |
1280 | | CHECK_WRITING_MODE(aWritingMode); |
1281 | | return mMargin.TopBottom(); |
1282 | | } |
1283 | | nscoord StartEnd(LogicalAxis aAxis, WritingMode aWM) const |
1284 | | { |
1285 | | return aAxis == eLogicalAxisInline ? IStartEnd(aWM) : BStartEnd(aWM); |
1286 | | } |
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 | | { |
1300 | | // We don't need to CHECK_WRITING_MODE here because the IStart or IEnd |
1301 | | // accessor that we call will do it. |
1302 | | return aWritingMode.IsBidiLTR() |
1303 | | ? IStart(aWritingMode) : IEnd(aWritingMode); |
1304 | | } |
1305 | | nscoord LineRight(WritingMode aWritingMode) const |
1306 | | { |
1307 | | return aWritingMode.IsBidiLTR() |
1308 | | ? IEnd(aWritingMode) : IStart(aWritingMode); |
1309 | | } |
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 | | { |
1317 | | CHECK_WRITING_MODE(aWritingMode); |
1318 | | return LogicalSize(aWritingMode, IStartEnd(), BStartEnd()); |
1319 | | } |
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 | 0 | { |
1327 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1328 | 0 | return aWritingMode.IsVertical() ? |
1329 | 0 | (aWritingMode.IsInlineReversed() ? IEnd() : IStart()) : BStart(); |
1330 | 0 | } |
1331 | | |
1332 | | nscoord Bottom(WritingMode aWritingMode) const |
1333 | | { |
1334 | | CHECK_WRITING_MODE(aWritingMode); |
1335 | | return aWritingMode.IsVertical() ? |
1336 | | (aWritingMode.IsInlineReversed() ? IStart() : IEnd()) : BEnd(); |
1337 | | } |
1338 | | |
1339 | | nscoord Left(WritingMode aWritingMode) const |
1340 | 0 | { |
1341 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1342 | 0 | return aWritingMode.IsVertical() ? |
1343 | 0 | (aWritingMode.IsVerticalLR() ? BStart() : BEnd()) : |
1344 | 0 | (aWritingMode.IsInlineReversed() ? IEnd() : IStart()); |
1345 | 0 | } |
1346 | | |
1347 | | nscoord Right(WritingMode aWritingMode) const |
1348 | | { |
1349 | | CHECK_WRITING_MODE(aWritingMode); |
1350 | | return aWritingMode.IsVertical() ? |
1351 | | (aWritingMode.IsVerticalLR() ? BEnd() : BStart()) : |
1352 | | (aWritingMode.IsInlineReversed() ? IStart() : IEnd()); |
1353 | | } |
1354 | | |
1355 | | nscoord LeftRight(WritingMode aWritingMode) const |
1356 | | { |
1357 | | CHECK_WRITING_MODE(aWritingMode); |
1358 | | return aWritingMode.IsVertical() ? BStartEnd() : IStartEnd(); |
1359 | | } |
1360 | | |
1361 | | nscoord TopBottom(WritingMode aWritingMode) const |
1362 | | { |
1363 | | CHECK_WRITING_MODE(aWritingMode); |
1364 | | return aWritingMode.IsVertical() ? IStartEnd() : BStartEnd(); |
1365 | | } |
1366 | | |
1367 | | void SizeTo(WritingMode aWritingMode, |
1368 | | nscoord aBStart, nscoord aIEnd, nscoord aBEnd, nscoord aIStart) |
1369 | 0 | { |
1370 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1371 | 0 | mMargin.SizeTo(aBStart, aIEnd, aBEnd, aIStart); |
1372 | 0 | } |
1373 | | |
1374 | | /** |
1375 | | * Return an nsMargin containing our physical coordinates |
1376 | | */ |
1377 | | nsMargin GetPhysicalMargin(WritingMode aWritingMode) const |
1378 | | { |
1379 | | CHECK_WRITING_MODE(aWritingMode); |
1380 | | return aWritingMode.IsVertical() |
1381 | | ? (aWritingMode.IsVerticalLR() |
1382 | | ? (aWritingMode.IsInlineReversed() |
1383 | | ? nsMargin(IEnd(), BEnd(), IStart(), BStart()) |
1384 | | : nsMargin(IStart(), BEnd(), IEnd(), BStart())) |
1385 | | : (aWritingMode.IsInlineReversed() |
1386 | | ? nsMargin(IEnd(), BStart(), IStart(), BEnd()) |
1387 | | : nsMargin(IStart(), BStart(), IEnd(), BEnd()))) |
1388 | | : (aWritingMode.IsInlineReversed() |
1389 | | ? nsMargin(BStart(), IStart(), BEnd(), IEnd()) |
1390 | | : nsMargin(BStart(), IEnd(), BEnd(), IStart())); |
1391 | | } |
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 | | { |
1399 | | CHECK_WRITING_MODE(aFromMode); |
1400 | | return aToMode == aFromMode ? |
1401 | | *this : LogicalMargin(aToMode, GetPhysicalMargin(aFromMode)); |
1402 | | } |
1403 | | |
1404 | | void ApplySkipSides(LogicalSides aSkipSides) |
1405 | | { |
1406 | | if (aSkipSides.BStart()) { |
1407 | | BStart() = 0; |
1408 | | } |
1409 | | if (aSkipSides.BEnd()) { |
1410 | | BEnd() = 0; |
1411 | | } |
1412 | | if (aSkipSides.IStart()) { |
1413 | | IStart() = 0; |
1414 | | } |
1415 | | if (aSkipSides.IEnd()) { |
1416 | | IEnd() = 0; |
1417 | | } |
1418 | | } |
1419 | | |
1420 | | bool IsAllZero() const |
1421 | | { |
1422 | | return (mMargin.left == 0 && mMargin.top == 0 && |
1423 | | mMargin.right == 0 && mMargin.bottom == 0); |
1424 | | } |
1425 | | |
1426 | | LogicalMargin operator+(const LogicalMargin& aMargin) const { |
1427 | | CHECK_WRITING_MODE(aMargin.GetWritingMode()); |
1428 | | return LogicalMargin(GetWritingMode(), |
1429 | | BStart() + aMargin.BStart(), |
1430 | | IEnd() + aMargin.IEnd(), |
1431 | | BEnd() + aMargin.BEnd(), |
1432 | | IStart() + aMargin.IStart()); |
1433 | | } |
1434 | | |
1435 | | LogicalMargin operator+=(const LogicalMargin& aMargin) |
1436 | | { |
1437 | | CHECK_WRITING_MODE(aMargin.GetWritingMode()); |
1438 | | mMargin += aMargin.mMargin; |
1439 | | return *this; |
1440 | | } |
1441 | | |
1442 | | LogicalMargin operator-(const LogicalMargin& aMargin) const { |
1443 | | CHECK_WRITING_MODE(aMargin.GetWritingMode()); |
1444 | | return LogicalMargin(GetWritingMode(), |
1445 | | BStart() - aMargin.BStart(), |
1446 | | IEnd() - aMargin.IEnd(), |
1447 | | BEnd() - aMargin.BEnd(), |
1448 | | IStart() - aMargin.IStart()); |
1449 | | } |
1450 | | |
1451 | | private: |
1452 | | friend class LogicalRect; |
1453 | | |
1454 | | LogicalMargin() = delete; |
1455 | | |
1456 | | #ifdef DEBUG |
1457 | | WritingMode GetWritingMode() const { return mWritingMode; } |
1458 | | #else |
1459 | | WritingMode GetWritingMode() const { return WritingMode::Unknown(); } |
1460 | | #endif |
1461 | | |
1462 | | nscoord IStart() const // inline-start margin |
1463 | | { |
1464 | | return mMargin.left; |
1465 | | } |
1466 | | nscoord IEnd() const // inline-end margin |
1467 | | { |
1468 | | return mMargin.right; |
1469 | | } |
1470 | | nscoord BStart() const // block-start margin |
1471 | | { |
1472 | | return mMargin.top; |
1473 | | } |
1474 | | nscoord BEnd() const // block-end margin |
1475 | | { |
1476 | | return mMargin.bottom; |
1477 | | } |
1478 | | |
1479 | | nscoord& IStart() // inline-start margin |
1480 | | { |
1481 | | return mMargin.left; |
1482 | | } |
1483 | | nscoord& IEnd() // inline-end margin |
1484 | | { |
1485 | | return mMargin.right; |
1486 | | } |
1487 | | nscoord& BStart() // block-start margin |
1488 | | { |
1489 | | return mMargin.top; |
1490 | | } |
1491 | | nscoord& BEnd() // block-end margin |
1492 | | { |
1493 | | return mMargin.bottom; |
1494 | | } |
1495 | | |
1496 | | nscoord IStartEnd() const // inline margins |
1497 | | { |
1498 | | return mMargin.LeftRight(); |
1499 | | } |
1500 | | nscoord BStartEnd() const // block margins |
1501 | | { |
1502 | | return mMargin.TopBottom(); |
1503 | | } |
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 | | { } |
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 | | { } |
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 | 0 | { |
1552 | 0 | CHECK_WRITING_MODE(aOrigin.GetWritingMode()); |
1553 | 0 | CHECK_WRITING_MODE(aSize.GetWritingMode()); |
1554 | 0 | } |
1555 | | |
1556 | | LogicalRect(WritingMode aWritingMode, |
1557 | | const nsRect& aRect, |
1558 | | const nsSize& aContainerSize) |
1559 | | #ifdef DEBUG |
1560 | | : mWritingMode(aWritingMode) |
1561 | | #endif |
1562 | | { |
1563 | | if (aWritingMode.IsVertical()) { |
1564 | | mBStart = aWritingMode.IsVerticalLR() |
1565 | | ? aRect.X() : aContainerSize.width - aRect.XMost(); |
1566 | | mIStart = aWritingMode.IsInlineReversed() |
1567 | | ? aContainerSize.height - aRect.YMost() : aRect.Y(); |
1568 | | mBSize = aRect.Width(); |
1569 | | mISize = aRect.Height(); |
1570 | | } else { |
1571 | | mIStart = aWritingMode.IsInlineReversed() |
1572 | | ? aContainerSize.width - aRect.XMost() : aRect.X(); |
1573 | | mBStart = aRect.Y(); |
1574 | | mISize = aRect.Width(); |
1575 | | mBSize = aRect.Height(); |
1576 | | } |
1577 | | } |
1578 | | |
1579 | | /** |
1580 | | * Inline- and block-dimension geometry. |
1581 | | */ |
1582 | | nscoord IStart(WritingMode aWritingMode) const // inline-start edge |
1583 | | { |
1584 | | CHECK_WRITING_MODE(aWritingMode); |
1585 | | return mIStart; |
1586 | | } |
1587 | | nscoord IEnd(WritingMode aWritingMode) const // inline-end edge |
1588 | | { |
1589 | | CHECK_WRITING_MODE(aWritingMode); |
1590 | | return mIStart + mISize; |
1591 | | } |
1592 | | nscoord ISize(WritingMode aWritingMode) const // inline-size |
1593 | | { |
1594 | | CHECK_WRITING_MODE(aWritingMode); |
1595 | | return mISize; |
1596 | | } |
1597 | | |
1598 | | nscoord BStart(WritingMode aWritingMode) const // block-start edge |
1599 | | { |
1600 | | CHECK_WRITING_MODE(aWritingMode); |
1601 | | return mBStart; |
1602 | | } |
1603 | | nscoord BEnd(WritingMode aWritingMode) const // block-end edge |
1604 | | { |
1605 | | CHECK_WRITING_MODE(aWritingMode); |
1606 | | return mBStart + mBSize; |
1607 | | } |
1608 | | nscoord BSize(WritingMode aWritingMode) const // block-size |
1609 | | { |
1610 | | CHECK_WRITING_MODE(aWritingMode); |
1611 | | return mBSize; |
1612 | | } |
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 | | { |
1620 | | CHECK_WRITING_MODE(aWritingMode); |
1621 | | return mIStart; |
1622 | | } |
1623 | | nscoord& ISize(WritingMode aWritingMode) // inline-size |
1624 | | { |
1625 | | CHECK_WRITING_MODE(aWritingMode); |
1626 | | return mISize; |
1627 | | } |
1628 | | nscoord& BStart(WritingMode aWritingMode) // block-start edge |
1629 | | { |
1630 | | CHECK_WRITING_MODE(aWritingMode); |
1631 | | return mBStart; |
1632 | | } |
1633 | | nscoord& BSize(WritingMode aWritingMode) // block-size |
1634 | | { |
1635 | | CHECK_WRITING_MODE(aWritingMode); |
1636 | | return mBSize; |
1637 | | } |
1638 | | |
1639 | | /** |
1640 | | * Accessors for line-relative coordinates |
1641 | | */ |
1642 | | nscoord LineLeft(WritingMode aWritingMode, |
1643 | | const nsSize& aContainerSize) const |
1644 | 0 | { |
1645 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1646 | 0 | if (aWritingMode.IsBidiLTR()) { |
1647 | 0 | return IStart(); |
1648 | 0 | } |
1649 | 0 | nscoord containerISize = |
1650 | 0 | aWritingMode.IsVertical() ? aContainerSize.height : aContainerSize.width; |
1651 | 0 | return containerISize - IEnd(); |
1652 | 0 | } |
1653 | | nscoord LineRight(WritingMode aWritingMode, |
1654 | | const nsSize& aContainerSize) const |
1655 | 0 | { |
1656 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1657 | 0 | if (aWritingMode.IsBidiLTR()) { |
1658 | 0 | return IEnd(); |
1659 | 0 | } |
1660 | 0 | nscoord containerISize = |
1661 | 0 | aWritingMode.IsVertical() ? aContainerSize.height : aContainerSize.width; |
1662 | 0 | return containerISize - IStart(); |
1663 | 0 | } |
1664 | | |
1665 | | /** |
1666 | | * Physical coordinates of the rect. |
1667 | | */ |
1668 | | nscoord X(WritingMode aWritingMode, nscoord aContainerWidth) const |
1669 | | { |
1670 | | CHECK_WRITING_MODE(aWritingMode); |
1671 | | if (aWritingMode.IsVertical()) { |
1672 | | return aWritingMode.IsVerticalLR() ? |
1673 | | mBStart : aContainerWidth - BEnd(); |
1674 | | } else { |
1675 | | return aWritingMode.IsInlineReversed() ? |
1676 | | aContainerWidth - IEnd() : mIStart; |
1677 | | } |
1678 | | } |
1679 | | |
1680 | | nscoord Y(WritingMode aWritingMode, nscoord aContainerHeight) const |
1681 | | { |
1682 | | CHECK_WRITING_MODE(aWritingMode); |
1683 | | if (aWritingMode.IsVertical()) { |
1684 | | return aWritingMode.IsInlineReversed() ? aContainerHeight - IEnd() |
1685 | | : mIStart; |
1686 | | } else { |
1687 | | return mBStart; |
1688 | | } |
1689 | | } |
1690 | | |
1691 | | nscoord Width(WritingMode aWritingMode) const |
1692 | | { |
1693 | | CHECK_WRITING_MODE(aWritingMode); |
1694 | | return aWritingMode.IsVertical() ? mBSize : mISize; |
1695 | | } |
1696 | | |
1697 | | nscoord Height(WritingMode aWritingMode) const |
1698 | | { |
1699 | | CHECK_WRITING_MODE(aWritingMode); |
1700 | | return aWritingMode.IsVertical() ? mISize : mBSize; |
1701 | | } |
1702 | | |
1703 | | nscoord XMost(WritingMode aWritingMode, nscoord aContainerWidth) const |
1704 | | { |
1705 | | CHECK_WRITING_MODE(aWritingMode); |
1706 | | if (aWritingMode.IsVertical()) { |
1707 | | return aWritingMode.IsVerticalLR() ? |
1708 | | BEnd() : aContainerWidth - mBStart; |
1709 | | } else { |
1710 | | return aWritingMode.IsInlineReversed() ? |
1711 | | aContainerWidth - mIStart : IEnd(); |
1712 | | } |
1713 | | } |
1714 | | |
1715 | | nscoord YMost(WritingMode aWritingMode, nscoord aContainerHeight) const |
1716 | | { |
1717 | | CHECK_WRITING_MODE(aWritingMode); |
1718 | | if (aWritingMode.IsVertical()) { |
1719 | | return aWritingMode.IsInlineReversed() ? aContainerHeight - mIStart |
1720 | | : IEnd(); |
1721 | | } else { |
1722 | | return mBStart; |
1723 | | } |
1724 | | } |
1725 | | |
1726 | | bool IsEmpty() const |
1727 | | { |
1728 | | return mISize <= 0 || mBSize <= 0; |
1729 | | } |
1730 | | |
1731 | | bool IsAllZero() const |
1732 | 0 | { |
1733 | 0 | return (mIStart == 0 && mBStart == 0 && |
1734 | 0 | mISize == 0 && mBSize == 0); |
1735 | 0 | } |
1736 | | |
1737 | | bool IsZeroSize() const |
1738 | | { |
1739 | | return (mISize == 0 && mBSize == 0); |
1740 | | } |
1741 | | |
1742 | | void SetEmpty() { mISize = mBSize = 0; } |
1743 | | |
1744 | | bool IsEqualEdges(const LogicalRect aOther) const |
1745 | | { |
1746 | | CHECK_WRITING_MODE(aOther.GetWritingMode()); |
1747 | | bool result = mIStart == aOther.mIStart && mBStart == aOther.mBStart && |
1748 | | mISize == aOther.mISize && mBSize == aOther.mBSize; |
1749 | | |
1750 | | // We want the same result as nsRect, so assert we get it. |
1751 | | MOZ_ASSERT(result == nsRect(mIStart, mBStart, mISize, mBSize). |
1752 | | IsEqualEdges(nsRect(aOther.mIStart, aOther.mBStart, |
1753 | | aOther.mISize, aOther.mBSize))); |
1754 | | return result; |
1755 | | } |
1756 | | |
1757 | | LogicalPoint Origin(WritingMode aWritingMode) const |
1758 | | { |
1759 | | CHECK_WRITING_MODE(aWritingMode); |
1760 | | return LogicalPoint(aWritingMode, IStart(), BStart()); |
1761 | | } |
1762 | | void SetOrigin(WritingMode aWritingMode, const LogicalPoint& aPoint) |
1763 | | { |
1764 | | IStart(aWritingMode) = aPoint.I(aWritingMode); |
1765 | | BStart(aWritingMode) = aPoint.B(aWritingMode); |
1766 | | } |
1767 | | |
1768 | | LogicalSize Size(WritingMode aWritingMode) const |
1769 | 0 | { |
1770 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1771 | 0 | return LogicalSize(aWritingMode, ISize(), BSize()); |
1772 | 0 | } |
1773 | | |
1774 | | LogicalRect operator+(const LogicalPoint& aPoint) const |
1775 | | { |
1776 | | CHECK_WRITING_MODE(aPoint.GetWritingMode()); |
1777 | | return LogicalRect(GetWritingMode(), |
1778 | | IStart() + aPoint.I(), BStart() + aPoint.B(), |
1779 | | ISize(), BSize()); |
1780 | | } |
1781 | | |
1782 | | LogicalRect& operator+=(const LogicalPoint& aPoint) |
1783 | | { |
1784 | | CHECK_WRITING_MODE(aPoint.GetWritingMode()); |
1785 | | mIStart += aPoint.mPoint.x; |
1786 | | mBStart += aPoint.mPoint.y; |
1787 | | return *this; |
1788 | | } |
1789 | | |
1790 | | LogicalRect operator-(const LogicalPoint& aPoint) const |
1791 | | { |
1792 | | CHECK_WRITING_MODE(aPoint.GetWritingMode()); |
1793 | | return LogicalRect(GetWritingMode(), |
1794 | | IStart() - aPoint.I(), BStart() - aPoint.B(), |
1795 | | ISize(), BSize()); |
1796 | | } |
1797 | | |
1798 | | LogicalRect& operator-=(const LogicalPoint& aPoint) |
1799 | | { |
1800 | | CHECK_WRITING_MODE(aPoint.GetWritingMode()); |
1801 | | mIStart -= aPoint.mPoint.x; |
1802 | | mBStart -= aPoint.mPoint.y; |
1803 | | return *this; |
1804 | | } |
1805 | | |
1806 | | void MoveBy(WritingMode aWritingMode, const LogicalPoint& aDelta) |
1807 | 0 | { |
1808 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1809 | 0 | CHECK_WRITING_MODE(aDelta.GetWritingMode()); |
1810 | 0 | IStart() += aDelta.I(); |
1811 | 0 | BStart() += aDelta.B(); |
1812 | 0 | } |
1813 | | |
1814 | | void Inflate(nscoord aD) |
1815 | | { |
1816 | | #ifdef DEBUG |
1817 | | // Compute using nsRect and assert the results match |
1818 | | nsRect rectDebug(mIStart, mBStart, mISize, mBSize); |
1819 | | rectDebug.Inflate(aD); |
1820 | | #endif |
1821 | | mIStart -= aD; |
1822 | | mBStart -= aD; |
1823 | | mISize += 2 * aD; |
1824 | | mBSize += 2 * aD; |
1825 | | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1826 | | } |
1827 | | void Inflate(nscoord aDI, nscoord aDB) |
1828 | | { |
1829 | | #ifdef DEBUG |
1830 | | // Compute using nsRect and assert the results match |
1831 | | nsRect rectDebug(mIStart, mBStart, mISize, mBSize); |
1832 | | rectDebug.Inflate(aDI, aDB); |
1833 | | #endif |
1834 | | mIStart -= aDI; |
1835 | | mBStart -= aDB; |
1836 | | mISize += 2 * aDI; |
1837 | | mBSize += 2 * aDB; |
1838 | | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1839 | | } |
1840 | | void Inflate(WritingMode aWritingMode, const LogicalMargin& aMargin) |
1841 | 0 | { |
1842 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1843 | 0 | 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 | 0 | mBStart -= aMargin.mMargin.top; |
1851 | 0 | mISize += aMargin.mMargin.LeftRight(); |
1852 | 0 | mBSize += aMargin.mMargin.TopBottom(); |
1853 | 0 | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1854 | 0 | } |
1855 | | |
1856 | | void Deflate(nscoord aD) |
1857 | | { |
1858 | | #ifdef DEBUG |
1859 | | // Compute using nsRect and assert the results match |
1860 | | nsRect rectDebug(mIStart, mBStart, mISize, mBSize); |
1861 | | rectDebug.Deflate(aD); |
1862 | | #endif |
1863 | | mIStart += aD; |
1864 | | mBStart += aD; |
1865 | | mISize = std::max(0, mISize - 2 * aD); |
1866 | | mBSize = std::max(0, mBSize - 2 * aD); |
1867 | | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1868 | | } |
1869 | | void Deflate(nscoord aDI, nscoord aDB) |
1870 | | { |
1871 | | #ifdef DEBUG |
1872 | | // Compute using nsRect and assert the results match |
1873 | | nsRect rectDebug(mIStart, mBStart, mISize, mBSize); |
1874 | | rectDebug.Deflate(aDI, aDB); |
1875 | | #endif |
1876 | | mIStart += aDI; |
1877 | | mBStart += aDB; |
1878 | | mISize = std::max(0, mISize - 2 * aDI); |
1879 | | mBSize = std::max(0, mBSize - 2 * aDB); |
1880 | | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1881 | | } |
1882 | | void Deflate(WritingMode aWritingMode, const LogicalMargin& aMargin) |
1883 | 0 | { |
1884 | 0 | CHECK_WRITING_MODE(aWritingMode); |
1885 | 0 | 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 | 0 | mBStart += aMargin.mMargin.top; |
1893 | 0 | mISize = std::max(0, mISize - aMargin.mMargin.LeftRight()); |
1894 | 0 | mBSize = std::max(0, mBSize - aMargin.mMargin.TopBottom()); |
1895 | 0 | MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1896 | 0 | } |
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 | | { |
1905 | | CHECK_WRITING_MODE(aWritingMode); |
1906 | | if (aWritingMode.IsVertical()) { |
1907 | | return nsRect(aWritingMode.IsVerticalLR() |
1908 | | ? BStart() : aContainerSize.width - BEnd(), |
1909 | | aWritingMode.IsInlineReversed() |
1910 | | ? aContainerSize.height - IEnd() : IStart(), |
1911 | | BSize(), ISize()); |
1912 | | } else { |
1913 | | return nsRect(aWritingMode.IsInlineReversed() |
1914 | | ? aContainerSize.width - IEnd() : IStart(), |
1915 | | BStart(), ISize(), BSize()); |
1916 | | } |
1917 | | } |
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 | | { |
1925 | | CHECK_WRITING_MODE(aFromMode); |
1926 | | return aToMode == aFromMode ? |
1927 | | *this : LogicalRect(aToMode, GetPhysicalRect(aFromMode, aContainerSize), |
1928 | | aContainerSize); |
1929 | | } |
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 | 0 | { |
1937 | 0 | CHECK_WRITING_MODE(aRect1.mWritingMode); |
1938 | 0 | 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 | 0 | nscoord iEnd = std::min(aRect1.IEnd(), aRect2.IEnd()); |
1949 | 0 | mIStart = std::max(aRect1.mIStart, aRect2.mIStart); |
1950 | 0 | mISize = iEnd - mIStart; |
1951 | 0 |
|
1952 | 0 | nscoord bEnd = std::min(aRect1.BEnd(), aRect2.BEnd()); |
1953 | 0 | mBStart = std::max(aRect1.mBStart, aRect2.mBStart); |
1954 | 0 | mBSize = bEnd - mBStart; |
1955 | 0 |
|
1956 | 0 | if (mISize < 0 || mBSize < 0) { |
1957 | 0 | mISize = 0; |
1958 | 0 | mBSize = 0; |
1959 | 0 | } |
1960 | 0 |
|
1961 | 0 | MOZ_ASSERT((rectDebug.IsEmpty() && (mISize == 0 || mBSize == 0)) || rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize))); |
1962 | 0 | return mISize > 0 && mBSize > 0; |
1963 | 0 | } |
1964 | | |
1965 | | private: |
1966 | | LogicalRect() = delete; |
1967 | | |
1968 | | #ifdef DEBUG |
1969 | | WritingMode GetWritingMode() const { return mWritingMode; } |
1970 | | #else |
1971 | | WritingMode GetWritingMode() const { return WritingMode::Unknown(); } |
1972 | | #endif |
1973 | | |
1974 | | nscoord IStart() const // inline-start edge |
1975 | | { |
1976 | | return mIStart; |
1977 | | } |
1978 | | nscoord IEnd() const // inline-end edge |
1979 | | { |
1980 | | return mIStart + mISize; |
1981 | | } |
1982 | | nscoord ISize() const // inline-size |
1983 | | { |
1984 | | return mISize; |
1985 | | } |
1986 | | |
1987 | | nscoord BStart() const // block-start edge |
1988 | | { |
1989 | | return mBStart; |
1990 | | } |
1991 | | nscoord BEnd() const // block-end edge |
1992 | | { |
1993 | | return mBStart + mBSize; |
1994 | | } |
1995 | | nscoord BSize() const // block-size |
1996 | | { |
1997 | | return mBSize; |
1998 | | } |
1999 | | |
2000 | | nscoord& IStart() // inline-start edge |
2001 | 0 | { |
2002 | 0 | return mIStart; |
2003 | 0 | } |
2004 | | nscoord& ISize() // inline-size |
2005 | | { |
2006 | | return mISize; |
2007 | | } |
2008 | | nscoord& BStart() // block-start edge |
2009 | 0 | { |
2010 | 0 | return mBStart; |
2011 | 0 | } |
2012 | | nscoord& BSize() // block-size |
2013 | | { |
2014 | | return mBSize; |
2015 | | } |
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 | | { |
2034 | | return GetUnit(aWM.PhysicalSide(aSide)); |
2035 | | } |
2036 | | |
2037 | | inline nsStyleUnit nsStyleSides::GetIStartUnit(mozilla::WritingMode aWM) const |
2038 | | { |
2039 | | return GetUnit(aWM, mozilla::eLogicalSideIStart); |
2040 | | } |
2041 | | |
2042 | | inline nsStyleUnit nsStyleSides::GetBStartUnit(mozilla::WritingMode aWM) const |
2043 | | { |
2044 | | return GetUnit(aWM, mozilla::eLogicalSideBStart); |
2045 | | } |
2046 | | |
2047 | | inline nsStyleUnit nsStyleSides::GetIEndUnit(mozilla::WritingMode aWM) const |
2048 | | { |
2049 | | return GetUnit(aWM, mozilla::eLogicalSideIEnd); |
2050 | | } |
2051 | | |
2052 | | inline nsStyleUnit nsStyleSides::GetBEndUnit(mozilla::WritingMode aWM) const |
2053 | | { |
2054 | | return GetUnit(aWM, mozilla::eLogicalSideBEnd); |
2055 | | } |
2056 | | |
2057 | | inline bool nsStyleSides::HasBlockAxisAuto(mozilla::WritingMode aWM) const |
2058 | 0 | { |
2059 | 0 | return GetBStartUnit(aWM) == eStyleUnit_Auto || |
2060 | 0 | GetBEndUnit(aWM) == eStyleUnit_Auto; |
2061 | 0 | } |
2062 | | |
2063 | | inline bool nsStyleSides::HasInlineAxisAuto(mozilla::WritingMode aWM) const |
2064 | 0 | { |
2065 | 0 | return GetIStartUnit(aWM) == eStyleUnit_Auto || |
2066 | 0 | GetIEndUnit(aWM) == eStyleUnit_Auto; |
2067 | 0 | } |
2068 | | |
2069 | | inline nsStyleCoord nsStyleSides::Get(mozilla::WritingMode aWM, |
2070 | | mozilla::LogicalSide aSide) const |
2071 | | { |
2072 | | return Get(aWM.PhysicalSide(aSide)); |
2073 | | } |
2074 | | |
2075 | | inline nsStyleCoord nsStyleSides::GetIStart(mozilla::WritingMode aWM) const |
2076 | | { |
2077 | | return Get(aWM, mozilla::eLogicalSideIStart); |
2078 | | } |
2079 | | |
2080 | | inline nsStyleCoord nsStyleSides::GetBStart(mozilla::WritingMode aWM) const |
2081 | | { |
2082 | | return Get(aWM, mozilla::eLogicalSideBStart); |
2083 | | } |
2084 | | |
2085 | | inline nsStyleCoord nsStyleSides::GetIEnd(mozilla::WritingMode aWM) const |
2086 | | { |
2087 | | return Get(aWM, mozilla::eLogicalSideIEnd); |
2088 | | } |
2089 | | |
2090 | | inline nsStyleCoord nsStyleSides::GetBEnd(mozilla::WritingMode aWM) const |
2091 | | { |
2092 | | return Get(aWM, mozilla::eLogicalSideBEnd); |
2093 | | } |
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 | | { |
2099 | | return aWM.IsVertical() ? mHeight : mWidth; |
2100 | | } |
2101 | | inline nsStyleCoord& nsStylePosition::MinISize(mozilla::WritingMode aWM) |
2102 | | { |
2103 | | return aWM.IsVertical() ? mMinHeight : mMinWidth; |
2104 | | } |
2105 | | inline nsStyleCoord& nsStylePosition::MaxISize(mozilla::WritingMode aWM) |
2106 | | { |
2107 | | return aWM.IsVertical() ? mMaxHeight : mMaxWidth; |
2108 | | } |
2109 | | inline nsStyleCoord& nsStylePosition::BSize(mozilla::WritingMode aWM) |
2110 | | { |
2111 | | return aWM.IsVertical() ? mWidth : mHeight; |
2112 | | } |
2113 | | inline nsStyleCoord& nsStylePosition::MinBSize(mozilla::WritingMode aWM) |
2114 | | { |
2115 | | return aWM.IsVertical() ? mMinWidth : mMinHeight; |
2116 | | } |
2117 | | inline nsStyleCoord& nsStylePosition::MaxBSize(mozilla::WritingMode aWM) |
2118 | | { |
2119 | | return aWM.IsVertical() ? mMaxWidth : mMaxHeight; |
2120 | | } |
2121 | | |
2122 | | inline const nsStyleCoord& |
2123 | | nsStylePosition::ISize(mozilla::WritingMode aWM) const |
2124 | | { |
2125 | | return aWM.IsVertical() ? mHeight : mWidth; |
2126 | | } |
2127 | | inline const nsStyleCoord& |
2128 | | nsStylePosition::MinISize(mozilla::WritingMode aWM) const |
2129 | | { |
2130 | | return aWM.IsVertical() ? mMinHeight : mMinWidth; |
2131 | | } |
2132 | | inline const nsStyleCoord& |
2133 | | nsStylePosition::MaxISize(mozilla::WritingMode aWM) const |
2134 | | { |
2135 | | return aWM.IsVertical() ? mMaxHeight : mMaxWidth; |
2136 | | } |
2137 | | inline const nsStyleCoord& |
2138 | | nsStylePosition::BSize(mozilla::WritingMode aWM) const |
2139 | | { |
2140 | | return aWM.IsVertical() ? mWidth : mHeight; |
2141 | | } |
2142 | | inline const nsStyleCoord& |
2143 | | nsStylePosition::MinBSize(mozilla::WritingMode aWM) const |
2144 | | { |
2145 | | return aWM.IsVertical() ? mMinWidth : mMinHeight; |
2146 | | } |
2147 | | inline const nsStyleCoord& |
2148 | | nsStylePosition::MaxBSize(mozilla::WritingMode aWM) const |
2149 | | { |
2150 | | return aWM.IsVertical() ? mMaxWidth : mMaxHeight; |
2151 | | } |
2152 | | |
2153 | | inline bool |
2154 | | nsStylePosition::ISizeDependsOnContainer(mozilla::WritingMode aWM) const |
2155 | 0 | { |
2156 | 0 | return aWM.IsVertical() ? HeightDependsOnContainer() |
2157 | 0 | : WidthDependsOnContainer(); |
2158 | 0 | } |
2159 | | inline bool |
2160 | | nsStylePosition::MinISizeDependsOnContainer(mozilla::WritingMode aWM) const |
2161 | 0 | { |
2162 | 0 | return aWM.IsVertical() ? MinHeightDependsOnContainer() |
2163 | 0 | : MinWidthDependsOnContainer(); |
2164 | 0 | } |
2165 | | inline bool |
2166 | | nsStylePosition::MaxISizeDependsOnContainer(mozilla::WritingMode aWM) const |
2167 | 0 | { |
2168 | 0 | return aWM.IsVertical() ? MaxHeightDependsOnContainer() |
2169 | 0 | : MaxWidthDependsOnContainer(); |
2170 | 0 | } |
2171 | | inline bool |
2172 | | nsStylePosition::BSizeDependsOnContainer(mozilla::WritingMode aWM) const |
2173 | | { |
2174 | | return aWM.IsVertical() ? WidthDependsOnContainer() |
2175 | | : HeightDependsOnContainer(); |
2176 | | } |
2177 | | inline bool |
2178 | | nsStylePosition::MinBSizeDependsOnContainer(mozilla::WritingMode aWM) const |
2179 | | { |
2180 | | return aWM.IsVertical() ? MinWidthDependsOnContainer() |
2181 | | : MinHeightDependsOnContainer(); |
2182 | | } |
2183 | | inline bool |
2184 | | nsStylePosition::MaxBSizeDependsOnContainer(mozilla::WritingMode aWM) const |
2185 | | { |
2186 | | return aWM.IsVertical() ? MaxWidthDependsOnContainer() |
2187 | | : MaxHeightDependsOnContainer(); |
2188 | | } |
2189 | | |
2190 | | inline bool |
2191 | | nsStyleMargin::HasBlockAxisAuto(mozilla::WritingMode aWM) const |
2192 | 0 | { |
2193 | 0 | return mMargin.HasBlockAxisAuto(aWM); |
2194 | 0 | } |
2195 | | inline bool |
2196 | | nsStyleMargin::HasInlineAxisAuto(mozilla::WritingMode aWM) const |
2197 | 0 | { |
2198 | 0 | return mMargin.HasInlineAxisAuto(aWM); |
2199 | 0 | } |
2200 | | |
2201 | | #endif // WritingModes_h_ |