blob: 68930db91950510b771d31d04091803f06e2436d [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "xfa/fgas/layout/fgas_textbreak.h"
8
9#include <algorithm>
10
dsinclaira52ab742016-09-29 13:59:29 -070011#include "core/fxcrt/fx_arabic.h"
dsinclaira52ab742016-09-29 13:59:29 -070012#include "core/fxcrt/fx_memory.h"
tsepeza9caab92016-12-14 05:57:10 -080013#include "third_party/base/ptr_util.h"
npm4b91a2d2016-11-21 15:19:44 -080014#include "xfa/fgas/font/cfgas_gefont.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040015#include "xfa/fgas/layout/fgas_linebreak.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040016
tsepez215507d2016-06-09 19:05:47 -070017namespace {
18
Dan Sinclairc36fe072017-03-09 16:58:12 -050019typedef CFX_BreakType (CFX_TxtBreak::*FX_TxtBreak_LPFAppendChar)(
Dan Sinclair068d3442017-03-13 10:15:36 -040020 CFX_TxtChar* pCurChar);
tsepez215507d2016-06-09 19:05:47 -070021const FX_TxtBreak_LPFAppendChar g_FX_TxtBreak_lpfAppendChar[16] = {
22 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Tab,
23 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Control,
24 &CFX_TxtBreak::AppendChar_Combination, &CFX_TxtBreak::AppendChar_Others,
25 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Arabic,
26 &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Arabic,
27 &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Arabic,
28 &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Others,
29 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Others,
30};
31
Dan Sinclairfc9b9882017-03-07 09:18:18 -050032bool IsCtrlCode(FX_WCHAR ch) {
33 uint32_t dwRet = (FX_GetUnicodeProperties(ch) & FX_CHARTYPEBITSMASK);
34 return dwRet == FX_CHARTYPE_Tab || dwRet == FX_CHARTYPE_Control;
35}
36
Dan Sinclairc36fe072017-03-09 16:58:12 -050037const int kMinimumTabWidth = 160000;
38
tsepez215507d2016-06-09 19:05:47 -070039} // namespace
40
Dan Sinclair52c73c22017-03-09 13:27:29 -050041CFX_TxtBreak::CFX_TxtBreak()
42 : m_iLineWidth(2000000),
Dan Sinclair1770c022016-03-14 14:14:16 -040043 m_dwLayoutStyles(0),
tsepezd19e9122016-11-02 15:43:18 -070044 m_bSingleLine(false),
45 m_bCombText(false),
Dan Sinclair1770c022016-03-14 14:14:16 -040046 m_iArabicContext(1),
47 m_iCurArabicContext(1),
dsinclair85d1f2c2016-06-23 12:40:16 -070048 m_pFont(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -040049 m_iFontSize(240),
tsepezd19e9122016-11-02 15:43:18 -070050 m_bEquidistant(true),
Dan Sinclair1770c022016-03-14 14:14:16 -040051 m_iTabWidth(720000),
52 m_wDefChar(0xFEFF),
53 m_wParagBreakChar(L'\n'),
54 m_iDefChar(0),
Dan Sinclair9e9bab62017-03-09 16:59:12 -050055 m_iAlignment(CFX_TxtLineAlignment_Left),
Dan Sinclair1770c022016-03-14 14:14:16 -040056 m_dwContextCharStyles(0),
57 m_iCombWidth(360000),
weilia2c06e42016-05-20 17:09:48 -070058 m_eCharType(FX_CHARTYPE_Unknown),
dsinclair85d1f2c2016-06-23 12:40:16 -070059 m_pCurLine(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -040060 m_iReady(0),
61 m_iTolerance(0),
62 m_iHorScale(100),
Dan Sinclair1770c022016-03-14 14:14:16 -040063 m_iCharSpace(0) {
Dan Sinclair52c73c22017-03-09 13:27:29 -050064 m_pCurLine = &m_TxtLine1;
Dan Sinclair1770c022016-03-14 14:14:16 -040065 ResetArabicContext();
66}
weili1b4f6b32016-08-04 16:37:48 -070067
Dan Sinclair1770c022016-03-14 14:14:16 -040068CFX_TxtBreak::~CFX_TxtBreak() {
69 Reset();
Dan Sinclair1770c022016-03-14 14:14:16 -040070}
weili1b4f6b32016-08-04 16:37:48 -070071
Dan Sinclair1770c022016-03-14 14:14:16 -040072void CFX_TxtBreak::SetLineWidth(FX_FLOAT fLineWidth) {
73 m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f);
dsinclair43854a52016-04-27 12:26:00 -070074 ASSERT(m_iLineWidth >= 20000);
Dan Sinclair1770c022016-03-14 14:14:16 -040075}
weili1b4f6b32016-08-04 16:37:48 -070076
tsepez736f28a2016-03-25 14:19:51 -070077void CFX_TxtBreak::SetLayoutStyles(uint32_t dwLayoutStyles) {
Dan Sinclair1770c022016-03-14 14:14:16 -040078 m_dwLayoutStyles = dwLayoutStyles;
Dan Sinclair1770c022016-03-14 14:14:16 -040079 m_bSingleLine = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
80 m_bCombText = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
81 ResetArabicContext();
Dan Sinclair1770c022016-03-14 14:14:16 -040082}
weili1b4f6b32016-08-04 16:37:48 -070083
tsepeze6477992017-01-05 12:57:00 -080084void CFX_TxtBreak::SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont) {
85 if (!pFont || pFont == m_pFont)
Dan Sinclair1770c022016-03-14 14:14:16 -040086 return;
tsepeze6477992017-01-05 12:57:00 -080087
Dan Sinclair1770c022016-03-14 14:14:16 -040088 SetBreakStatus();
89 m_pFont = pFont;
Dan Sinclair17f31182017-03-01 09:31:51 -050090 FontChanged();
Dan Sinclair1770c022016-03-14 14:14:16 -040091}
weili1b4f6b32016-08-04 16:37:48 -070092
Dan Sinclair1770c022016-03-14 14:14:16 -040093void CFX_TxtBreak::SetFontSize(FX_FLOAT fFontSize) {
94 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
Dan Sinclair17f31182017-03-01 09:31:51 -050095 if (m_iFontSize == iFontSize)
Dan Sinclair1770c022016-03-14 14:14:16 -040096 return;
Dan Sinclair17f31182017-03-01 09:31:51 -050097
Dan Sinclair1770c022016-03-14 14:14:16 -040098 SetBreakStatus();
99 m_iFontSize = iFontSize;
Dan Sinclair17f31182017-03-01 09:31:51 -0500100 FontChanged();
101}
102
103void CFX_TxtBreak::FontChanged() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400104 m_iDefChar = 0;
Dan Sinclair17f31182017-03-01 09:31:51 -0500105 if (m_wDefChar == 0xFEFF || !m_pFont)
106 return;
107
108 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false);
109 m_iDefChar *= m_iFontSize;
Dan Sinclair1770c022016-03-14 14:14:16 -0400110}
weili1b4f6b32016-08-04 16:37:48 -0700111
tsepezd19e9122016-11-02 15:43:18 -0700112void CFX_TxtBreak::SetTabWidth(FX_FLOAT fTabWidth, bool bEquidistant) {
Dan Sinclairc36fe072017-03-09 16:58:12 -0500113 m_iTabWidth = std::max(FXSYS_round(fTabWidth * 20000.0f), kMinimumTabWidth);
Dan Sinclair1770c022016-03-14 14:14:16 -0400114 m_bEquidistant = bEquidistant;
115}
weili1b4f6b32016-08-04 16:37:48 -0700116
Dan Sinclair1770c022016-03-14 14:14:16 -0400117void CFX_TxtBreak::SetDefaultChar(FX_WCHAR wch) {
118 m_wDefChar = wch;
119 m_iDefChar = 0;
Dan Sinclair17f31182017-03-01 09:31:51 -0500120 if (m_wDefChar == 0xFEFF || !m_pFont)
121 return;
122
123 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false);
124 if (m_iDefChar < 0)
125 m_iDefChar = 0;
126 else
127 m_iDefChar *= m_iFontSize;
Dan Sinclair1770c022016-03-14 14:14:16 -0400128}
weili1b4f6b32016-08-04 16:37:48 -0700129
Dan Sinclair1770c022016-03-14 14:14:16 -0400130void CFX_TxtBreak::SetParagraphBreakChar(FX_WCHAR wch) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500131 if (wch != L'\r' && wch != L'\n')
Dan Sinclair1770c022016-03-14 14:14:16 -0400132 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400133 m_wParagBreakChar = wch;
134}
weili1b4f6b32016-08-04 16:37:48 -0700135
Dan Sinclair1770c022016-03-14 14:14:16 -0400136void CFX_TxtBreak::SetLineBreakTolerance(FX_FLOAT fTolerance) {
137 m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
138}
weili1b4f6b32016-08-04 16:37:48 -0700139
Dan Sinclair1770c022016-03-14 14:14:16 -0400140void CFX_TxtBreak::SetAlignment(int32_t iAlignment) {
Dan Sinclair9e9bab62017-03-09 16:59:12 -0500141 ASSERT(iAlignment >= CFX_TxtLineAlignment_Left &&
142 iAlignment <= CFX_TxtLineAlignment_Justified);
Dan Sinclair1770c022016-03-14 14:14:16 -0400143 m_iAlignment = iAlignment;
144 ResetArabicContext();
145}
weili1b4f6b32016-08-04 16:37:48 -0700146
Dan Sinclair1770c022016-03-14 14:14:16 -0400147void CFX_TxtBreak::ResetContextCharStyles() {
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400148 m_dwContextCharStyles = m_iAlignment;
Dan Sinclair1770c022016-03-14 14:14:16 -0400149 m_dwContextCharStyles |= (m_iArabicContext << 8);
150}
weili1b4f6b32016-08-04 16:37:48 -0700151
Dan Sinclair1770c022016-03-14 14:14:16 -0400152void CFX_TxtBreak::SetCombWidth(FX_FLOAT fCombWidth) {
153 m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f);
154}
weili1b4f6b32016-08-04 16:37:48 -0700155
Dan Sinclair1770c022016-03-14 14:14:16 -0400156void CFX_TxtBreak::SetBreakStatus() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400157 int32_t iCount = m_pCurLine->CountChars();
Dan Sinclair17f31182017-03-01 09:31:51 -0500158 if (iCount < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400159 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500160
tsepez215507d2016-06-09 19:05:47 -0700161 CFX_TxtChar* pTC = m_pCurLine->GetCharPtr(iCount - 1);
Dan Sinclairc36fe072017-03-09 16:58:12 -0500162 if (pTC->m_dwStatus == CFX_BreakType::None)
163 pTC->m_dwStatus = CFX_BreakType::Piece;
Dan Sinclair1770c022016-03-14 14:14:16 -0400164}
weili1b4f6b32016-08-04 16:37:48 -0700165
Dan Sinclair1770c022016-03-14 14:14:16 -0400166void CFX_TxtBreak::SetHorizontalScale(int32_t iScale) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500167 if (iScale < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400168 iScale = 0;
Dan Sinclair17f31182017-03-01 09:31:51 -0500169 if (iScale == m_iHorScale)
Dan Sinclair1770c022016-03-14 14:14:16 -0400170 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500171
Dan Sinclair1770c022016-03-14 14:14:16 -0400172 SetBreakStatus();
173 m_iHorScale = iScale;
174}
weili1b4f6b32016-08-04 16:37:48 -0700175
Dan Sinclair1770c022016-03-14 14:14:16 -0400176void CFX_TxtBreak::SetCharSpace(FX_FLOAT fCharSpace) {
177 m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
178}
weili1b4f6b32016-08-04 16:37:48 -0700179
tsepezd19e9122016-11-02 15:43:18 -0700180CFX_TxtChar* CFX_TxtBreak::GetLastChar(int32_t index, bool bOmitChar) const {
Dan Sinclair52c73c22017-03-09 13:27:29 -0500181 std::vector<CFX_TxtChar>& ca = m_pCurLine->m_LineChars;
tsepez33316fc2017-01-24 12:17:40 -0800182 int32_t iCount = pdfium::CollectionSize<int32_t>(ca);
Dan Sinclair17f31182017-03-01 09:31:51 -0500183 if (index < 0 || index >= iCount)
dsinclair85d1f2c2016-06-23 12:40:16 -0700184 return nullptr;
Dan Sinclair17f31182017-03-01 09:31:51 -0500185
Dan Sinclair1770c022016-03-14 14:14:16 -0400186 int32_t iStart = iCount - 1;
187 while (iStart > -1) {
tsepez33316fc2017-01-24 12:17:40 -0800188 CFX_TxtChar* pTC = &ca[iStart--];
Dan Sinclair17f31182017-03-01 09:31:51 -0500189 if (bOmitChar && pTC->GetCharType() == FX_CHARTYPE_Combination)
Dan Sinclair1770c022016-03-14 14:14:16 -0400190 continue;
Dan Sinclair17f31182017-03-01 09:31:51 -0500191 if (--index < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400192 return pTC;
Dan Sinclair1770c022016-03-14 14:14:16 -0400193 }
dsinclair85d1f2c2016-06-23 12:40:16 -0700194 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400195}
weili1b4f6b32016-08-04 16:37:48 -0700196
Dan Sinclair52c73c22017-03-09 13:27:29 -0500197const CFX_TxtLine* CFX_TxtBreak::GetTxtLine() const {
dsinclair85d1f2c2016-06-23 12:40:16 -0700198 if (m_iReady == 1)
Dan Sinclair52c73c22017-03-09 13:27:29 -0500199 return &m_TxtLine1;
dsinclair85d1f2c2016-06-23 12:40:16 -0700200 if (m_iReady == 2)
Dan Sinclair52c73c22017-03-09 13:27:29 -0500201 return &m_TxtLine2;
dsinclair85d1f2c2016-06-23 12:40:16 -0700202 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400203}
weili1b4f6b32016-08-04 16:37:48 -0700204
Dan Sinclair52c73c22017-03-09 13:27:29 -0500205const CFX_TxtPieceArray* CFX_TxtBreak::GetTxtPieces() const {
206 const CFX_TxtLine* pTxtLine = GetTxtLine();
207 return pTxtLine ? &pTxtLine->m_LinePieces : nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400208}
weili1b4f6b32016-08-04 16:37:48 -0700209
weilia2c06e42016-05-20 17:09:48 -0700210inline FX_CHARTYPE CFX_TxtBreak::GetUnifiedCharType(
211 FX_CHARTYPE chartype) const {
212 return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype;
Dan Sinclair1770c022016-03-14 14:14:16 -0400213}
weili1b4f6b32016-08-04 16:37:48 -0700214
Dan Sinclair1770c022016-03-14 14:14:16 -0400215void CFX_TxtBreak::ResetArabicContext() {
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400216 m_iCurAlignment = m_iAlignment;
Dan Sinclair1770c022016-03-14 14:14:16 -0400217 ResetContextCharStyles();
218}
weili1b4f6b32016-08-04 16:37:48 -0700219
tsepez215507d2016-06-09 19:05:47 -0700220void CFX_TxtBreak::AppendChar_PageLoad(CFX_TxtChar* pCurChar,
221 uint32_t dwProps) {
Dan Sinclairc36fe072017-03-09 16:58:12 -0500222 pCurChar->m_dwStatus = CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400223 pCurChar->m_dwCharStyles = m_dwContextCharStyles;
224}
weili1b4f6b32016-08-04 16:37:48 -0700225
Dan Sinclair068d3442017-03-13 10:15:36 -0400226CFX_BreakType CFX_TxtBreak::AppendChar_Combination(CFX_TxtChar* pCurChar) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400227 FX_WCHAR wch = pCurChar->m_wCharCode;
228 FX_WCHAR wForm;
229 int32_t iCharWidth = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400230 pCurChar->m_iCharWidth = -1;
231 if (m_bCombText) {
232 iCharWidth = m_iCombWidth;
233 } else {
Dan Sinclair068d3442017-03-13 10:15:36 -0400234 wForm = wch;
235 CFX_TxtChar* pLastChar = GetLastChar(0, false);
236 if (pLastChar &&
237 (pLastChar->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicShadda) == 0) {
238 bool bShadda = false;
239 if (wch == 0x0651) {
240 FX_WCHAR wLast = pLastChar->m_wCharCode;
241 if (wLast >= 0x064C && wLast <= 0x0650) {
242 wForm = FX_GetArabicFromShaddaTable(wLast);
243 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400244 }
Dan Sinclair068d3442017-03-13 10:15:36 -0400245 } else if (wch >= 0x064C && wch <= 0x0650) {
246 if (pLastChar->m_wCharCode == 0x0651) {
247 wForm = FX_GetArabicFromShaddaTable(wch);
248 bShadda = true;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500249 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400250 }
Dan Sinclair068d3442017-03-13 10:15:36 -0400251 if (bShadda) {
252 pLastChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
253 pLastChar->m_iCharWidth = 0;
254 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
255 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400256 }
Dan Sinclair068d3442017-03-13 10:15:36 -0400257 if (!m_pFont->GetCharWidth(wForm, iCharWidth, false))
258 iCharWidth = 0;
259
Dan Sinclair1770c022016-03-14 14:14:16 -0400260 iCharWidth *= m_iFontSize;
261 iCharWidth = iCharWidth * m_iHorScale / 100;
262 }
263 pCurChar->m_iCharWidth = -iCharWidth;
Dan Sinclairc36fe072017-03-09 16:58:12 -0500264 return CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400265}
weili1b4f6b32016-08-04 16:37:48 -0700266
Dan Sinclair068d3442017-03-13 10:15:36 -0400267CFX_BreakType CFX_TxtBreak::AppendChar_Tab(CFX_TxtChar* pCurChar) {
weilia2c06e42016-05-20 17:09:48 -0700268 m_eCharType = FX_CHARTYPE_Tab;
Dan Sinclairc36fe072017-03-09 16:58:12 -0500269 return CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400270}
weili1b4f6b32016-08-04 16:37:48 -0700271
Dan Sinclair068d3442017-03-13 10:15:36 -0400272CFX_BreakType CFX_TxtBreak::AppendChar_Control(CFX_TxtChar* pCurChar) {
weilia2c06e42016-05-20 17:09:48 -0700273 m_eCharType = FX_CHARTYPE_Control;
Dan Sinclairc36fe072017-03-09 16:58:12 -0500274 CFX_BreakType dwRet = CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400275 if (!m_bSingleLine) {
276 FX_WCHAR wch = pCurChar->m_wCharCode;
277 switch (wch) {
278 case L'\v':
279 case 0x2028:
Dan Sinclairc36fe072017-03-09 16:58:12 -0500280 dwRet = CFX_BreakType::Line;
Dan Sinclair1770c022016-03-14 14:14:16 -0400281 break;
282 case L'\f':
Dan Sinclairc36fe072017-03-09 16:58:12 -0500283 dwRet = CFX_BreakType::Page;
Dan Sinclair1770c022016-03-14 14:14:16 -0400284 break;
285 case 0x2029:
Dan Sinclairc36fe072017-03-09 16:58:12 -0500286 dwRet = CFX_BreakType::Paragraph;
Dan Sinclair1770c022016-03-14 14:14:16 -0400287 break;
288 default:
Dan Sinclair17f31182017-03-01 09:31:51 -0500289 if (wch == m_wParagBreakChar)
Dan Sinclairc36fe072017-03-09 16:58:12 -0500290 dwRet = CFX_BreakType::Paragraph;
Dan Sinclair1770c022016-03-14 14:14:16 -0400291 break;
292 }
Dan Sinclairc36fe072017-03-09 16:58:12 -0500293 if (dwRet != CFX_BreakType::None)
Dan Sinclair1770c022016-03-14 14:14:16 -0400294 dwRet = EndBreak(dwRet);
Dan Sinclair1770c022016-03-14 14:14:16 -0400295 }
296 return dwRet;
297}
weili1b4f6b32016-08-04 16:37:48 -0700298
Dan Sinclair068d3442017-03-13 10:15:36 -0400299CFX_BreakType CFX_TxtBreak::AppendChar_Arabic(CFX_TxtChar* pCurChar) {
weilia2c06e42016-05-20 17:09:48 -0700300 FX_CHARTYPE chartype = pCurChar->GetCharType();
Dan Sinclair1770c022016-03-14 14:14:16 -0400301 int32_t& iLineWidth = m_pCurLine->m_iWidth;
302 FX_WCHAR wForm;
303 int32_t iCharWidth = 0;
Dan Sinclairfb906e32017-02-28 10:20:12 -0500304 CFX_TxtChar* pLastChar = nullptr;
tsepezd19e9122016-11-02 15:43:18 -0700305 bool bAlef = false;
weilia2c06e42016-05-20 17:09:48 -0700306 if (!m_bCombText && m_eCharType >= FX_CHARTYPE_ArabicAlef &&
307 m_eCharType <= FX_CHARTYPE_ArabicDistortion) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400308 pLastChar = GetLastChar(1);
dsinclair85d1f2c2016-06-23 12:40:16 -0700309 if (pLastChar) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400310 iCharWidth = pLastChar->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500311 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400312 iLineWidth -= iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500313
Dan Sinclair1770c022016-03-14 14:14:16 -0400314 CFX_Char* pPrevChar = GetLastChar(2);
tsepeze00f75c2016-05-06 13:15:46 -0700315 wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar);
Dan Sinclair1770c022016-03-14 14:14:16 -0400316 bAlef = (wForm == 0xFEFF &&
317 pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef);
Dan Sinclair068d3442017-03-13 10:15:36 -0400318 m_pFont->GetCharWidth(wForm, iCharWidth, false);
Dan Sinclair17f31182017-03-01 09:31:51 -0500319
320 if (wForm == 0xFEFF)
Dan Sinclair1770c022016-03-14 14:14:16 -0400321 iCharWidth = m_iDefChar;
Dan Sinclair17f31182017-03-01 09:31:51 -0500322
Dan Sinclair1770c022016-03-14 14:14:16 -0400323 iCharWidth *= m_iFontSize;
324 iCharWidth = iCharWidth * m_iHorScale / 100;
325 pLastChar->m_iCharWidth = iCharWidth;
326 iLineWidth += iCharWidth;
327 iCharWidth = 0;
328 }
329 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500330
weilia2c06e42016-05-20 17:09:48 -0700331 m_eCharType = chartype;
dsinclair85d1f2c2016-06-23 12:40:16 -0700332 wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar,
333 nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400334 if (m_bCombText) {
335 iCharWidth = m_iCombWidth;
336 } else {
Dan Sinclair068d3442017-03-13 10:15:36 -0400337 m_pFont->GetCharWidth(wForm, iCharWidth, false);
Dan Sinclair17f31182017-03-01 09:31:51 -0500338
339 if (wForm == 0xFEFF)
Dan Sinclair1770c022016-03-14 14:14:16 -0400340 iCharWidth = m_iDefChar;
Dan Sinclair17f31182017-03-01 09:31:51 -0500341
Dan Sinclair1770c022016-03-14 14:14:16 -0400342 iCharWidth *= m_iFontSize;
343 iCharWidth = iCharWidth * m_iHorScale / 100;
344 }
345 pCurChar->m_iCharWidth = iCharWidth;
346 iLineWidth += iCharWidth;
347 m_pCurLine->m_iArabicChars++;
Dan Sinclair17f31182017-03-01 09:31:51 -0500348 if (!m_bSingleLine && iLineWidth > m_iLineWidth + m_iTolerance)
Dan Sinclairc36fe072017-03-09 16:58:12 -0500349 return EndBreak(CFX_BreakType::Line);
350 return CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400351}
weili1b4f6b32016-08-04 16:37:48 -0700352
Dan Sinclair068d3442017-03-13 10:15:36 -0400353CFX_BreakType CFX_TxtBreak::AppendChar_Others(CFX_TxtChar* pCurChar) {
weilia2c06e42016-05-20 17:09:48 -0700354 FX_CHARTYPE chartype = pCurChar->GetCharType();
Dan Sinclair1770c022016-03-14 14:14:16 -0400355 int32_t& iLineWidth = m_pCurLine->m_iWidth;
356 int32_t iCharWidth = 0;
weilia2c06e42016-05-20 17:09:48 -0700357 m_eCharType = chartype;
Dan Sinclair1770c022016-03-14 14:14:16 -0400358 FX_WCHAR wch = pCurChar->m_wCharCode;
359 FX_WCHAR wForm = wch;
Dan Sinclair17f31182017-03-01 09:31:51 -0500360
Dan Sinclair1770c022016-03-14 14:14:16 -0400361 if (m_bCombText) {
362 iCharWidth = m_iCombWidth;
363 } else {
Dan Sinclair068d3442017-03-13 10:15:36 -0400364 if (!m_pFont->GetCharWidth(wForm, iCharWidth, false))
Dan Sinclair1770c022016-03-14 14:14:16 -0400365 iCharWidth = m_iDefChar;
Dan Sinclair17f31182017-03-01 09:31:51 -0500366
Dan Sinclair1770c022016-03-14 14:14:16 -0400367 iCharWidth *= m_iFontSize;
368 iCharWidth = iCharWidth * m_iHorScale / 100;
369 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500370
Dan Sinclair1770c022016-03-14 14:14:16 -0400371 iCharWidth += m_iCharSpace;
372 pCurChar->m_iCharWidth = iCharWidth;
373 iLineWidth += iCharWidth;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500374 if (!m_bSingleLine && chartype != FX_CHARTYPE_Space &&
375 iLineWidth > m_iLineWidth + m_iTolerance) {
Dan Sinclairc36fe072017-03-09 16:58:12 -0500376 return EndBreak(CFX_BreakType::Line);
Dan Sinclair52c73c22017-03-09 13:27:29 -0500377 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500378
Dan Sinclairc36fe072017-03-09 16:58:12 -0500379 return CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400380}
tsepez215507d2016-06-09 19:05:47 -0700381
Dan Sinclairc36fe072017-03-09 16:58:12 -0500382CFX_BreakType CFX_TxtBreak::AppendChar(FX_WCHAR wch) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500383 uint32_t dwProps = kTextLayoutCodeProperties[static_cast<uint16_t>(wch)];
weilia2c06e42016-05-20 17:09:48 -0700384 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
Dan Sinclair52c73c22017-03-09 13:27:29 -0500385 m_pCurLine->m_LineChars.emplace_back();
Dan Sinclair17f31182017-03-01 09:31:51 -0500386
Dan Sinclair52c73c22017-03-09 13:27:29 -0500387 CFX_TxtChar* pCurChar = &m_pCurLine->m_LineChars.back();
Dan Sinclair17f31182017-03-01 09:31:51 -0500388 pCurChar->m_wCharCode = static_cast<uint16_t>(wch);
Dan Sinclair1770c022016-03-14 14:14:16 -0400389 pCurChar->m_dwCharProps = dwProps;
390 pCurChar->m_dwCharStyles = 0;
391 pCurChar->m_iCharWidth = 0;
392 pCurChar->m_iHorizontalScale = m_iHorScale;
Dan Sinclair70719432017-02-28 14:48:51 -0500393 pCurChar->m_iVerticalScale = 100;
Dan Sinclairc36fe072017-03-09 16:58:12 -0500394 pCurChar->m_dwStatus = CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400395 pCurChar->m_iBidiClass = 0;
396 pCurChar->m_iBidiLevel = 0;
397 pCurChar->m_iBidiPos = 0;
398 pCurChar->m_iBidiOrder = 0;
Dan Sinclair1c97fd12017-03-09 16:58:55 -0500399
Dan Sinclair1770c022016-03-14 14:14:16 -0400400 AppendChar_PageLoad(pCurChar, dwProps);
Dan Sinclairc36fe072017-03-09 16:58:12 -0500401 CFX_BreakType dwRet1 = CFX_BreakType::None;
weilia2c06e42016-05-20 17:09:48 -0700402 if (chartype != FX_CHARTYPE_Combination &&
Dan Sinclair17f31182017-03-01 09:31:51 -0500403 GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) &&
404 m_eCharType != FX_CHARTYPE_Unknown &&
405 m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine &&
406 (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) {
Dan Sinclairc36fe072017-03-09 16:58:12 -0500407 dwRet1 = EndBreak(CFX_BreakType::Line);
Dan Sinclair17f31182017-03-01 09:31:51 -0500408 int32_t iCount = m_pCurLine->CountChars();
409 if (iCount > 0)
Dan Sinclair52c73c22017-03-09 13:27:29 -0500410 pCurChar = &m_pCurLine->m_LineChars[iCount - 1];
Dan Sinclair1770c022016-03-14 14:14:16 -0400411 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500412
Dan Sinclairc36fe072017-03-09 16:58:12 -0500413 CFX_BreakType dwRet2 =
weilia2c06e42016-05-20 17:09:48 -0700414 (this->*g_FX_TxtBreak_lpfAppendChar[chartype >> FX_CHARTYPEBITS])(
Dan Sinclair068d3442017-03-13 10:15:36 -0400415 pCurChar);
Dan Sinclair1770c022016-03-14 14:14:16 -0400416 return std::max(dwRet1, dwRet2);
417}
weili1b4f6b32016-08-04 16:37:48 -0700418
Dan Sinclairc36fe072017-03-09 16:58:12 -0500419bool CFX_TxtBreak::EndBreak_SplitLine(CFX_TxtLine* pNextLine, bool bAllChars) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400420 int32_t iCount = m_pCurLine->CountChars();
tsepezd19e9122016-11-02 15:43:18 -0700421 bool bDone = false;
Dan Sinclairfb906e32017-02-28 10:20:12 -0500422 CFX_TxtChar* pTC;
Dan Sinclair1770c022016-03-14 14:14:16 -0400423 if (!m_bSingleLine && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance) {
424 pTC = m_pCurLine->GetCharPtr(iCount - 1);
425 switch (pTC->GetCharType()) {
426 case FX_CHARTYPE_Tab:
427 case FX_CHARTYPE_Control:
Dan Sinclair1770c022016-03-14 14:14:16 -0400428 case FX_CHARTYPE_Space:
Dan Sinclair1770c022016-03-14 14:14:16 -0400429 break;
430 default:
Dan Sinclair52c73c22017-03-09 13:27:29 -0500431 SplitTextLine(m_pCurLine, pNextLine, bAllChars);
tsepezd19e9122016-11-02 15:43:18 -0700432 bDone = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400433 break;
434 }
435 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500436
Dan Sinclair1770c022016-03-14 14:14:16 -0400437 iCount = m_pCurLine->CountChars();
Dan Sinclair1770c022016-03-14 14:14:16 -0400438 CFX_TxtPiece tp;
Dan Sinclair1770c022016-03-14 14:14:16 -0400439 if (bAllChars && !bDone) {
440 int32_t iEndPos = m_pCurLine->m_iWidth;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500441 GetBreakPos(m_pCurLine->m_LineChars, iEndPos, bAllChars, true);
Dan Sinclair1770c022016-03-14 14:14:16 -0400442 }
tsepezd19e9122016-11-02 15:43:18 -0700443 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400444}
weili1b4f6b32016-08-04 16:37:48 -0700445
Tom Sepez4a211142017-03-01 14:41:25 -0800446void CFX_TxtBreak::EndBreak_BidiLine(std::deque<FX_TPO>* tpos,
Dan Sinclairc36fe072017-03-09 16:58:12 -0500447 CFX_BreakType dwStatus) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400448 CFX_TxtPiece tp;
449 FX_TPO tpo;
450 CFX_TxtChar* pTC;
Dan Sinclair17f31182017-03-01 09:31:51 -0500451 int32_t i;
452 int32_t j;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500453 std::vector<CFX_TxtChar>& chars = m_pCurLine->m_LineChars;
Dan Sinclair1770c022016-03-14 14:14:16 -0400454 int32_t iCount = m_pCurLine->CountChars();
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400455 bool bDone = m_pCurLine->m_iArabicChars > 0;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500456 if (bDone) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400457 int32_t iBidiNum = 0;
458 for (i = 0; i < iCount; i++) {
tsepez33316fc2017-01-24 12:17:40 -0800459 pTC = &chars[i];
Dan Sinclair1770c022016-03-14 14:14:16 -0400460 pTC->m_iBidiPos = i;
Dan Sinclair17f31182017-03-01 09:31:51 -0500461 if (pTC->GetCharType() != FX_CHARTYPE_Control)
Dan Sinclair1770c022016-03-14 14:14:16 -0400462 iBidiNum = i;
Dan Sinclair17f31182017-03-01 09:31:51 -0500463 if (i == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400464 pTC->m_iBidiLevel = 1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400465 }
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400466 FX_BidiLine(chars, iBidiNum + 1, 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400467 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500468
Dan Sinclair52c73c22017-03-09 13:27:29 -0500469 CFX_TxtPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400470 if (bDone) {
Dan Sinclairc36fe072017-03-09 16:58:12 -0500471 tp.m_dwStatus = CFX_BreakType::Piece;
Dan Sinclair1770c022016-03-14 14:14:16 -0400472 tp.m_iStartPos = m_pCurLine->m_iStart;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500473 tp.m_pChars = &m_pCurLine->m_LineChars;
Dan Sinclair17f31182017-03-01 09:31:51 -0500474 int32_t iBidiLevel = -1;
475 int32_t iCharWidth;
476 i = 0;
477 j = -1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400478 while (i < iCount) {
tsepez33316fc2017-01-24 12:17:40 -0800479 pTC = &chars[i];
Dan Sinclair1770c022016-03-14 14:14:16 -0400480 if (iBidiLevel < 0) {
481 iBidiLevel = pTC->m_iBidiLevel;
482 tp.m_iWidth = 0;
483 tp.m_iBidiLevel = iBidiLevel;
484 tp.m_iBidiPos = pTC->m_iBidiOrder;
485 tp.m_dwCharStyles = pTC->m_dwCharStyles;
Dan Sinclair1770c022016-03-14 14:14:16 -0400486 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
Dan Sinclair70719432017-02-28 14:48:51 -0500487 tp.m_iVerticalScale = pTC->m_iVerticalScale;
Dan Sinclairc36fe072017-03-09 16:58:12 -0500488 tp.m_dwStatus = CFX_BreakType::Piece;
Dan Sinclair1770c022016-03-14 14:14:16 -0400489 }
Dan Sinclairc36fe072017-03-09 16:58:12 -0500490 if (iBidiLevel != pTC->m_iBidiLevel ||
491 pTC->m_dwStatus != CFX_BreakType::None) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400492 if (iBidiLevel == pTC->m_iBidiLevel) {
493 tp.m_dwStatus = pTC->m_dwStatus;
494 iCharWidth = pTC->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500495 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400496 tp.m_iWidth += iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500497
Dan Sinclair1770c022016-03-14 14:14:16 -0400498 i++;
499 }
500 tp.m_iChars = i - tp.m_iStartChar;
501 pCurPieces->Add(tp);
502 tp.m_iStartPos += tp.m_iWidth;
503 tp.m_iStartChar = i;
504 tpo.index = ++j;
505 tpo.pos = tp.m_iBidiPos;
Tom Sepez4a211142017-03-01 14:41:25 -0800506 tpos->push_back(tpo);
Dan Sinclair1770c022016-03-14 14:14:16 -0400507 iBidiLevel = -1;
508 } else {
509 iCharWidth = pTC->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500510 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400511 tp.m_iWidth += iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500512
Dan Sinclair1770c022016-03-14 14:14:16 -0400513 i++;
514 }
515 }
516 if (i > tp.m_iStartChar) {
517 tp.m_dwStatus = dwStatus;
518 tp.m_iChars = i - tp.m_iStartChar;
519 pCurPieces->Add(tp);
520 tpo.index = ++j;
521 tpo.pos = tp.m_iBidiPos;
Tom Sepez4a211142017-03-01 14:41:25 -0800522 tpos->push_back(tpo);
Dan Sinclair1770c022016-03-14 14:14:16 -0400523 }
524 if (j > -1) {
525 if (j > 0) {
Tom Sepez4a211142017-03-01 14:41:25 -0800526 std::sort(tpos->begin(), tpos->end());
Dan Sinclair1770c022016-03-14 14:14:16 -0400527 int32_t iStartPos = 0;
528 for (i = 0; i <= j; i++) {
Tom Sepez4a211142017-03-01 14:41:25 -0800529 tpo = (*tpos)[i];
Dan Sinclair1770c022016-03-14 14:14:16 -0400530 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
531 ttp.m_iStartPos = iStartPos;
532 iStartPos += ttp.m_iWidth;
533 }
534 }
535 CFX_TxtPiece& ttp = pCurPieces->GetAt(j);
536 ttp.m_dwStatus = dwStatus;
537 }
538 } else {
539 tp.m_dwStatus = dwStatus;
540 tp.m_iStartPos = m_pCurLine->m_iStart;
541 tp.m_iWidth = m_pCurLine->m_iWidth;
542 tp.m_iStartChar = 0;
543 tp.m_iChars = iCount;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500544 tp.m_pChars = &m_pCurLine->m_LineChars;
tsepez33316fc2017-01-24 12:17:40 -0800545 pTC = &chars[0];
Dan Sinclair1770c022016-03-14 14:14:16 -0400546 tp.m_dwCharStyles = pTC->m_dwCharStyles;
547 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
Dan Sinclair70719432017-02-28 14:48:51 -0500548 tp.m_iVerticalScale = pTC->m_iVerticalScale;
Dan Sinclair1770c022016-03-14 14:14:16 -0400549 pCurPieces->Add(tp);
Tom Sepez4a211142017-03-01 14:41:25 -0800550 tpos->push_back({0, 0});
Dan Sinclair1770c022016-03-14 14:14:16 -0400551 }
552}
weili1b4f6b32016-08-04 16:37:48 -0700553
Tom Sepez4a211142017-03-01 14:41:25 -0800554void CFX_TxtBreak::EndBreak_Alignment(const std::deque<FX_TPO>& tpos,
tsepezd19e9122016-11-02 15:43:18 -0700555 bool bAllChars,
Dan Sinclairc36fe072017-03-09 16:58:12 -0500556 CFX_BreakType dwStatus) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500557 int32_t iNetWidth = m_pCurLine->m_iWidth;
558 int32_t iGapChars = 0;
559 int32_t iCharWidth;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500560 CFX_TxtPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
Dan Sinclair17f31182017-03-01 09:31:51 -0500561 int32_t i;
562 int32_t j;
563 int32_t iCount = pCurPieces->GetSize();
tsepezd19e9122016-11-02 15:43:18 -0700564 bool bFind = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400565 FX_TPO tpo;
566 CFX_TxtChar* pTC;
weilia2c06e42016-05-20 17:09:48 -0700567 FX_CHARTYPE chartype;
Dan Sinclair1770c022016-03-14 14:14:16 -0400568 for (i = iCount - 1; i > -1; i--) {
Tom Sepez4a211142017-03-01 14:41:25 -0800569 tpo = tpos[i];
Dan Sinclair1770c022016-03-14 14:14:16 -0400570 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
Dan Sinclair17f31182017-03-01 09:31:51 -0500571 if (!bFind)
Dan Sinclair1770c022016-03-14 14:14:16 -0400572 iNetWidth = ttp.GetEndPos();
Dan Sinclair17f31182017-03-01 09:31:51 -0500573
tsepezd19e9122016-11-02 15:43:18 -0700574 bool bArabic = FX_IsOdd(ttp.m_iBidiLevel);
Dan Sinclair1770c022016-03-14 14:14:16 -0400575 j = bArabic ? 0 : ttp.m_iChars - 1;
576 while (j > -1 && j < ttp.m_iChars) {
577 pTC = ttp.GetCharPtr(j);
Dan Sinclair17f31182017-03-01 09:31:51 -0500578 if (pTC->m_nBreakType == FX_LBT_DIRECT_BRK)
Dan Sinclair1770c022016-03-14 14:14:16 -0400579 iGapChars++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400580 if (!bFind || !bAllChars) {
weilia2c06e42016-05-20 17:09:48 -0700581 chartype = pTC->GetCharType();
582 if (chartype == FX_CHARTYPE_Space || chartype == FX_CHARTYPE_Control) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400583 if (!bFind) {
584 iCharWidth = pTC->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500585 if (bAllChars && iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400586 iNetWidth -= iCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -0400587 }
588 } else {
tsepezd19e9122016-11-02 15:43:18 -0700589 bFind = true;
Dan Sinclair17f31182017-03-01 09:31:51 -0500590 if (!bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400591 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400592 }
593 }
594 j += bArabic ? 1 : -1;
595 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500596 if (!bAllChars && bFind)
Dan Sinclair1770c022016-03-14 14:14:16 -0400597 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400598 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500599
Dan Sinclair1770c022016-03-14 14:14:16 -0400600 int32_t iOffset = m_iLineWidth - iNetWidth;
Dan Sinclair9e9bab62017-03-09 16:59:12 -0500601 if (iGapChars > 0 && m_iCurAlignment & CFX_TxtLineAlignment_Justified &&
602 dwStatus != CFX_BreakType::Paragraph) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400603 int32_t iStart = -1;
604 for (i = 0; i < iCount; i++) {
Tom Sepez4a211142017-03-01 14:41:25 -0800605 tpo = tpos[i];
Dan Sinclair1770c022016-03-14 14:14:16 -0400606 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
Dan Sinclair17f31182017-03-01 09:31:51 -0500607 if (iStart < -1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400608 iStart = ttp.m_iStartPos;
Dan Sinclair17f31182017-03-01 09:31:51 -0500609 else
Dan Sinclair1770c022016-03-14 14:14:16 -0400610 ttp.m_iStartPos = iStart;
Dan Sinclair17f31182017-03-01 09:31:51 -0500611
Dan Sinclair1770c022016-03-14 14:14:16 -0400612 for (j = 0; j < ttp.m_iChars; j++) {
613 pTC = ttp.GetCharPtr(j);
Dan Sinclair17f31182017-03-01 09:31:51 -0500614 if (pTC->m_nBreakType != FX_LBT_DIRECT_BRK || pTC->m_iCharWidth < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400615 continue;
Dan Sinclair17f31182017-03-01 09:31:51 -0500616
617 int32_t k = iOffset / iGapChars;
Dan Sinclair1770c022016-03-14 14:14:16 -0400618 pTC->m_iCharWidth += k;
619 ttp.m_iWidth += k;
620 iOffset -= k;
621 iGapChars--;
Dan Sinclair17f31182017-03-01 09:31:51 -0500622 if (iGapChars < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400623 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400624 }
625 iStart += ttp.m_iWidth;
626 }
Dan Sinclair9e9bab62017-03-09 16:59:12 -0500627 } else if (m_iCurAlignment & CFX_TxtLineAlignment_Center ||
628 m_iCurAlignment & CFX_TxtLineAlignment_Right) {
629 if (m_iCurAlignment & CFX_TxtLineAlignment_Center &&
630 !(m_iCurAlignment & CFX_TxtLineAlignment_Right)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400631 iOffset /= 2;
Dan Sinclair9e9bab62017-03-09 16:59:12 -0500632 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400633 if (iOffset > 0) {
634 for (i = 0; i < iCount; i++) {
635 CFX_TxtPiece& ttp = pCurPieces->GetAt(i);
636 ttp.m_iStartPos += iOffset;
637 }
638 }
639 }
640}
weili1b4f6b32016-08-04 16:37:48 -0700641
Dan Sinclairc36fe072017-03-09 16:58:12 -0500642CFX_BreakType CFX_TxtBreak::EndBreak(CFX_BreakType dwStatus) {
643 ASSERT(dwStatus != CFX_BreakType::None);
Dan Sinclair52c73c22017-03-09 13:27:29 -0500644 const CFX_TxtPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
Dan Sinclair1770c022016-03-14 14:14:16 -0400645 int32_t iCount = pCurPieces->GetSize();
646 if (iCount > 0) {
647 CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(--iCount);
Dan Sinclairc36fe072017-03-09 16:58:12 -0500648 if (dwStatus != CFX_BreakType::Piece)
Dan Sinclair1770c022016-03-14 14:14:16 -0400649 pLastPiece->m_dwStatus = dwStatus;
Dan Sinclair17f31182017-03-01 09:31:51 -0500650 else
Dan Sinclair1770c022016-03-14 14:14:16 -0400651 dwStatus = pLastPiece->m_dwStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400652 return dwStatus;
653 } else {
Dan Sinclair52c73c22017-03-09 13:27:29 -0500654 const CFX_TxtLine* pLastLine = GetTxtLine();
dsinclair85d1f2c2016-06-23 12:40:16 -0700655 if (pLastLine) {
Dan Sinclair52c73c22017-03-09 13:27:29 -0500656 pCurPieces = &pLastLine->m_LinePieces;
Dan Sinclair1770c022016-03-14 14:14:16 -0400657 iCount = pCurPieces->GetSize();
658 if (iCount-- > 0) {
659 CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(iCount);
Dan Sinclairc36fe072017-03-09 16:58:12 -0500660 if (dwStatus != CFX_BreakType::Piece)
Dan Sinclair1770c022016-03-14 14:14:16 -0400661 pLastPiece->m_dwStatus = dwStatus;
Dan Sinclair17f31182017-03-01 09:31:51 -0500662 else
Dan Sinclair1770c022016-03-14 14:14:16 -0400663 dwStatus = pLastPiece->m_dwStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400664 return dwStatus;
665 }
Dan Sinclairc36fe072017-03-09 16:58:12 -0500666 return CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400667 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500668
Dan Sinclair1770c022016-03-14 14:14:16 -0400669 iCount = m_pCurLine->CountChars();
Dan Sinclair17f31182017-03-01 09:31:51 -0500670 if (iCount < 1)
Dan Sinclairc36fe072017-03-09 16:58:12 -0500671 return CFX_BreakType::None;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500672
673 CFX_TxtChar* pTC = m_pCurLine->GetCharPtr(iCount - 1);
674 pTC->m_dwStatus = dwStatus;
Dan Sinclairc36fe072017-03-09 16:58:12 -0500675 if (dwStatus == CFX_BreakType::Piece)
Dan Sinclair1770c022016-03-14 14:14:16 -0400676 return dwStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400677 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500678
Dan Sinclair52c73c22017-03-09 13:27:29 -0500679 m_iReady = m_pCurLine == &m_TxtLine1 ? 1 : 2;
Dan Sinclair1770c022016-03-14 14:14:16 -0400680 CFX_TxtLine* pNextLine =
Dan Sinclair52c73c22017-03-09 13:27:29 -0500681 m_pCurLine == &m_TxtLine1 ? &m_TxtLine2 : &m_TxtLine1;
Dan Sinclair9e9bab62017-03-09 16:59:12 -0500682 bool bAllChars = m_iCurAlignment > CFX_TxtLineAlignment_Right;
Dan Sinclairc36fe072017-03-09 16:58:12 -0500683 if (!EndBreak_SplitLine(pNextLine, bAllChars)) {
Tom Sepez4a211142017-03-01 14:41:25 -0800684 std::deque<FX_TPO> tpos;
685 EndBreak_BidiLine(&tpos, dwStatus);
Dan Sinclair9e9bab62017-03-09 16:59:12 -0500686 if (m_iCurAlignment > CFX_TxtLineAlignment_Left)
Dan Sinclair17f31182017-03-01 09:31:51 -0500687 EndBreak_Alignment(tpos, bAllChars, dwStatus);
Dan Sinclair1770c022016-03-14 14:14:16 -0400688 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500689
Dan Sinclair1770c022016-03-14 14:14:16 -0400690 m_pCurLine = pNextLine;
Tom Sepez4a211142017-03-01 14:41:25 -0800691 CFX_Char* pTC = GetLastChar(0, false);
weilia2c06e42016-05-20 17:09:48 -0700692 m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown;
Dan Sinclairc36fe072017-03-09 16:58:12 -0500693 if (dwStatus == CFX_BreakType::Paragraph) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400694 m_iArabicContext = m_iCurArabicContext = 1;
695 ResetArabicContext();
696 }
697 return dwStatus;
698}
weili1b4f6b32016-08-04 16:37:48 -0700699
tsepez33316fc2017-01-24 12:17:40 -0800700int32_t CFX_TxtBreak::GetBreakPos(std::vector<CFX_TxtChar>& ca,
Dan Sinclair1770c022016-03-14 14:14:16 -0400701 int32_t& iEndPos,
tsepezd19e9122016-11-02 15:43:18 -0700702 bool bAllChars,
703 bool bOnlyBrk) {
tsepez33316fc2017-01-24 12:17:40 -0800704 int32_t iLength = pdfium::CollectionSize<int32_t>(ca) - 1;
Dan Sinclair17f31182017-03-01 09:31:51 -0500705 if (iLength < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400706 return iLength;
Dan Sinclair17f31182017-03-01 09:31:51 -0500707
708 int32_t iBreak = -1;
709 int32_t iBreakPos = -1;
710 int32_t iIndirect = -1;
711 int32_t iIndirectPos = -1;
712 int32_t iLast = -1;
713 int32_t iLastPos = -1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400714 if (m_bSingleLine || iEndPos <= m_iLineWidth) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500715 if (!bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400716 return iLength;
Dan Sinclair17f31182017-03-01 09:31:51 -0500717
Dan Sinclair1770c022016-03-14 14:14:16 -0400718 iBreak = iLength;
719 iBreakPos = iEndPos;
720 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500721
Dan Sinclair1770c022016-03-14 14:14:16 -0400722 FX_LINEBREAKTYPE eType;
Dan Sinclair17f31182017-03-01 09:31:51 -0500723 uint32_t nCodeProp;
724 uint32_t nCur;
725 uint32_t nNext;
tsepez33316fc2017-01-24 12:17:40 -0800726 CFX_Char* pCur = &ca[iLength--];
Dan Sinclair17f31182017-03-01 09:31:51 -0500727 if (bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400728 pCur->m_nBreakType = FX_LBT_UNKNOWN;
Dan Sinclair17f31182017-03-01 09:31:51 -0500729
Dan Sinclair1770c022016-03-14 14:14:16 -0400730 nCodeProp = pCur->m_dwCharProps;
731 nNext = nCodeProp & 0x003F;
732 int32_t iCharWidth = pCur->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500733 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400734 iEndPos -= iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500735
Dan Sinclair1770c022016-03-14 14:14:16 -0400736 while (iLength >= 0) {
tsepez33316fc2017-01-24 12:17:40 -0800737 pCur = &ca[iLength];
Dan Sinclair1770c022016-03-14 14:14:16 -0400738 nCodeProp = pCur->m_dwCharProps;
739 nCur = nCodeProp & 0x003F;
740 if (nCur == FX_CBP_SP) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500741 if (nNext == FX_CBP_SP)
Dan Sinclair52c73c22017-03-09 13:27:29 -0500742 eType = FX_LBT_PROHIBITED_BRK;
Dan Sinclair17f31182017-03-01 09:31:51 -0500743 else
tsepezf49747f2016-06-10 15:24:47 -0700744 eType = gs_FX_LineBreak_PairTable[nCur][nNext];
Dan Sinclair1770c022016-03-14 14:14:16 -0400745 } else {
Dan Sinclair17f31182017-03-01 09:31:51 -0500746 if (nNext == FX_CBP_SP)
Dan Sinclair1770c022016-03-14 14:14:16 -0400747 eType = FX_LBT_PROHIBITED_BRK;
Dan Sinclair17f31182017-03-01 09:31:51 -0500748 else
tsepezf49747f2016-06-10 15:24:47 -0700749 eType = gs_FX_LineBreak_PairTable[nCur][nNext];
Dan Sinclair1770c022016-03-14 14:14:16 -0400750 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500751 if (bAllChars)
752 pCur->m_nBreakType = static_cast<uint8_t>(eType);
Dan Sinclair1770c022016-03-14 14:14:16 -0400753 if (!bOnlyBrk) {
Dan Sinclair52c73c22017-03-09 13:27:29 -0500754 if (m_bSingleLine || iEndPos <= m_iLineWidth || nCur == FX_CBP_SP) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400755 if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) {
756 iBreak = iLength;
757 iBreakPos = iEndPos;
Dan Sinclair17f31182017-03-01 09:31:51 -0500758 if (!bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400759 return iLength;
Dan Sinclair1770c022016-03-14 14:14:16 -0400760 } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) {
761 iIndirect = iLength;
762 iIndirectPos = iEndPos;
763 }
764 if (iLast < 0) {
765 iLast = iLength;
766 iLastPos = iEndPos;
767 }
768 }
769 iCharWidth = pCur->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500770 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400771 iEndPos -= iCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -0400772 }
773 nNext = nCodeProp & 0x003F;
774 iLength--;
775 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500776 if (bOnlyBrk)
Dan Sinclair1770c022016-03-14 14:14:16 -0400777 return 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400778 if (iBreak > -1) {
779 iEndPos = iBreakPos;
780 return iBreak;
781 }
782 if (iIndirect > -1) {
783 iEndPos = iIndirectPos;
784 return iIndirect;
785 }
786 if (iLast > -1) {
787 iEndPos = iLastPos;
788 return iLast;
789 }
790 return 0;
791}
weili1b4f6b32016-08-04 16:37:48 -0700792
Dan Sinclair1770c022016-03-14 14:14:16 -0400793void CFX_TxtBreak::SplitTextLine(CFX_TxtLine* pCurLine,
794 CFX_TxtLine* pNextLine,
tsepezd19e9122016-11-02 15:43:18 -0700795 bool bAllChars) {
dsinclair85d1f2c2016-06-23 12:40:16 -0700796 ASSERT(pCurLine && pNextLine);
Dan Sinclair1770c022016-03-14 14:14:16 -0400797 int32_t iCount = pCurLine->CountChars();
Dan Sinclair17f31182017-03-01 09:31:51 -0500798 if (iCount < 2)
Dan Sinclair1770c022016-03-14 14:14:16 -0400799 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500800
Dan Sinclair1770c022016-03-14 14:14:16 -0400801 int32_t iEndPos = pCurLine->m_iWidth;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500802 std::vector<CFX_TxtChar>& curChars = pCurLine->m_LineChars;
tsepezd19e9122016-11-02 15:43:18 -0700803 int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false);
Dan Sinclair17f31182017-03-01 09:31:51 -0500804 if (iCharPos < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400805 iCharPos = 0;
Dan Sinclair17f31182017-03-01 09:31:51 -0500806
Dan Sinclair1770c022016-03-14 14:14:16 -0400807 iCharPos++;
808 if (iCharPos >= iCount) {
tsepezd19e9122016-11-02 15:43:18 -0700809 pNextLine->RemoveAll(true);
tsepez33316fc2017-01-24 12:17:40 -0800810 CFX_Char* pTC = &curChars[iCharPos - 1];
Dan Sinclair1770c022016-03-14 14:14:16 -0400811 pTC->m_nBreakType = FX_LBT_UNKNOWN;
812 return;
813 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500814
Dan Sinclair52c73c22017-03-09 13:27:29 -0500815 pNextLine->m_LineChars =
tsepez33316fc2017-01-24 12:17:40 -0800816 std::vector<CFX_TxtChar>(curChars.begin() + iCharPos, curChars.end());
817 curChars.erase(curChars.begin() + iCharPos, curChars.end());
Dan Sinclair1770c022016-03-14 14:14:16 -0400818 pCurLine->m_iWidth = iEndPos;
tsepez33316fc2017-01-24 12:17:40 -0800819 CFX_TxtChar* pTC = &curChars[iCharPos - 1];
Dan Sinclair1770c022016-03-14 14:14:16 -0400820 pTC->m_nBreakType = FX_LBT_UNKNOWN;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500821 iCount = pdfium::CollectionSize<int>(pNextLine->m_LineChars);
tsepez33316fc2017-01-24 12:17:40 -0800822 int32_t iWidth = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400823 for (int32_t i = 0; i < iCount; i++) {
Dan Sinclair52c73c22017-03-09 13:27:29 -0500824 if (pNextLine->m_LineChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400825 pCurLine->m_iArabicChars--;
826 pNextLine->m_iArabicChars++;
827 }
Dan Sinclair52c73c22017-03-09 13:27:29 -0500828 iWidth += std::max(0, pNextLine->m_LineChars[i].m_iCharWidth);
Dan Sinclairc36fe072017-03-09 16:58:12 -0500829 pNextLine->m_LineChars[i].m_dwStatus = CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400830 }
831 pNextLine->m_iWidth = iWidth;
832}
weili1b4f6b32016-08-04 16:37:48 -0700833
Dan Sinclair1770c022016-03-14 14:14:16 -0400834int32_t CFX_TxtBreak::CountBreakPieces() const {
Dan Sinclair52c73c22017-03-09 13:27:29 -0500835 const CFX_TxtPieceArray* pTxtPieces = GetTxtPieces();
dsinclair85d1f2c2016-06-23 12:40:16 -0700836 return pTxtPieces ? pTxtPieces->GetSize() : 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400837}
weili1b4f6b32016-08-04 16:37:48 -0700838
Dan Sinclair1770c022016-03-14 14:14:16 -0400839const CFX_TxtPiece* CFX_TxtBreak::GetBreakPiece(int32_t index) const {
Dan Sinclair52c73c22017-03-09 13:27:29 -0500840 const CFX_TxtPieceArray* pTxtPieces = GetTxtPieces();
Dan Sinclair17f31182017-03-01 09:31:51 -0500841 if (!pTxtPieces)
dsinclair85d1f2c2016-06-23 12:40:16 -0700842 return nullptr;
Dan Sinclair17f31182017-03-01 09:31:51 -0500843 if (index < 0 || index >= pTxtPieces->GetSize())
dsinclair85d1f2c2016-06-23 12:40:16 -0700844 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400845 return pTxtPieces->GetPtrAt(index);
846}
weili1b4f6b32016-08-04 16:37:48 -0700847
Dan Sinclair1770c022016-03-14 14:14:16 -0400848void CFX_TxtBreak::ClearBreakPieces() {
Dan Sinclair52c73c22017-03-09 13:27:29 -0500849 const CFX_TxtLine* pTxtLine = GetTxtLine();
Dan Sinclair17f31182017-03-01 09:31:51 -0500850 if (pTxtLine)
Dan Sinclair52c73c22017-03-09 13:27:29 -0500851 const_cast<CFX_TxtLine*>(pTxtLine)->RemoveAll(true);
Dan Sinclair1770c022016-03-14 14:14:16 -0400852 m_iReady = 0;
853}
weili1b4f6b32016-08-04 16:37:48 -0700854
Dan Sinclair1770c022016-03-14 14:14:16 -0400855void CFX_TxtBreak::Reset() {
weilia2c06e42016-05-20 17:09:48 -0700856 m_eCharType = FX_CHARTYPE_Unknown;
Dan Sinclair17f31182017-03-01 09:31:51 -0500857 m_iArabicContext = 1;
858 m_iCurArabicContext = 1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400859 ResetArabicContext();
Dan Sinclair52c73c22017-03-09 13:27:29 -0500860 m_TxtLine1.RemoveAll(true);
861 m_TxtLine2.RemoveAll(true);
Dan Sinclair1770c022016-03-14 14:14:16 -0400862}
863
864struct FX_FORMCHAR {
Tom Sepez62a70f92016-03-21 15:00:20 -0700865 uint16_t wch;
866 uint16_t wForm;
Dan Sinclair1770c022016-03-14 14:14:16 -0400867 int32_t iWidth;
868};
869
870int32_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun,
871 FXTEXT_CHARPOS* pCharPos,
tsepezd19e9122016-11-02 15:43:18 -0700872 bool bCharCode,
Tom Sepeze65d62c2017-03-01 13:18:50 -0800873 CFX_WideString* pWSForms) const {
Dan Sinclair17f31182017-03-01 09:31:51 -0500874 if (!pTxtRun || pTxtRun->iLength < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400875 return 0;
Dan Sinclair17f31182017-03-01 09:31:51 -0500876
Dan Sinclair575898e2017-03-13 10:16:05 -0400877 CFDE_TxtEdtPage* pAccess = pTxtRun->pAccess;
dsinclair705f8292016-06-07 10:10:45 -0700878 const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity;
tsepezd4033292016-04-19 12:03:15 -0700879 const FX_WCHAR* pStr = pTxtRun->wsStr.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -0400880 int32_t* pWidths = pTxtRun->pWidths;
881 int32_t iLength = pTxtRun->iLength - 1;
tsepeze6477992017-01-05 12:57:00 -0800882 CFX_RetainPtr<CFGAS_GEFont> pFont = pTxtRun->pFont;
tsepez736f28a2016-03-25 14:19:51 -0700883 uint32_t dwStyles = pTxtRun->dwStyles;
Dan Sinclair1770c022016-03-14 14:14:16 -0400884 CFX_RectF rtText(*pTxtRun->pRect);
tsepezd19e9122016-11-02 15:43:18 -0700885 bool bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400886 FX_FLOAT fFontSize = pTxtRun->fFontSize;
887 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
888 int32_t iAscent = pFont->GetAscent();
889 int32_t iDescent = pFont->GetDescent();
890 int32_t iMaxHeight = iAscent - iDescent;
891 FX_FLOAT fFontHeight = fFontSize;
892 FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight;
Dan Sinclair17f31182017-03-01 09:31:51 -0500893 FX_FLOAT fX = rtText.left;
894 FX_FLOAT fY;
895 FX_FLOAT fCharWidth;
896 FX_FLOAT fCharHeight;
Dan Sinclair1770c022016-03-14 14:14:16 -0400897 int32_t iHorScale = pTxtRun->iHorizontalScale;
898 int32_t iVerScale = pTxtRun->iVerticalScale;
tsepezd19e9122016-11-02 15:43:18 -0700899 bool bSkipSpace = pTxtRun->bSkipSpace;
Dan Sinclair1770c022016-03-14 14:14:16 -0400900 FX_FORMCHAR formChars[3];
901 FX_FLOAT fYBase;
Dan Sinclair17f31182017-03-01 09:31:51 -0500902
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400903 if (bRTLPiece)
904 fX = rtText.right();
Dan Sinclair17f31182017-03-01 09:31:51 -0500905
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400906 fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f;
907 fY = fYBase + fAscent;
Dan Sinclair17f31182017-03-01 09:31:51 -0500908
weili038aa532016-05-20 15:38:29 -0700909 int32_t iCount = 0;
910 int32_t iNext = 0;
911 FX_WCHAR wPrev = 0xFEFF;
912 FX_WCHAR wNext = 0xFEFF;
913 FX_WCHAR wForm = 0xFEFF;
914 FX_WCHAR wLast = 0xFEFF;
tsepezd19e9122016-11-02 15:43:18 -0700915 bool bShadda = false;
916 bool bLam = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400917 for (int32_t i = 0; i <= iLength; i++) {
weili038aa532016-05-20 15:38:29 -0700918 int32_t iWidth;
919 FX_WCHAR wch;
dsinclair85d1f2c2016-06-23 12:40:16 -0700920 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400921 wch = pAccess->GetChar(pIdentity, i);
922 iWidth = pAccess->GetWidth(pIdentity, i);
923 } else {
924 wch = *pStr++;
925 iWidth = *pWidths++;
926 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500927
weili038aa532016-05-20 15:38:29 -0700928 uint32_t dwProps = FX_GetUnicodeProperties(wch);
weilia2c06e42016-05-20 17:09:48 -0700929 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
930 if (chartype == FX_CHARTYPE_ArabicAlef && iWidth == 0) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400931 wPrev = 0xFEFF;
932 wLast = wch;
933 continue;
934 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500935
weilia2c06e42016-05-20 17:09:48 -0700936 if (chartype >= FX_CHARTYPE_ArabicAlef) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400937 if (i < iLength) {
dsinclair85d1f2c2016-06-23 12:40:16 -0700938 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400939 iNext = i + 1;
940 while (iNext <= iLength) {
941 wNext = pAccess->GetChar(pIdentity, iNext);
942 dwProps = FX_GetUnicodeProperties(wNext);
Dan Sinclair17f31182017-03-01 09:31:51 -0500943 if ((dwProps & FX_CHARTYPEBITSMASK) != FX_CHARTYPE_Combination)
Dan Sinclair1770c022016-03-14 14:14:16 -0400944 break;
Dan Sinclair17f31182017-03-01 09:31:51 -0500945
Dan Sinclair1770c022016-03-14 14:14:16 -0400946 iNext++;
947 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500948 if (iNext > iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -0400949 wNext = 0xFEFF;
Dan Sinclair1770c022016-03-14 14:14:16 -0400950 } else {
951 int32_t j = -1;
952 do {
953 j++;
Dan Sinclair17f31182017-03-01 09:31:51 -0500954 if (i + j >= iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -0400955 break;
Dan Sinclair17f31182017-03-01 09:31:51 -0500956
Dan Sinclair1770c022016-03-14 14:14:16 -0400957 wNext = pStr[j];
958 dwProps = FX_GetUnicodeProperties(wNext);
959 } while ((dwProps & FX_CHARTYPEBITSMASK) == FX_CHARTYPE_Combination);
Dan Sinclair17f31182017-03-01 09:31:51 -0500960 if (i + j >= iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -0400961 wNext = 0xFEFF;
Dan Sinclair1770c022016-03-14 14:14:16 -0400962 }
963 } else {
964 wNext = 0xFEFF;
965 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500966
tsepeze00f75c2016-05-06 13:15:46 -0700967 wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext);
Dan Sinclair1770c022016-03-14 14:14:16 -0400968 bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647);
weilia2c06e42016-05-20 17:09:48 -0700969 } else if (chartype == FX_CHARTYPE_Combination) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400970 wForm = wch;
971 if (wch >= 0x064C && wch <= 0x0651) {
972 if (bShadda) {
973 wForm = 0xFEFF;
tsepezd19e9122016-11-02 15:43:18 -0700974 bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400975 } else {
976 wNext = 0xFEFF;
dsinclair85d1f2c2016-06-23 12:40:16 -0700977 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400978 iNext = i + 1;
Dan Sinclair17f31182017-03-01 09:31:51 -0500979 if (iNext <= iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -0400980 wNext = pAccess->GetChar(pIdentity, iNext);
Dan Sinclair1770c022016-03-14 14:14:16 -0400981 } else {
Dan Sinclair17f31182017-03-01 09:31:51 -0500982 if (i < iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -0400983 wNext = *pStr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400984 }
985 if (wch == 0x0651) {
986 if (wNext >= 0x064C && wNext <= 0x0650) {
987 wForm = FX_GetArabicFromShaddaTable(wNext);
tsepezd19e9122016-11-02 15:43:18 -0700988 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400989 }
990 } else {
991 if (wNext == 0x0651) {
992 wForm = FX_GetArabicFromShaddaTable(wch);
tsepezd19e9122016-11-02 15:43:18 -0700993 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400994 }
995 }
996 }
997 } else {
tsepezd19e9122016-11-02 15:43:18 -0700998 bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400999 }
weilia2c06e42016-05-20 17:09:48 -07001000 } else if (chartype == FX_CHARTYPE_Numeric) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001001 wForm = wch;
Dan Sinclair1770c022016-03-14 14:14:16 -04001002 } else if (wch == L'.') {
1003 wForm = wch;
Dan Sinclair1770c022016-03-14 14:14:16 -04001004 } else if (wch == L',') {
1005 wForm = wch;
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001006 } else if (bRTLPiece) {
1007 wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001008 } else {
1009 wForm = wch;
1010 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001011 if (chartype != FX_CHARTYPE_Combination)
tsepezd19e9122016-11-02 15:43:18 -07001012 bShadda = false;
Dan Sinclair17f31182017-03-01 09:31:51 -05001013 if (chartype < FX_CHARTYPE_ArabicAlef)
tsepezd19e9122016-11-02 15:43:18 -07001014 bLam = false;
Dan Sinclair17f31182017-03-01 09:31:51 -05001015
Dan Sinclair1770c022016-03-14 14:14:16 -04001016 dwProps = FX_GetUnicodeProperties(wForm);
tsepezd19e9122016-11-02 15:43:18 -07001017 bool bEmptyChar =
weilia2c06e42016-05-20 17:09:48 -07001018 (chartype >= FX_CHARTYPE_Tab && chartype <= FX_CHARTYPE_Control);
Dan Sinclair17f31182017-03-01 09:31:51 -05001019 if (wForm == 0xFEFF)
tsepezd19e9122016-11-02 15:43:18 -07001020 bEmptyChar = true;
Dan Sinclair17f31182017-03-01 09:31:51 -05001021
weili038aa532016-05-20 15:38:29 -07001022 int32_t iForms = bLam ? 3 : 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04001023 iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms;
dsinclair85d1f2c2016-06-23 12:40:16 -07001024 if (!pCharPos) {
Dan Sinclair17f31182017-03-01 09:31:51 -05001025 if (iWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001026 wPrev = wch;
Dan Sinclair1770c022016-03-14 14:14:16 -04001027 wLast = wch;
1028 continue;
1029 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001030
weili038aa532016-05-20 15:38:29 -07001031 int32_t iCharWidth = iWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -05001032 if (iCharWidth < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001033 iCharWidth = -iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -05001034
Dan Sinclair1770c022016-03-14 14:14:16 -04001035 iCharWidth /= iFontSize;
1036 formChars[0].wch = wch;
1037 formChars[0].wForm = wForm;
1038 formChars[0].iWidth = iCharWidth;
1039 if (bLam) {
1040 formChars[1].wForm = 0x0651;
1041 iCharWidth = 0;
tsepezd19e9122016-11-02 15:43:18 -07001042 pFont->GetCharWidth(0x0651, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001043 formChars[1].iWidth = iCharWidth;
1044 formChars[2].wForm = 0x0670;
1045 iCharWidth = 0;
tsepezd19e9122016-11-02 15:43:18 -07001046 pFont->GetCharWidth(0x0670, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001047 formChars[2].iWidth = iCharWidth;
1048 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001049
Dan Sinclair1770c022016-03-14 14:14:16 -04001050 for (int32_t j = 0; j < iForms; j++) {
1051 wForm = (FX_WCHAR)formChars[j].wForm;
1052 iCharWidth = formChars[j].iWidth;
1053 if (j > 0) {
weilia2c06e42016-05-20 17:09:48 -07001054 chartype = FX_CHARTYPE_Combination;
Dan Sinclair1770c022016-03-14 14:14:16 -04001055 wch = wForm;
1056 wLast = (FX_WCHAR)formChars[j - 1].wForm;
1057 }
1058 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
1059 pCharPos->m_GlyphIndex =
tsepezd19e9122016-11-02 15:43:18 -07001060 bCharCode ? wch : pFont->GetGlyphIndex(wForm, false);
thestigec51ac32016-06-20 10:38:52 -07001061#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
Dan Sinclair1770c022016-03-14 14:14:16 -04001062 pCharPos->m_ExtGID = pCharPos->m_GlyphIndex;
thestigec51ac32016-06-20 10:38:52 -07001063#endif
Dan Sinclair1770c022016-03-14 14:14:16 -04001064 pCharPos->m_FontCharWidth = iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -05001065 if (pWSForms)
Dan Sinclair1770c022016-03-14 14:14:16 -04001066 *pWSForms += wForm;
Dan Sinclair1770c022016-03-14 14:14:16 -04001067 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001068
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001069 int32_t iCharHeight = 1000;
Dan Sinclair17f31182017-03-01 09:31:51 -05001070
Dan Sinclair1770c022016-03-14 14:14:16 -04001071 fCharWidth = fFontSize * iCharWidth / 1000.0f;
1072 fCharHeight = fFontSize * iCharHeight / 1000.0f;
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001073 if (bRTLPiece && chartype != FX_CHARTYPE_Combination)
1074 fX -= fCharWidth;
1075
Dan Sinclair1770c022016-03-14 14:14:16 -04001076 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001077 pCharPos->m_Origin = CFX_PointF(fX, fY);
Dan Sinclair1770c022016-03-14 14:14:16 -04001078 if ((dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0) {
1079 int32_t iFormWidth = iCharWidth;
tsepezd19e9122016-11-02 15:43:18 -07001080 pFont->GetCharWidth(wForm, iFormWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001081 FX_FLOAT fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f;
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001082 pCharPos->m_Origin.x += fOffset;
Dan Sinclair1770c022016-03-14 14:14:16 -04001083 }
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001084
weilia2c06e42016-05-20 17:09:48 -07001085 if (chartype == FX_CHARTYPE_Combination) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001086 CFX_Rect rtBBox;
tsepez6fd07ef2017-01-06 09:48:18 -08001087 if (pFont->GetCharBBox(wForm, &rtBBox, false)) {
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001088 pCharPos->m_Origin.y =
Dan Sinclair1770c022016-03-14 14:14:16 -04001089 fYBase + fFontSize -
1090 fFontSize * (FX_FLOAT)rtBBox.height / (FX_FLOAT)iMaxHeight;
1091 }
1092 if (wForm == wch && wLast != 0xFEFF) {
tsepez736f28a2016-03-25 14:19:51 -07001093 uint32_t dwLastProps = FX_GetUnicodeProperties(wLast);
Dan Sinclair1770c022016-03-14 14:14:16 -04001094 if ((dwLastProps & FX_CHARTYPEBITSMASK) ==
1095 FX_CHARTYPE_Combination) {
weilidb444d22016-06-02 15:48:15 -07001096 CFX_Rect rtBox;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001097 if (pFont->GetCharBBox(wLast, &rtBox, false))
1098 pCharPos->m_Origin.y -= fFontSize * rtBox.height / iMaxHeight;
Dan Sinclair1770c022016-03-14 14:14:16 -04001099 }
1100 }
1101 }
1102 CFX_PointF ptOffset;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001103 pCharPos->m_Origin.x += ptOffset.x;
1104 pCharPos->m_Origin.y -= ptOffset.y;
Dan Sinclair1770c022016-03-14 14:14:16 -04001105 }
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001106 if (!bRTLPiece && chartype != FX_CHARTYPE_Combination)
1107 fX += fCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -05001108
Dan Sinclair1770c022016-03-14 14:14:16 -04001109 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
tsepezd19e9122016-11-02 15:43:18 -07001110 pCharPos->m_bGlyphAdjust = true;
Dan Sinclair068d3442017-03-13 10:15:36 -04001111 pCharPos->m_AdjustMatrix[0] = -1;
1112 pCharPos->m_AdjustMatrix[1] = 0;
1113 pCharPos->m_AdjustMatrix[2] = 0;
1114 pCharPos->m_AdjustMatrix[3] = 1;
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001115
Dan Sinclair1770c022016-03-14 14:14:16 -04001116 if (iHorScale != 100 || iVerScale != 100) {
1117 pCharPos->m_AdjustMatrix[0] =
1118 pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f;
1119 pCharPos->m_AdjustMatrix[1] =
1120 pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f;
1121 pCharPos->m_AdjustMatrix[2] =
1122 pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f;
1123 pCharPos->m_AdjustMatrix[3] =
1124 pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f;
1125 }
1126 pCharPos++;
1127 }
1128 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001129 if (iWidth > 0)
1130 wPrev = static_cast<FX_WCHAR>(formChars[0].wch);
Dan Sinclair1770c022016-03-14 14:14:16 -04001131 wLast = wch;
1132 }
1133 return iCount;
1134}
weili1b4f6b32016-08-04 16:37:48 -07001135
Tom Sepezc803cbc2017-03-02 12:21:15 -08001136std::vector<CFX_RectF> CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun,
1137 bool bCharBBox) const {
tsepeze6477992017-01-05 12:57:00 -08001138 if (!pTxtRun || pTxtRun->iLength < 1)
Tom Sepezc803cbc2017-03-02 12:21:15 -08001139 return std::vector<CFX_RectF>();
tsepeze6477992017-01-05 12:57:00 -08001140
Dan Sinclair575898e2017-03-13 10:16:05 -04001141 CFDE_TxtEdtPage* pAccess = pTxtRun->pAccess;
dsinclair705f8292016-06-07 10:10:45 -07001142 const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity;
tsepezd4033292016-04-19 12:03:15 -07001143 const FX_WCHAR* pStr = pTxtRun->wsStr.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04001144 int32_t* pWidths = pTxtRun->pWidths;
1145 int32_t iLength = pTxtRun->iLength;
1146 CFX_RectF rect(*pTxtRun->pRect);
Dan Sinclair1770c022016-03-14 14:14:16 -04001147 FX_FLOAT fFontSize = pTxtRun->fFontSize;
1148 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
1149 FX_FLOAT fScale = fFontSize / 1000.0f;
tsepeze6477992017-01-05 12:57:00 -08001150 CFX_RetainPtr<CFGAS_GEFont> pFont = pTxtRun->pFont;
1151 if (!pFont)
tsepezd19e9122016-11-02 15:43:18 -07001152 bCharBBox = false;
tsepeze6477992017-01-05 12:57:00 -08001153
Dan Sinclair1770c022016-03-14 14:14:16 -04001154 CFX_Rect bbox;
tsepeze6477992017-01-05 12:57:00 -08001155 if (bCharBBox)
tsepez6fd07ef2017-01-06 09:48:18 -08001156 bCharBBox = pFont->GetBBox(&bbox);
tsepeze6477992017-01-05 12:57:00 -08001157
Dan Sinclair1770c022016-03-14 14:14:16 -04001158 FX_FLOAT fLeft = std::max(0.0f, bbox.left * fScale);
1159 FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale);
Tom Sepezc803cbc2017-03-02 12:21:15 -08001160 bool bRTLPiece = !!(pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel);
Tom Sepezc803cbc2017-03-02 12:21:15 -08001161 bool bSingleLine = !!(pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_SingleLine);
1162 bool bCombText = !!(pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_CombText);
Dan Sinclair17f31182017-03-01 09:31:51 -05001163 FX_WCHAR wch;
1164 FX_WCHAR wLineBreakChar = pTxtRun->wLineBreakChar;
Dan Sinclair1770c022016-03-14 14:14:16 -04001165 int32_t iCharSize;
Dan Sinclair17f31182017-03-01 09:31:51 -05001166 FX_FLOAT fCharSize;
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001167 FX_FLOAT fStart = bRTLPiece ? rect.right() : rect.left;
Dan Sinclair17f31182017-03-01 09:31:51 -05001168
Tom Sepezc803cbc2017-03-02 12:21:15 -08001169 std::vector<CFX_RectF> rtArray(iLength);
Dan Sinclair1770c022016-03-14 14:14:16 -04001170 for (int32_t i = 0; i < iLength; i++) {
dsinclair85d1f2c2016-06-23 12:40:16 -07001171 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001172 wch = pAccess->GetChar(pIdentity, i);
1173 iCharSize = pAccess->GetWidth(pIdentity, i);
1174 } else {
1175 wch = *pStr++;
1176 iCharSize = *pWidths++;
1177 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001178 fCharSize = static_cast<FX_FLOAT>(iCharSize) / 20000.0f;
Dan Sinclairfc9b9882017-03-07 09:18:18 -05001179 bool bRet = (!bSingleLine && IsCtrlCode(wch));
Dan Sinclair1770c022016-03-14 14:14:16 -04001180 if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 ||
1181 (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) {
tsepezd19e9122016-11-02 15:43:18 -07001182 bRet = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001183 }
1184 if (bRet) {
1185 iCharSize = iFontSize * 500;
1186 fCharSize = fFontSize / 2.0f;
1187 }
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001188 rect.left = fStart;
1189 if (bRTLPiece) {
1190 rect.left -= fCharSize;
1191 fStart -= fCharSize;
Dan Sinclair1770c022016-03-14 14:14:16 -04001192 } else {
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001193 fStart += fCharSize;
Dan Sinclair1770c022016-03-14 14:14:16 -04001194 }
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001195 rect.width = fCharSize;
Dan Sinclair17f31182017-03-01 09:31:51 -05001196
Dan Sinclair1770c022016-03-14 14:14:16 -04001197 if (bCharBBox && !bRet) {
1198 int32_t iCharWidth = 1000;
thestig2c065322016-09-26 14:16:43 -07001199 pFont->GetCharWidth(wch, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001200 FX_FLOAT fRTLeft = 0, fCharWidth = 0;
1201 if (iCharWidth > 0) {
1202 fCharWidth = iCharWidth * fScale;
1203 fRTLeft = fLeft;
Dan Sinclair17f31182017-03-01 09:31:51 -05001204 if (bCombText)
Dan Sinclair1770c022016-03-14 14:14:16 -04001205 fRTLeft = (rect.width - fCharWidth) / 2.0f;
Dan Sinclair1770c022016-03-14 14:14:16 -04001206 }
1207 CFX_RectF rtBBoxF;
Dan Sinclaira5a3de92017-03-13 10:14:21 -04001208 rtBBoxF.left = rect.left + fRTLeft;
1209 rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f;
1210 rtBBoxF.width = fCharWidth;
1211 rtBBoxF.height = fHeight;
1212 rtBBoxF.top = std::max(rtBBoxF.top, 0.0f);
Tom Sepezc803cbc2017-03-02 12:21:15 -08001213 rtArray[i] = rtBBoxF;
Dan Sinclair1770c022016-03-14 14:14:16 -04001214 continue;
1215 }
Tom Sepezc803cbc2017-03-02 12:21:15 -08001216 rtArray[i] = rect;
Dan Sinclair1770c022016-03-14 14:14:16 -04001217 }
Tom Sepezc803cbc2017-03-02 12:21:15 -08001218 return rtArray;
Dan Sinclair1770c022016-03-14 14:14:16 -04001219}
weilieec3a362016-06-18 06:25:37 -07001220
1221FX_TXTRUN::FX_TXTRUN()
1222 : pAccess(nullptr),
1223 pIdentity(nullptr),
1224 pWidths(nullptr),
1225 iLength(0),
1226 pFont(nullptr),
1227 fFontSize(12),
1228 dwStyles(0),
1229 iHorizontalScale(100),
1230 iVerticalScale(100),
weilieec3a362016-06-18 06:25:37 -07001231 dwCharStyles(0),
1232 pRect(nullptr),
1233 wLineBreakChar(L'\n'),
tsepezd19e9122016-11-02 15:43:18 -07001234 bSkipSpace(true) {}
weilieec3a362016-06-18 06:25:37 -07001235
1236FX_TXTRUN::~FX_TXTRUN() {}
1237
1238FX_TXTRUN::FX_TXTRUN(const FX_TXTRUN& other) = default;
1239
1240CFX_TxtPiece::CFX_TxtPiece()
Dan Sinclairc36fe072017-03-09 16:58:12 -05001241 : m_dwStatus(CFX_BreakType::Piece),
weilieec3a362016-06-18 06:25:37 -07001242 m_iStartPos(0),
1243 m_iWidth(-1),
1244 m_iStartChar(0),
1245 m_iChars(0),
1246 m_iBidiLevel(0),
1247 m_iBidiPos(0),
1248 m_iHorizontalScale(100),
1249 m_iVerticalScale(100),
1250 m_dwCharStyles(0),
Dan Sinclair1c97fd12017-03-09 16:58:55 -05001251 m_pChars(nullptr) {}
weilieec3a362016-06-18 06:25:37 -07001252
Dan Sinclair52c73c22017-03-09 13:27:29 -05001253CFX_TxtLine::CFX_TxtLine()
1254 : m_LinePieces(16), m_iStart(0), m_iWidth(0), m_iArabicChars(0) {}
weilieec3a362016-06-18 06:25:37 -07001255
1256CFX_TxtLine::~CFX_TxtLine() {
1257 RemoveAll();
weilieec3a362016-06-18 06:25:37 -07001258}