blob: 69baa14c6c1b5206accee168bf2f1df03d629dd8 [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),
Dan Sinclair1770c022016-03-14 14:14:16 -040070 m_iCharSpace(0) {
71 m_bPagination = (m_dwPolicies & FX_TXTBREAKPOLICY_Pagination) != 0;
weili1b4f6b32016-08-04 16:37:48 -070072 int32_t iSize = m_bPagination ? sizeof(CFX_Char) : sizeof(CFX_TxtChar);
tsepeza9caab92016-12-14 05:57:10 -080073 m_pTxtLine1 = pdfium::MakeUnique<CFX_TxtLine>(iSize);
74 m_pTxtLine2 = pdfium::MakeUnique<CFX_TxtLine>(iSize);
weili1b4f6b32016-08-04 16:37:48 -070075 m_pCurLine = m_pTxtLine1.get();
Dan Sinclair1770c022016-03-14 14:14:16 -040076 ResetArabicContext();
77}
weili1b4f6b32016-08-04 16:37:48 -070078
Dan Sinclair1770c022016-03-14 14:14:16 -040079CFX_TxtBreak::~CFX_TxtBreak() {
80 Reset();
Dan Sinclair1770c022016-03-14 14:14:16 -040081}
weili1b4f6b32016-08-04 16:37:48 -070082
Dan Sinclair1770c022016-03-14 14:14:16 -040083void CFX_TxtBreak::SetLineWidth(FX_FLOAT fLineWidth) {
84 m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f);
dsinclair43854a52016-04-27 12:26:00 -070085 ASSERT(m_iLineWidth >= 20000);
Dan Sinclair1770c022016-03-14 14:14:16 -040086}
weili1b4f6b32016-08-04 16:37:48 -070087
Dan Sinclair1770c022016-03-14 14:14:16 -040088void CFX_TxtBreak::SetLinePos(FX_FLOAT fLinePos) {
Dan Sinclair17f31182017-03-01 09:31:51 -050089 int32_t iLinePos =
90 std::min(std::max(FXSYS_round(fLinePos * 20000.0f), 0), m_iLineWidth);
Dan Sinclair1770c022016-03-14 14:14:16 -040091 m_pCurLine->m_iStart = iLinePos;
92 m_pCurLine->m_iWidth += iLinePos;
93}
weili1b4f6b32016-08-04 16:37:48 -070094
tsepez736f28a2016-03-25 14:19:51 -070095void CFX_TxtBreak::SetLayoutStyles(uint32_t dwLayoutStyles) {
Dan Sinclair1770c022016-03-14 14:14:16 -040096 m_dwLayoutStyles = dwLayoutStyles;
97 m_bVertical = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0;
98 m_bArabicContext = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ArabicContext) != 0;
99 m_bArabicShapes = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ArabicShapes) != 0;
100 m_bRTL = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_RTLReadingOrder) != 0;
101 m_bSingleLine = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
102 m_bCombText = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
103 ResetArabicContext();
104 m_iLineRotation = GetLineRotation(m_dwLayoutStyles);
105 m_iRotation = m_iLineRotation + m_iCharRotation;
106 m_iRotation %= 4;
107}
weili1b4f6b32016-08-04 16:37:48 -0700108
tsepeze6477992017-01-05 12:57:00 -0800109void CFX_TxtBreak::SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont) {
110 if (!pFont || pFont == m_pFont)
Dan Sinclair1770c022016-03-14 14:14:16 -0400111 return;
tsepeze6477992017-01-05 12:57:00 -0800112
Dan Sinclair1770c022016-03-14 14:14:16 -0400113 SetBreakStatus();
114 m_pFont = pFont;
Dan Sinclair17f31182017-03-01 09:31:51 -0500115 FontChanged();
Dan Sinclair1770c022016-03-14 14:14:16 -0400116}
weili1b4f6b32016-08-04 16:37:48 -0700117
Dan Sinclair1770c022016-03-14 14:14:16 -0400118void CFX_TxtBreak::SetFontSize(FX_FLOAT fFontSize) {
119 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
Dan Sinclair17f31182017-03-01 09:31:51 -0500120 if (m_iFontSize == iFontSize)
Dan Sinclair1770c022016-03-14 14:14:16 -0400121 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500122
Dan Sinclair1770c022016-03-14 14:14:16 -0400123 SetBreakStatus();
124 m_iFontSize = iFontSize;
Dan Sinclair17f31182017-03-01 09:31:51 -0500125 FontChanged();
126}
127
128void CFX_TxtBreak::FontChanged() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400129 m_iDefChar = 0;
Dan Sinclair17f31182017-03-01 09:31:51 -0500130 if (m_wDefChar == 0xFEFF || !m_pFont)
131 return;
132
133 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false);
134 m_iDefChar *= m_iFontSize;
Dan Sinclair1770c022016-03-14 14:14:16 -0400135}
weili1b4f6b32016-08-04 16:37:48 -0700136
tsepezd19e9122016-11-02 15:43:18 -0700137void CFX_TxtBreak::SetTabWidth(FX_FLOAT fTabWidth, bool bEquidistant) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400138 m_iTabWidth = FXSYS_round(fTabWidth * 20000.0f);
Dan Sinclair17f31182017-03-01 09:31:51 -0500139 if (m_iTabWidth < FX_TXTBREAK_MinimumTabWidth)
Dan Sinclair1770c022016-03-14 14:14:16 -0400140 m_iTabWidth = FX_TXTBREAK_MinimumTabWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500141
Dan Sinclair1770c022016-03-14 14:14:16 -0400142 m_bEquidistant = bEquidistant;
143}
weili1b4f6b32016-08-04 16:37:48 -0700144
Dan Sinclair1770c022016-03-14 14:14:16 -0400145void CFX_TxtBreak::SetDefaultChar(FX_WCHAR wch) {
146 m_wDefChar = wch;
147 m_iDefChar = 0;
Dan Sinclair17f31182017-03-01 09:31:51 -0500148 if (m_wDefChar == 0xFEFF || !m_pFont)
149 return;
150
151 m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, false);
152 if (m_iDefChar < 0)
153 m_iDefChar = 0;
154 else
155 m_iDefChar *= m_iFontSize;
Dan Sinclair1770c022016-03-14 14:14:16 -0400156}
weili1b4f6b32016-08-04 16:37:48 -0700157
Dan Sinclair1770c022016-03-14 14:14:16 -0400158void CFX_TxtBreak::SetParagraphBreakChar(FX_WCHAR wch) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500159 if (wch != L'\r' && wch != L'\n')
Dan Sinclair1770c022016-03-14 14:14:16 -0400160 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400161 m_wParagBreakChar = wch;
162}
weili1b4f6b32016-08-04 16:37:48 -0700163
Dan Sinclair1770c022016-03-14 14:14:16 -0400164void CFX_TxtBreak::SetLineBreakTolerance(FX_FLOAT fTolerance) {
165 m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
166}
weili1b4f6b32016-08-04 16:37:48 -0700167
Dan Sinclair1770c022016-03-14 14:14:16 -0400168void CFX_TxtBreak::SetCharRotation(int32_t iCharRotation) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500169 if (iCharRotation < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400170 iCharRotation += (-iCharRotation / 4 + 1) * 4;
Dan Sinclair17f31182017-03-01 09:31:51 -0500171 else if (iCharRotation > 3)
Dan Sinclair1770c022016-03-14 14:14:16 -0400172 iCharRotation -= (iCharRotation / 4) * 4;
Dan Sinclair17f31182017-03-01 09:31:51 -0500173
174 if (m_iCharRotation == iCharRotation)
Dan Sinclair1770c022016-03-14 14:14:16 -0400175 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500176
Dan Sinclair1770c022016-03-14 14:14:16 -0400177 SetBreakStatus();
178 m_iCharRotation = iCharRotation;
179 m_iRotation = m_iLineRotation + m_iCharRotation;
180 m_iRotation %= 4;
181}
weili1b4f6b32016-08-04 16:37:48 -0700182
Dan Sinclair1770c022016-03-14 14:14:16 -0400183void CFX_TxtBreak::SetAlignment(int32_t iAlignment) {
dsinclair43854a52016-04-27 12:26:00 -0700184 ASSERT(iAlignment >= FX_TXTLINEALIGNMENT_Left &&
185 iAlignment <= FX_TXTLINEALIGNMENT_Distributed);
Dan Sinclair1770c022016-03-14 14:14:16 -0400186 m_iAlignment = iAlignment;
187 ResetArabicContext();
188}
weili1b4f6b32016-08-04 16:37:48 -0700189
Dan Sinclair1770c022016-03-14 14:14:16 -0400190void CFX_TxtBreak::ResetContextCharStyles() {
191 m_dwContextCharStyles = m_bArabicContext ? m_iCurAlignment : m_iAlignment;
Dan Sinclair17f31182017-03-01 09:31:51 -0500192 if (m_bArabicNumber)
Dan Sinclair1770c022016-03-14 14:14:16 -0400193 m_dwContextCharStyles |= FX_TXTCHARSTYLE_ArabicNumber;
Dan Sinclair17f31182017-03-01 09:31:51 -0500194 if (m_bArabicComma)
Dan Sinclair1770c022016-03-14 14:14:16 -0400195 m_dwContextCharStyles |= FX_TXTCHARSTYLE_ArabicComma;
Dan Sinclair17f31182017-03-01 09:31:51 -0500196 if ((m_bArabicContext && m_bCurRTL) || (!m_bArabicContext && m_bRTL))
Dan Sinclair1770c022016-03-14 14:14:16 -0400197 m_dwContextCharStyles |= FX_TXTCHARSTYLE_RTLReadingOrder;
Dan Sinclair1770c022016-03-14 14:14:16 -0400198 m_dwContextCharStyles |= (m_iArabicContext << 8);
199}
weili1b4f6b32016-08-04 16:37:48 -0700200
Dan Sinclair1770c022016-03-14 14:14:16 -0400201void CFX_TxtBreak::SetCombWidth(FX_FLOAT fCombWidth) {
202 m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f);
203}
weili1b4f6b32016-08-04 16:37:48 -0700204
Dan Sinclair1770c022016-03-14 14:14:16 -0400205void CFX_TxtBreak::SetUserData(void* pUserData) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500206 if (m_pUserData == pUserData)
Dan Sinclair1770c022016-03-14 14:14:16 -0400207 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500208
Dan Sinclair1770c022016-03-14 14:14:16 -0400209 SetBreakStatus();
210 m_pUserData = pUserData;
211}
weili1b4f6b32016-08-04 16:37:48 -0700212
Dan Sinclair1770c022016-03-14 14:14:16 -0400213void CFX_TxtBreak::SetBreakStatus() {
Dan Sinclair17f31182017-03-01 09:31:51 -0500214 if (m_bPagination)
Dan Sinclair1770c022016-03-14 14:14:16 -0400215 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500216
Dan Sinclair1770c022016-03-14 14:14:16 -0400217 int32_t iCount = m_pCurLine->CountChars();
Dan Sinclair17f31182017-03-01 09:31:51 -0500218 if (iCount < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400219 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500220
tsepez215507d2016-06-09 19:05:47 -0700221 CFX_TxtChar* pTC = m_pCurLine->GetCharPtr(iCount - 1);
Dan Sinclair17f31182017-03-01 09:31:51 -0500222 if (pTC->m_dwStatus == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400223 pTC->m_dwStatus = FX_TXTBREAK_PieceBreak;
Dan Sinclair1770c022016-03-14 14:14:16 -0400224}
weili1b4f6b32016-08-04 16:37:48 -0700225
Dan Sinclair1770c022016-03-14 14:14:16 -0400226void CFX_TxtBreak::SetHorizontalScale(int32_t iScale) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500227 if (iScale < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400228 iScale = 0;
Dan Sinclair17f31182017-03-01 09:31:51 -0500229 if (iScale == m_iHorScale)
Dan Sinclair1770c022016-03-14 14:14:16 -0400230 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500231
Dan Sinclair1770c022016-03-14 14:14:16 -0400232 SetBreakStatus();
233 m_iHorScale = iScale;
234}
weili1b4f6b32016-08-04 16:37:48 -0700235
Dan Sinclair1770c022016-03-14 14:14:16 -0400236void CFX_TxtBreak::SetCharSpace(FX_FLOAT fCharSpace) {
237 m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
238}
weili1b4f6b32016-08-04 16:37:48 -0700239
Dan Sinclair1770c022016-03-14 14:14:16 -0400240static const int32_t gs_FX_TxtLineRotations[8] = {0, 3, 1, 0, 2, 1, 3, 2};
Dan Sinclair17f31182017-03-01 09:31:51 -0500241
tsepez736f28a2016-03-25 14:19:51 -0700242int32_t CFX_TxtBreak::GetLineRotation(uint32_t dwStyles) const {
Dan Sinclair1770c022016-03-14 14:14:16 -0400243 return gs_FX_TxtLineRotations[(dwStyles & 0x0E) >> 1];
244}
weili1b4f6b32016-08-04 16:37:48 -0700245
tsepezd19e9122016-11-02 15:43:18 -0700246CFX_TxtChar* CFX_TxtBreak::GetLastChar(int32_t index, bool bOmitChar) const {
tsepez33316fc2017-01-24 12:17:40 -0800247 std::vector<CFX_TxtChar>& ca = *m_pCurLine->m_pLineChars.get();
248 int32_t iCount = pdfium::CollectionSize<int32_t>(ca);
Dan Sinclair17f31182017-03-01 09:31:51 -0500249 if (index < 0 || index >= iCount)
dsinclair85d1f2c2016-06-23 12:40:16 -0700250 return nullptr;
Dan Sinclair17f31182017-03-01 09:31:51 -0500251
Dan Sinclair1770c022016-03-14 14:14:16 -0400252 int32_t iStart = iCount - 1;
253 while (iStart > -1) {
tsepez33316fc2017-01-24 12:17:40 -0800254 CFX_TxtChar* pTC = &ca[iStart--];
Dan Sinclair17f31182017-03-01 09:31:51 -0500255 if (bOmitChar && pTC->GetCharType() == FX_CHARTYPE_Combination)
Dan Sinclair1770c022016-03-14 14:14:16 -0400256 continue;
Dan Sinclair17f31182017-03-01 09:31:51 -0500257 if (--index < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400258 return pTC;
Dan Sinclair1770c022016-03-14 14:14:16 -0400259 }
dsinclair85d1f2c2016-06-23 12:40:16 -0700260 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400261}
weili1b4f6b32016-08-04 16:37:48 -0700262
Dan Sinclaire3409532017-02-28 14:51:28 -0500263CFX_TxtLine* CFX_TxtBreak::GetTxtLine() const {
dsinclair85d1f2c2016-06-23 12:40:16 -0700264 if (m_iReady == 1)
weili1b4f6b32016-08-04 16:37:48 -0700265 return m_pTxtLine1.get();
dsinclair85d1f2c2016-06-23 12:40:16 -0700266 if (m_iReady == 2)
weili1b4f6b32016-08-04 16:37:48 -0700267 return m_pTxtLine2.get();
dsinclair85d1f2c2016-06-23 12:40:16 -0700268 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400269}
weili1b4f6b32016-08-04 16:37:48 -0700270
Dan Sinclaire3409532017-02-28 14:51:28 -0500271CFX_TxtPieceArray* CFX_TxtBreak::GetTxtPieces() const {
272 CFX_TxtLine* pTxtLine = GetTxtLine();
Dan Sinclair17f31182017-03-01 09:31:51 -0500273 return pTxtLine ? pTxtLine->m_pLinePieces.get() : nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400274}
weili1b4f6b32016-08-04 16:37:48 -0700275
weilia2c06e42016-05-20 17:09:48 -0700276inline FX_CHARTYPE CFX_TxtBreak::GetUnifiedCharType(
277 FX_CHARTYPE chartype) const {
278 return chartype >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : chartype;
Dan Sinclair1770c022016-03-14 14:14:16 -0400279}
weili1b4f6b32016-08-04 16:37:48 -0700280
Dan Sinclair1770c022016-03-14 14:14:16 -0400281void CFX_TxtBreak::ResetArabicContext() {
282 if (m_bArabicContext) {
283 m_bCurRTL = m_iCurArabicContext > 1;
284 m_iCurAlignment = m_iCurArabicContext > 1 ? FX_TXTLINEALIGNMENT_Right
285 : FX_TXTLINEALIGNMENT_Left;
286 m_iCurAlignment |= (m_iAlignment & FX_TXTLINEALIGNMENT_HigherMask);
287 m_bArabicNumber = m_iArabicContext >= 1 && m_bArabicShapes;
288 } else {
289 if (m_bPagination) {
tsepezd19e9122016-11-02 15:43:18 -0700290 m_bCurRTL = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400291 m_iCurAlignment = 0;
292 } else {
293 m_bCurRTL = m_bRTL;
294 m_iCurAlignment = m_iAlignment;
295 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500296 if (m_bRTL)
Dan Sinclair1770c022016-03-14 14:14:16 -0400297 m_bArabicNumber = m_iArabicContext >= 1;
Dan Sinclair17f31182017-03-01 09:31:51 -0500298 else
Dan Sinclair1770c022016-03-14 14:14:16 -0400299 m_bArabicNumber = m_iArabicContext > 1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400300 m_bArabicNumber = m_bArabicNumber && m_bArabicShapes;
301 }
302 m_bArabicComma = m_bArabicNumber;
303 ResetContextCharStyles();
304}
weili1b4f6b32016-08-04 16:37:48 -0700305
tsepez215507d2016-06-09 19:05:47 -0700306void CFX_TxtBreak::AppendChar_PageLoad(CFX_TxtChar* pCurChar,
307 uint32_t dwProps) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400308 if (!m_bPagination) {
tsepez215507d2016-06-09 19:05:47 -0700309 pCurChar->m_dwStatus = 0;
310 pCurChar->m_pUserData = m_pUserData;
Dan Sinclair1770c022016-03-14 14:14:16 -0400311 }
312 if (m_bArabicContext || m_bArabicShapes) {
313 int32_t iBidiCls = (dwProps & FX_BIDICLASSBITSMASK) >> FX_BIDICLASSBITS;
314 int32_t iArabicContext =
315 (iBidiCls == FX_BIDICLASS_R || iBidiCls == FX_BIDICLASS_AL)
316 ? 2
317 : ((iBidiCls == FX_BIDICLASS_L || iBidiCls == FX_BIDICLASS_S) ? 0
318 : 1);
319 if (iArabicContext != m_iArabicContext && iArabicContext != 1) {
320 m_iArabicContext = iArabicContext;
Dan Sinclair17f31182017-03-01 09:31:51 -0500321 if (m_iCurArabicContext == 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400322 m_iCurArabicContext = iArabicContext;
Dan Sinclair17f31182017-03-01 09:31:51 -0500323
Dan Sinclair1770c022016-03-14 14:14:16 -0400324 ResetArabicContext();
325 if (!m_bPagination) {
tsepezd19e9122016-11-02 15:43:18 -0700326 CFX_TxtChar* pLastChar = GetLastChar(1, false);
Dan Sinclair17f31182017-03-01 09:31:51 -0500327 if (pLastChar && pLastChar->m_dwStatus < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400328 pLastChar->m_dwStatus = FX_TXTBREAK_PieceBreak;
Dan Sinclair1770c022016-03-14 14:14:16 -0400329 }
330 }
331 }
332 pCurChar->m_dwCharStyles = m_dwContextCharStyles;
333}
weili1b4f6b32016-08-04 16:37:48 -0700334
tsepez215507d2016-06-09 19:05:47 -0700335uint32_t CFX_TxtBreak::AppendChar_Combination(CFX_TxtChar* pCurChar,
Dan Sinclair1770c022016-03-14 14:14:16 -0400336 int32_t iRotation) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400337 FX_WCHAR wch = pCurChar->m_wCharCode;
338 FX_WCHAR wForm;
339 int32_t iCharWidth = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400340 pCurChar->m_iCharWidth = -1;
341 if (m_bCombText) {
342 iCharWidth = m_iCombWidth;
343 } else {
344 if (m_bVertical != FX_IsOdd(iRotation)) {
345 iCharWidth = 1000;
346 } else {
347 wForm = wch;
348 if (!m_bPagination) {
tsepezd19e9122016-11-02 15:43:18 -0700349 CFX_TxtChar* pLastChar = GetLastChar(0, false);
tsepez215507d2016-06-09 19:05:47 -0700350 if (pLastChar &&
351 (pLastChar->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicShadda) == 0) {
tsepezd19e9122016-11-02 15:43:18 -0700352 bool bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400353 if (wch == 0x0651) {
354 FX_WCHAR wLast = pLastChar->m_wCharCode;
355 if (wLast >= 0x064C && wLast <= 0x0650) {
356 wForm = FX_GetArabicFromShaddaTable(wLast);
tsepezd19e9122016-11-02 15:43:18 -0700357 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400358 }
359 } else if (wch >= 0x064C && wch <= 0x0650) {
360 if (pLastChar->m_wCharCode == 0x0651) {
361 wForm = FX_GetArabicFromShaddaTable(wch);
tsepezd19e9122016-11-02 15:43:18 -0700362 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400363 }
364 }
365 if (bShadda) {
tsepez215507d2016-06-09 19:05:47 -0700366 pLastChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
367 pLastChar->m_iCharWidth = 0;
368 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
Dan Sinclair1770c022016-03-14 14:14:16 -0400369 }
370 }
371 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500372 if (!m_pFont->GetCharWidth(wForm, iCharWidth, false))
Dan Sinclair1770c022016-03-14 14:14:16 -0400373 iCharWidth = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400374 }
375 iCharWidth *= m_iFontSize;
376 iCharWidth = iCharWidth * m_iHorScale / 100;
377 }
378 pCurChar->m_iCharWidth = -iCharWidth;
379 return FX_TXTBREAK_None;
380}
weili1b4f6b32016-08-04 16:37:48 -0700381
tsepez215507d2016-06-09 19:05:47 -0700382uint32_t CFX_TxtBreak::AppendChar_Tab(CFX_TxtChar* pCurChar,
383 int32_t iRotation) {
weilia2c06e42016-05-20 17:09:48 -0700384 m_eCharType = FX_CHARTYPE_Tab;
Dan Sinclair17f31182017-03-01 09:31:51 -0500385 if ((m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ExpandTab) == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400386 return FX_TXTBREAK_None;
Dan Sinclair17f31182017-03-01 09:31:51 -0500387
Dan Sinclair1770c022016-03-14 14:14:16 -0400388 int32_t& iLineWidth = m_pCurLine->m_iWidth;
389 int32_t iCharWidth;
390 if (m_bCombText) {
391 iCharWidth = m_iCombWidth;
392 } else {
393 if (m_bEquidistant) {
394 iCharWidth = iLineWidth;
395 iCharWidth = m_iTabWidth * (iCharWidth / m_iTabWidth + 1) - iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500396 if (iCharWidth < FX_TXTBREAK_MinimumTabWidth)
Dan Sinclair1770c022016-03-14 14:14:16 -0400397 iCharWidth += m_iTabWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -0400398 } else {
399 iCharWidth = m_iTabWidth;
400 }
401 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500402
Dan Sinclair1770c022016-03-14 14:14:16 -0400403 pCurChar->m_iCharWidth = iCharWidth;
404 iLineWidth += iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500405 if (!m_bSingleLine && iLineWidth >= m_iLineWidth + m_iTolerance)
Dan Sinclair1770c022016-03-14 14:14:16 -0400406 return EndBreak(FX_TXTBREAK_LineBreak);
Dan Sinclair17f31182017-03-01 09:31:51 -0500407
Dan Sinclair1770c022016-03-14 14:14:16 -0400408 return FX_TXTBREAK_None;
409}
weili1b4f6b32016-08-04 16:37:48 -0700410
tsepez215507d2016-06-09 19:05:47 -0700411uint32_t CFX_TxtBreak::AppendChar_Control(CFX_TxtChar* pCurChar,
Dan Sinclair1770c022016-03-14 14:14:16 -0400412 int32_t iRotation) {
weilia2c06e42016-05-20 17:09:48 -0700413 m_eCharType = FX_CHARTYPE_Control;
tsepez736f28a2016-03-25 14:19:51 -0700414 uint32_t dwRet = FX_TXTBREAK_None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400415 if (!m_bSingleLine) {
416 FX_WCHAR wch = pCurChar->m_wCharCode;
417 switch (wch) {
418 case L'\v':
419 case 0x2028:
420 dwRet = FX_TXTBREAK_LineBreak;
421 break;
422 case L'\f':
423 dwRet = FX_TXTBREAK_PageBreak;
424 break;
425 case 0x2029:
426 dwRet = FX_TXTBREAK_ParagraphBreak;
427 break;
428 default:
Dan Sinclair17f31182017-03-01 09:31:51 -0500429 if (wch == m_wParagBreakChar)
Dan Sinclair1770c022016-03-14 14:14:16 -0400430 dwRet = FX_TXTBREAK_ParagraphBreak;
Dan Sinclair1770c022016-03-14 14:14:16 -0400431 break;
432 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500433 if (dwRet != FX_TXTBREAK_None)
Dan Sinclair1770c022016-03-14 14:14:16 -0400434 dwRet = EndBreak(dwRet);
Dan Sinclair1770c022016-03-14 14:14:16 -0400435 }
436 return dwRet;
437}
weili1b4f6b32016-08-04 16:37:48 -0700438
tsepez215507d2016-06-09 19:05:47 -0700439uint32_t CFX_TxtBreak::AppendChar_Arabic(CFX_TxtChar* pCurChar,
Dan Sinclair1770c022016-03-14 14:14:16 -0400440 int32_t iRotation) {
weilia2c06e42016-05-20 17:09:48 -0700441 FX_CHARTYPE chartype = pCurChar->GetCharType();
Dan Sinclair1770c022016-03-14 14:14:16 -0400442 int32_t& iLineWidth = m_pCurLine->m_iWidth;
443 FX_WCHAR wForm;
444 int32_t iCharWidth = 0;
Dan Sinclairfb906e32017-02-28 10:20:12 -0500445 CFX_TxtChar* pLastChar = nullptr;
tsepezd19e9122016-11-02 15:43:18 -0700446 bool bAlef = false;
weilia2c06e42016-05-20 17:09:48 -0700447 if (!m_bCombText && m_eCharType >= FX_CHARTYPE_ArabicAlef &&
448 m_eCharType <= FX_CHARTYPE_ArabicDistortion) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400449 pLastChar = GetLastChar(1);
dsinclair85d1f2c2016-06-23 12:40:16 -0700450 if (pLastChar) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400451 iCharWidth = pLastChar->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500452 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400453 iLineWidth -= iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500454
Dan Sinclair1770c022016-03-14 14:14:16 -0400455 CFX_Char* pPrevChar = GetLastChar(2);
tsepeze00f75c2016-05-06 13:15:46 -0700456 wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar);
Dan Sinclair1770c022016-03-14 14:14:16 -0400457 bAlef = (wForm == 0xFEFF &&
458 pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef);
459 int32_t iLastRotation = pLastChar->m_nRotation + m_iLineRotation;
Dan Sinclair17f31182017-03-01 09:31:51 -0500460 if (m_bVertical && (pLastChar->m_dwCharProps & 0x8000) != 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400461 iLastRotation++;
Dan Sinclair17f31182017-03-01 09:31:51 -0500462 if (m_bVertical != FX_IsOdd(iLastRotation))
Dan Sinclair1770c022016-03-14 14:14:16 -0400463 iCharWidth = 1000;
Dan Sinclair17f31182017-03-01 09:31:51 -0500464 else
tsepezd19e9122016-11-02 15:43:18 -0700465 m_pFont->GetCharWidth(wForm, iCharWidth, false);
Dan Sinclair17f31182017-03-01 09:31:51 -0500466
467 if (wForm == 0xFEFF)
Dan Sinclair1770c022016-03-14 14:14:16 -0400468 iCharWidth = m_iDefChar;
Dan Sinclair17f31182017-03-01 09:31:51 -0500469
Dan Sinclair1770c022016-03-14 14:14:16 -0400470 iCharWidth *= m_iFontSize;
471 iCharWidth = iCharWidth * m_iHorScale / 100;
472 pLastChar->m_iCharWidth = iCharWidth;
473 iLineWidth += iCharWidth;
474 iCharWidth = 0;
475 }
476 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500477
weilia2c06e42016-05-20 17:09:48 -0700478 m_eCharType = chartype;
dsinclair85d1f2c2016-06-23 12:40:16 -0700479 wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar,
480 nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400481 if (m_bCombText) {
482 iCharWidth = m_iCombWidth;
483 } else {
Dan Sinclair17f31182017-03-01 09:31:51 -0500484 if (m_bVertical != FX_IsOdd(iRotation))
Dan Sinclair1770c022016-03-14 14:14:16 -0400485 iCharWidth = 1000;
Dan Sinclair17f31182017-03-01 09:31:51 -0500486 else
tsepezd19e9122016-11-02 15:43:18 -0700487 m_pFont->GetCharWidth(wForm, iCharWidth, false);
Dan Sinclair17f31182017-03-01 09:31:51 -0500488
489 if (wForm == 0xFEFF)
Dan Sinclair1770c022016-03-14 14:14:16 -0400490 iCharWidth = m_iDefChar;
Dan Sinclair17f31182017-03-01 09:31:51 -0500491
Dan Sinclair1770c022016-03-14 14:14:16 -0400492 iCharWidth *= m_iFontSize;
493 iCharWidth = iCharWidth * m_iHorScale / 100;
494 }
495 pCurChar->m_iCharWidth = iCharWidth;
496 iLineWidth += iCharWidth;
497 m_pCurLine->m_iArabicChars++;
Dan Sinclair17f31182017-03-01 09:31:51 -0500498 if (!m_bSingleLine && iLineWidth > m_iLineWidth + m_iTolerance)
Dan Sinclair1770c022016-03-14 14:14:16 -0400499 return EndBreak(FX_TXTBREAK_LineBreak);
Dan Sinclair1770c022016-03-14 14:14:16 -0400500 return FX_TXTBREAK_None;
501}
weili1b4f6b32016-08-04 16:37:48 -0700502
tsepez215507d2016-06-09 19:05:47 -0700503uint32_t CFX_TxtBreak::AppendChar_Others(CFX_TxtChar* pCurChar,
Dan Sinclair1770c022016-03-14 14:14:16 -0400504 int32_t iRotation) {
tsepez736f28a2016-03-25 14:19:51 -0700505 uint32_t dwProps = pCurChar->m_dwCharProps;
weilia2c06e42016-05-20 17:09:48 -0700506 FX_CHARTYPE chartype = pCurChar->GetCharType();
Dan Sinclair1770c022016-03-14 14:14:16 -0400507 int32_t& iLineWidth = m_pCurLine->m_iWidth;
508 int32_t iCharWidth = 0;
weilia2c06e42016-05-20 17:09:48 -0700509 m_eCharType = chartype;
Dan Sinclair1770c022016-03-14 14:14:16 -0400510 FX_WCHAR wch = pCurChar->m_wCharCode;
511 FX_WCHAR wForm = wch;
weilia2c06e42016-05-20 17:09:48 -0700512 if (chartype == FX_CHARTYPE_Numeric) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400513 if (m_bArabicNumber) {
514 wForm = wch + 0x0630;
515 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicIndic;
516 }
517 } else if (wch == L',') {
518 if (m_bArabicShapes && m_iCurArabicContext > 0) {
519 wForm = 0x060C;
520 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicComma;
521 }
522 } else if (m_bCurRTL || m_bVertical) {
523 wForm = FX_GetMirrorChar(wch, dwProps, m_bCurRTL, m_bVertical);
524 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500525
Dan Sinclair1770c022016-03-14 14:14:16 -0400526 if (m_bCombText) {
527 iCharWidth = m_iCombWidth;
528 } else {
Dan Sinclair17f31182017-03-01 09:31:51 -0500529 if (m_bVertical != FX_IsOdd(iRotation))
Dan Sinclair1770c022016-03-14 14:14:16 -0400530 iCharWidth = 1000;
Dan Sinclair17f31182017-03-01 09:31:51 -0500531 else if (!m_pFont->GetCharWidth(wForm, iCharWidth, false))
Dan Sinclair1770c022016-03-14 14:14:16 -0400532 iCharWidth = m_iDefChar;
Dan Sinclair17f31182017-03-01 09:31:51 -0500533
Dan Sinclair1770c022016-03-14 14:14:16 -0400534 iCharWidth *= m_iFontSize;
535 iCharWidth = iCharWidth * m_iHorScale / 100;
536 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500537
Dan Sinclair1770c022016-03-14 14:14:16 -0400538 iCharWidth += m_iCharSpace;
539 pCurChar->m_iCharWidth = iCharWidth;
540 iLineWidth += iCharWidth;
tsepezd19e9122016-11-02 15:43:18 -0700541 bool bBreak = (chartype != FX_CHARTYPE_Space ||
542 (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0);
Dan Sinclair17f31182017-03-01 09:31:51 -0500543 if (!m_bSingleLine && bBreak && iLineWidth > m_iLineWidth + m_iTolerance)
Dan Sinclair1770c022016-03-14 14:14:16 -0400544 return EndBreak(FX_TXTBREAK_LineBreak);
Dan Sinclair17f31182017-03-01 09:31:51 -0500545
Dan Sinclair1770c022016-03-14 14:14:16 -0400546 return FX_TXTBREAK_None;
547}
tsepez215507d2016-06-09 19:05:47 -0700548
tsepez736f28a2016-03-25 14:19:51 -0700549uint32_t CFX_TxtBreak::AppendChar(FX_WCHAR wch) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500550 uint32_t dwProps = kTextLayoutCodeProperties[static_cast<uint16_t>(wch)];
weilia2c06e42016-05-20 17:09:48 -0700551 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
tsepez33316fc2017-01-24 12:17:40 -0800552 m_pCurLine->m_pLineChars->emplace_back();
Dan Sinclair17f31182017-03-01 09:31:51 -0500553
tsepez33316fc2017-01-24 12:17:40 -0800554 CFX_TxtChar* pCurChar = &m_pCurLine->m_pLineChars->back();
Dan Sinclair17f31182017-03-01 09:31:51 -0500555 pCurChar->m_wCharCode = static_cast<uint16_t>(wch);
Dan Sinclair1770c022016-03-14 14:14:16 -0400556 pCurChar->m_nRotation = m_iCharRotation;
557 pCurChar->m_dwCharProps = dwProps;
558 pCurChar->m_dwCharStyles = 0;
559 pCurChar->m_iCharWidth = 0;
560 pCurChar->m_iHorizontalScale = m_iHorScale;
Dan Sinclair70719432017-02-28 14:48:51 -0500561 pCurChar->m_iVerticalScale = 100;
Dan Sinclair1770c022016-03-14 14:14:16 -0400562 pCurChar->m_dwStatus = 0;
563 pCurChar->m_iBidiClass = 0;
564 pCurChar->m_iBidiLevel = 0;
565 pCurChar->m_iBidiPos = 0;
566 pCurChar->m_iBidiOrder = 0;
dsinclair85d1f2c2016-06-23 12:40:16 -0700567 pCurChar->m_pUserData = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400568 AppendChar_PageLoad(pCurChar, dwProps);
tsepez736f28a2016-03-25 14:19:51 -0700569 uint32_t dwRet1 = FX_TXTBREAK_None;
weilia2c06e42016-05-20 17:09:48 -0700570 if (chartype != FX_CHARTYPE_Combination &&
Dan Sinclair17f31182017-03-01 09:31:51 -0500571 GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) &&
572 m_eCharType != FX_CHARTYPE_Unknown &&
573 m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine &&
574 (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) {
575 dwRet1 = EndBreak(FX_TXTBREAK_LineBreak);
576 int32_t iCount = m_pCurLine->CountChars();
577 if (iCount > 0)
578 pCurChar = &(*m_pCurLine->m_pLineChars)[iCount - 1];
Dan Sinclair1770c022016-03-14 14:14:16 -0400579 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500580
Dan Sinclair1770c022016-03-14 14:14:16 -0400581 int32_t iRotation = m_iRotation;
Dan Sinclair17f31182017-03-01 09:31:51 -0500582 if (m_bVertical && (dwProps & 0x8000) != 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400583 iRotation = (iRotation + 1) % 4;
Dan Sinclair17f31182017-03-01 09:31:51 -0500584
tsepez736f28a2016-03-25 14:19:51 -0700585 uint32_t dwRet2 =
weilia2c06e42016-05-20 17:09:48 -0700586 (this->*g_FX_TxtBreak_lpfAppendChar[chartype >> FX_CHARTYPEBITS])(
Dan Sinclair1770c022016-03-14 14:14:16 -0400587 pCurChar, iRotation);
588 return std::max(dwRet1, dwRet2);
589}
weili1b4f6b32016-08-04 16:37:48 -0700590
Dan Sinclair1770c022016-03-14 14:14:16 -0400591void CFX_TxtBreak::EndBreak_UpdateArabicShapes() {
dsinclair43854a52016-04-27 12:26:00 -0700592 ASSERT(m_bArabicShapes);
Dan Sinclair1770c022016-03-14 14:14:16 -0400593 int32_t iCount = m_pCurLine->CountChars();
Dan Sinclair17f31182017-03-01 09:31:51 -0500594 if (iCount < 2)
Dan Sinclair1770c022016-03-14 14:14:16 -0400595 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500596
Dan Sinclair1770c022016-03-14 14:14:16 -0400597 int32_t& iLineWidth = m_pCurLine->m_iWidth;
Dan Sinclairfb906e32017-02-28 10:20:12 -0500598 CFX_TxtChar* pCur = m_pCurLine->GetCharPtr(0);
tsepezd19e9122016-11-02 15:43:18 -0700599 bool bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400600 pCur = m_pCurLine->GetCharPtr(1);
601 FX_WCHAR wch, wForm;
tsepezd19e9122016-11-02 15:43:18 -0700602 bool bNextNum;
thestig2c065322016-09-26 14:16:43 -0700603 int32_t i = 1;
604 int32_t iCharWidth;
605 int32_t iRotation;
Dan Sinclairfb906e32017-02-28 10:20:12 -0500606 CFX_TxtChar* pNext;
Dan Sinclair1770c022016-03-14 14:14:16 -0400607 do {
608 i++;
609 if (i < iCount) {
610 pNext = m_pCurLine->GetCharPtr(i);
611 bNextNum = (pNext->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
612 } else {
dsinclair85d1f2c2016-06-23 12:40:16 -0700613 pNext = nullptr;
tsepezd19e9122016-11-02 15:43:18 -0700614 bNextNum = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400615 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500616
Dan Sinclair1770c022016-03-14 14:14:16 -0400617 wch = pCur->m_wCharCode;
618 if (wch == L'.') {
619 if (bPrevNum && bNextNum) {
620 iRotation = m_iRotation;
Dan Sinclair17f31182017-03-01 09:31:51 -0500621 if (m_bVertical && (pCur->m_dwCharProps & 0x8000) != 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400622 iRotation = ((iRotation + 1) & 0x03);
Dan Sinclair17f31182017-03-01 09:31:51 -0500623
Dan Sinclair1770c022016-03-14 14:14:16 -0400624 wForm = wch == L'.' ? 0x066B : 0x066C;
625 iLineWidth -= pCur->m_iCharWidth;
626 if (m_bCombText) {
627 iCharWidth = m_iCombWidth;
628 } else {
Dan Sinclair17f31182017-03-01 09:31:51 -0500629 if (m_bVertical != FX_IsOdd(iRotation))
Dan Sinclair1770c022016-03-14 14:14:16 -0400630 iCharWidth = 1000;
Dan Sinclair17f31182017-03-01 09:31:51 -0500631 else if (!m_pFont->GetCharWidth(wForm, iCharWidth, false))
Dan Sinclair1770c022016-03-14 14:14:16 -0400632 iCharWidth = m_iDefChar;
Dan Sinclair17f31182017-03-01 09:31:51 -0500633
Dan Sinclair1770c022016-03-14 14:14:16 -0400634 iCharWidth *= m_iFontSize;
635 iCharWidth = iCharWidth * m_iHorScale / 100;
636 }
637 pCur->m_iCharWidth = iCharWidth;
638 iLineWidth += iCharWidth;
639 }
640 }
641 bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
642 pCur = pNext;
643 } while (i < iCount);
644}
weili1b4f6b32016-08-04 16:37:48 -0700645
tsepezd19e9122016-11-02 15:43:18 -0700646bool CFX_TxtBreak::EndBreak_SplitLine(CFX_TxtLine* pNextLine,
647 bool bAllChars,
648 uint32_t dwStatus) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400649 int32_t iCount = m_pCurLine->CountChars();
tsepezd19e9122016-11-02 15:43:18 -0700650 bool bDone = false;
Dan Sinclairfb906e32017-02-28 10:20:12 -0500651 CFX_TxtChar* pTC;
Dan Sinclair1770c022016-03-14 14:14:16 -0400652 if (!m_bSingleLine && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance) {
653 pTC = m_pCurLine->GetCharPtr(iCount - 1);
654 switch (pTC->GetCharType()) {
655 case FX_CHARTYPE_Tab:
656 case FX_CHARTYPE_Control:
657 break;
658 case FX_CHARTYPE_Space:
659 if ((m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0) {
660 SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
tsepezd19e9122016-11-02 15:43:18 -0700661 bDone = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400662 }
663 break;
664 default:
665 SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
tsepezd19e9122016-11-02 15:43:18 -0700666 bDone = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400667 break;
668 }
669 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500670
Dan Sinclair1770c022016-03-14 14:14:16 -0400671 iCount = m_pCurLine->CountChars();
weili1b4f6b32016-08-04 16:37:48 -0700672 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400673 CFX_TxtPiece tp;
674 if (m_bPagination) {
675 tp.m_dwStatus = dwStatus;
676 tp.m_iStartPos = m_pCurLine->m_iStart;
677 tp.m_iWidth = m_pCurLine->m_iWidth;
678 tp.m_iStartChar = 0;
679 tp.m_iChars = iCount;
weili1b4f6b32016-08-04 16:37:48 -0700680 tp.m_pChars = m_pCurLine->m_pLineChars.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400681 tp.m_pUserData = m_pUserData;
682 pTC = m_pCurLine->GetCharPtr(0);
683 tp.m_dwCharStyles = pTC->m_dwCharStyles;
684 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
Dan Sinclair70719432017-02-28 14:48:51 -0500685 tp.m_iVerticalScale = pTC->m_iVerticalScale;
Dan Sinclair1770c022016-03-14 14:14:16 -0400686 pCurPieces->Add(tp);
687 m_pCurLine = pNextLine;
weilia2c06e42016-05-20 17:09:48 -0700688 m_eCharType = FX_CHARTYPE_Unknown;
tsepezd19e9122016-11-02 15:43:18 -0700689 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400690 }
691 if (bAllChars && !bDone) {
692 int32_t iEndPos = m_pCurLine->m_iWidth;
tsepezd19e9122016-11-02 15:43:18 -0700693 GetBreakPos(*m_pCurLine->m_pLineChars.get(), iEndPos, bAllChars, true);
Dan Sinclair1770c022016-03-14 14:14:16 -0400694 }
tsepezd19e9122016-11-02 15:43:18 -0700695 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400696}
weili1b4f6b32016-08-04 16:37:48 -0700697
tsepez736f28a2016-03-25 14:19:51 -0700698void CFX_TxtBreak::EndBreak_BidiLine(CFX_TPOArray& tpos, uint32_t dwStatus) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400699 CFX_TxtPiece tp;
700 FX_TPO tpo;
701 CFX_TxtChar* pTC;
Dan Sinclair17f31182017-03-01 09:31:51 -0500702 int32_t i;
703 int32_t j;
tsepez33316fc2017-01-24 12:17:40 -0800704 std::vector<CFX_TxtChar>& chars = *m_pCurLine->m_pLineChars.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400705 int32_t iCount = m_pCurLine->CountChars();
tsepezd19e9122016-11-02 15:43:18 -0700706 bool bDone = (m_pCurLine->m_iArabicChars > 0 || m_bCurRTL);
Dan Sinclair1770c022016-03-14 14:14:16 -0400707 if (!m_bPagination && bDone) {
708 int32_t iBidiNum = 0;
709 for (i = 0; i < iCount; i++) {
tsepez33316fc2017-01-24 12:17:40 -0800710 pTC = &chars[i];
Dan Sinclair1770c022016-03-14 14:14:16 -0400711 pTC->m_iBidiPos = i;
Dan Sinclair17f31182017-03-01 09:31:51 -0500712 if (pTC->GetCharType() != FX_CHARTYPE_Control)
Dan Sinclair1770c022016-03-14 14:14:16 -0400713 iBidiNum = i;
Dan Sinclair17f31182017-03-01 09:31:51 -0500714 if (i == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400715 pTC->m_iBidiLevel = 1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400716 }
717 FX_BidiLine(chars, iBidiNum + 1, m_bCurRTL ? 1 : 0);
718 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500719
weili1b4f6b32016-08-04 16:37:48 -0700720 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400721 if (!m_bPagination &&
722 (bDone || (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_MutipleFormat) != 0)) {
723 tp.m_dwStatus = FX_TXTBREAK_PieceBreak;
724 tp.m_iStartPos = m_pCurLine->m_iStart;
weili1b4f6b32016-08-04 16:37:48 -0700725 tp.m_pChars = m_pCurLine->m_pLineChars.get();
Dan Sinclair17f31182017-03-01 09:31:51 -0500726 int32_t iBidiLevel = -1;
727 int32_t iCharWidth;
728 i = 0;
729 j = -1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400730 while (i < iCount) {
tsepez33316fc2017-01-24 12:17:40 -0800731 pTC = &chars[i];
Dan Sinclair1770c022016-03-14 14:14:16 -0400732 if (iBidiLevel < 0) {
733 iBidiLevel = pTC->m_iBidiLevel;
734 tp.m_iWidth = 0;
735 tp.m_iBidiLevel = iBidiLevel;
736 tp.m_iBidiPos = pTC->m_iBidiOrder;
737 tp.m_dwCharStyles = pTC->m_dwCharStyles;
738 tp.m_pUserData = pTC->m_pUserData;
739 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
Dan Sinclair70719432017-02-28 14:48:51 -0500740 tp.m_iVerticalScale = pTC->m_iVerticalScale;
Dan Sinclair1770c022016-03-14 14:14:16 -0400741 tp.m_dwStatus = FX_TXTBREAK_PieceBreak;
742 }
743 if (iBidiLevel != pTC->m_iBidiLevel || pTC->m_dwStatus != 0) {
744 if (iBidiLevel == pTC->m_iBidiLevel) {
745 tp.m_dwStatus = pTC->m_dwStatus;
746 iCharWidth = pTC->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500747 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400748 tp.m_iWidth += iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500749
Dan Sinclair1770c022016-03-14 14:14:16 -0400750 i++;
751 }
752 tp.m_iChars = i - tp.m_iStartChar;
753 pCurPieces->Add(tp);
754 tp.m_iStartPos += tp.m_iWidth;
755 tp.m_iStartChar = i;
756 tpo.index = ++j;
757 tpo.pos = tp.m_iBidiPos;
758 tpos.Add(tpo);
759 iBidiLevel = -1;
760 } else {
761 iCharWidth = pTC->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500762 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400763 tp.m_iWidth += iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500764
Dan Sinclair1770c022016-03-14 14:14:16 -0400765 i++;
766 }
767 }
768 if (i > tp.m_iStartChar) {
769 tp.m_dwStatus = dwStatus;
770 tp.m_iChars = i - tp.m_iStartChar;
771 pCurPieces->Add(tp);
772 tpo.index = ++j;
773 tpo.pos = tp.m_iBidiPos;
774 tpos.Add(tpo);
775 }
776 if (j > -1) {
777 if (j > 0) {
778 FX_TEXTLAYOUT_PieceSort(tpos, 0, j);
779 int32_t iStartPos = 0;
780 for (i = 0; i <= j; i++) {
781 tpo = tpos.GetAt(i);
782 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
783 ttp.m_iStartPos = iStartPos;
784 iStartPos += ttp.m_iWidth;
785 }
786 }
787 CFX_TxtPiece& ttp = pCurPieces->GetAt(j);
788 ttp.m_dwStatus = dwStatus;
789 }
790 } else {
791 tp.m_dwStatus = dwStatus;
792 tp.m_iStartPos = m_pCurLine->m_iStart;
793 tp.m_iWidth = m_pCurLine->m_iWidth;
794 tp.m_iStartChar = 0;
795 tp.m_iChars = iCount;
weili1b4f6b32016-08-04 16:37:48 -0700796 tp.m_pChars = m_pCurLine->m_pLineChars.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400797 tp.m_pUserData = m_pUserData;
tsepez33316fc2017-01-24 12:17:40 -0800798 pTC = &chars[0];
Dan Sinclair1770c022016-03-14 14:14:16 -0400799 tp.m_dwCharStyles = pTC->m_dwCharStyles;
800 tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
Dan Sinclair70719432017-02-28 14:48:51 -0500801 tp.m_iVerticalScale = pTC->m_iVerticalScale;
Dan Sinclair1770c022016-03-14 14:14:16 -0400802 pCurPieces->Add(tp);
803 tpo.index = 0;
804 tpo.pos = 0;
805 tpos.Add(tpo);
806 }
807}
weili1b4f6b32016-08-04 16:37:48 -0700808
Dan Sinclair1770c022016-03-14 14:14:16 -0400809void CFX_TxtBreak::EndBreak_Alignment(CFX_TPOArray& tpos,
tsepezd19e9122016-11-02 15:43:18 -0700810 bool bAllChars,
tsepez736f28a2016-03-25 14:19:51 -0700811 uint32_t dwStatus) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500812 int32_t iNetWidth = m_pCurLine->m_iWidth;
813 int32_t iGapChars = 0;
814 int32_t iCharWidth;
weili1b4f6b32016-08-04 16:37:48 -0700815 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces.get();
Dan Sinclair17f31182017-03-01 09:31:51 -0500816 int32_t i;
817 int32_t j;
818 int32_t iCount = pCurPieces->GetSize();
tsepezd19e9122016-11-02 15:43:18 -0700819 bool bFind = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400820 FX_TPO tpo;
821 CFX_TxtChar* pTC;
weilia2c06e42016-05-20 17:09:48 -0700822 FX_CHARTYPE chartype;
Dan Sinclair1770c022016-03-14 14:14:16 -0400823 for (i = iCount - 1; i > -1; i--) {
824 tpo = tpos.GetAt(i);
825 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
Dan Sinclair17f31182017-03-01 09:31:51 -0500826 if (!bFind)
Dan Sinclair1770c022016-03-14 14:14:16 -0400827 iNetWidth = ttp.GetEndPos();
Dan Sinclair17f31182017-03-01 09:31:51 -0500828
tsepezd19e9122016-11-02 15:43:18 -0700829 bool bArabic = FX_IsOdd(ttp.m_iBidiLevel);
Dan Sinclair1770c022016-03-14 14:14:16 -0400830 j = bArabic ? 0 : ttp.m_iChars - 1;
831 while (j > -1 && j < ttp.m_iChars) {
832 pTC = ttp.GetCharPtr(j);
Dan Sinclair17f31182017-03-01 09:31:51 -0500833 if (pTC->m_nBreakType == FX_LBT_DIRECT_BRK)
Dan Sinclair1770c022016-03-14 14:14:16 -0400834 iGapChars++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400835 if (!bFind || !bAllChars) {
weilia2c06e42016-05-20 17:09:48 -0700836 chartype = pTC->GetCharType();
837 if (chartype == FX_CHARTYPE_Space || chartype == FX_CHARTYPE_Control) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400838 if (!bFind) {
839 iCharWidth = pTC->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500840 if (bAllChars && iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400841 iNetWidth -= iCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -0400842 }
843 } else {
tsepezd19e9122016-11-02 15:43:18 -0700844 bFind = true;
Dan Sinclair17f31182017-03-01 09:31:51 -0500845 if (!bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400846 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400847 }
848 }
849 j += bArabic ? 1 : -1;
850 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500851 if (!bAllChars && bFind)
Dan Sinclair1770c022016-03-14 14:14:16 -0400852 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400853 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500854
Dan Sinclair1770c022016-03-14 14:14:16 -0400855 int32_t iOffset = m_iLineWidth - iNetWidth;
856 int32_t iLowerAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_LowerMask);
857 int32_t iHigherAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_HigherMask);
858 if (iGapChars > 0 && (iHigherAlignment == FX_TXTLINEALIGNMENT_Distributed ||
859 (iHigherAlignment == FX_TXTLINEALIGNMENT_Justified &&
860 dwStatus != FX_TXTBREAK_ParagraphBreak))) {
861 int32_t iStart = -1;
862 for (i = 0; i < iCount; i++) {
863 tpo = tpos.GetAt(i);
864 CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
Dan Sinclair17f31182017-03-01 09:31:51 -0500865 if (iStart < -1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400866 iStart = ttp.m_iStartPos;
Dan Sinclair17f31182017-03-01 09:31:51 -0500867 else
Dan Sinclair1770c022016-03-14 14:14:16 -0400868 ttp.m_iStartPos = iStart;
Dan Sinclair17f31182017-03-01 09:31:51 -0500869
Dan Sinclair1770c022016-03-14 14:14:16 -0400870 for (j = 0; j < ttp.m_iChars; j++) {
871 pTC = ttp.GetCharPtr(j);
Dan Sinclair17f31182017-03-01 09:31:51 -0500872 if (pTC->m_nBreakType != FX_LBT_DIRECT_BRK || pTC->m_iCharWidth < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400873 continue;
Dan Sinclair17f31182017-03-01 09:31:51 -0500874
875 int32_t k = iOffset / iGapChars;
Dan Sinclair1770c022016-03-14 14:14:16 -0400876 pTC->m_iCharWidth += k;
877 ttp.m_iWidth += k;
878 iOffset -= k;
879 iGapChars--;
Dan Sinclair17f31182017-03-01 09:31:51 -0500880 if (iGapChars < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400881 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400882 }
883 iStart += ttp.m_iWidth;
884 }
885 } else if (iLowerAlignment > FX_TXTLINEALIGNMENT_Left) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500886 if (iLowerAlignment == FX_TXTLINEALIGNMENT_Center)
Dan Sinclair1770c022016-03-14 14:14:16 -0400887 iOffset /= 2;
Dan Sinclair1770c022016-03-14 14:14:16 -0400888 if (iOffset > 0) {
889 for (i = 0; i < iCount; i++) {
890 CFX_TxtPiece& ttp = pCurPieces->GetAt(i);
891 ttp.m_iStartPos += iOffset;
892 }
893 }
894 }
895}
weili1b4f6b32016-08-04 16:37:48 -0700896
tsepez736f28a2016-03-25 14:19:51 -0700897uint32_t CFX_TxtBreak::EndBreak(uint32_t dwStatus) {
dsinclair43854a52016-04-27 12:26:00 -0700898 ASSERT(dwStatus >= FX_TXTBREAK_PieceBreak &&
899 dwStatus <= FX_TXTBREAK_PageBreak);
weili1b4f6b32016-08-04 16:37:48 -0700900 CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400901 int32_t iCount = pCurPieces->GetSize();
902 if (iCount > 0) {
903 CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(--iCount);
Dan Sinclair17f31182017-03-01 09:31:51 -0500904 if (dwStatus > FX_TXTBREAK_PieceBreak)
Dan Sinclair1770c022016-03-14 14:14:16 -0400905 pLastPiece->m_dwStatus = dwStatus;
Dan Sinclair17f31182017-03-01 09:31:51 -0500906 else
Dan Sinclair1770c022016-03-14 14:14:16 -0400907 dwStatus = pLastPiece->m_dwStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400908 return dwStatus;
909 } else {
Dan Sinclaire3409532017-02-28 14:51:28 -0500910 CFX_TxtLine* pLastLine = GetTxtLine();
dsinclair85d1f2c2016-06-23 12:40:16 -0700911 if (pLastLine) {
weili1b4f6b32016-08-04 16:37:48 -0700912 pCurPieces = pLastLine->m_pLinePieces.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400913 iCount = pCurPieces->GetSize();
914 if (iCount-- > 0) {
915 CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(iCount);
Dan Sinclair17f31182017-03-01 09:31:51 -0500916 if (dwStatus > FX_TXTBREAK_PieceBreak)
Dan Sinclair1770c022016-03-14 14:14:16 -0400917 pLastPiece->m_dwStatus = dwStatus;
Dan Sinclair17f31182017-03-01 09:31:51 -0500918 else
Dan Sinclair1770c022016-03-14 14:14:16 -0400919 dwStatus = pLastPiece->m_dwStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400920 return dwStatus;
921 }
922 return FX_TXTBREAK_None;
923 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500924
Dan Sinclair1770c022016-03-14 14:14:16 -0400925 iCount = m_pCurLine->CountChars();
Dan Sinclair17f31182017-03-01 09:31:51 -0500926 if (iCount < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400927 return FX_TXTBREAK_None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400928 if (!m_bPagination) {
929 CFX_TxtChar* pTC = m_pCurLine->GetCharPtr(iCount - 1);
930 pTC->m_dwStatus = dwStatus;
931 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500932 if (dwStatus <= FX_TXTBREAK_PieceBreak)
Dan Sinclair1770c022016-03-14 14:14:16 -0400933 return dwStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400934 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500935
weili1b4f6b32016-08-04 16:37:48 -0700936 m_iReady = (m_pCurLine == m_pTxtLine1.get()) ? 1 : 2;
Dan Sinclair1770c022016-03-14 14:14:16 -0400937 CFX_TxtLine* pNextLine =
weili1b4f6b32016-08-04 16:37:48 -0700938 (m_pCurLine == m_pTxtLine1.get()) ? m_pTxtLine2.get() : m_pTxtLine1.get();
tsepezd19e9122016-11-02 15:43:18 -0700939 bool bAllChars = (m_iCurAlignment > FX_TXTLINEALIGNMENT_Right);
dsinclair34965452016-07-18 13:14:49 -0700940 CFX_TPOArray tpos(100);
Dan Sinclair1770c022016-03-14 14:14:16 -0400941 CFX_Char* pTC;
Dan Sinclair17f31182017-03-01 09:31:51 -0500942 if (m_bArabicShapes)
Dan Sinclair1770c022016-03-14 14:14:16 -0400943 EndBreak_UpdateArabicShapes();
Dan Sinclair17f31182017-03-01 09:31:51 -0500944 if (!EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) {
945 EndBreak_BidiLine(tpos, dwStatus);
946 if (!m_bPagination && m_iCurAlignment > FX_TXTLINEALIGNMENT_Left)
947 EndBreak_Alignment(tpos, bAllChars, dwStatus);
Dan Sinclair1770c022016-03-14 14:14:16 -0400948 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500949
Dan Sinclair1770c022016-03-14 14:14:16 -0400950 m_pCurLine = pNextLine;
tsepezd19e9122016-11-02 15:43:18 -0700951 pTC = GetLastChar(0, false);
weilia2c06e42016-05-20 17:09:48 -0700952 m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown;
Dan Sinclair1770c022016-03-14 14:14:16 -0400953 if (dwStatus == FX_TXTBREAK_ParagraphBreak) {
954 m_iArabicContext = m_iCurArabicContext = 1;
955 ResetArabicContext();
956 }
957 return dwStatus;
958}
weili1b4f6b32016-08-04 16:37:48 -0700959
tsepez33316fc2017-01-24 12:17:40 -0800960int32_t CFX_TxtBreak::GetBreakPos(std::vector<CFX_TxtChar>& ca,
Dan Sinclair1770c022016-03-14 14:14:16 -0400961 int32_t& iEndPos,
tsepezd19e9122016-11-02 15:43:18 -0700962 bool bAllChars,
963 bool bOnlyBrk) {
tsepez33316fc2017-01-24 12:17:40 -0800964 int32_t iLength = pdfium::CollectionSize<int32_t>(ca) - 1;
Dan Sinclair17f31182017-03-01 09:31:51 -0500965 if (iLength < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400966 return iLength;
Dan Sinclair17f31182017-03-01 09:31:51 -0500967
968 int32_t iBreak = -1;
969 int32_t iBreakPos = -1;
970 int32_t iIndirect = -1;
971 int32_t iIndirectPos = -1;
972 int32_t iLast = -1;
973 int32_t iLastPos = -1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400974 if (m_bSingleLine || iEndPos <= m_iLineWidth) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500975 if (!bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400976 return iLength;
Dan Sinclair17f31182017-03-01 09:31:51 -0500977
Dan Sinclair1770c022016-03-14 14:14:16 -0400978 iBreak = iLength;
979 iBreakPos = iEndPos;
980 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500981
tsepezd19e9122016-11-02 15:43:18 -0700982 bool bSpaceBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0;
983 bool bNumberBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_NumberBreak) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400984 FX_LINEBREAKTYPE eType;
Dan Sinclair17f31182017-03-01 09:31:51 -0500985 uint32_t nCodeProp;
986 uint32_t nCur;
987 uint32_t nNext;
tsepez33316fc2017-01-24 12:17:40 -0800988 CFX_Char* pCur = &ca[iLength--];
Dan Sinclair17f31182017-03-01 09:31:51 -0500989 if (bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400990 pCur->m_nBreakType = FX_LBT_UNKNOWN;
Dan Sinclair17f31182017-03-01 09:31:51 -0500991
Dan Sinclair1770c022016-03-14 14:14:16 -0400992 nCodeProp = pCur->m_dwCharProps;
993 nNext = nCodeProp & 0x003F;
994 int32_t iCharWidth = pCur->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500995 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400996 iEndPos -= iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500997
Dan Sinclair1770c022016-03-14 14:14:16 -0400998 while (iLength >= 0) {
tsepez33316fc2017-01-24 12:17:40 -0800999 pCur = &ca[iLength];
Dan Sinclair1770c022016-03-14 14:14:16 -04001000 nCodeProp = pCur->m_dwCharProps;
1001 nCur = nCodeProp & 0x003F;
1002 if (nCur == FX_CBP_SP) {
Dan Sinclair17f31182017-03-01 09:31:51 -05001003 if (nNext == FX_CBP_SP)
Dan Sinclair1770c022016-03-14 14:14:16 -04001004 eType = bSpaceBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
Dan Sinclair17f31182017-03-01 09:31:51 -05001005 else
tsepezf49747f2016-06-10 15:24:47 -07001006 eType = gs_FX_LineBreak_PairTable[nCur][nNext];
Dan Sinclair1770c022016-03-14 14:14:16 -04001007 } else if (bNumberBreak && nCur == FX_CBP_NU && nNext == FX_CBP_NU) {
1008 eType = FX_LBT_DIRECT_BRK;
1009 } else {
Dan Sinclair17f31182017-03-01 09:31:51 -05001010 if (nNext == FX_CBP_SP)
Dan Sinclair1770c022016-03-14 14:14:16 -04001011 eType = FX_LBT_PROHIBITED_BRK;
Dan Sinclair17f31182017-03-01 09:31:51 -05001012 else
tsepezf49747f2016-06-10 15:24:47 -07001013 eType = gs_FX_LineBreak_PairTable[nCur][nNext];
Dan Sinclair1770c022016-03-14 14:14:16 -04001014 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001015 if (bAllChars)
1016 pCur->m_nBreakType = static_cast<uint8_t>(eType);
Dan Sinclair1770c022016-03-14 14:14:16 -04001017 if (!bOnlyBrk) {
1018 if (m_bSingleLine || iEndPos <= m_iLineWidth ||
1019 (nCur == FX_CBP_SP && !bSpaceBreak)) {
1020 if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) {
1021 iBreak = iLength;
1022 iBreakPos = iEndPos;
Dan Sinclair17f31182017-03-01 09:31:51 -05001023 if (!bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -04001024 return iLength;
Dan Sinclair1770c022016-03-14 14:14:16 -04001025 } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) {
1026 iIndirect = iLength;
1027 iIndirectPos = iEndPos;
1028 }
1029 if (iLast < 0) {
1030 iLast = iLength;
1031 iLastPos = iEndPos;
1032 }
1033 }
1034 iCharWidth = pCur->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -05001035 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001036 iEndPos -= iCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -04001037 }
1038 nNext = nCodeProp & 0x003F;
1039 iLength--;
1040 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001041 if (bOnlyBrk)
Dan Sinclair1770c022016-03-14 14:14:16 -04001042 return 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001043 if (iBreak > -1) {
1044 iEndPos = iBreakPos;
1045 return iBreak;
1046 }
1047 if (iIndirect > -1) {
1048 iEndPos = iIndirectPos;
1049 return iIndirect;
1050 }
1051 if (iLast > -1) {
1052 iEndPos = iLastPos;
1053 return iLast;
1054 }
1055 return 0;
1056}
weili1b4f6b32016-08-04 16:37:48 -07001057
Dan Sinclair1770c022016-03-14 14:14:16 -04001058void CFX_TxtBreak::SplitTextLine(CFX_TxtLine* pCurLine,
1059 CFX_TxtLine* pNextLine,
tsepezd19e9122016-11-02 15:43:18 -07001060 bool bAllChars) {
dsinclair85d1f2c2016-06-23 12:40:16 -07001061 ASSERT(pCurLine && pNextLine);
Dan Sinclair1770c022016-03-14 14:14:16 -04001062 int32_t iCount = pCurLine->CountChars();
Dan Sinclair17f31182017-03-01 09:31:51 -05001063 if (iCount < 2)
Dan Sinclair1770c022016-03-14 14:14:16 -04001064 return;
Dan Sinclair17f31182017-03-01 09:31:51 -05001065
Dan Sinclair1770c022016-03-14 14:14:16 -04001066 int32_t iEndPos = pCurLine->m_iWidth;
tsepez33316fc2017-01-24 12:17:40 -08001067 std::vector<CFX_TxtChar>& curChars = *pCurLine->m_pLineChars;
tsepezd19e9122016-11-02 15:43:18 -07001068 int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false);
Dan Sinclair17f31182017-03-01 09:31:51 -05001069 if (iCharPos < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001070 iCharPos = 0;
Dan Sinclair17f31182017-03-01 09:31:51 -05001071
Dan Sinclair1770c022016-03-14 14:14:16 -04001072 iCharPos++;
1073 if (iCharPos >= iCount) {
tsepezd19e9122016-11-02 15:43:18 -07001074 pNextLine->RemoveAll(true);
tsepez33316fc2017-01-24 12:17:40 -08001075 CFX_Char* pTC = &curChars[iCharPos - 1];
Dan Sinclair1770c022016-03-14 14:14:16 -04001076 pTC->m_nBreakType = FX_LBT_UNKNOWN;
1077 return;
1078 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001079
1080 // m_pLineChars is a unique_ptr<vector>. Assign the ref into nextChars
1081 // so we can change the m_pLineChars vector ...
tsepez33316fc2017-01-24 12:17:40 -08001082 std::vector<CFX_TxtChar>& nextChars = *pNextLine->m_pLineChars;
1083 nextChars =
1084 std::vector<CFX_TxtChar>(curChars.begin() + iCharPos, curChars.end());
1085 curChars.erase(curChars.begin() + iCharPos, curChars.end());
Dan Sinclair1770c022016-03-14 14:14:16 -04001086 pCurLine->m_iWidth = iEndPos;
tsepez33316fc2017-01-24 12:17:40 -08001087 CFX_TxtChar* pTC = &curChars[iCharPos - 1];
Dan Sinclair1770c022016-03-14 14:14:16 -04001088 pTC->m_nBreakType = FX_LBT_UNKNOWN;
tsepez33316fc2017-01-24 12:17:40 -08001089 iCount = pdfium::CollectionSize<int>(nextChars);
1090 int32_t iWidth = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001091 for (int32_t i = 0; i < iCount; i++) {
Dan Sinclair17f31182017-03-01 09:31:51 -05001092 if (nextChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001093 pCurLine->m_iArabicChars--;
1094 pNextLine->m_iArabicChars++;
1095 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001096 int32_t iCharWidth = nextChars[i].m_iCharWidth;
tsepez33316fc2017-01-24 12:17:40 -08001097 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001098 iWidth += iCharWidth;
tsepez33316fc2017-01-24 12:17:40 -08001099 if (m_bPagination)
Dan Sinclair1770c022016-03-14 14:14:16 -04001100 continue;
Dan Sinclair17f31182017-03-01 09:31:51 -05001101
1102 nextChars[i].m_dwStatus = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001103 }
1104 pNextLine->m_iWidth = iWidth;
1105}
weili1b4f6b32016-08-04 16:37:48 -07001106
Dan Sinclair1770c022016-03-14 14:14:16 -04001107int32_t CFX_TxtBreak::CountBreakPieces() const {
Dan Sinclaire3409532017-02-28 14:51:28 -05001108 CFX_TxtPieceArray* pTxtPieces = GetTxtPieces();
dsinclair85d1f2c2016-06-23 12:40:16 -07001109 return pTxtPieces ? pTxtPieces->GetSize() : 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001110}
weili1b4f6b32016-08-04 16:37:48 -07001111
Dan Sinclair1770c022016-03-14 14:14:16 -04001112const CFX_TxtPiece* CFX_TxtBreak::GetBreakPiece(int32_t index) const {
Dan Sinclaire3409532017-02-28 14:51:28 -05001113 CFX_TxtPieceArray* pTxtPieces = GetTxtPieces();
Dan Sinclair17f31182017-03-01 09:31:51 -05001114 if (!pTxtPieces)
dsinclair85d1f2c2016-06-23 12:40:16 -07001115 return nullptr;
Dan Sinclair17f31182017-03-01 09:31:51 -05001116 if (index < 0 || index >= pTxtPieces->GetSize())
dsinclair85d1f2c2016-06-23 12:40:16 -07001117 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001118 return pTxtPieces->GetPtrAt(index);
1119}
weili1b4f6b32016-08-04 16:37:48 -07001120
Dan Sinclair1770c022016-03-14 14:14:16 -04001121void CFX_TxtBreak::ClearBreakPieces() {
Dan Sinclaire3409532017-02-28 14:51:28 -05001122 CFX_TxtLine* pTxtLine = GetTxtLine();
Dan Sinclair17f31182017-03-01 09:31:51 -05001123 if (pTxtLine)
tsepezd19e9122016-11-02 15:43:18 -07001124 pTxtLine->RemoveAll(true);
Dan Sinclair1770c022016-03-14 14:14:16 -04001125 m_iReady = 0;
1126}
weili1b4f6b32016-08-04 16:37:48 -07001127
Dan Sinclair1770c022016-03-14 14:14:16 -04001128void CFX_TxtBreak::Reset() {
weilia2c06e42016-05-20 17:09:48 -07001129 m_eCharType = FX_CHARTYPE_Unknown;
Dan Sinclair17f31182017-03-01 09:31:51 -05001130 m_iArabicContext = 1;
1131 m_iCurArabicContext = 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04001132 ResetArabicContext();
tsepezd19e9122016-11-02 15:43:18 -07001133 m_pTxtLine1->RemoveAll(true);
1134 m_pTxtLine2->RemoveAll(true);
Dan Sinclair1770c022016-03-14 14:14:16 -04001135}
1136
1137struct FX_FORMCHAR {
Tom Sepez62a70f92016-03-21 15:00:20 -07001138 uint16_t wch;
1139 uint16_t wForm;
Dan Sinclair1770c022016-03-14 14:14:16 -04001140 int32_t iWidth;
1141};
1142
1143int32_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun,
1144 FXTEXT_CHARPOS* pCharPos,
tsepezd19e9122016-11-02 15:43:18 -07001145 bool bCharCode,
Dan Sinclair1770c022016-03-14 14:14:16 -04001146 CFX_WideString* pWSForms,
1147 FX_AdjustCharDisplayPos pAdjustPos) const {
Dan Sinclair17f31182017-03-01 09:31:51 -05001148 if (!pTxtRun || pTxtRun->iLength < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -04001149 return 0;
Dan Sinclair17f31182017-03-01 09:31:51 -05001150
Dan Sinclair1770c022016-03-14 14:14:16 -04001151 IFX_TxtAccess* pAccess = pTxtRun->pAccess;
dsinclair705f8292016-06-07 10:10:45 -07001152 const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity;
tsepezd4033292016-04-19 12:03:15 -07001153 const FX_WCHAR* pStr = pTxtRun->wsStr.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04001154 int32_t* pWidths = pTxtRun->pWidths;
1155 int32_t iLength = pTxtRun->iLength - 1;
tsepeze6477992017-01-05 12:57:00 -08001156 CFX_RetainPtr<CFGAS_GEFont> pFont = pTxtRun->pFont;
tsepez736f28a2016-03-25 14:19:51 -07001157 uint32_t dwStyles = pTxtRun->dwStyles;
Dan Sinclair1770c022016-03-14 14:14:16 -04001158 CFX_RectF rtText(*pTxtRun->pRect);
tsepezd19e9122016-11-02 15:43:18 -07001159 bool bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
1160 bool bArabicNumber =
Dan Sinclair1770c022016-03-14 14:14:16 -04001161 (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicNumber) != 0;
tsepezd19e9122016-11-02 15:43:18 -07001162 bool bArabicComma =
Dan Sinclair1770c022016-03-14 14:14:16 -04001163 (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicComma) != 0;
1164 FX_FLOAT fFontSize = pTxtRun->fFontSize;
1165 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
1166 int32_t iAscent = pFont->GetAscent();
1167 int32_t iDescent = pFont->GetDescent();
1168 int32_t iMaxHeight = iAscent - iDescent;
1169 FX_FLOAT fFontHeight = fFontSize;
1170 FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight;
1171 FX_FLOAT fDescent = fFontHeight * (FX_FLOAT)iDescent / (FX_FLOAT)iMaxHeight;
tsepezd19e9122016-11-02 15:43:18 -07001172 bool bVerticalDoc = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0;
1173 bool bVerticalChar = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001174 int32_t iRotation = GetLineRotation(dwStyles) + pTxtRun->iCharRotation;
Dan Sinclair17f31182017-03-01 09:31:51 -05001175 FX_FLOAT fX = rtText.left;
1176 FX_FLOAT fY;
1177 FX_FLOAT fCharWidth;
1178 FX_FLOAT fCharHeight;
Dan Sinclair1770c022016-03-14 14:14:16 -04001179 int32_t iHorScale = pTxtRun->iHorizontalScale;
1180 int32_t iVerScale = pTxtRun->iVerticalScale;
tsepezd19e9122016-11-02 15:43:18 -07001181 bool bSkipSpace = pTxtRun->bSkipSpace;
Dan Sinclair1770c022016-03-14 14:14:16 -04001182 FX_FORMCHAR formChars[3];
1183 FX_FLOAT fYBase;
Dan Sinclair17f31182017-03-01 09:31:51 -05001184
Dan Sinclair1770c022016-03-14 14:14:16 -04001185 if (bVerticalDoc) {
1186 fX += (rtText.width - fFontSize) / 2.0f;
1187 fYBase = bRTLPiece ? rtText.bottom() : rtText.top;
1188 fY = fYBase;
1189 } else {
Dan Sinclair17f31182017-03-01 09:31:51 -05001190 if (bRTLPiece)
Dan Sinclair1770c022016-03-14 14:14:16 -04001191 fX = rtText.right();
Dan Sinclair17f31182017-03-01 09:31:51 -05001192
Dan Sinclair1770c022016-03-14 14:14:16 -04001193 fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f;
1194 fY = fYBase + fAscent;
1195 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001196
weili038aa532016-05-20 15:38:29 -07001197 int32_t iCount = 0;
1198 int32_t iNext = 0;
1199 FX_WCHAR wPrev = 0xFEFF;
1200 FX_WCHAR wNext = 0xFEFF;
1201 FX_WCHAR wForm = 0xFEFF;
1202 FX_WCHAR wLast = 0xFEFF;
tsepezd19e9122016-11-02 15:43:18 -07001203 bool bShadda = false;
1204 bool bLam = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001205 for (int32_t i = 0; i <= iLength; i++) {
weili038aa532016-05-20 15:38:29 -07001206 int32_t iWidth;
1207 FX_WCHAR wch;
dsinclair85d1f2c2016-06-23 12:40:16 -07001208 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001209 wch = pAccess->GetChar(pIdentity, i);
1210 iWidth = pAccess->GetWidth(pIdentity, i);
1211 } else {
1212 wch = *pStr++;
1213 iWidth = *pWidths++;
1214 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001215
weili038aa532016-05-20 15:38:29 -07001216 uint32_t dwProps = FX_GetUnicodeProperties(wch);
weilia2c06e42016-05-20 17:09:48 -07001217 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
1218 if (chartype == FX_CHARTYPE_ArabicAlef && iWidth == 0) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001219 wPrev = 0xFEFF;
1220 wLast = wch;
1221 continue;
1222 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001223
weilia2c06e42016-05-20 17:09:48 -07001224 if (chartype >= FX_CHARTYPE_ArabicAlef) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001225 if (i < iLength) {
dsinclair85d1f2c2016-06-23 12:40:16 -07001226 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001227 iNext = i + 1;
1228 while (iNext <= iLength) {
1229 wNext = pAccess->GetChar(pIdentity, iNext);
1230 dwProps = FX_GetUnicodeProperties(wNext);
Dan Sinclair17f31182017-03-01 09:31:51 -05001231 if ((dwProps & FX_CHARTYPEBITSMASK) != FX_CHARTYPE_Combination)
Dan Sinclair1770c022016-03-14 14:14:16 -04001232 break;
Dan Sinclair17f31182017-03-01 09:31:51 -05001233
Dan Sinclair1770c022016-03-14 14:14:16 -04001234 iNext++;
1235 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001236 if (iNext > iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -04001237 wNext = 0xFEFF;
Dan Sinclair1770c022016-03-14 14:14:16 -04001238 } else {
1239 int32_t j = -1;
1240 do {
1241 j++;
Dan Sinclair17f31182017-03-01 09:31:51 -05001242 if (i + j >= iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -04001243 break;
Dan Sinclair17f31182017-03-01 09:31:51 -05001244
Dan Sinclair1770c022016-03-14 14:14:16 -04001245 wNext = pStr[j];
1246 dwProps = FX_GetUnicodeProperties(wNext);
1247 } while ((dwProps & FX_CHARTYPEBITSMASK) == FX_CHARTYPE_Combination);
Dan Sinclair17f31182017-03-01 09:31:51 -05001248 if (i + j >= iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -04001249 wNext = 0xFEFF;
Dan Sinclair1770c022016-03-14 14:14:16 -04001250 }
1251 } else {
1252 wNext = 0xFEFF;
1253 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001254
tsepeze00f75c2016-05-06 13:15:46 -07001255 wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext);
Dan Sinclair1770c022016-03-14 14:14:16 -04001256 bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647);
weilia2c06e42016-05-20 17:09:48 -07001257 } else if (chartype == FX_CHARTYPE_Combination) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001258 wForm = wch;
1259 if (wch >= 0x064C && wch <= 0x0651) {
1260 if (bShadda) {
1261 wForm = 0xFEFF;
tsepezd19e9122016-11-02 15:43:18 -07001262 bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001263 } else {
1264 wNext = 0xFEFF;
dsinclair85d1f2c2016-06-23 12:40:16 -07001265 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001266 iNext = i + 1;
Dan Sinclair17f31182017-03-01 09:31:51 -05001267 if (iNext <= iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -04001268 wNext = pAccess->GetChar(pIdentity, iNext);
Dan Sinclair1770c022016-03-14 14:14:16 -04001269 } else {
Dan Sinclair17f31182017-03-01 09:31:51 -05001270 if (i < iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -04001271 wNext = *pStr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001272 }
1273 if (wch == 0x0651) {
1274 if (wNext >= 0x064C && wNext <= 0x0650) {
1275 wForm = FX_GetArabicFromShaddaTable(wNext);
tsepezd19e9122016-11-02 15:43:18 -07001276 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001277 }
1278 } else {
1279 if (wNext == 0x0651) {
1280 wForm = FX_GetArabicFromShaddaTable(wch);
tsepezd19e9122016-11-02 15:43:18 -07001281 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001282 }
1283 }
1284 }
1285 } else {
tsepezd19e9122016-11-02 15:43:18 -07001286 bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001287 }
weilia2c06e42016-05-20 17:09:48 -07001288 } else if (chartype == FX_CHARTYPE_Numeric) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001289 wForm = wch;
Dan Sinclair17f31182017-03-01 09:31:51 -05001290 if (bArabicNumber)
Dan Sinclair1770c022016-03-14 14:14:16 -04001291 wForm += 0x0630;
Dan Sinclair1770c022016-03-14 14:14:16 -04001292 } else if (wch == L'.') {
1293 wForm = wch;
1294 if (bArabicNumber) {
1295 wNext = 0xFEFF;
dsinclair85d1f2c2016-06-23 12:40:16 -07001296 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001297 iNext = i + 1;
Dan Sinclair17f31182017-03-01 09:31:51 -05001298 if (iNext <= iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -04001299 wNext = pAccess->GetChar(pIdentity, iNext);
Dan Sinclair1770c022016-03-14 14:14:16 -04001300 } else {
Dan Sinclair17f31182017-03-01 09:31:51 -05001301 if (i < iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -04001302 wNext = *pStr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001303 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001304 if (wNext >= L'0' && wNext <= L'9')
Dan Sinclair1770c022016-03-14 14:14:16 -04001305 wForm = 0x066B;
Dan Sinclair1770c022016-03-14 14:14:16 -04001306 }
1307 } else if (wch == L',') {
1308 wForm = wch;
Dan Sinclair17f31182017-03-01 09:31:51 -05001309 if (bArabicComma)
Dan Sinclair1770c022016-03-14 14:14:16 -04001310 wForm = 0x060C;
Dan Sinclair1770c022016-03-14 14:14:16 -04001311 } else if (bRTLPiece || bVerticalChar) {
1312 wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, bVerticalChar);
1313 } else {
1314 wForm = wch;
1315 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001316 if (chartype != FX_CHARTYPE_Combination)
tsepezd19e9122016-11-02 15:43:18 -07001317 bShadda = false;
Dan Sinclair17f31182017-03-01 09:31:51 -05001318 if (chartype < FX_CHARTYPE_ArabicAlef)
tsepezd19e9122016-11-02 15:43:18 -07001319 bLam = false;
Dan Sinclair17f31182017-03-01 09:31:51 -05001320
Dan Sinclair1770c022016-03-14 14:14:16 -04001321 dwProps = FX_GetUnicodeProperties(wForm);
weili038aa532016-05-20 15:38:29 -07001322 int32_t iCharRotation = iRotation;
Dan Sinclair17f31182017-03-01 09:31:51 -05001323 if (bVerticalChar && (dwProps & 0x8000) != 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001324 iCharRotation++;
Dan Sinclair17f31182017-03-01 09:31:51 -05001325
Dan Sinclair1770c022016-03-14 14:14:16 -04001326 iCharRotation %= 4;
tsepezd19e9122016-11-02 15:43:18 -07001327 bool bEmptyChar =
weilia2c06e42016-05-20 17:09:48 -07001328 (chartype >= FX_CHARTYPE_Tab && chartype <= FX_CHARTYPE_Control);
Dan Sinclair17f31182017-03-01 09:31:51 -05001329 if (wForm == 0xFEFF)
tsepezd19e9122016-11-02 15:43:18 -07001330 bEmptyChar = true;
Dan Sinclair17f31182017-03-01 09:31:51 -05001331
weili038aa532016-05-20 15:38:29 -07001332 int32_t iForms = bLam ? 3 : 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04001333 iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms;
dsinclair85d1f2c2016-06-23 12:40:16 -07001334 if (!pCharPos) {
Dan Sinclair17f31182017-03-01 09:31:51 -05001335 if (iWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001336 wPrev = wch;
Dan Sinclair1770c022016-03-14 14:14:16 -04001337 wLast = wch;
1338 continue;
1339 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001340
weili038aa532016-05-20 15:38:29 -07001341 int32_t iCharWidth = iWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -05001342 if (iCharWidth < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001343 iCharWidth = -iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -05001344
Dan Sinclair1770c022016-03-14 14:14:16 -04001345 iCharWidth /= iFontSize;
1346 formChars[0].wch = wch;
1347 formChars[0].wForm = wForm;
1348 formChars[0].iWidth = iCharWidth;
1349 if (bLam) {
1350 formChars[1].wForm = 0x0651;
1351 iCharWidth = 0;
tsepezd19e9122016-11-02 15:43:18 -07001352 pFont->GetCharWidth(0x0651, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001353 formChars[1].iWidth = iCharWidth;
1354 formChars[2].wForm = 0x0670;
1355 iCharWidth = 0;
tsepezd19e9122016-11-02 15:43:18 -07001356 pFont->GetCharWidth(0x0670, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001357 formChars[2].iWidth = iCharWidth;
1358 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001359
Dan Sinclair1770c022016-03-14 14:14:16 -04001360 for (int32_t j = 0; j < iForms; j++) {
1361 wForm = (FX_WCHAR)formChars[j].wForm;
1362 iCharWidth = formChars[j].iWidth;
1363 if (j > 0) {
weilia2c06e42016-05-20 17:09:48 -07001364 chartype = FX_CHARTYPE_Combination;
Dan Sinclair1770c022016-03-14 14:14:16 -04001365 wch = wForm;
1366 wLast = (FX_WCHAR)formChars[j - 1].wForm;
1367 }
1368 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
1369 pCharPos->m_GlyphIndex =
tsepezd19e9122016-11-02 15:43:18 -07001370 bCharCode ? wch : pFont->GetGlyphIndex(wForm, false);
thestigec51ac32016-06-20 10:38:52 -07001371#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
Dan Sinclair1770c022016-03-14 14:14:16 -04001372 pCharPos->m_ExtGID = pCharPos->m_GlyphIndex;
thestigec51ac32016-06-20 10:38:52 -07001373#endif
Dan Sinclair1770c022016-03-14 14:14:16 -04001374 pCharPos->m_FontCharWidth = iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -05001375 if (pWSForms)
Dan Sinclair1770c022016-03-14 14:14:16 -04001376 *pWSForms += wForm;
Dan Sinclair1770c022016-03-14 14:14:16 -04001377 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001378
weili038aa532016-05-20 15:38:29 -07001379 int32_t iCharHeight;
Dan Sinclair1770c022016-03-14 14:14:16 -04001380 if (bVerticalDoc) {
1381 iCharHeight = iCharWidth;
1382 iCharWidth = 1000;
1383 } else {
1384 iCharHeight = 1000;
1385 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001386
Dan Sinclair1770c022016-03-14 14:14:16 -04001387 fCharWidth = fFontSize * iCharWidth / 1000.0f;
1388 fCharHeight = fFontSize * iCharHeight / 1000.0f;
weilia2c06e42016-05-20 17:09:48 -07001389 if (bRTLPiece && chartype != FX_CHARTYPE_Combination) {
Dan Sinclair17f31182017-03-01 09:31:51 -05001390 if (bVerticalDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04001391 fY -= fCharHeight;
Dan Sinclair17f31182017-03-01 09:31:51 -05001392 else
Dan Sinclair1770c022016-03-14 14:14:16 -04001393 fX -= fCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -04001394 }
1395 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001396 pCharPos->m_Origin = CFX_PointF(fX, fY);
Dan Sinclair1770c022016-03-14 14:14:16 -04001397 if ((dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0) {
1398 int32_t iFormWidth = iCharWidth;
tsepezd19e9122016-11-02 15:43:18 -07001399 pFont->GetCharWidth(wForm, iFormWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001400 FX_FLOAT fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001401 if (bVerticalDoc)
1402 pCharPos->m_Origin.y += fOffset;
1403 else
1404 pCharPos->m_Origin.x += fOffset;
Dan Sinclair1770c022016-03-14 14:14:16 -04001405 }
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001406
weilia2c06e42016-05-20 17:09:48 -07001407 if (chartype == FX_CHARTYPE_Combination) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001408 CFX_Rect rtBBox;
tsepez6fd07ef2017-01-06 09:48:18 -08001409 if (pFont->GetCharBBox(wForm, &rtBBox, false)) {
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001410 pCharPos->m_Origin.y =
Dan Sinclair1770c022016-03-14 14:14:16 -04001411 fYBase + fFontSize -
1412 fFontSize * (FX_FLOAT)rtBBox.height / (FX_FLOAT)iMaxHeight;
1413 }
1414 if (wForm == wch && wLast != 0xFEFF) {
tsepez736f28a2016-03-25 14:19:51 -07001415 uint32_t dwLastProps = FX_GetUnicodeProperties(wLast);
Dan Sinclair1770c022016-03-14 14:14:16 -04001416 if ((dwLastProps & FX_CHARTYPEBITSMASK) ==
1417 FX_CHARTYPE_Combination) {
weilidb444d22016-06-02 15:48:15 -07001418 CFX_Rect rtBox;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001419 if (pFont->GetCharBBox(wLast, &rtBox, false))
1420 pCharPos->m_Origin.y -= fFontSize * rtBox.height / iMaxHeight;
Dan Sinclair1770c022016-03-14 14:14:16 -04001421 }
1422 }
1423 }
1424 CFX_PointF ptOffset;
tsepezd19e9122016-11-02 15:43:18 -07001425 bool bAdjusted = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001426 if (pAdjustPos) {
1427 bAdjusted = pAdjustPos(wForm, bCharCode, pFont, fFontSize,
1428 bVerticalChar, ptOffset);
1429 }
1430 if (!bAdjusted && bVerticalChar && (dwProps & 0x00010000) != 0) {
1431 CFX_Rect rtBBox;
tsepez6fd07ef2017-01-06 09:48:18 -08001432 if (pFont->GetCharBBox(wForm, &rtBBox, false)) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001433 ptOffset.x = fFontSize * (850 - rtBBox.right()) / iMaxHeight;
1434 ptOffset.y = fFontSize * (iAscent - rtBBox.top - 150) / iMaxHeight;
1435 }
1436 }
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001437 pCharPos->m_Origin.x += ptOffset.x;
1438 pCharPos->m_Origin.y -= ptOffset.y;
Dan Sinclair1770c022016-03-14 14:14:16 -04001439 }
weilia2c06e42016-05-20 17:09:48 -07001440 if (!bRTLPiece && chartype != FX_CHARTYPE_Combination) {
Dan Sinclair17f31182017-03-01 09:31:51 -05001441 if (bVerticalDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04001442 fY += fCharHeight;
Dan Sinclair17f31182017-03-01 09:31:51 -05001443 else
Dan Sinclair1770c022016-03-14 14:14:16 -04001444 fX += fCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -04001445 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001446
Dan Sinclair1770c022016-03-14 14:14:16 -04001447 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
tsepezd19e9122016-11-02 15:43:18 -07001448 pCharPos->m_bGlyphAdjust = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001449 if (bVerticalDoc) {
1450 if (iCharRotation == 0) {
1451 pCharPos->m_AdjustMatrix[0] = -1;
1452 pCharPos->m_AdjustMatrix[1] = 0;
1453 pCharPos->m_AdjustMatrix[2] = 0;
1454 pCharPos->m_AdjustMatrix[3] = 1;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001455 pCharPos->m_Origin.y += fAscent;
Dan Sinclair1770c022016-03-14 14:14:16 -04001456 } else if (iCharRotation == 1) {
1457 pCharPos->m_AdjustMatrix[0] = 0;
1458 pCharPos->m_AdjustMatrix[1] = -1;
1459 pCharPos->m_AdjustMatrix[2] = -1;
1460 pCharPos->m_AdjustMatrix[3] = 0;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001461 pCharPos->m_Origin.x -= fDescent;
Dan Sinclair1770c022016-03-14 14:14:16 -04001462 } else if (iCharRotation == 2) {
1463 pCharPos->m_AdjustMatrix[0] = 1;
1464 pCharPos->m_AdjustMatrix[1] = 0;
1465 pCharPos->m_AdjustMatrix[2] = 0;
1466 pCharPos->m_AdjustMatrix[3] = -1;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001467 pCharPos->m_Origin.x += fCharWidth;
1468 pCharPos->m_Origin.y += fAscent;
Dan Sinclair1770c022016-03-14 14:14:16 -04001469 } else {
1470 pCharPos->m_AdjustMatrix[0] = 0;
1471 pCharPos->m_AdjustMatrix[1] = 1;
1472 pCharPos->m_AdjustMatrix[2] = 1;
1473 pCharPos->m_AdjustMatrix[3] = 0;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001474 pCharPos->m_Origin.x += fAscent;
Dan Sinclair1770c022016-03-14 14:14:16 -04001475 }
1476 } else {
1477 if (iCharRotation == 0) {
1478 pCharPos->m_AdjustMatrix[0] = -1;
1479 pCharPos->m_AdjustMatrix[1] = 0;
1480 pCharPos->m_AdjustMatrix[2] = 0;
1481 pCharPos->m_AdjustMatrix[3] = 1;
1482 } else if (iCharRotation == 1) {
1483 pCharPos->m_AdjustMatrix[0] = 0;
1484 pCharPos->m_AdjustMatrix[1] = -1;
1485 pCharPos->m_AdjustMatrix[2] = -1;
1486 pCharPos->m_AdjustMatrix[3] = 0;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001487 pCharPos->m_Origin.x -= fDescent;
1488 pCharPos->m_Origin.y -= fAscent + fDescent;
Dan Sinclair1770c022016-03-14 14:14:16 -04001489 } else if (iCharRotation == 2) {
1490 pCharPos->m_AdjustMatrix[0] = 1;
1491 pCharPos->m_AdjustMatrix[1] = 0;
1492 pCharPos->m_AdjustMatrix[2] = 0;
1493 pCharPos->m_AdjustMatrix[3] = -1;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001494 pCharPos->m_Origin.x += fCharWidth;
1495 pCharPos->m_Origin.y -= fAscent;
Dan Sinclair1770c022016-03-14 14:14:16 -04001496 } else {
1497 pCharPos->m_AdjustMatrix[0] = 0;
1498 pCharPos->m_AdjustMatrix[1] = 1;
1499 pCharPos->m_AdjustMatrix[2] = 1;
1500 pCharPos->m_AdjustMatrix[3] = 0;
Dan Sinclair2c02fae2017-02-16 13:42:11 -05001501 pCharPos->m_Origin.x += fAscent;
Dan Sinclair1770c022016-03-14 14:14:16 -04001502 }
1503 }
1504 if (iHorScale != 100 || iVerScale != 100) {
1505 pCharPos->m_AdjustMatrix[0] =
1506 pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f;
1507 pCharPos->m_AdjustMatrix[1] =
1508 pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f;
1509 pCharPos->m_AdjustMatrix[2] =
1510 pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f;
1511 pCharPos->m_AdjustMatrix[3] =
1512 pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f;
1513 }
1514 pCharPos++;
1515 }
1516 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001517 if (iWidth > 0)
1518 wPrev = static_cast<FX_WCHAR>(formChars[0].wch);
Dan Sinclair1770c022016-03-14 14:14:16 -04001519 wLast = wch;
1520 }
1521 return iCount;
1522}
weili1b4f6b32016-08-04 16:37:48 -07001523
Dan Sinclair1770c022016-03-14 14:14:16 -04001524int32_t CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun,
tsepez3d328762017-01-24 06:12:34 -08001525 std::vector<CFX_RectF>* rtArray,
tsepezd19e9122016-11-02 15:43:18 -07001526 bool bCharBBox) const {
tsepeze6477992017-01-05 12:57:00 -08001527 if (!pTxtRun || pTxtRun->iLength < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -04001528 return 0;
tsepeze6477992017-01-05 12:57:00 -08001529
Dan Sinclair1770c022016-03-14 14:14:16 -04001530 IFX_TxtAccess* pAccess = pTxtRun->pAccess;
dsinclair705f8292016-06-07 10:10:45 -07001531 const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity;
tsepezd4033292016-04-19 12:03:15 -07001532 const FX_WCHAR* pStr = pTxtRun->wsStr.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04001533 int32_t* pWidths = pTxtRun->pWidths;
1534 int32_t iLength = pTxtRun->iLength;
1535 CFX_RectF rect(*pTxtRun->pRect);
tsepezd19e9122016-11-02 15:43:18 -07001536 bool bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001537 FX_FLOAT fFontSize = pTxtRun->fFontSize;
1538 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
1539 FX_FLOAT fScale = fFontSize / 1000.0f;
tsepeze6477992017-01-05 12:57:00 -08001540 CFX_RetainPtr<CFGAS_GEFont> pFont = pTxtRun->pFont;
1541 if (!pFont)
tsepezd19e9122016-11-02 15:43:18 -07001542 bCharBBox = false;
tsepeze6477992017-01-05 12:57:00 -08001543
Dan Sinclair1770c022016-03-14 14:14:16 -04001544 CFX_Rect bbox;
tsepeze6477992017-01-05 12:57:00 -08001545 if (bCharBBox)
tsepez6fd07ef2017-01-06 09:48:18 -08001546 bCharBBox = pFont->GetBBox(&bbox);
tsepeze6477992017-01-05 12:57:00 -08001547
Dan Sinclair1770c022016-03-14 14:14:16 -04001548 FX_FLOAT fLeft = std::max(0.0f, bbox.left * fScale);
1549 FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale);
tsepez3d328762017-01-24 06:12:34 -08001550 rtArray->clear();
1551 rtArray->resize(iLength);
Dan Sinclair17f31182017-03-01 09:31:51 -05001552
tsepezd19e9122016-11-02 15:43:18 -07001553 bool bVertical = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0;
1554 bool bSingleLine = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
1555 bool bCombText = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
Dan Sinclair17f31182017-03-01 09:31:51 -05001556 FX_WCHAR wch;
1557 FX_WCHAR wLineBreakChar = pTxtRun->wLineBreakChar;
Dan Sinclair1770c022016-03-14 14:14:16 -04001558 int32_t iCharSize;
Dan Sinclair17f31182017-03-01 09:31:51 -05001559 FX_FLOAT fCharSize;
1560 FX_FLOAT fStart;
1561 if (bVertical)
Dan Sinclair1770c022016-03-14 14:14:16 -04001562 fStart = bRTLPiece ? rect.bottom() : rect.top;
Dan Sinclair17f31182017-03-01 09:31:51 -05001563 else
Dan Sinclair1770c022016-03-14 14:14:16 -04001564 fStart = bRTLPiece ? rect.right() : rect.left;
Dan Sinclair17f31182017-03-01 09:31:51 -05001565
Dan Sinclair1770c022016-03-14 14:14:16 -04001566 for (int32_t i = 0; i < iLength; i++) {
dsinclair85d1f2c2016-06-23 12:40:16 -07001567 if (pAccess) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001568 wch = pAccess->GetChar(pIdentity, i);
1569 iCharSize = pAccess->GetWidth(pIdentity, i);
1570 } else {
1571 wch = *pStr++;
1572 iCharSize = *pWidths++;
1573 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001574 fCharSize = static_cast<FX_FLOAT>(iCharSize) / 20000.0f;
tsepezd19e9122016-11-02 15:43:18 -07001575 bool bRet = (!bSingleLine && FX_IsCtrlCode(wch));
Dan Sinclair1770c022016-03-14 14:14:16 -04001576 if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 ||
1577 (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) {
tsepezd19e9122016-11-02 15:43:18 -07001578 bRet = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001579 }
1580 if (bRet) {
1581 iCharSize = iFontSize * 500;
1582 fCharSize = fFontSize / 2.0f;
1583 }
1584 if (bVertical) {
1585 rect.top = fStart;
1586 if (bRTLPiece) {
1587 rect.top -= fCharSize;
1588 fStart -= fCharSize;
1589 } else {
1590 fStart += fCharSize;
1591 }
1592 rect.height = fCharSize;
1593 } else {
1594 rect.left = fStart;
1595 if (bRTLPiece) {
1596 rect.left -= fCharSize;
1597 fStart -= fCharSize;
1598 } else {
1599 fStart += fCharSize;
1600 }
1601 rect.width = fCharSize;
1602 }
Dan Sinclair17f31182017-03-01 09:31:51 -05001603
Dan Sinclair1770c022016-03-14 14:14:16 -04001604 if (bCharBBox && !bRet) {
1605 int32_t iCharWidth = 1000;
thestig2c065322016-09-26 14:16:43 -07001606 pFont->GetCharWidth(wch, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001607 FX_FLOAT fRTLeft = 0, fCharWidth = 0;
1608 if (iCharWidth > 0) {
1609 fCharWidth = iCharWidth * fScale;
1610 fRTLeft = fLeft;
Dan Sinclair17f31182017-03-01 09:31:51 -05001611 if (bCombText)
Dan Sinclair1770c022016-03-14 14:14:16 -04001612 fRTLeft = (rect.width - fCharWidth) / 2.0f;
Dan Sinclair1770c022016-03-14 14:14:16 -04001613 }
1614 CFX_RectF rtBBoxF;
1615 if (bVertical) {
1616 rtBBoxF.top = rect.left + fRTLeft;
1617 rtBBoxF.left = rect.top + (rect.height - fHeight) / 2.0f;
1618 rtBBoxF.height = fCharWidth;
1619 rtBBoxF.width = fHeight;
1620 rtBBoxF.left = std::max(rtBBoxF.left, 0.0f);
1621 } else {
1622 rtBBoxF.left = rect.left + fRTLeft;
1623 rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f;
1624 rtBBoxF.width = fCharWidth;
1625 rtBBoxF.height = fHeight;
1626 rtBBoxF.top = std::max(rtBBoxF.top, 0.0f);
1627 }
tsepez3d328762017-01-24 06:12:34 -08001628 (*rtArray)[i] = rtBBoxF;
Dan Sinclair1770c022016-03-14 14:14:16 -04001629 continue;
1630 }
tsepez3d328762017-01-24 06:12:34 -08001631 (*rtArray)[i] = rect;
Dan Sinclair1770c022016-03-14 14:14:16 -04001632 }
1633 return iLength;
1634}
weilieec3a362016-06-18 06:25:37 -07001635
1636FX_TXTRUN::FX_TXTRUN()
1637 : pAccess(nullptr),
1638 pIdentity(nullptr),
1639 pWidths(nullptr),
1640 iLength(0),
1641 pFont(nullptr),
1642 fFontSize(12),
1643 dwStyles(0),
1644 iHorizontalScale(100),
1645 iVerticalScale(100),
1646 iCharRotation(0),
1647 dwCharStyles(0),
1648 pRect(nullptr),
1649 wLineBreakChar(L'\n'),
tsepezd19e9122016-11-02 15:43:18 -07001650 bSkipSpace(true) {}
weilieec3a362016-06-18 06:25:37 -07001651
1652FX_TXTRUN::~FX_TXTRUN() {}
1653
1654FX_TXTRUN::FX_TXTRUN(const FX_TXTRUN& other) = default;
1655
1656CFX_TxtPiece::CFX_TxtPiece()
1657 : m_dwStatus(FX_TXTBREAK_PieceBreak),
1658 m_iStartPos(0),
1659 m_iWidth(-1),
1660 m_iStartChar(0),
1661 m_iChars(0),
1662 m_iBidiLevel(0),
1663 m_iBidiPos(0),
1664 m_iHorizontalScale(100),
1665 m_iVerticalScale(100),
1666 m_dwCharStyles(0),
dsinclair85d1f2c2016-06-23 12:40:16 -07001667 m_pChars(nullptr),
1668 m_pUserData(nullptr) {}
weilieec3a362016-06-18 06:25:37 -07001669
1670CFX_TxtLine::CFX_TxtLine(int32_t iBlockSize)
tsepez33316fc2017-01-24 12:17:40 -08001671 : m_pLineChars(new std::vector<CFX_TxtChar>),
weili1b4f6b32016-08-04 16:37:48 -07001672 m_pLinePieces(new CFX_TxtPieceArray(16)),
1673 m_iStart(0),
1674 m_iWidth(0),
1675 m_iArabicChars(0) {}
weilieec3a362016-06-18 06:25:37 -07001676
1677CFX_TxtLine::~CFX_TxtLine() {
1678 RemoveAll();
weilieec3a362016-06-18 06:25:37 -07001679}