Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/generic/JustificationUtils.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_JustificationUtils_h_
8
#define mozilla_JustificationUtils_h_
9
10
#include "mozilla/Attributes.h"
11
#include "nsCoord.h"
12
13
namespace mozilla {
14
15
/**
16
 * Jutification Algorithm
17
 *
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:
24
 *
25
 *                    你*好*世*界*hello*' '*world
26
 *
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:
32
 *
33
 *              你 | 好 | 世 | 界  |hello|  ' '  |world
34
 *
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.
38
 */
39
40
struct JustificationInfo
41
{
42
  // Number of expansion opportunities inside a span. It doesn't include
43
  // any opportunities between this span and the one before or after.
44
  int32_t mInnerOpportunities;
45
  // The justifiability of the start and end sides of the span.
46
  bool mIsStartJustifiable;
47
  bool mIsEndJustifiable;
48
49
  constexpr JustificationInfo()
50
    : mInnerOpportunities(0)
51
    , mIsStartJustifiable(false)
52
    , mIsEndJustifiable(false)
53
0
  {
54
0
  }
55
56
  // Claim that the last opportunity should be cancelled
57
  // because the trailing space just gets trimmed.
58
  void CancelOpportunityForTrimmedSpace()
59
0
  {
60
0
    if (mInnerOpportunities > 0) {
61
0
      mInnerOpportunities--;
62
0
    } else {
63
0
      // There is no inner opportunities, hence the whole frame must
64
0
      // contain only the trimmed space, because any content before
65
0
      // space would cause an inner opportunity. The space made each
66
0
      // side justifiable, which should be cancelled now.
67
0
      mIsStartJustifiable = false;
68
0
      mIsEndJustifiable = false;
69
0
    }
70
0
  }
71
};
72
73
struct JustificationAssignment
74
{
75
  // There are at most 2 gaps per end, so it is enough to use 2 bits.
76
  uint8_t mGapsAtStart : 2;
77
  uint8_t mGapsAtEnd : 2;
78
79
  constexpr JustificationAssignment()
80
    : mGapsAtStart(0)
81
    , mGapsAtEnd(0)
82
0
  {
83
0
  }
84
85
0
  int32_t TotalGaps() const { return mGapsAtStart + mGapsAtEnd; }
86
};
87
88
struct JustificationApplicationState
89
{
90
  struct
91
  {
92
    // The total number of justification gaps to be processed.
93
    int32_t mCount;
94
    // The number of justification gaps which have been handled.
95
    int32_t mHandled;
96
  } mGaps;
97
98
  struct
99
  {
100
    // The total spacing left in a line before justification.
101
    nscoord mAvailable;
102
    // The spacing has been consumed by handled justification gaps.
103
    nscoord mConsumed;
104
  } mWidth;
105
106
  JustificationApplicationState(int32_t aGaps, nscoord aWidth)
107
0
  {
108
0
    mGaps.mCount = aGaps;
109
0
    mGaps.mHandled = 0;
110
0
    mWidth.mAvailable = aWidth;
111
0
    mWidth.mConsumed = 0;
112
0
  }
113
114
  bool IsJustifiable() const
115
0
  {
116
0
    return mGaps.mCount > 0 && mWidth.mAvailable > 0;
117
0
  }
118
119
  nscoord Consume(int32_t aGaps)
120
0
  {
121
0
    mGaps.mHandled += aGaps;
122
0
    nscoord newAllocate = (mWidth.mAvailable * mGaps.mHandled) / mGaps.mCount;
123
0
    nscoord deltaWidth = newAllocate - mWidth.mConsumed;
124
0
    mWidth.mConsumed = newAllocate;
125
0
    return deltaWidth;
126
0
  }
127
};
128
129
class JustificationUtils
130
{
131
public:
132
  // Compute justification gaps should be applied on a unit.
133
  static int32_t CountGaps(const JustificationInfo& aInfo,
134
                           const JustificationAssignment& aAssign)
135
0
  {
136
0
    // Justification gaps include two gaps for each inner opportunities
137
0
    // and the gaps given assigned to the ends.
138
0
    return aInfo.mInnerOpportunities * 2 + aAssign.TotalGaps();
139
0
  }
140
};
141
142
} // namespace mozilla
143
144
#endif /* !defined(mozilla_JustificationUtils_h_) */