Bug 1867925 - Mark some storage-access-api tests as intermittent after wpt-sync....
[gecko.git] / layout / generic / JustificationUtils.h
blob346a8b618680f406cb03948f1bc99b8fe9050949
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/. */
7 #ifndef mozilla_JustificationUtils_h_
8 #define mozilla_JustificationUtils_h_
10 #include "mozilla/Attributes.h"
11 #include "nsCoord.h"
13 namespace mozilla {
15 /**
16 * Jutification Algorithm
18 * The justification algorithm is based on expansion opportunities
19 * between justifiable clusters. By this algorithm, there is one
20 * expansion opportunity at each side of a justifiable cluster, and
21 * at most one opportunity between two clusters. For example, if there
22 * is a line in a Chinese document is: "你好世界hello world", then
23 * the expansion opportunities (marked as '*') would be:
25 * 你*好*世*界*hello*' '*world
27 * The spacing left in a line will then be distributed equally to each
28 * opportunities. Because we want that, only justifiable clusters get
29 * expanded, and the split point between two justifiable clusters would
30 * be at the middle of the spacing, each expansion opportunities will be
31 * filled by two justification gaps. The example above would be:
33 * 你 | 好 | 世 | 界 |hello| ' ' |world
35 * In the algorithm, information about expansion opportunities is stored
36 * in structure JustificationInfo, and the assignment of justification
37 * gaps is in structure JustificationAssignment.
40 struct JustificationInfo {
41 // Number of expansion opportunities inside a span. It doesn't include
42 // any opportunities between this span and the one before or after.
43 int32_t mInnerOpportunities;
44 // The justifiability of the start and end sides of the span.
45 bool mIsStartJustifiable;
46 bool mIsEndJustifiable;
48 constexpr JustificationInfo()
49 : mInnerOpportunities(0),
50 mIsStartJustifiable(false),
51 mIsEndJustifiable(false) {}
53 // Claim that the last opportunity should be cancelled
54 // because the trailing space just gets trimmed.
55 void CancelOpportunityForTrimmedSpace() {
56 if (mInnerOpportunities > 0) {
57 mInnerOpportunities--;
58 } else {
59 // There is no inner opportunities, hence the whole frame must
60 // contain only the trimmed space, because any content before
61 // space would cause an inner opportunity. The space made each
62 // side justifiable, which should be cancelled now.
63 mIsStartJustifiable = false;
64 mIsEndJustifiable = false;
69 struct JustificationAssignment {
70 // There are at most 2 gaps per end, so it is enough to use 2 bits.
71 uint8_t mGapsAtStart : 2;
72 uint8_t mGapsAtEnd : 2;
74 constexpr JustificationAssignment() : mGapsAtStart(0), mGapsAtEnd(0) {}
76 int32_t TotalGaps() const { return mGapsAtStart + mGapsAtEnd; }
79 struct JustificationApplicationState {
80 struct {
81 // The total number of justification gaps to be processed.
82 int32_t mCount;
83 // The number of justification gaps which have been handled.
84 int32_t mHandled;
85 } mGaps;
87 struct {
88 // The total spacing left in a line before justification.
89 nscoord mAvailable;
90 // The spacing has been consumed by handled justification gaps.
91 nscoord mConsumed;
92 } mWidth;
94 JustificationApplicationState(int32_t aGaps, nscoord aWidth) {
95 mGaps.mCount = aGaps;
96 mGaps.mHandled = 0;
97 mWidth.mAvailable = aWidth;
98 mWidth.mConsumed = 0;
101 bool IsJustifiable() const {
102 return mGaps.mCount > 0 && mWidth.mAvailable > 0;
105 nscoord Consume(int32_t aGaps) {
106 mGaps.mHandled += aGaps;
107 nscoord newAllocate = (mWidth.mAvailable * mGaps.mHandled) / mGaps.mCount;
108 nscoord deltaWidth = newAllocate - mWidth.mConsumed;
109 mWidth.mConsumed = newAllocate;
110 return deltaWidth;
114 class JustificationUtils {
115 public:
116 // Compute justification gaps should be applied on a unit.
117 static int32_t CountGaps(const JustificationInfo& aInfo,
118 const JustificationAssignment& aAssign) {
119 // Justification gaps include two gaps for each inner opportunities
120 // and the gaps given assigned to the ends.
121 return aInfo.mInnerOpportunities * 2 + aAssign.TotalGaps();
125 } // namespace mozilla
127 #endif /* !defined(mozilla_JustificationUtils_h_) */