blob: a3f8e9841de4d2e2197d371a70088bda0d6a1e02 [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"
12#include "core/fxcrt/fx_arb.h"
13#include "core/fxcrt/fx_memory.h"
tsepeza9caab92016-12-14 05:57:10 -080014#include "third_party/base/ptr_util.h"
npm4b91a2d2016-11-21 15:19:44 -080015#include "xfa/fgas/font/cfgas_gefont.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040016#include "xfa/fgas/layout/fgas_linebreak.h"
17#include "xfa/fgas/layout/fgas_unicode.h"
18
tsepez215507d2016-06-09 19:05:47 -070019namespace {
20
21typedef uint32_t (CFX_TxtBreak::*FX_TxtBreak_LPFAppendChar)(
22 CFX_TxtChar* pCurChar,
23 int32_t iRotation);
24const FX_TxtBreak_LPFAppendChar g_FX_TxtBreak_lpfAppendChar[16] = {
25 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Tab,
26 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Control,
27 &CFX_TxtBreak::AppendChar_Combination, &CFX_TxtBreak::AppendChar_Others,
28 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Arabic,
29 &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Arabic,
30 &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Arabic,
31 &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Others,
32 &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Others,
33};
34
35} // namespace
36
tsepez736f28a2016-03-25 14:19:51 -070037CFX_TxtBreak::CFX_TxtBreak(uint32_t dwPolicies)
Dan Sinclair1770c022016-03-14 14:14:16 -040038 : m_dwPolicies(dwPolicies),
Dan Sinclair1770c022016-03-14 14:14:16 -040039 m_iLineWidth(2000000),
40 m_dwLayoutStyles(0),
tsepezd19e9122016-11-02 15:43:18 -070041 m_bVertical(false),
42 m_bArabicContext(false),
43 m_bArabicShapes(false),
44 m_bRTL(false),
45 m_bSingleLine(false),
46 m_bCombText(false),
Dan Sinclair1770c022016-03-14 14:14:16 -040047 m_iArabicContext(1),
48 m_iCurArabicContext(1),
dsinclair85d1f2c2016-06-23 12:40:16 -070049 m_pFont(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -040050 m_iFontSize(240),
tsepezd19e9122016-11-02 15:43:18 -070051 m_bEquidistant(true),
Dan Sinclair1770c022016-03-14 14:14:16 -040052 m_iTabWidth(720000),
53 m_wDefChar(0xFEFF),
54 m_wParagBreakChar(L'\n'),
55 m_iDefChar(0),
56 m_iLineRotation(0),
57 m_iCharRotation(0),
58 m_iRotation(0),
59 m_iAlignment(FX_TXTLINEALIGNMENT_Left),
60 m_dwContextCharStyles(0),
61 m_iCombWidth(360000),
dsinclair85d1f2c2016-06-23 12:40:16 -070062 m_pUserData(nullptr),
weilia2c06e42016-05-20 17:09:48 -070063 m_eCharType(FX_CHARTYPE_Unknown),
tsepezd19e9122016-11-02 15:43:18 -070064 m_bArabicNumber(false),
65 m_bArabicComma(false),
dsinclair85d1f2c2016-06-23 12:40:16 -070066 m_pCurLine(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -040067 m_iReady(0),
68 m_iTolerance(0),
69 m_iHorScale(100),
70 m_iVerScale(100),
71 m_iCharSpace(0) {
72 m_bPagination = (m_dwPolicies & FX_TXTBREAKPOLICY_Pagination) != 0;
weili1b4f6b32016-08-04 16:37:48 -070073 int32_t iSize = m_bPagination ? sizeof(CFX_Char) : sizeof(CFX_TxtChar);
tsepeza9caab92016-12-14 05:57:10 -080074 m_pTxtLine1 = pdfium::MakeUnique<CFX_TxtLine>(iSize);
75 m_pTxtLine2 = pdfium::MakeUnique<CFX_TxtLine>(iSize);
weili1b4f6b32016-08-04 16:37:48 -070076 m_pCurLine = m_pTxtLine1.get();
Dan Sinclair1770c022016-03-14 14:14:16 -040077 ResetArabicContext();
78}
weili1b4f6b32016-08-04 16:37:48 -070079
Dan Sinclair1770c022016-03-14 14:14:16 -040080CFX_TxtBreak::~CFX_TxtBreak() {
81 Reset();
Dan Sinclair1770c022016-03-14 14:14:16 -040082}
weili1b4f6b32016-08-04 16:37:48 -070083
Dan Sinclair1770c022016-03-14 14:14:16 -040084void CFX_TxtBreak::SetLineWidth(FX_FLOAT fLineWidth) {
85 m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f);
dsinclair43854a52016-04-27 12:26:00 -070086 ASSERT(m_iLineWidth >= 20000);
Dan Sinclair1770c022016-03-14 14:14:16 -040087}
weili1b4f6b32016-08-04 16:37:48 -070088
Dan Sinclair1770c022016-03-14 14:14:16 -040089void CFX_TxtBreak::SetLinePos(FX_FLOAT fLinePos) {
90 int32_t iLinePos = FXSYS_round(fLinePos * 20000.0f);
91 if (iLinePos < 0) {
92 iLinePos = 0;
93 }
94 if (iLinePos > m_iLineWidth) {
95 iLinePos = m_iLineWidth;
96 }
97 m_pCurLine->m_iStart = iLinePos;
98 m_pCurLine->m_iWidth += iLinePos;
99}
weili1b4f6b32016-08-04 16:37:48 -0700100
tsepez736f28a2016-03-25 14:19:51 -0700101void CFX_TxtBreak::SetLayoutStyles(uint32_t dwLayoutStyles) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400102 m_dwLayoutStyles = dwLayoutStyles;
103 m_bVertical = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0;
104 m_bArabicContext = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ArabicContext) != 0;
105 m_bArabicShapes = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ArabicShapes) != 0;
106 m_bRTL = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_RTLReadingOrder) != 0;
107 m_bSingleLine = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
108 m_bCombText = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
109 ResetArabicContext();
110 m_iLineRotation = GetLineRotation(m_dwLayoutStyles);
111 m_iRotation = m_iLineRotation + m_iCharRotation;
112 m_iRotation %= 4;
113}
weili1b4f6b32016-08-04 16:37:48 -0700114
thestiga4fdfc52016-06-07 17:33:37 -0700115void CFX_TxtBreak::SetFont(CFGAS_GEFont* pFont) {
dsinclair85d1f2c2016-06-23 12:40:16 -0700116 if (!pFont) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400117 return;
118 }
119 if (m_pFont == pFont) {
120 return;
121 }
122 SetBreakStatus();
123 m_pFont = pFont;
124 m_iDefChar = 0;
dsinclair85d1f2c2016-06-23 12:40:16 -0700125 if (m_wDefChar != 0xFEFF && m_pFont) {
tsepezd19e9122016-11-02 15:43:18 -0700126 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400127 m_iDefChar *= m_iFontSize;
128 }
129}
weili1b4f6b32016-08-04 16:37:48 -0700130
Dan Sinclair1770c022016-03-14 14:14:16 -0400131void CFX_TxtBreak::SetFontSize(FX_FLOAT fFontSize) {
132 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
133 if (m_iFontSize == iFontSize) {
134 return;
135 }
136 SetBreakStatus();
137 m_iFontSize = iFontSize;
138 m_iDefChar = 0;
dsinclair85d1f2c2016-06-23 12:40:16 -0700139 if (m_wDefChar != 0xFEFF && m_pFont) {
tsepezd19e9122016-11-02 15:43:18 -0700140 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400141 m_iDefChar *= m_iFontSize;
142 }
143}
weili1b4f6b32016-08-04 16:37:48 -0700144
tsepezd19e9122016-11-02 15:43:18 -0700145void CFX_TxtBreak::SetTabWidth(FX_FLOAT fTabWidth, bool bEquidistant) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400146 m_iTabWidth = FXSYS_round(fTabWidth * 20000.0f);
147 if (m_iTabWidth < FX_TXTBREAK_MinimumTabWidth) {
148 m_iTabWidth = FX_TXTBREAK_MinimumTabWidth;
149 }
150 m_bEquidistant = bEquidistant;
151}
weili1b4f6b32016-08-04 16:37:48 -0700152
Dan Sinclair1770c022016-03-14 14:14:16 -0400153void CFX_TxtBreak::SetDefaultChar(FX_WCHAR wch) {
154 m_wDefChar = wch;
155 m_iDefChar = 0;
dsinclair85d1f2c2016-06-23 12:40:16 -0700156 if (m_wDefChar != 0xFEFF && m_pFont) {
tsepezd19e9122016-11-02 15:43:18 -0700157 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400158 if (m_iDefChar < 0) {
159 m_iDefChar = 0;
160 } else {
161 m_iDefChar *= m_iFontSize;
162 }
163 }
164}
weili1b4f6b32016-08-04 16:37:48 -0700165
Dan Sinclair1770c022016-03-14 14:14:16 -0400166void CFX_TxtBreak::SetParagraphBreakChar(FX_WCHAR wch) {
167 if (wch != L'\r' && wch != L'\n') {
168 return;
169 }
170 m_wParagBreakChar = wch;
171}
weili1b4f6b32016-08-04 16:37:48 -0700172
Dan Sinclair1770c022016-03-14 14:14:16 -0400173void CFX_TxtBreak::SetLineBreakTolerance(FX_FLOAT fTolerance) {
174 m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
175}
weili1b4f6b32016-08-04 16:37:48 -0700176
Dan Sinclair1770c022016-03-14 14:14:16 -0400177void CFX_TxtBreak::SetCharRotation(int32_t iCharRotation) {
178 if (iCharRotation < 0) {
179 iCharRotation += (-iCharRotation / 4 + 1) * 4;
180 } else if (iCharRotation > 3) {
181 iCharRotation -= (iCharRotation / 4) * 4;
182 }
183 if (m_iCharRotation == iCharRotation) {
184 return;
185 }
186 SetBreakStatus();
187 m_iCharRotation = iCharRotation;
188 m_iRotation = m_iLineRotation + m_iCharRotation;
189 m_iRotation %= 4;
190}
weili1b4f6b32016-08-04 16:37:48 -0700191
Dan Sinclair1770c022016-03-14 14:14:16 -0400192void CFX_TxtBreak::SetAlignment(int32_t iAlignment) {
dsinclair43854a52016-04-27 12:26:00 -0700193 ASSERT(iAlignment >= FX_TXTLINEALIGNMENT_Left &&
194 iAlignment <= FX_TXTLINEALIGNMENT_Distributed);
Dan Sinclair1770c022016-03-14 14:14:16 -0400195 m_iAlignment = iAlignment;
196 ResetArabicContext();
197}
weili1b4f6b32016-08-04 16:37:48 -0700198
Dan Sinclair1770c022016-03-14 14:14:16 -0400199void CFX_TxtBreak::ResetContextCharStyles() {
200 m_dwContextCharStyles = m_bArabicContext ? m_iCurAlignment : m_iAlignment;
201 if (m_bArabicNumber) {
202 m_dwContextCharStyles |= FX_TXTCHARSTYLE_ArabicNumber;
203 }
204 if (m_bArabicComma) {
205 m_dwContextCharStyles |= FX_TXTCHARSTYLE_ArabicComma;
206 }
207 if ((m_bArabicContext && m_bCurRTL) || (!m_bArabicContext && m_bRTL)) {
208 m_dwContextCharStyles |= FX_TXTCHARSTYLE_RTLReadingOrder;
209 }
210 m_dwContextCharStyles |= (m_iArabicContext << 8);
211}
weili1b4f6b32016-08-04 16:37:48 -0700212
tsepez736f28a2016-03-25 14:19:51 -0700213uint32_t CFX_TxtBreak::GetContextCharStyles() const {
Dan Sinclair1770c022016-03-14 14:14:16 -0400214 return m_dwContextCharStyles;
215}
weili1b4f6b32016-08-04 16:37:48 -0700216
tsepez736f28a2016-03-25 14:19:51 -0700217void CFX_TxtBreak::SetContextCharStyles(uint32_t dwCharStyles) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400218 m_iCurAlignment = dwCharStyles & 0x0F;
219 m_bArabicNumber = (dwCharStyles & FX_TXTCHARSTYLE_ArabicNumber) != 0;
220 m_bArabicComma = (dwCharStyles & FX_TXTCHARSTYLE_ArabicComma) != 0;
221 m_bCurRTL = (dwCharStyles & FX_TXTCHARSTYLE_RTLReadingOrder) != 0;
222 m_iCurArabicContext = m_iArabicContext = ((dwCharStyles & 0x0300) >> 8);
223 ResetContextCharStyles();
224}
weili1b4f6b32016-08-04 16:37:48 -0700225
Dan Sinclair1770c022016-03-14 14:14:16 -0400226void CFX_TxtBreak::SetCombWidth(FX_FLOAT fCombWidth) {
227 m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f);
228}
weili1b4f6b32016-08-04 16:37:48 -0700229
Dan Sinclair1770c022016-03-14 14:14:16 -0400230void CFX_TxtBreak::SetUserData(void* pUserData) {
231 if (m_pUserData == pUserData) {
232 return;
233 }
234 SetBreakStatus();
235 m_pUserData = pUserData;
236}
weili1b4f6b32016-08-04 16:37:48 -0700237
Dan Sinclair1770c022016-03-14 14:14:16 -0400238void CFX_TxtBreak::SetBreakStatus() {
239 if (m_bPagination) {
240 return;
241 }
242 int32_t iCount = m_pCurLine->CountChars();
243 if (iCount < 1) {
244 return;
245 }
tsepez215507d2016-06-09 19:05:47 -0700246 CFX_TxtChar* pTC = m_pCurLine->GetCharPtr(iCount - 1);
Dan Sinclair1770c022016-03-14 14:14:16 -0400247 if (pTC->m_dwStatus == 0) {
248 pTC->m_dwStatus = FX_TXTBREAK_PieceBreak;
249 }
250}
weili1b4f6b32016-08-04 16:37:48 -0700251
Dan Sinclair1770c022016-03-14 14:14:16 -0400252void CFX_TxtBreak::SetHorizontalScale(int32_t iScale) {
253 if (iScale < 0) {
254 iScale = 0;
255 }
256 if (iScale == m_iHorScale) {
257 return;
258 }
259 SetBreakStatus();
260 m_iHorScale = iScale;
261}
weili1b4f6b32016-08-04 16:37:48 -0700262
Dan Sinclair1770c022016-03-14 14:14:16 -0400263void CFX_TxtBreak::SetVerticalScale(int32_t iScale) {
264 if (iScale < 0) {
265 iScale = 0;
266 }
267 if (iScale == m_iHorScale) {
268 return;
269 }
270 SetBreakStatus();
271 m_iVerScale = iScale;
272}
weili1b4f6b32016-08-04 16:37:48 -0700273
Dan Sinclair1770c022016-03-14 14:14:16 -0400274void CFX_TxtBreak::SetCharSpace(FX_FLOAT fCharSpace) {
275 m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
276}
weili1b4f6b32016-08-04 16:37:48 -0700277
Dan Sinclair1770c022016-03-14 14:14:16 -0400278static const int32_t gs_FX_TxtLineRotations[8] = {0, 3, 1, 0, 2, 1, 3, 2};
tsepez736f28a2016-03-25 14:19:51 -0700279int32_t CFX_TxtBreak::GetLineRotation(uint32_t dwStyles) const {
Dan Sinclair1770c022016-03-14 14:14:16 -0400280 return gs_FX_TxtLineRotations[(dwStyles & 0x0E) >> 1];
281}
weili1b4f6b32016-08-04 16:37:48 -0700282
tsepezd19e9122016-11-02 15:43:18 -0700283CFX_TxtChar* CFX_TxtBreak::GetLastChar(int32_t index, bool bOmitChar) const {
weili1b4f6b32016-08-04 16:37:48 -0700284 CFX_TxtCharArray& ca = *m_pCurLine->m_pLineChars.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400285 int32_t iCount = ca.GetSize();
286 if (index < 0 || index >= iCount) {
dsinclair85d1f2c2016-06-23 12:40:16 -0700287 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400288 }
289 CFX_TxtChar* pTC;
290 int32_t iStart = iCount - 1;
291 while (iStart > -1) {
292 pTC = ca.GetDataPtr(iStart--);
293 if (bOmitChar && pTC->GetCharType() == FX_CHARTYPE_Combination) {
294 continue;
295 }
296 if (--index < 0) {
297 return pTC;
298 }
299 }
dsinclair85d1f2c2016-06-23 12:40:16 -0700300 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400301}
weili1b4f6b32016-08-04 16:37:48 -0700302
tsepezd19e9122016-11-02 15:43:18 -0700303CFX_TxtLine* CFX_TxtBreak::GetTxtLine(bool bReady) const {
dsinclair85d1f2c2016-06-23 12:40:16 -0700304 if (!bReady)
Dan Sinclair1770c022016-03-14 14:14:16 -0400305 return m_pCurLine;
dsinclair85d1f2c2016-06-23 12:40:16 -0700306 if (m_iReady == 1)
weili1b4f6b32016-08-04 16:37:48 -0700307 return m_pTxtLine1.get();
dsinclair85d1f2c2016-06-23 12:40:16 -0700308 if (m_iReady == 2)
weili1b4f6b32016-08-04 16:37:48 -0700309 return m_pTxtLine2.get();
dsinclair85d1f2c2016-06-23 12:40:16 -0700310 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400311}
weili1b4f6b32016-08-04 16:37:48 -0700312
tsepezd19e9122016-11-02 15:43:18 -0700313CFX_TxtPieceArray* CFX_TxtBreak::GetTxtPieces(bool bReady) const {
Dan Sinclair1770c022016-03-14 14:14:16 -0400314 CFX_TxtLine* pTxtLine = GetTxtLine(bReady);
dsinclair85d1f2c2016-06-23 12:40:16 -0700315 if (!pTxtLine) {
316 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400317 }
weili1b4f6b32016-08-04 16:37:48 -0700318 return pTxtLine->m_pLinePieces.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400319}
weili1b4f6b32016-08-04 16:37:48 -0700320
weilia2c06e42016-05-20 17:09:48 -0700321inline FX_CHARTYPE CFX_TxtBreak::GetUnifiedCharType(
322 FX_CHARTYPE chartype) const {
323 return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype;
Dan Sinclair1770c022016-03-14 14:14:16 -0400324}
weili1b4f6b32016-08-04 16:37:48 -0700325
Dan Sinclair1770c022016-03-14 14:14:16 -0400326void CFX_TxtBreak::ResetArabicContext() {
327 if (m_bArabicContext) {
328 m_bCurRTL = m_iCurArabicContext > 1;
329 m_iCurAlignment = m_iCurArabicContext > 1 ? FX_TXTLINEALIGNMENT_Right
330 : FX_TXTLINEALIGNMENT_Left;
331 m_iCurAlignment |= (m_iAlignment & FX_TXTLINEALIGNMENT_HigherMask);
332 m_bArabicNumber = m_iArabicContext >= 1 && m_bArabicShapes;
333 } else {
334 if (m_bPagination) {
tsepezd19e9122016-11-02 15:43:18 -0700335 m_bCurRTL = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400336 m_iCurAlignment = 0;
337 } else {
338 m_bCurRTL = m_bRTL;
339 m_iCurAlignment = m_iAlignment;
340 }
341 if (m_bRTL) {
342 m_bArabicNumber = m_iArabicContext >= 1;
343 } else {
344 m_bArabicNumber = m_iArabicContext > 1;
345 }
346 m_bArabicNumber = m_bArabicNumber && m_bArabicShapes;
347 }
348 m_bArabicComma = m_bArabicNumber;
349 ResetContextCharStyles();
350}
weili1b4f6b32016-08-04 16:37:48 -0700351
tsepez215507d2016-06-09 19:05:47 -0700352void CFX_TxtBreak::AppendChar_PageLoad(CFX_TxtChar* pCurChar,
353 uint32_t dwProps) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400354 if (!m_bPagination) {
tsepez215507d2016-06-09 19:05:47 -0700355 pCurChar->m_dwStatus = 0;
356 pCurChar->m_pUserData = m_pUserData;
Dan Sinclair1770c022016-03-14 14:14:16 -0400357 }
358 if (m_bArabicContext || m_bArabicShapes) {
359 int32_t iBidiCls = (dwProps & FX_BIDICLASSBITSMASK) >> FX_BIDICLASSBITS;
360 int32_t iArabicContext =
361 (iBidiCls == FX_BIDICLASS_R || iBidiCls == FX_BIDICLASS_AL)
362 ? 2
363 : ((iBidiCls == FX_BIDICLASS_L || iBidiCls == FX_BIDICLASS_S) ? 0
364 : 1);
365 if (iArabicContext != m_iArabicContext && iArabicContext != 1) {
366 m_iArabicContext = iArabicContext;
367 if (m_iCurArabicContext == 1) {
368 m_iCurArabicContext = iArabicContext;
369 }
370 ResetArabicContext();
371 if (!m_bPagination) {
tsepezd19e9122016-11-02 15:43:18 -0700372 CFX_TxtChar* pLastChar = GetLastChar(1, false);
dsinclair85d1f2c2016-06-23 12:40:16 -0700373 if (pLastChar && pLastChar->m_dwStatus < 1) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400374 pLastChar->m_dwStatus = FX_TXTBREAK_PieceBreak;
375 }
376 }
377 }
378 }
379 pCurChar->m_dwCharStyles = m_dwContextCharStyles;
380}
weili1b4f6b32016-08-04 16:37:48 -0700381
tsepez215507d2016-06-09 19:05:47 -0700382uint32_t CFX_TxtBreak::AppendChar_Combination(CFX_TxtChar* pCurChar,
Dan Sinclair1770c022016-03-14 14:14:16 -0400383 int32_t iRotation) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400384 FX_WCHAR wch = pCurChar->m_wCharCode;
385 FX_WCHAR wForm;
386 int32_t iCharWidth = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400387 pCurChar->m_iCharWidth = -1;
388 if (m_bCombText) {
389 iCharWidth = m_iCombWidth;
390 } else {
391 if (m_bVertical != FX_IsOdd(iRotation)) {
392 iCharWidth = 1000;
393 } else {
394 wForm = wch;
395 if (!m_bPagination) {
tsepezd19e9122016-11-02 15:43:18 -0700396 CFX_TxtChar* pLastChar = GetLastChar(0, false);
tsepez215507d2016-06-09 19:05:47 -0700397 if (pLastChar &&
398 (pLastChar->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicShadda) == 0) {
tsepezd19e9122016-11-02 15:43:18 -0700399 bool bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400400 if (wch == 0x0651) {
401 FX_WCHAR wLast = pLastChar->m_wCharCode;
402 if (wLast >= 0x064C && wLast <= 0x0650) {
403 wForm = FX_GetArabicFromShaddaTable(wLast);
tsepezd19e9122016-11-02 15:43:18 -0700404 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400405 }
406 } else if (wch >= 0x064C && wch <= 0x0650) {
407 if (pLastChar->m_wCharCode == 0x0651) {
408 wForm = FX_GetArabicFromShaddaTable(wch);
tsepezd19e9122016-11-02 15:43:18 -0700409 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400410 }
411 }
412 if (bShadda) {
tsepez215507d2016-06-09 19:05:47 -0700413 pLastChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
414 pLastChar->m_iCharWidth = 0;
415 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
Dan Sinclair1770c022016-03-14 14:14:16 -0400416 }
417 }
418 }
tsepezd19e9122016-11-02 15:43:18 -0700419 if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400420 iCharWidth = 0;
421 }
422 }
423 iCharWidth *= m_iFontSize;
424 iCharWidth = iCharWidth * m_iHorScale / 100;
425 }
426 pCurChar->m_iCharWidth = -iCharWidth;
427 return FX_TXTBREAK_None;
428}
weili1b4f6b32016-08-04 16:37:48 -0700429
tsepez215507d2016-06-09 19:05:47 -0700430uint32_t CFX_TxtBreak::AppendChar_Tab(CFX_TxtChar* pCurChar,
431 int32_t iRotation) {
weilia2c06e42016-05-20 17:09:48 -0700432 m_eCharType = FX_CHARTYPE_Tab;
Dan Sinclair1770c022016-03-14 14:14:16 -0400433 if ((m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ExpandTab) == 0) {
434 return FX_TXTBREAK_None;
435 }
436 int32_t& iLineWidth = m_pCurLine->m_iWidth;
437 int32_t iCharWidth;
438 if (m_bCombText) {
439 iCharWidth = m_iCombWidth;
440 } else {
441 if (m_bEquidistant) {
442 iCharWidth = iLineWidth;
443 iCharWidth = m_iTabWidth * (iCharWidth / m_iTabWidth + 1) - iCharWidth;
444 if (iCharWidth < FX_TXTBREAK_MinimumTabWidth) {
445 iCharWidth += m_iTabWidth;
446 }
447 } else {
448 iCharWidth = m_iTabWidth;
449 }
450 }
451 pCurChar->m_iCharWidth = iCharWidth;
452 iLineWidth += iCharWidth;
453 if (!m_bSingleLine && iLineWidth >= m_iLineWidth + m_iTolerance) {
454 return EndBreak(FX_TXTBREAK_LineBreak);
455 }
456 return FX_TXTBREAK_None;
457}
weili1b4f6b32016-08-04 16:37:48 -0700458
tsepez215507d2016-06-09 19:05:47 -0700459uint32_t CFX_TxtBreak::AppendChar_Control(CFX_TxtChar* pCurChar,
Dan Sinclair1770c022016-03-14 14:14:16 -0400460 int32_t iRotation) {
weilia2c06e42016-05-20 17:09:48 -0700461 m_eCharType = FX_CHARTYPE_Control;
tsepez736f28a2016-03-25 14:19:51 -0700462 uint32_t dwRet = FX_TXTBREAK_None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400463 if (!m_bSingleLine) {
464 FX_WCHAR wch = pCurChar->m_wCharCode;
465 switch (wch) {
466 case L'\v':
467 case 0x2028:
468 dwRet = FX_TXTBREAK_LineBreak;
469 break;
470 case L'\f':
471 dwRet = FX_TXTBREAK_PageBreak;
472 break;
473 case 0x2029:
474 dwRet = FX_TXTBREAK_ParagraphBreak;
475 break;
476 default:
477 if (wch == m_wParagBreakChar) {
478 dwRet = FX_TXTBREAK_ParagraphBreak;
479 }
480 break;
481 }
482 if (dwRet != FX_TXTBREAK_None) {
483 dwRet = EndBreak(dwRet);
484 }
485 }
486 return dwRet;
487}
weili1b4f6b32016-08-04 16:37:48 -0700488
tsepez215507d2016-06-09 19:05:47 -0700489uint32_t CFX_TxtBreak::AppendChar_Arabic(CFX_TxtChar* pCurChar,
Dan Sinclair1770c022016-03-14 14:14:16 -0400490 int32_t iRotation) {
weilia2c06e42016-05-20 17:09:48 -0700491 FX_CHARTYPE chartype = pCurChar->GetCharType();
Dan Sinclair1770c022016-03-14 14:14:16 -0400492 int32_t& iLineWidth = m_pCurLine->m_iWidth;
493 FX_WCHAR wForm;
494 int32_t iCharWidth = 0;
dsinclair85d1f2c2016-06-23 12:40:16 -0700495 CFX_Char* pLastChar = nullptr;
tsepezd19e9122016-11-02 15:43:18 -0700496 bool bAlef = false;
weilia2c06e42016-05-20 17:09:48 -0700497 if (!m_bCombText && m_eCharType >= FX_CHARTYPE_ArabicAlef &&
498 m_eCharType <= FX_CHARTYPE_ArabicDistortion) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400499 pLastChar = GetLastChar(1);
dsinclair85d1f2c2016-06-23 12:40:16 -0700500 if (pLastChar) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400501 iCharWidth = pLastChar->m_iCharWidth;
502 if (iCharWidth > 0) {
503 iLineWidth -= iCharWidth;
504 }
505 CFX_Char* pPrevChar = GetLastChar(2);
tsepeze00f75c2016-05-06 13:15:46 -0700506 wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar);
Dan Sinclair1770c022016-03-14 14:14:16 -0400507 bAlef = (wForm == 0xFEFF &&
508 pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef);
509 int32_t iLastRotation = pLastChar->m_nRotation + m_iLineRotation;
510 if (m_bVertical && (pLastChar->m_dwCharProps & 0x8000) != 0) {
511 iLastRotation++;
512 }
513 if (m_bVertical != FX_IsOdd(iLastRotation)) {
514 iCharWidth = 1000;
515 } else {
tsepezd19e9122016-11-02 15:43:18 -0700516 m_pFont->GetCharWidth(wForm, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400517 }
518 if (wForm == 0xFEFF) {
519 iCharWidth = m_iDefChar;
520 }
521 iCharWidth *= m_iFontSize;
522 iCharWidth = iCharWidth * m_iHorScale / 100;
523 pLastChar->m_iCharWidth = iCharWidth;
524 iLineWidth += iCharWidth;
525 iCharWidth = 0;
526 }
527 }
weilia2c06e42016-05-20 17:09:48 -0700528 m_eCharType = chartype;
dsinclair85d1f2c2016-06-23 12:40:16 -0700529 wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar,
530 nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400531 if (m_bCombText) {
532 iCharWidth = m_iCombWidth;
533 } else {
534 if (m_bVertical != FX_IsOdd(iRotation)) {
535 iCharWidth = 1000;
536 } else {
tsepezd19e9122016-11-02 15:43:18 -0700537 m_pFont->GetCharWidth(wForm, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400538 }
539 if (wForm == 0xFEFF) {
540 iCharWidth = m_iDefChar;
541 }
542 iCharWidth *= m_iFontSize;
543 iCharWidth = iCharWidth * m_iHorScale / 100;
544 }
545 pCurChar->m_iCharWidth = iCharWidth;
546 iLineWidth += iCharWidth;
547 m_pCurLine->m_iArabicChars++;
548 if (!m_bSingleLine && iLineWidth > m_iLineWidth + m_iTolerance) {
549 return EndBreak(FX_TXTBREAK_LineBreak);
550 }
551 return FX_TXTBREAK_None;
552}
weili1b4f6b32016-08-04 16:37:48 -0700553
tsepez215507d2016-06-09 19:05:47 -0700554uint32_t CFX_TxtBreak::AppendChar_Others(CFX_TxtChar* pCurChar,
Dan Sinclair1770c022016-03-14 14:14:16 -0400555 int32_t iRotation) {
tsepez736f28a2016-03-25 14:19:51 -0700556 uint32_t dwProps = pCurChar->m_dwCharProps;
weilia2c06e42016-05-20 17:09:48 -0700557 FX_CHARTYPE chartype = pCurChar->GetCharType();
Dan Sinclair1770c022016-03-14 14:14:16 -0400558 int32_t& iLineWidth = m_pCurLine->m_iWidth;
559 int32_t iCharWidth = 0;
weilia2c06e42016-05-20 17:09:48 -0700560 m_eCharType = chartype;
Dan Sinclair1770c022016-03-14 14:14:16 -0400561 FX_WCHAR wch = pCurChar->m_wCharCode;
562 FX_WCHAR wForm = wch;
weilia2c06e42016-05-20 17:09:48 -0700563 if (chartype == FX_CHARTYPE_Numeric) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400564 if (m_bArabicNumber) {
565 wForm = wch + 0x0630;
566 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicIndic;
567 }
568 } else if (wch == L',') {
569 if (m_bArabicShapes && m_iCurArabicContext > 0) {
570 wForm = 0x060C;
571 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicComma;
572 }
573 } else if (m_bCurRTL || m_bVertical) {
574 wForm = FX_GetMirrorChar(wch, dwProps, m_bCurRTL, m_bVertical);
575 }
576 if (m_bCombText) {
577 iCharWidth = m_iCombWidth;
578 } else {
579 if (m_bVertical != FX_IsOdd(iRotation)) {
580 iCharWidth = 1000;
tsepezd19e9122016-11-02 15:43:18 -0700581 } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400582 iCharWidth = m_iDefChar;
583 }
584 iCharWidth *= m_iFontSize;
585 iCharWidth = iCharWidth * m_iHorScale / 100;
586 }
587 iCharWidth += m_iCharSpace;
588 pCurChar->m_iCharWidth = iCharWidth;
589 iLineWidth += iCharWidth;
tsepezd19e9122016-11-02 15:43:18 -0700590 bool bBreak = (chartype != FX_CHARTYPE_Space ||
591 (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400592 if (!m_bSingleLine && bBreak && iLineWidth > m_iLineWidth + m_iTolerance) {
593 return EndBreak(FX_TXTBREAK_LineBreak);
594 }
595 return FX_TXTBREAK_None;
596}
tsepez215507d2016-06-09 19:05:47 -0700597
tsepez736f28a2016-03-25 14:19:51 -0700598uint32_t CFX_TxtBreak::AppendChar(FX_WCHAR wch) {
599 uint32_t dwProps = kTextLayoutCodeProperties[(uint16_t)wch];
weilia2c06e42016-05-20 17:09:48 -0700600 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
Dan Sinclair1770c022016-03-14 14:14:16 -0400601 CFX_TxtChar* pCurChar = m_pCurLine->m_pLineChars->AddSpace();
Tom Sepez62a70f92016-03-21 15:00:20 -0700602 pCurChar->m_wCharCode = (uint16_t)wch;
Dan Sinclair1770c022016-03-14 14:14:16 -0400603 pCurChar->m_nRotation = m_iCharRotation;
604 pCurChar->m_dwCharProps = dwProps;
605 pCurChar->m_dwCharStyles = 0;
606 pCurChar->m_iCharWidth = 0;
607 pCurChar->m_iHorizontalScale = m_iHorScale;
608 pCurChar->m_iVertialScale = m_iVerScale;
609 pCurChar->m_dwStatus = 0;
610 pCurChar->m_iBidiClass = 0;
611 pCurChar->m_iBidiLevel = 0;
612 pCurChar->m_iBidiPos = 0;
613 pCurChar->m_iBidiOrder = 0;
dsinclair85d1f2c2016-06-23 12:40:16 -0700614 pCurChar->m_pUserData = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400615 AppendChar_PageLoad(pCurChar, dwProps);
tsepez736f28a2016-03-25 14:19:51 -0700616 uint32_t dwRet1 = FX_TXTBREAK_None;
weilia2c06e42016-05-20 17:09:48 -0700617 if (chartype != FX_CHARTYPE_Combination &&
618 GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype)) {
619 if (m_eCharType != FX_CHARTYPE_Unknown &&
Dan Sinclair1770c022016-03-14 14:14:16 -0400620 m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine) {
weilia2c06e42016-05-20 17:09:48 -0700621 if (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400622 dwRet1 = EndBreak(FX_TXTBREAK_LineBreak);
623 int32_t iCount = m_pCurLine->CountChars();
624 if (iCount > 0) {
625 pCurChar = m_pCurLine->m_pLineChars->GetDataPtr(iCount - 1);
626 }
627 }
628 }
629 }
630 int32_t iRotation = m_iRotation;
631 if (m_bVertical && (dwProps & 0x8000) != 0) {
632 iRotation = (iRotation + 1) % 4;
633 }
tsepez736f28a2016-03-25 14:19:51 -0700634 uint32_t dwRet2 =
weilia2c06e42016-05-20 17:09:48 -0700635 (this->*g_FX_TxtBreak_lpfAppendChar[chartype >> FX_CHARTYPEBITS])(
Dan Sinclair1770c022016-03-14 14:14:16 -0400636 pCurChar, iRotation);
637 return std::max(dwRet1, dwRet2);
638}
weili1b4f6b32016-08-04 16:37:48 -0700639
Dan Sinclair1770c022016-03-14 14:14:16 -0400640void CFX_TxtBreak::EndBreak_UpdateArabicShapes() {
dsinclair43854a52016-04-27 12:26:00 -0700641 ASSERT(m_bArabicShapes);
Dan Sinclair1770c022016-03-14 14:14:16 -0400642 int32_t iCount = m_pCurLine->CountChars();
643 if (iCount < 2) {
644 return;
645 }
646 int32_t& iLineWidth = m_pCurLine->m_iWidth;
thestig2c065322016-09-26 14:16:43 -0700647 CFX_Char* pCur = m_pCurLine->GetCharPtr(0);
tsepezd19e9122016-11-02 15:43:18 -0700648 bool bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400649 pCur = m_pCurLine->GetCharPtr(1);
650 FX_WCHAR wch, wForm;
tsepezd19e9122016-11-02 15:43:18 -0700651 bool bNextNum;
thestig2c065322016-09-26 14:16:43 -0700652 int32_t i = 1;
653 int32_t iCharWidth;
654 int32_t iRotation;
655 CFX_Char* pNext;
Dan Sinclair1770c022016-03-14 14:14:16 -0400656 do {
657 i++;
658 if (i < iCount) {
659 pNext = m_pCurLine->GetCharPtr(i);
660 bNextNum = (pNext->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
661 } else {
dsinclair85d1f2c2016-06-23 12:40:16 -0700662 pNext = nullptr;
tsepezd19e9122016-11-02 15:43:18 -0700663 bNextNum = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400664 }
665 wch = pCur->m_wCharCode;
666 if (wch == L'.') {
667 if (bPrevNum && bNextNum) {
668 iRotation = m_iRotation;
669 if (m_bVertical && (pCur->m_dwCharProps & 0x8000) != 0) {
670 iRotation = ((iRotation + 1) & 0x03);
671 }
672 wForm = wch == L'.' ? 0x066B : 0x066C;
673 iLineWidth -= pCur->m_iCharWidth;
674 if (m_bCombText) {
675 iCharWidth = m_iCombWidth;
676 } else {
677 if (m_bVertical != FX_IsOdd(iRotation)) {
678 iCharWidth = 1000;
tsepezd19e9122016-11-02 15:43:18 -0700679 } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400680 iCharWidth = m_iDefChar;
681 }
682 iCharWidth *= m_iFontSize;
683 iCharWidth = iCharWidth * m_iHorScale / 100;
684 }
685 pCur->m_iCharWidth = iCharWidth;
686 iLineWidth += iCharWidth;
687 }
688 }
689 bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
690 pCur = pNext;
691 } while (i < iCount);
692}
weili1b4f6b32016-08-04 16:37:48 -0700693
tsepezd19e9122016-11-02 15:43:18 -0700694bool CFX_TxtBreak::EndBreak_SplitLine(CFX_TxtLine* pNextLine,
695 bool bAllChars,
696 uint32_t dwStatus) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400697 int32_t iCount = m_pCurLine->CountChars();
tsepezd19e9122016-11-02 15:43:18 -0700698 bool bDone = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400699 CFX_Char* pTC;
700 if (!m_bSingleLine && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance) {
701 pTC = m_pCurLine->GetCharPtr(iCount - 1);
702 switch (pTC->GetCharType()) {
703 case FX_CHARTYPE_Tab:
704 case FX_CHARTYPE_Control:
705 break;
706 case FX_CHARTYPE_Space:
707 if ((m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0) {
708 SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
tsepezd19e9122016-11-02 15:43:18 -0700709 bDone = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400710 }
711 break;
712 default:
713 SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
tsepezd19e9122016-11-02 15:43:18 -0700714 bDone = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400715 break;
716 }
717 }
718 iCount = m_pCurLine->CountChars();
weili1b4f6b32016-08-04 16:37:48 -0700719 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400720 CFX_TxtPiece tp;
721 if (m_bPagination) {
722 tp.m_dwStatus = dwStatus;
723 tp.m_iStartPos = m_pCurLine->m_iStart;
724 tp.m_iWidth = m_pCurLine->m_iWidth;
725 tp.m_iStartChar = 0;
726 tp.m_iChars = iCount;
weili1b4f6b32016-08-04 16:37:48 -0700727 tp.m_pChars = m_pCurLine->m_pLineChars.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400728 tp.m_pUserData = m_pUserData;
729 pTC = m_pCurLine->GetCharPtr(0);
730 tp.m_dwCharStyles = pTC->m_dwCharStyles;
731 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
732 tp.m_iVerticalScale = pTC->m_iVertialScale;
733 pCurPieces->Add(tp);
734 m_pCurLine = pNextLine;
weilia2c06e42016-05-20 17:09:48 -0700735 m_eCharType = FX_CHARTYPE_Unknown;
tsepezd19e9122016-11-02 15:43:18 -0700736 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400737 }
738 if (bAllChars && !bDone) {
739 int32_t iEndPos = m_pCurLine->m_iWidth;
tsepezd19e9122016-11-02 15:43:18 -0700740 GetBreakPos(*m_pCurLine->m_pLineChars.get(), iEndPos, bAllChars, true);
Dan Sinclair1770c022016-03-14 14:14:16 -0400741 }
tsepezd19e9122016-11-02 15:43:18 -0700742 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400743}
weili1b4f6b32016-08-04 16:37:48 -0700744
tsepez736f28a2016-03-25 14:19:51 -0700745void CFX_TxtBreak::EndBreak_BidiLine(CFX_TPOArray& tpos, uint32_t dwStatus) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400746 CFX_TxtPiece tp;
747 FX_TPO tpo;
748 CFX_TxtChar* pTC;
749 int32_t i, j;
weili1b4f6b32016-08-04 16:37:48 -0700750 CFX_TxtCharArray& chars = *m_pCurLine->m_pLineChars.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400751 int32_t iCount = m_pCurLine->CountChars();
tsepezd19e9122016-11-02 15:43:18 -0700752 bool bDone = (m_pCurLine->m_iArabicChars > 0 || m_bCurRTL);
Dan Sinclair1770c022016-03-14 14:14:16 -0400753 if (!m_bPagination && bDone) {
754 int32_t iBidiNum = 0;
755 for (i = 0; i < iCount; i++) {
756 pTC = chars.GetDataPtr(i);
757 pTC->m_iBidiPos = i;
758 if (pTC->GetCharType() != FX_CHARTYPE_Control) {
759 iBidiNum = i;
760 }
761 if (i == 0) {
762 pTC->m_iBidiLevel = 1;
763 }
764 }
765 FX_BidiLine(chars, iBidiNum + 1, m_bCurRTL ? 1 : 0);
766 }
weili1b4f6b32016-08-04 16:37:48 -0700767 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400768 if (!m_bPagination &&
769 (bDone || (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_MutipleFormat) != 0)) {
770 tp.m_dwStatus = FX_TXTBREAK_PieceBreak;
771 tp.m_iStartPos = m_pCurLine->m_iStart;
weili1b4f6b32016-08-04 16:37:48 -0700772 tp.m_pChars = m_pCurLine->m_pLineChars.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400773 int32_t iBidiLevel = -1, iCharWidth;
774 i = 0, j = -1;
775 while (i < iCount) {
776 pTC = chars.GetDataPtr(i);
777 if (iBidiLevel < 0) {
778 iBidiLevel = pTC->m_iBidiLevel;
779 tp.m_iWidth = 0;
780 tp.m_iBidiLevel = iBidiLevel;
781 tp.m_iBidiPos = pTC->m_iBidiOrder;
782 tp.m_dwCharStyles = pTC->m_dwCharStyles;
783 tp.m_pUserData = pTC->m_pUserData;
784 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
785 tp.m_iVerticalScale = pTC->m_iVertialScale;
786 tp.m_dwStatus = FX_TXTBREAK_PieceBreak;
787 }
788 if (iBidiLevel != pTC->m_iBidiLevel || pTC->m_dwStatus != 0) {
789 if (iBidiLevel == pTC->m_iBidiLevel) {
790 tp.m_dwStatus = pTC->m_dwStatus;
791 iCharWidth = pTC->m_iCharWidth;
792 if (iCharWidth > 0) {
793 tp.m_iWidth += iCharWidth;
794 }
795 i++;
796 }
797 tp.m_iChars = i - tp.m_iStartChar;
798 pCurPieces->Add(tp);
799 tp.m_iStartPos += tp.m_iWidth;
800 tp.m_iStartChar = i;
801 tpo.index = ++j;
802 tpo.pos = tp.m_iBidiPos;
803 tpos.Add(tpo);
804 iBidiLevel = -1;
805 } else {
806 iCharWidth = pTC->m_iCharWidth;
807 if (iCharWidth > 0) {
808 tp.m_iWidth += iCharWidth;
809 }
810 i++;
811 }
812 }
813 if (i > tp.m_iStartChar) {
814 tp.m_dwStatus = dwStatus;
815 tp.m_iChars = i - tp.m_iStartChar;
816 pCurPieces->Add(tp);
817 tpo.index = ++j;
818 tpo.pos = tp.m_iBidiPos;
819 tpos.Add(tpo);
820 }
821 if (j > -1) {
822 if (j > 0) {
823 FX_TEXTLAYOUT_PieceSort(tpos, 0, j);
824 int32_t iStartPos = 0;
825 for (i = 0; i <= j; i++) {
826 tpo = tpos.GetAt(i);
827 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
828 ttp.m_iStartPos = iStartPos;
829 iStartPos += ttp.m_iWidth;
830 }
831 }
832 CFX_TxtPiece& ttp = pCurPieces->GetAt(j);
833 ttp.m_dwStatus = dwStatus;
834 }
835 } else {
836 tp.m_dwStatus = dwStatus;
837 tp.m_iStartPos = m_pCurLine->m_iStart;
838 tp.m_iWidth = m_pCurLine->m_iWidth;
839 tp.m_iStartChar = 0;
840 tp.m_iChars = iCount;
weili1b4f6b32016-08-04 16:37:48 -0700841 tp.m_pChars = m_pCurLine->m_pLineChars.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400842 tp.m_pUserData = m_pUserData;
843 pTC = chars.GetDataPtr(0);
844 tp.m_dwCharStyles = pTC->m_dwCharStyles;
845 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
846 tp.m_iVerticalScale = pTC->m_iVertialScale;
847 pCurPieces->Add(tp);
848 tpo.index = 0;
849 tpo.pos = 0;
850 tpos.Add(tpo);
851 }
852}
weili1b4f6b32016-08-04 16:37:48 -0700853
Dan Sinclair1770c022016-03-14 14:14:16 -0400854void CFX_TxtBreak::EndBreak_Alignment(CFX_TPOArray& tpos,
tsepezd19e9122016-11-02 15:43:18 -0700855 bool bAllChars,
tsepez736f28a2016-03-25 14:19:51 -0700856 uint32_t dwStatus) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400857 int32_t iNetWidth = m_pCurLine->m_iWidth, iGapChars = 0, iCharWidth;
weili1b4f6b32016-08-04 16:37:48 -0700858 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400859 int32_t i, j, iCount = pCurPieces->GetSize();
tsepezd19e9122016-11-02 15:43:18 -0700860 bool bFind = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400861 FX_TPO tpo;
862 CFX_TxtChar* pTC;
weilia2c06e42016-05-20 17:09:48 -0700863 FX_CHARTYPE chartype;
Dan Sinclair1770c022016-03-14 14:14:16 -0400864 for (i = iCount - 1; i > -1; i--) {
865 tpo = tpos.GetAt(i);
866 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
867 if (!bFind) {
868 iNetWidth = ttp.GetEndPos();
869 }
tsepezd19e9122016-11-02 15:43:18 -0700870 bool bArabic = FX_IsOdd(ttp.m_iBidiLevel);
Dan Sinclair1770c022016-03-14 14:14:16 -0400871 j = bArabic ? 0 : ttp.m_iChars - 1;
872 while (j > -1 && j < ttp.m_iChars) {
873 pTC = ttp.GetCharPtr(j);
874 if (pTC->m_nBreakType == FX_LBT_DIRECT_BRK) {
875 iGapChars++;
876 }
877 if (!bFind || !bAllChars) {
weilia2c06e42016-05-20 17:09:48 -0700878 chartype = pTC->GetCharType();
879 if (chartype == FX_CHARTYPE_Space || chartype == FX_CHARTYPE_Control) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400880 if (!bFind) {
881 iCharWidth = pTC->m_iCharWidth;
882 if (bAllChars && iCharWidth > 0) {
883 iNetWidth -= iCharWidth;
884 }
885 }
886 } else {
tsepezd19e9122016-11-02 15:43:18 -0700887 bFind = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400888 if (!bAllChars) {
889 break;
890 }
891 }
892 }
893 j += bArabic ? 1 : -1;
894 }
895 if (!bAllChars && bFind) {
896 break;
897 }
898 }
899 int32_t iOffset = m_iLineWidth - iNetWidth;
900 int32_t iLowerAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_LowerMask);
901 int32_t iHigherAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_HigherMask);
902 if (iGapChars > 0 && (iHigherAlignment == FX_TXTLINEALIGNMENT_Distributed ||
903 (iHigherAlignment == FX_TXTLINEALIGNMENT_Justified &&
904 dwStatus != FX_TXTBREAK_ParagraphBreak))) {
905 int32_t iStart = -1;
906 for (i = 0; i < iCount; i++) {
907 tpo = tpos.GetAt(i);
908 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
909 if (iStart < -1) {
910 iStart = ttp.m_iStartPos;
911 } else {
912 ttp.m_iStartPos = iStart;
913 }
914 int32_t k;
915 for (j = 0; j < ttp.m_iChars; j++) {
916 pTC = ttp.GetCharPtr(j);
917 if (pTC->m_nBreakType != FX_LBT_DIRECT_BRK || pTC->m_iCharWidth < 0) {
918 continue;
919 }
920 k = iOffset / iGapChars;
921 pTC->m_iCharWidth += k;
922 ttp.m_iWidth += k;
923 iOffset -= k;
924 iGapChars--;
925 if (iGapChars < 1) {
926 break;
927 }
928 }
929 iStart += ttp.m_iWidth;
930 }
931 } else if (iLowerAlignment > FX_TXTLINEALIGNMENT_Left) {
932 if (iLowerAlignment == FX_TXTLINEALIGNMENT_Center) {
933 iOffset /= 2;
934 }
935 if (iOffset > 0) {
936 for (i = 0; i < iCount; i++) {
937 CFX_TxtPiece& ttp = pCurPieces->GetAt(i);
938 ttp.m_iStartPos += iOffset;
939 }
940 }
941 }
942}
weili1b4f6b32016-08-04 16:37:48 -0700943
tsepez736f28a2016-03-25 14:19:51 -0700944uint32_t CFX_TxtBreak::EndBreak(uint32_t dwStatus) {
dsinclair43854a52016-04-27 12:26:00 -0700945 ASSERT(dwStatus >= FX_TXTBREAK_PieceBreak &&
946 dwStatus <= FX_TXTBREAK_PageBreak);
weili1b4f6b32016-08-04 16:37:48 -0700947 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400948 int32_t iCount = pCurPieces->GetSize();
949 if (iCount > 0) {
950 CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(--iCount);
951 if (dwStatus > FX_TXTBREAK_PieceBreak) {
952 pLastPiece->m_dwStatus = dwStatus;
953 } else {
954 dwStatus = pLastPiece->m_dwStatus;
955 }
956 return dwStatus;
957 } else {
tsepezd19e9122016-11-02 15:43:18 -0700958 CFX_TxtLine* pLastLine = GetTxtLine(true);
dsinclair85d1f2c2016-06-23 12:40:16 -0700959 if (pLastLine) {
weili1b4f6b32016-08-04 16:37:48 -0700960 pCurPieces = pLastLine->m_pLinePieces.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400961 iCount = pCurPieces->GetSize();
962 if (iCount-- > 0) {
963 CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(iCount);
964 if (dwStatus > FX_TXTBREAK_PieceBreak) {
965 pLastPiece->m_dwStatus = dwStatus;
966 } else {
967 dwStatus = pLastPiece->m_dwStatus;
968 }
969 return dwStatus;
970 }
971 return FX_TXTBREAK_None;
972 }
973 iCount = m_pCurLine->CountChars();
974 if (iCount < 1) {
975 return FX_TXTBREAK_None;
976 }
977 if (!m_bPagination) {
978 CFX_TxtChar* pTC = m_pCurLine->GetCharPtr(iCount - 1);
979 pTC->m_dwStatus = dwStatus;
980 }
981 if (dwStatus <= FX_TXTBREAK_PieceBreak) {
982 return dwStatus;
983 }
984 }
weili1b4f6b32016-08-04 16:37:48 -0700985 m_iReady = (m_pCurLine == m_pTxtLine1.get()) ? 1 : 2;
Dan Sinclair1770c022016-03-14 14:14:16 -0400986 CFX_TxtLine* pNextLine =
weili1b4f6b32016-08-04 16:37:48 -0700987 (m_pCurLine == m_pTxtLine1.get()) ? m_pTxtLine2.get() : m_pTxtLine1.get();
tsepezd19e9122016-11-02 15:43:18 -0700988 bool bAllChars = (m_iCurAlignment > FX_TXTLINEALIGNMENT_Right);
dsinclair34965452016-07-18 13:14:49 -0700989 CFX_TPOArray tpos(100);
Dan Sinclair1770c022016-03-14 14:14:16 -0400990 CFX_Char* pTC;
991 if (m_bArabicShapes) {
992 EndBreak_UpdateArabicShapes();
993 }
994 if (EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) {
995 goto EndBreak_Ret;
996 }
997 EndBreak_BidiLine(tpos, dwStatus);
998 if (!m_bPagination && m_iCurAlignment > FX_TXTLINEALIGNMENT_Left) {
999 EndBreak_Alignment(tpos, bAllChars, dwStatus);
1000 }
1001EndBreak_Ret:
1002 m_pCurLine = pNextLine;
tsepezd19e9122016-11-02 15:43:18 -07001003 pTC = GetLastChar(0, false);
weilia2c06e42016-05-20 17:09:48 -07001004 m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown;
Dan Sinclair1770c022016-03-14 14:14:16 -04001005 if (dwStatus == FX_TXTBREAK_ParagraphBreak) {
1006 m_iArabicContext = m_iCurArabicContext = 1;
1007 ResetArabicContext();
1008 }
1009 return dwStatus;
1010}
weili1b4f6b32016-08-04 16:37:48 -07001011
Dan Sinclair1770c022016-03-14 14:14:16 -04001012int32_t CFX_TxtBreak::GetBreakPos(CFX_TxtCharArray& ca,
1013 int32_t& iEndPos,
tsepezd19e9122016-11-02 15:43:18 -07001014 bool bAllChars,
1015 bool bOnlyBrk) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001016 int32_t iLength = ca.GetSize() - 1;
1017 if (iLength < 1) {
1018 return iLength;
1019 }
1020 int32_t iBreak = -1, iBreakPos = -1, iIndirect = -1, iIndirectPos = -1,
1021 iLast = -1, iLastPos = -1;
1022 if (m_bSingleLine || iEndPos <= m_iLineWidth) {
1023 if (!bAllChars) {
1024 return iLength;
1025 }
1026 iBreak = iLength;
1027 iBreakPos = iEndPos;
1028 }
tsepezd19e9122016-11-02 15:43:18 -07001029 bool bSpaceBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0;
1030 bool bNumberBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_NumberBreak) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001031 FX_LINEBREAKTYPE eType;
tsepez736f28a2016-03-25 14:19:51 -07001032 uint32_t nCodeProp, nCur, nNext;
Dan Sinclair1770c022016-03-14 14:14:16 -04001033 CFX_Char* pCur = ca.GetDataPtr(iLength--);
1034 if (bAllChars) {
1035 pCur->m_nBreakType = FX_LBT_UNKNOWN;
1036 }
1037 nCodeProp = pCur->m_dwCharProps;
1038 nNext = nCodeProp & 0x003F;
1039 int32_t iCharWidth = pCur->m_iCharWidth;
1040 if (iCharWidth > 0) {
1041 iEndPos -= iCharWidth;
1042 }
1043 while (iLength >= 0) {
1044 pCur = ca.GetDataPtr(iLength);
1045 nCodeProp = pCur->m_dwCharProps;
1046 nCur = nCodeProp & 0x003F;
1047 if (nCur == FX_CBP_SP) {
1048 if (nNext == FX_CBP_SP) {
1049 eType = bSpaceBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
1050 } else {
tsepezf49747f2016-06-10 15:24:47 -07001051 eType = gs_FX_LineBreak_PairTable[nCur][nNext];
Dan Sinclair1770c022016-03-14 14:14:16 -04001052 }
1053 } else if (bNumberBreak && nCur == FX_CBP_NU && nNext == FX_CBP_NU) {
1054 eType = FX_LBT_DIRECT_BRK;
1055 } else {
1056 if (nNext == FX_CBP_SP) {
1057 eType = FX_LBT_PROHIBITED_BRK;
1058 } else {
tsepezf49747f2016-06-10 15:24:47 -07001059 eType = gs_FX_LineBreak_PairTable[nCur][nNext];
Dan Sinclair1770c022016-03-14 14:14:16 -04001060 }
1061 }
1062 if (bAllChars) {
1063 pCur->m_nBreakType = (uint8_t)eType;
1064 }
1065 if (!bOnlyBrk) {
1066 if (m_bSingleLine || iEndPos <= m_iLineWidth ||
1067 (nCur == FX_CBP_SP && !bSpaceBreak)) {
1068 if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) {
1069 iBreak = iLength;
1070 iBreakPos = iEndPos;
1071 if (!bAllChars) {
1072 return iLength;
1073 }
1074 } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) {
1075 iIndirect = iLength;
1076 iIndirectPos = iEndPos;
1077 }
1078 if (iLast < 0) {
1079 iLast = iLength;
1080 iLastPos = iEndPos;
1081 }
1082 }
1083 iCharWidth = pCur->m_iCharWidth;
1084 if (iCharWidth > 0) {
1085 iEndPos -= iCharWidth;
1086 }
1087 }
1088 nNext = nCodeProp & 0x003F;
1089 iLength--;
1090 }
1091 if (bOnlyBrk) {
1092 return 0;
1093 }
1094 if (iBreak > -1) {
1095 iEndPos = iBreakPos;
1096 return iBreak;
1097 }
1098 if (iIndirect > -1) {
1099 iEndPos = iIndirectPos;
1100 return iIndirect;
1101 }
1102 if (iLast > -1) {
1103 iEndPos = iLastPos;
1104 return iLast;
1105 }
1106 return 0;
1107}
weili1b4f6b32016-08-04 16:37:48 -07001108
Dan Sinclair1770c022016-03-14 14:14:16 -04001109void CFX_TxtBreak::SplitTextLine(CFX_TxtLine* pCurLine,
1110 CFX_TxtLine* pNextLine,
tsepezd19e9122016-11-02 15:43:18 -07001111 bool bAllChars) {
dsinclair85d1f2c2016-06-23 12:40:16 -07001112 ASSERT(pCurLine && pNextLine);
Dan Sinclair1770c022016-03-14 14:14:16 -04001113 int32_t iCount = pCurLine->CountChars();
1114 if (iCount < 2) {
1115 return;
1116 }
1117 int32_t iEndPos = pCurLine->m_iWidth;
weili1b4f6b32016-08-04 16:37:48 -07001118 CFX_TxtCharArray& curChars = *pCurLine->m_pLineChars.get();
tsepezd19e9122016-11-02 15:43:18 -07001119 int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001120 if (iCharPos < 0) {
1121 iCharPos = 0;
1122 }
1123 iCharPos++;
1124 if (iCharPos >= iCount) {
tsepezd19e9122016-11-02 15:43:18 -07001125 pNextLine->RemoveAll(true);
Dan Sinclair1770c022016-03-14 14:14:16 -04001126 CFX_Char* pTC = curChars.GetDataPtr(iCharPos - 1);
1127 pTC->m_nBreakType = FX_LBT_UNKNOWN;
1128 return;
1129 }
weili1b4f6b32016-08-04 16:37:48 -07001130 CFX_TxtCharArray& nextChars = *pNextLine->m_pLineChars.get();
Dan Sinclair1770c022016-03-14 14:14:16 -04001131 int cur_size = curChars.GetSize();
1132 nextChars.SetSize(cur_size - iCharPos);
1133 FXSYS_memcpy(nextChars.GetData(), curChars.GetDataPtr(iCharPos),
1134 (cur_size - iCharPos) * sizeof(CFX_TxtChar));
1135 iCount -= iCharPos;
1136 cur_size = curChars.GetSize();
1137 curChars.RemoveAt(cur_size - iCount, iCount);
1138 pCurLine->m_iWidth = iEndPos;
1139 CFX_TxtChar* pTC = curChars.GetDataPtr(iCharPos - 1);
1140 pTC->m_nBreakType = FX_LBT_UNKNOWN;
1141 iCount = nextChars.GetSize();
1142 int32_t iCharWidth, iWidth = 0;
1143 for (int32_t i = 0; i < iCount; i++) {
1144 pTC = nextChars.GetDataPtr(i);
1145 if (pTC->GetCharType() >= FX_CHARTYPE_ArabicAlef) {
1146 pCurLine->m_iArabicChars--;
1147 pNextLine->m_iArabicChars++;
1148 }
1149 iCharWidth = pTC->m_iCharWidth;
1150 if (iCharWidth > 0) {
1151 iWidth += iCharWidth;
1152 }
1153 if (m_bPagination) {
1154 continue;
1155 }
1156 pTC->m_dwStatus = 0;
1157 }
1158 pNextLine->m_iWidth = iWidth;
1159}
weili1b4f6b32016-08-04 16:37:48 -07001160
Dan Sinclair1770c022016-03-14 14:14:16 -04001161int32_t CFX_TxtBreak::CountBreakChars() const {
tsepezd19e9122016-11-02 15:43:18 -07001162 CFX_TxtLine* pTxtLine = GetTxtLine(true);
dsinclair85d1f2c2016-06-23 12:40:16 -07001163 return pTxtLine ? pTxtLine->CountChars() : 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001164}
weili1b4f6b32016-08-04 16:37:48 -07001165
Dan Sinclair1770c022016-03-14 14:14:16 -04001166int32_t CFX_TxtBreak::CountBreakPieces() const {
tsepezd19e9122016-11-02 15:43:18 -07001167 CFX_TxtPieceArray* pTxtPieces = GetTxtPieces(true);
dsinclair85d1f2c2016-06-23 12:40:16 -07001168 return pTxtPieces ? pTxtPieces->GetSize() : 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001169}
weili1b4f6b32016-08-04 16:37:48 -07001170
Dan Sinclair1770c022016-03-14 14:14:16 -04001171const CFX_TxtPiece* CFX_TxtBreak::GetBreakPiece(int32_t index) const {
tsepezd19e9122016-11-02 15:43:18 -07001172 CFX_TxtPieceArray* pTxtPieces = GetTxtPieces(true);
dsinclair85d1f2c2016-06-23 12:40:16 -07001173 if (!pTxtPieces) {
1174 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001175 }
1176 if (index < 0 || index >= pTxtPieces->GetSize()) {
dsinclair85d1f2c2016-06-23 12:40:16 -07001177 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001178 }
1179 return pTxtPieces->GetPtrAt(index);
1180}
weili1b4f6b32016-08-04 16:37:48 -07001181
Dan Sinclair1770c022016-03-14 14:14:16 -04001182void CFX_TxtBreak::ClearBreakPieces() {
tsepezd19e9122016-11-02 15:43:18 -07001183 CFX_TxtLine* pTxtLine = GetTxtLine(true);
dsinclair85d1f2c2016-06-23 12:40:16 -07001184 if (pTxtLine) {
tsepezd19e9122016-11-02 15:43:18 -07001185 pTxtLine->RemoveAll(true);
Dan Sinclair1770c022016-03-14 14:14:16 -04001186 }
1187 m_iReady = 0;
1188}
weili1b4f6b32016-08-04 16:37:48 -07001189
Dan Sinclair1770c022016-03-14 14:14:16 -04001190void CFX_TxtBreak::Reset() {
weilia2c06e42016-05-20 17:09:48 -07001191 m_eCharType = FX_CHARTYPE_Unknown;
Dan Sinclair1770c022016-03-14 14:14:16 -04001192 m_iArabicContext = m_iCurArabicContext = 1;
1193 ResetArabicContext();
tsepezd19e9122016-11-02 15:43:18 -07001194 m_pTxtLine1->RemoveAll(true);
1195 m_pTxtLine2->RemoveAll(true);
Dan Sinclair1770c022016-03-14 14:14:16 -04001196}
1197
1198struct FX_FORMCHAR {
Tom Sepez62a70f92016-03-21 15:00:20 -07001199 uint16_t wch;
1200 uint16_t wForm;
Dan Sinclair1770c022016-03-14 14:14:16 -04001201 int32_t iWidth;
1202};
1203
1204int32_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun,
1205 FXTEXT_CHARPOS* pCharPos,
tsepezd19e9122016-11-02 15:43:18 -07001206 bool bCharCode,
Dan Sinclair1770c022016-03-14 14:14:16 -04001207 CFX_WideString* pWSForms,
1208 FX_AdjustCharDisplayPos pAdjustPos) const {
dsinclair85d1f2c2016-06-23 12:40:16 -07001209 if (!pTxtRun || pTxtRun->iLength < 1) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001210 return 0;
1211 }
1212 IFX_TxtAccess* pAccess = pTxtRun->pAccess;
dsinclair705f8292016-06-07 10:10:45 -07001213 const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity;
tsepezd4033292016-04-19 12:03:15 -07001214 const FX_WCHAR* pStr = pTxtRun->wsStr.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04001215 int32_t* pWidths = pTxtRun->pWidths;
1216 int32_t iLength = pTxtRun->iLength - 1;
thestiga4fdfc52016-06-07 17:33:37 -07001217 CFGAS_GEFont* pFont = pTxtRun->pFont;
tsepez736f28a2016-03-25 14:19:51 -07001218 uint32_t dwStyles = pTxtRun->dwStyles;
Dan Sinclair1770c022016-03-14 14:14:16 -04001219 CFX_RectF rtText(*pTxtRun->pRect);
tsepezd19e9122016-11-02 15:43:18 -07001220 bool bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
1221 bool bArabicNumber =
Dan Sinclair1770c022016-03-14 14:14:16 -04001222 (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicNumber) != 0;
tsepezd19e9122016-11-02 15:43:18 -07001223 bool bArabicComma =
Dan Sinclair1770c022016-03-14 14:14:16 -04001224 (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicComma) != 0;
1225 FX_FLOAT fFontSize = pTxtRun->fFontSize;
1226 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
1227 int32_t iAscent = pFont->GetAscent();
1228 int32_t iDescent = pFont->GetDescent();
1229 int32_t iMaxHeight = iAscent - iDescent;
1230 FX_FLOAT fFontHeight = fFontSize;
1231 FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight;
1232 FX_FLOAT fDescent = fFontHeight * (FX_FLOAT)iDescent / (FX_FLOAT)iMaxHeight;
tsepezd19e9122016-11-02 15:43:18 -07001233 bool bVerticalDoc = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0;
1234 bool bVerticalChar = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001235 int32_t iRotation = GetLineRotation(dwStyles) + pTxtRun->iCharRotation;
Dan Sinclair1770c022016-03-14 14:14:16 -04001236 FX_FLOAT fX, fY, fCharWidth, fCharHeight;
1237 int32_t iHorScale = pTxtRun->iHorizontalScale;
1238 int32_t iVerScale = pTxtRun->iVerticalScale;
tsepezd19e9122016-11-02 15:43:18 -07001239 bool bSkipSpace = pTxtRun->bSkipSpace;
Dan Sinclair1770c022016-03-14 14:14:16 -04001240 FX_FORMCHAR formChars[3];
1241 FX_FLOAT fYBase;
1242 fX = rtText.left;
1243 if (bVerticalDoc) {
1244 fX += (rtText.width - fFontSize) / 2.0f;
1245 fYBase = bRTLPiece ? rtText.bottom() : rtText.top;
1246 fY = fYBase;
1247 } else {
1248 if (bRTLPiece) {
1249 fX = rtText.right();
1250 }
1251 fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f;
1252 fY = fYBase + fAscent;
1253 }
weili038aa532016-05-20 15:38:29 -07001254 int32_t iCount = 0;
1255 int32_t iNext = 0;
1256 FX_WCHAR wPrev = 0xFEFF;
1257 FX_WCHAR wNext = 0xFEFF;
1258 FX_WCHAR wForm = 0xFEFF;
1259 FX_WCHAR wLast = 0xFEFF;
tsepezd19e9122016-11-02 15:43:18 -07001260 bool bShadda = false;
1261 bool bLam = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001262 for (int32_t i = 0; i <= iLength; i++) {
weili038aa532016-05-20 15:38:29 -07001263 int32_t iWidth;
1264 FX_WCHAR wch;
dsinclair85d1f2c2016-06-23 12:40:16 -07001265 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001266 wch = pAccess->GetChar(pIdentity, i);
1267 iWidth = pAccess->GetWidth(pIdentity, i);
1268 } else {
1269 wch = *pStr++;
1270 iWidth = *pWidths++;
1271 }
weili038aa532016-05-20 15:38:29 -07001272 uint32_t dwProps = FX_GetUnicodeProperties(wch);
weilia2c06e42016-05-20 17:09:48 -07001273 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
1274 if (chartype == FX_CHARTYPE_ArabicAlef && iWidth == 0) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001275 wPrev = 0xFEFF;
1276 wLast = wch;
1277 continue;
1278 }
weilia2c06e42016-05-20 17:09:48 -07001279 if (chartype >= FX_CHARTYPE_ArabicAlef) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001280 if (i < iLength) {
dsinclair85d1f2c2016-06-23 12:40:16 -07001281 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001282 iNext = i + 1;
1283 while (iNext <= iLength) {
1284 wNext = pAccess->GetChar(pIdentity, iNext);
1285 dwProps = FX_GetUnicodeProperties(wNext);
1286 if ((dwProps & FX_CHARTYPEBITSMASK) != FX_CHARTYPE_Combination) {
1287 break;
1288 }
1289 iNext++;
1290 }
1291 if (iNext > iLength) {
1292 wNext = 0xFEFF;
1293 }
1294 } else {
1295 int32_t j = -1;
1296 do {
1297 j++;
1298 if (i + j >= iLength) {
1299 break;
1300 }
1301 wNext = pStr[j];
1302 dwProps = FX_GetUnicodeProperties(wNext);
1303 } while ((dwProps & FX_CHARTYPEBITSMASK) == FX_CHARTYPE_Combination);
1304 if (i + j >= iLength) {
1305 wNext = 0xFEFF;
1306 }
1307 }
1308 } else {
1309 wNext = 0xFEFF;
1310 }
tsepeze00f75c2016-05-06 13:15:46 -07001311 wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext);
Dan Sinclair1770c022016-03-14 14:14:16 -04001312 bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647);
weilia2c06e42016-05-20 17:09:48 -07001313 } else if (chartype == FX_CHARTYPE_Combination) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001314 wForm = wch;
1315 if (wch >= 0x064C && wch <= 0x0651) {
1316 if (bShadda) {
1317 wForm = 0xFEFF;
tsepezd19e9122016-11-02 15:43:18 -07001318 bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001319 } else {
1320 wNext = 0xFEFF;
dsinclair85d1f2c2016-06-23 12:40:16 -07001321 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001322 iNext = i + 1;
1323 if (iNext <= iLength) {
1324 wNext = pAccess->GetChar(pIdentity, iNext);
1325 }
1326 } else {
1327 if (i < iLength) {
1328 wNext = *pStr;
1329 }
1330 }
1331 if (wch == 0x0651) {
1332 if (wNext >= 0x064C && wNext <= 0x0650) {
1333 wForm = FX_GetArabicFromShaddaTable(wNext);
tsepezd19e9122016-11-02 15:43:18 -07001334 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001335 }
1336 } else {
1337 if (wNext == 0x0651) {
1338 wForm = FX_GetArabicFromShaddaTable(wch);
tsepezd19e9122016-11-02 15:43:18 -07001339 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001340 }
1341 }
1342 }
1343 } else {
tsepezd19e9122016-11-02 15:43:18 -07001344 bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001345 }
weilia2c06e42016-05-20 17:09:48 -07001346 } else if (chartype == FX_CHARTYPE_Numeric) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001347 wForm = wch;
1348 if (bArabicNumber) {
1349 wForm += 0x0630;
1350 }
1351 } else if (wch == L'.') {
1352 wForm = wch;
1353 if (bArabicNumber) {
1354 wNext = 0xFEFF;
dsinclair85d1f2c2016-06-23 12:40:16 -07001355 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001356 iNext = i + 1;
1357 if (iNext <= iLength) {
1358 wNext = pAccess->GetChar(pIdentity, iNext);
1359 }
1360 } else {
1361 if (i < iLength) {
1362 wNext = *pStr;
1363 }
1364 }
1365 if (wNext >= L'0' && wNext <= L'9') {
1366 wForm = 0x066B;
1367 }
1368 }
1369 } else if (wch == L',') {
1370 wForm = wch;
1371 if (bArabicComma) {
1372 wForm = 0x060C;
1373 }
1374 } else if (bRTLPiece || bVerticalChar) {
1375 wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, bVerticalChar);
1376 } else {
1377 wForm = wch;
1378 }
weilia2c06e42016-05-20 17:09:48 -07001379 if (chartype != FX_CHARTYPE_Combination) {
tsepezd19e9122016-11-02 15:43:18 -07001380 bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001381 }
weilia2c06e42016-05-20 17:09:48 -07001382 if (chartype < FX_CHARTYPE_ArabicAlef) {
tsepezd19e9122016-11-02 15:43:18 -07001383 bLam = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001384 }
1385 dwProps = FX_GetUnicodeProperties(wForm);
weili038aa532016-05-20 15:38:29 -07001386 int32_t iCharRotation = iRotation;
Dan Sinclair1770c022016-03-14 14:14:16 -04001387 if (bVerticalChar && (dwProps & 0x8000) != 0) {
1388 iCharRotation++;
1389 }
1390 iCharRotation %= 4;
tsepezd19e9122016-11-02 15:43:18 -07001391 bool bEmptyChar =
weilia2c06e42016-05-20 17:09:48 -07001392 (chartype >= FX_CHARTYPE_Tab && chartype <= FX_CHARTYPE_Control);
Dan Sinclair1770c022016-03-14 14:14:16 -04001393 if (wForm == 0xFEFF) {
tsepezd19e9122016-11-02 15:43:18 -07001394 bEmptyChar = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001395 }
weili038aa532016-05-20 15:38:29 -07001396 int32_t iForms = bLam ? 3 : 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04001397 iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms;
dsinclair85d1f2c2016-06-23 12:40:16 -07001398 if (!pCharPos) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001399 if (iWidth > 0) {
1400 wPrev = wch;
1401 }
1402 wLast = wch;
1403 continue;
1404 }
weili038aa532016-05-20 15:38:29 -07001405 int32_t iCharWidth = iWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -04001406 if (iCharWidth < 0) {
1407 iCharWidth = -iCharWidth;
1408 }
1409 iCharWidth /= iFontSize;
1410 formChars[0].wch = wch;
1411 formChars[0].wForm = wForm;
1412 formChars[0].iWidth = iCharWidth;
1413 if (bLam) {
1414 formChars[1].wForm = 0x0651;
1415 iCharWidth = 0;
tsepezd19e9122016-11-02 15:43:18 -07001416 pFont->GetCharWidth(0x0651, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001417 formChars[1].iWidth = iCharWidth;
1418 formChars[2].wForm = 0x0670;
1419 iCharWidth = 0;
tsepezd19e9122016-11-02 15:43:18 -07001420 pFont->GetCharWidth(0x0670, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001421 formChars[2].iWidth = iCharWidth;
1422 }
1423 for (int32_t j = 0; j < iForms; j++) {
1424 wForm = (FX_WCHAR)formChars[j].wForm;
1425 iCharWidth = formChars[j].iWidth;
1426 if (j > 0) {
weilia2c06e42016-05-20 17:09:48 -07001427 chartype = FX_CHARTYPE_Combination;
Dan Sinclair1770c022016-03-14 14:14:16 -04001428 wch = wForm;
1429 wLast = (FX_WCHAR)formChars[j - 1].wForm;
1430 }
1431 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
1432 pCharPos->m_GlyphIndex =
tsepezd19e9122016-11-02 15:43:18 -07001433 bCharCode ? wch : pFont->GetGlyphIndex(wForm, false);
thestigec51ac32016-06-20 10:38:52 -07001434#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
Dan Sinclair1770c022016-03-14 14:14:16 -04001435 pCharPos->m_ExtGID = pCharPos->m_GlyphIndex;
thestigec51ac32016-06-20 10:38:52 -07001436#endif
Dan Sinclair1770c022016-03-14 14:14:16 -04001437 pCharPos->m_FontCharWidth = iCharWidth;
1438 if (pWSForms) {
1439 *pWSForms += wForm;
1440 }
1441 }
weili038aa532016-05-20 15:38:29 -07001442 int32_t iCharHeight;
Dan Sinclair1770c022016-03-14 14:14:16 -04001443 if (bVerticalDoc) {
1444 iCharHeight = iCharWidth;
1445 iCharWidth = 1000;
1446 } else {
1447 iCharHeight = 1000;
1448 }
1449 fCharWidth = fFontSize * iCharWidth / 1000.0f;
1450 fCharHeight = fFontSize * iCharHeight / 1000.0f;
weilia2c06e42016-05-20 17:09:48 -07001451 if (bRTLPiece && chartype != FX_CHARTYPE_Combination) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001452 if (bVerticalDoc) {
1453 fY -= fCharHeight;
1454 } else {
1455 fX -= fCharWidth;
1456 }
1457 }
1458 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
1459 pCharPos->m_OriginX = fX;
1460 pCharPos->m_OriginY = fY;
1461 if ((dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0) {
1462 int32_t iFormWidth = iCharWidth;
tsepezd19e9122016-11-02 15:43:18 -07001463 pFont->GetCharWidth(wForm, iFormWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001464 FX_FLOAT fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f;
1465 if (bVerticalDoc) {
1466 pCharPos->m_OriginY += fOffset;
1467 } else {
1468 pCharPos->m_OriginX += fOffset;
1469 }
1470 }
weilia2c06e42016-05-20 17:09:48 -07001471 if (chartype == FX_CHARTYPE_Combination) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001472 CFX_Rect rtBBox;
1473 rtBBox.Reset();
tsepezd19e9122016-11-02 15:43:18 -07001474 if (pFont->GetCharBBox(wForm, rtBBox, false)) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001475 pCharPos->m_OriginY =
1476 fYBase + fFontSize -
1477 fFontSize * (FX_FLOAT)rtBBox.height / (FX_FLOAT)iMaxHeight;
1478 }
1479 if (wForm == wch && wLast != 0xFEFF) {
tsepez736f28a2016-03-25 14:19:51 -07001480 uint32_t dwLastProps = FX_GetUnicodeProperties(wLast);
Dan Sinclair1770c022016-03-14 14:14:16 -04001481 if ((dwLastProps & FX_CHARTYPEBITSMASK) ==
1482 FX_CHARTYPE_Combination) {
weilidb444d22016-06-02 15:48:15 -07001483 CFX_Rect rtBox;
1484 rtBox.Reset();
tsepezd19e9122016-11-02 15:43:18 -07001485 if (pFont->GetCharBBox(wLast, rtBox, false)) {
weilidb444d22016-06-02 15:48:15 -07001486 pCharPos->m_OriginY -= fFontSize * rtBox.height / iMaxHeight;
Dan Sinclair1770c022016-03-14 14:14:16 -04001487 }
1488 }
1489 }
1490 }
1491 CFX_PointF ptOffset;
tsepezd19e9122016-11-02 15:43:18 -07001492 bool bAdjusted = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001493 if (pAdjustPos) {
1494 bAdjusted = pAdjustPos(wForm, bCharCode, pFont, fFontSize,
1495 bVerticalChar, ptOffset);
1496 }
1497 if (!bAdjusted && bVerticalChar && (dwProps & 0x00010000) != 0) {
1498 CFX_Rect rtBBox;
1499 rtBBox.Reset();
tsepezd19e9122016-11-02 15:43:18 -07001500 if (pFont->GetCharBBox(wForm, rtBBox, false)) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001501 ptOffset.x = fFontSize * (850 - rtBBox.right()) / iMaxHeight;
1502 ptOffset.y = fFontSize * (iAscent - rtBBox.top - 150) / iMaxHeight;
1503 }
1504 }
1505 pCharPos->m_OriginX += ptOffset.x;
1506 pCharPos->m_OriginY -= ptOffset.y;
1507 }
weilia2c06e42016-05-20 17:09:48 -07001508 if (!bRTLPiece && chartype != FX_CHARTYPE_Combination) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001509 if (bVerticalDoc) {
1510 fY += fCharHeight;
1511 } else {
1512 fX += fCharWidth;
1513 }
1514 }
1515 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
tsepezd19e9122016-11-02 15:43:18 -07001516 pCharPos->m_bGlyphAdjust = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001517 if (bVerticalDoc) {
1518 if (iCharRotation == 0) {
1519 pCharPos->m_AdjustMatrix[0] = -1;
1520 pCharPos->m_AdjustMatrix[1] = 0;
1521 pCharPos->m_AdjustMatrix[2] = 0;
1522 pCharPos->m_AdjustMatrix[3] = 1;
1523 pCharPos->m_OriginY += fAscent;
1524 } else if (iCharRotation == 1) {
1525 pCharPos->m_AdjustMatrix[0] = 0;
1526 pCharPos->m_AdjustMatrix[1] = -1;
1527 pCharPos->m_AdjustMatrix[2] = -1;
1528 pCharPos->m_AdjustMatrix[3] = 0;
1529 pCharPos->m_OriginX -= fDescent;
1530 } else if (iCharRotation == 2) {
1531 pCharPos->m_AdjustMatrix[0] = 1;
1532 pCharPos->m_AdjustMatrix[1] = 0;
1533 pCharPos->m_AdjustMatrix[2] = 0;
1534 pCharPos->m_AdjustMatrix[3] = -1;
1535 pCharPos->m_OriginX += fCharWidth;
1536 pCharPos->m_OriginY += fAscent;
1537 } else {
1538 pCharPos->m_AdjustMatrix[0] = 0;
1539 pCharPos->m_AdjustMatrix[1] = 1;
1540 pCharPos->m_AdjustMatrix[2] = 1;
1541 pCharPos->m_AdjustMatrix[3] = 0;
1542 pCharPos->m_OriginX += fAscent;
1543 }
1544 } else {
1545 if (iCharRotation == 0) {
1546 pCharPos->m_AdjustMatrix[0] = -1;
1547 pCharPos->m_AdjustMatrix[1] = 0;
1548 pCharPos->m_AdjustMatrix[2] = 0;
1549 pCharPos->m_AdjustMatrix[3] = 1;
1550 } else if (iCharRotation == 1) {
1551 pCharPos->m_AdjustMatrix[0] = 0;
1552 pCharPos->m_AdjustMatrix[1] = -1;
1553 pCharPos->m_AdjustMatrix[2] = -1;
1554 pCharPos->m_AdjustMatrix[3] = 0;
1555 pCharPos->m_OriginX -= fDescent;
1556 pCharPos->m_OriginY -= fAscent + fDescent;
1557 } else if (iCharRotation == 2) {
1558 pCharPos->m_AdjustMatrix[0] = 1;
1559 pCharPos->m_AdjustMatrix[1] = 0;
1560 pCharPos->m_AdjustMatrix[2] = 0;
1561 pCharPos->m_AdjustMatrix[3] = -1;
1562 pCharPos->m_OriginX += fCharWidth;
1563 pCharPos->m_OriginY -= fAscent;
1564 } else {
1565 pCharPos->m_AdjustMatrix[0] = 0;
1566 pCharPos->m_AdjustMatrix[1] = 1;
1567 pCharPos->m_AdjustMatrix[2] = 1;
1568 pCharPos->m_AdjustMatrix[3] = 0;
1569 pCharPos->m_OriginX += fAscent;
1570 }
1571 }
1572 if (iHorScale != 100 || iVerScale != 100) {
1573 pCharPos->m_AdjustMatrix[0] =
1574 pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f;
1575 pCharPos->m_AdjustMatrix[1] =
1576 pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f;
1577 pCharPos->m_AdjustMatrix[2] =
1578 pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f;
1579 pCharPos->m_AdjustMatrix[3] =
1580 pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f;
1581 }
1582 pCharPos++;
1583 }
1584 }
1585 if (iWidth > 0) {
1586 wPrev = (FX_WCHAR)formChars[0].wch;
1587 }
1588 wLast = wch;
1589 }
1590 return iCount;
1591}
weili1b4f6b32016-08-04 16:37:48 -07001592
Dan Sinclair1770c022016-03-14 14:14:16 -04001593int32_t CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun,
1594 CFX_RectFArray& rtArray,
tsepezd19e9122016-11-02 15:43:18 -07001595 bool bCharBBox) const {
dsinclair85d1f2c2016-06-23 12:40:16 -07001596 if (!pTxtRun || pTxtRun->iLength < 1) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001597 return 0;
1598 }
1599 IFX_TxtAccess* pAccess = pTxtRun->pAccess;
dsinclair705f8292016-06-07 10:10:45 -07001600 const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity;
tsepezd4033292016-04-19 12:03:15 -07001601 const FX_WCHAR* pStr = pTxtRun->wsStr.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04001602 int32_t* pWidths = pTxtRun->pWidths;
1603 int32_t iLength = pTxtRun->iLength;
1604 CFX_RectF rect(*pTxtRun->pRect);
tsepezd19e9122016-11-02 15:43:18 -07001605 bool bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001606 FX_FLOAT fFontSize = pTxtRun->fFontSize;
1607 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
1608 FX_FLOAT fScale = fFontSize / 1000.0f;
thestiga4fdfc52016-06-07 17:33:37 -07001609 CFGAS_GEFont* pFont = pTxtRun->pFont;
dsinclair85d1f2c2016-06-23 12:40:16 -07001610 if (!pFont) {
tsepezd19e9122016-11-02 15:43:18 -07001611 bCharBBox = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001612 }
1613 CFX_Rect bbox;
1614 bbox.Set(0, 0, 0, 0);
1615 if (bCharBBox) {
1616 bCharBBox = pFont->GetBBox(bbox);
1617 }
1618 FX_FLOAT fLeft = std::max(0.0f, bbox.left * fScale);
1619 FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale);
1620 rtArray.RemoveAll();
1621 rtArray.SetSize(iLength);
tsepezd19e9122016-11-02 15:43:18 -07001622 bool bVertical = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0;
1623 bool bSingleLine = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
1624 bool bCombText = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001625 FX_WCHAR wch, wLineBreakChar = pTxtRun->wLineBreakChar;
1626 int32_t iCharSize;
1627 FX_FLOAT fCharSize, fStart;
1628 if (bVertical) {
1629 fStart = bRTLPiece ? rect.bottom() : rect.top;
1630 } else {
1631 fStart = bRTLPiece ? rect.right() : rect.left;
1632 }
1633 for (int32_t i = 0; i < iLength; i++) {
dsinclair85d1f2c2016-06-23 12:40:16 -07001634 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001635 wch = pAccess->GetChar(pIdentity, i);
1636 iCharSize = pAccess->GetWidth(pIdentity, i);
1637 } else {
1638 wch = *pStr++;
1639 iCharSize = *pWidths++;
1640 }
1641 fCharSize = (FX_FLOAT)iCharSize / 20000.0f;
tsepezd19e9122016-11-02 15:43:18 -07001642 bool bRet = (!bSingleLine && FX_IsCtrlCode(wch));
Dan Sinclair1770c022016-03-14 14:14:16 -04001643 if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 ||
1644 (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) {
tsepezd19e9122016-11-02 15:43:18 -07001645 bRet = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001646 }
1647 if (bRet) {
1648 iCharSize = iFontSize * 500;
1649 fCharSize = fFontSize / 2.0f;
1650 }
1651 if (bVertical) {
1652 rect.top = fStart;
1653 if (bRTLPiece) {
1654 rect.top -= fCharSize;
1655 fStart -= fCharSize;
1656 } else {
1657 fStart += fCharSize;
1658 }
1659 rect.height = fCharSize;
1660 } else {
1661 rect.left = fStart;
1662 if (bRTLPiece) {
1663 rect.left -= fCharSize;
1664 fStart -= fCharSize;
1665 } else {
1666 fStart += fCharSize;
1667 }
1668 rect.width = fCharSize;
1669 }
1670 if (bCharBBox && !bRet) {
1671 int32_t iCharWidth = 1000;
thestig2c065322016-09-26 14:16:43 -07001672 pFont->GetCharWidth(wch, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001673 FX_FLOAT fRTLeft = 0, fCharWidth = 0;
1674 if (iCharWidth > 0) {
1675 fCharWidth = iCharWidth * fScale;
1676 fRTLeft = fLeft;
1677 if (bCombText) {
1678 fRTLeft = (rect.width - fCharWidth) / 2.0f;
1679 }
1680 }
1681 CFX_RectF rtBBoxF;
1682 if (bVertical) {
1683 rtBBoxF.top = rect.left + fRTLeft;
1684 rtBBoxF.left = rect.top + (rect.height - fHeight) / 2.0f;
1685 rtBBoxF.height = fCharWidth;
1686 rtBBoxF.width = fHeight;
1687 rtBBoxF.left = std::max(rtBBoxF.left, 0.0f);
1688 } else {
1689 rtBBoxF.left = rect.left + fRTLeft;
1690 rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f;
1691 rtBBoxF.width = fCharWidth;
1692 rtBBoxF.height = fHeight;
1693 rtBBoxF.top = std::max(rtBBoxF.top, 0.0f);
1694 }
1695 rtArray.SetAt(i, rtBBoxF);
1696 continue;
1697 }
1698 rtArray.SetAt(i, rect);
1699 }
1700 return iLength;
1701}
weilieec3a362016-06-18 06:25:37 -07001702
1703FX_TXTRUN::FX_TXTRUN()
1704 : pAccess(nullptr),
1705 pIdentity(nullptr),
1706 pWidths(nullptr),
1707 iLength(0),
1708 pFont(nullptr),
1709 fFontSize(12),
1710 dwStyles(0),
1711 iHorizontalScale(100),
1712 iVerticalScale(100),
1713 iCharRotation(0),
1714 dwCharStyles(0),
1715 pRect(nullptr),
1716 wLineBreakChar(L'\n'),
tsepezd19e9122016-11-02 15:43:18 -07001717 bSkipSpace(true) {}
weilieec3a362016-06-18 06:25:37 -07001718
1719FX_TXTRUN::~FX_TXTRUN() {}
1720
1721FX_TXTRUN::FX_TXTRUN(const FX_TXTRUN& other) = default;
1722
1723CFX_TxtPiece::CFX_TxtPiece()
1724 : m_dwStatus(FX_TXTBREAK_PieceBreak),
1725 m_iStartPos(0),
1726 m_iWidth(-1),
1727 m_iStartChar(0),
1728 m_iChars(0),
1729 m_iBidiLevel(0),
1730 m_iBidiPos(0),
1731 m_iHorizontalScale(100),
1732 m_iVerticalScale(100),
1733 m_dwCharStyles(0),
dsinclair85d1f2c2016-06-23 12:40:16 -07001734 m_pChars(nullptr),
1735 m_pUserData(nullptr) {}
weilieec3a362016-06-18 06:25:37 -07001736
1737CFX_TxtLine::CFX_TxtLine(int32_t iBlockSize)
weili1b4f6b32016-08-04 16:37:48 -07001738 : m_pLineChars(new CFX_TxtCharArray),
1739 m_pLinePieces(new CFX_TxtPieceArray(16)),
1740 m_iStart(0),
1741 m_iWidth(0),
1742 m_iArabicChars(0) {}
weilieec3a362016-06-18 06:25:37 -07001743
1744CFX_TxtLine::~CFX_TxtLine() {
1745 RemoveAll();
weilieec3a362016-06-18 06:25:37 -07001746}