xref: /aosp_15_r20/external/pdfium/xfa/fgas/layout/cfgas_break.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2017 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker 
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker 
7*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fgas/layout/cfgas_break.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include <algorithm>
10*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
11*3ac0a46fSAndroid Build Coastguard Worker #include <vector>
12*3ac0a46fSAndroid Build Coastguard Worker 
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_safe_types.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/stl_util.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fgas/font/cfgas_gefont.h"
16*3ac0a46fSAndroid Build Coastguard Worker 
17*3ac0a46fSAndroid Build Coastguard Worker const float CFGAS_Break::kConversionFactor = 20000.0f;
18*3ac0a46fSAndroid Build Coastguard Worker const int CFGAS_Break::kMinimumTabWidth = 160000;
19*3ac0a46fSAndroid Build Coastguard Worker 
CFGAS_Break(Mask<LayoutStyle> dwLayoutStyles)20*3ac0a46fSAndroid Build Coastguard Worker CFGAS_Break::CFGAS_Break(Mask<LayoutStyle> dwLayoutStyles)
21*3ac0a46fSAndroid Build Coastguard Worker     : m_dwLayoutStyles(dwLayoutStyles), m_pCurLine(&m_Lines[0]) {}
22*3ac0a46fSAndroid Build Coastguard Worker 
23*3ac0a46fSAndroid Build Coastguard Worker CFGAS_Break::~CFGAS_Break() = default;
24*3ac0a46fSAndroid Build Coastguard Worker 
Reset()25*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::Reset() {
26*3ac0a46fSAndroid Build Coastguard Worker   m_eCharType = FX_CHARTYPE::kUnknown;
27*3ac0a46fSAndroid Build Coastguard Worker   for (CFGAS_BreakLine& line : m_Lines)
28*3ac0a46fSAndroid Build Coastguard Worker     line.Clear();
29*3ac0a46fSAndroid Build Coastguard Worker }
30*3ac0a46fSAndroid Build Coastguard Worker 
SetLayoutStyles(Mask<LayoutStyle> dwLayoutStyles)31*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetLayoutStyles(Mask<LayoutStyle> dwLayoutStyles) {
32*3ac0a46fSAndroid Build Coastguard Worker   m_dwLayoutStyles = dwLayoutStyles;
33*3ac0a46fSAndroid Build Coastguard Worker   m_bSingleLine = !!(m_dwLayoutStyles & LayoutStyle::kSingleLine);
34*3ac0a46fSAndroid Build Coastguard Worker   m_bCombText = !!(m_dwLayoutStyles & LayoutStyle::kCombText);
35*3ac0a46fSAndroid Build Coastguard Worker }
36*3ac0a46fSAndroid Build Coastguard Worker 
SetHorizontalScale(int32_t iScale)37*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetHorizontalScale(int32_t iScale) {
38*3ac0a46fSAndroid Build Coastguard Worker   iScale = std::max(iScale, 0);
39*3ac0a46fSAndroid Build Coastguard Worker   if (m_iHorizontalScale == iScale)
40*3ac0a46fSAndroid Build Coastguard Worker     return;
41*3ac0a46fSAndroid Build Coastguard Worker 
42*3ac0a46fSAndroid Build Coastguard Worker   SetBreakStatus();
43*3ac0a46fSAndroid Build Coastguard Worker   m_iHorizontalScale = iScale;
44*3ac0a46fSAndroid Build Coastguard Worker }
45*3ac0a46fSAndroid Build Coastguard Worker 
SetVerticalScale(int32_t iScale)46*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetVerticalScale(int32_t iScale) {
47*3ac0a46fSAndroid Build Coastguard Worker   if (iScale < 0)
48*3ac0a46fSAndroid Build Coastguard Worker     iScale = 0;
49*3ac0a46fSAndroid Build Coastguard Worker   if (m_iVerticalScale == iScale)
50*3ac0a46fSAndroid Build Coastguard Worker     return;
51*3ac0a46fSAndroid Build Coastguard Worker 
52*3ac0a46fSAndroid Build Coastguard Worker   SetBreakStatus();
53*3ac0a46fSAndroid Build Coastguard Worker   m_iVerticalScale = iScale;
54*3ac0a46fSAndroid Build Coastguard Worker }
55*3ac0a46fSAndroid Build Coastguard Worker 
SetFont(RetainPtr<CFGAS_GEFont> pFont)56*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetFont(RetainPtr<CFGAS_GEFont> pFont) {
57*3ac0a46fSAndroid Build Coastguard Worker   if (!pFont || pFont == m_pFont)
58*3ac0a46fSAndroid Build Coastguard Worker     return;
59*3ac0a46fSAndroid Build Coastguard Worker 
60*3ac0a46fSAndroid Build Coastguard Worker   SetBreakStatus();
61*3ac0a46fSAndroid Build Coastguard Worker   m_pFont = std::move(pFont);
62*3ac0a46fSAndroid Build Coastguard Worker }
63*3ac0a46fSAndroid Build Coastguard Worker 
SetFontSize(float fFontSize)64*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetFontSize(float fFontSize) {
65*3ac0a46fSAndroid Build Coastguard Worker   int32_t iFontSize = FXSYS_roundf(fFontSize * 20.0f);
66*3ac0a46fSAndroid Build Coastguard Worker   if (m_iFontSize == iFontSize)
67*3ac0a46fSAndroid Build Coastguard Worker     return;
68*3ac0a46fSAndroid Build Coastguard Worker 
69*3ac0a46fSAndroid Build Coastguard Worker   SetBreakStatus();
70*3ac0a46fSAndroid Build Coastguard Worker   m_iFontSize = iFontSize;
71*3ac0a46fSAndroid Build Coastguard Worker }
72*3ac0a46fSAndroid Build Coastguard Worker 
SetBreakStatus()73*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetBreakStatus() {
74*3ac0a46fSAndroid Build Coastguard Worker   ++m_dwIdentity;
75*3ac0a46fSAndroid Build Coastguard Worker 
76*3ac0a46fSAndroid Build Coastguard Worker   CFGAS_Char* tc = m_pCurLine->LastChar();
77*3ac0a46fSAndroid Build Coastguard Worker   if (tc && tc->m_dwStatus == CFGAS_Char::BreakType::kNone)
78*3ac0a46fSAndroid Build Coastguard Worker     tc->m_dwStatus = CFGAS_Char::BreakType::kPiece;
79*3ac0a46fSAndroid Build Coastguard Worker }
80*3ac0a46fSAndroid Build Coastguard Worker 
IsGreaterThanLineWidth(int32_t width) const81*3ac0a46fSAndroid Build Coastguard Worker bool CFGAS_Break::IsGreaterThanLineWidth(int32_t width) const {
82*3ac0a46fSAndroid Build Coastguard Worker   FX_SAFE_INT32 line_width = m_iLineWidth;
83*3ac0a46fSAndroid Build Coastguard Worker   line_width += m_iTolerance;
84*3ac0a46fSAndroid Build Coastguard Worker   return line_width.IsValid() && width > line_width.ValueOrDie();
85*3ac0a46fSAndroid Build Coastguard Worker }
86*3ac0a46fSAndroid Build Coastguard Worker 
GetUnifiedCharType(FX_CHARTYPE chartype) const87*3ac0a46fSAndroid Build Coastguard Worker FX_CHARTYPE CFGAS_Break::GetUnifiedCharType(FX_CHARTYPE chartype) const {
88*3ac0a46fSAndroid Build Coastguard Worker   return chartype >= FX_CHARTYPE::kArabicAlef ? FX_CHARTYPE::kArabic : chartype;
89*3ac0a46fSAndroid Build Coastguard Worker }
90*3ac0a46fSAndroid Build Coastguard Worker 
SetTabWidth(float fTabWidth)91*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetTabWidth(float fTabWidth) {
92*3ac0a46fSAndroid Build Coastguard Worker   // Note, the use of max here was only done in the TxtBreak code. Leaving this
93*3ac0a46fSAndroid Build Coastguard Worker   // in for the RTFBreak code for consistency. If we see issues with tab widths
94*3ac0a46fSAndroid Build Coastguard Worker   // we may need to fix this.
95*3ac0a46fSAndroid Build Coastguard Worker   m_iTabWidth =
96*3ac0a46fSAndroid Build Coastguard Worker       std::max(FXSYS_roundf(fTabWidth * kConversionFactor), kMinimumTabWidth);
97*3ac0a46fSAndroid Build Coastguard Worker }
98*3ac0a46fSAndroid Build Coastguard Worker 
SetParagraphBreakChar(wchar_t wch)99*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetParagraphBreakChar(wchar_t wch) {
100*3ac0a46fSAndroid Build Coastguard Worker   if (wch != L'\r' && wch != L'\n')
101*3ac0a46fSAndroid Build Coastguard Worker     return;
102*3ac0a46fSAndroid Build Coastguard Worker   m_wParagraphBreakChar = wch;
103*3ac0a46fSAndroid Build Coastguard Worker }
104*3ac0a46fSAndroid Build Coastguard Worker 
SetLineBreakTolerance(float fTolerance)105*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetLineBreakTolerance(float fTolerance) {
106*3ac0a46fSAndroid Build Coastguard Worker   m_iTolerance = FXSYS_roundf(fTolerance * kConversionFactor);
107*3ac0a46fSAndroid Build Coastguard Worker }
108*3ac0a46fSAndroid Build Coastguard Worker 
SetCharSpace(float fCharSpace)109*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetCharSpace(float fCharSpace) {
110*3ac0a46fSAndroid Build Coastguard Worker   m_iCharSpace = FXSYS_roundf(fCharSpace * kConversionFactor);
111*3ac0a46fSAndroid Build Coastguard Worker }
112*3ac0a46fSAndroid Build Coastguard Worker 
SetLineBoundary(float fLineStart,float fLineEnd)113*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::SetLineBoundary(float fLineStart, float fLineEnd) {
114*3ac0a46fSAndroid Build Coastguard Worker   if (fLineStart > fLineEnd)
115*3ac0a46fSAndroid Build Coastguard Worker     return;
116*3ac0a46fSAndroid Build Coastguard Worker 
117*3ac0a46fSAndroid Build Coastguard Worker   m_iLineStart = FXSYS_roundf(fLineStart * kConversionFactor);
118*3ac0a46fSAndroid Build Coastguard Worker   m_iLineWidth = FXSYS_roundf(fLineEnd * kConversionFactor);
119*3ac0a46fSAndroid Build Coastguard Worker   m_pCurLine->m_iStart = std::min(m_pCurLine->m_iStart, m_iLineWidth);
120*3ac0a46fSAndroid Build Coastguard Worker   m_pCurLine->m_iStart = std::max(m_pCurLine->m_iStart, m_iLineStart);
121*3ac0a46fSAndroid Build Coastguard Worker }
122*3ac0a46fSAndroid Build Coastguard Worker 
GetLastChar(int32_t index,bool bOmitChar,bool bRichText) const123*3ac0a46fSAndroid Build Coastguard Worker CFGAS_Char* CFGAS_Break::GetLastChar(int32_t index,
124*3ac0a46fSAndroid Build Coastguard Worker                                      bool bOmitChar,
125*3ac0a46fSAndroid Build Coastguard Worker                                      bool bRichText) const {
126*3ac0a46fSAndroid Build Coastguard Worker   std::vector<CFGAS_Char>& tca = m_pCurLine->m_LineChars;
127*3ac0a46fSAndroid Build Coastguard Worker   if (!fxcrt::IndexInBounds(tca, index))
128*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
129*3ac0a46fSAndroid Build Coastguard Worker 
130*3ac0a46fSAndroid Build Coastguard Worker   int32_t iStart = fxcrt::CollectionSize<int32_t>(tca) - 1;
131*3ac0a46fSAndroid Build Coastguard Worker   while (iStart > -1) {
132*3ac0a46fSAndroid Build Coastguard Worker     CFGAS_Char* pTC = &tca[iStart--];
133*3ac0a46fSAndroid Build Coastguard Worker     if (((bRichText && pTC->m_iCharWidth < 0) || bOmitChar) &&
134*3ac0a46fSAndroid Build Coastguard Worker         pTC->GetCharType() == FX_CHARTYPE::kCombination) {
135*3ac0a46fSAndroid Build Coastguard Worker       continue;
136*3ac0a46fSAndroid Build Coastguard Worker     }
137*3ac0a46fSAndroid Build Coastguard Worker     if (--index < 0)
138*3ac0a46fSAndroid Build Coastguard Worker       return pTC;
139*3ac0a46fSAndroid Build Coastguard Worker   }
140*3ac0a46fSAndroid Build Coastguard Worker   return nullptr;
141*3ac0a46fSAndroid Build Coastguard Worker }
142*3ac0a46fSAndroid Build Coastguard Worker 
CountBreakPieces() const143*3ac0a46fSAndroid Build Coastguard Worker int32_t CFGAS_Break::CountBreakPieces() const {
144*3ac0a46fSAndroid Build Coastguard Worker   return HasLine() ? fxcrt::CollectionSize<int32_t>(
145*3ac0a46fSAndroid Build Coastguard Worker                          m_Lines[m_iReadyLineIndex].m_LinePieces)
146*3ac0a46fSAndroid Build Coastguard Worker                    : 0;
147*3ac0a46fSAndroid Build Coastguard Worker }
148*3ac0a46fSAndroid Build Coastguard Worker 
GetBreakPieceUnstable(int32_t index) const149*3ac0a46fSAndroid Build Coastguard Worker const CFGAS_BreakPiece* CFGAS_Break::GetBreakPieceUnstable(
150*3ac0a46fSAndroid Build Coastguard Worker     int32_t index) const {
151*3ac0a46fSAndroid Build Coastguard Worker   if (!HasLine())
152*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
153*3ac0a46fSAndroid Build Coastguard Worker   if (!fxcrt::IndexInBounds(m_Lines[m_iReadyLineIndex].m_LinePieces, index))
154*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
155*3ac0a46fSAndroid Build Coastguard Worker   return &m_Lines[m_iReadyLineIndex].m_LinePieces[index];
156*3ac0a46fSAndroid Build Coastguard Worker }
157*3ac0a46fSAndroid Build Coastguard Worker 
ClearBreakPieces()158*3ac0a46fSAndroid Build Coastguard Worker void CFGAS_Break::ClearBreakPieces() {
159*3ac0a46fSAndroid Build Coastguard Worker   if (HasLine())
160*3ac0a46fSAndroid Build Coastguard Worker     m_Lines[m_iReadyLineIndex].Clear();
161*3ac0a46fSAndroid Build Coastguard Worker   m_iReadyLineIndex = -1;
162*3ac0a46fSAndroid Build Coastguard Worker }
163