blob: 9fe5a432f6ede0a9d17f849f75390349376e5eb1 [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
Dan Sinclair994acdc2017-04-18 13:56:39 -04007#include "xfa/fgas/layout/cfx_txtbreak.h"
Dan Sinclair1770c022016-03-14 14:14:16 -04008
9#include <algorithm>
10
dsinclaira52ab742016-09-29 13:59:29 -070011#include "core/fxcrt/fx_arabic.h"
Dan Sinclair235818f2017-08-31 14:26:25 -040012#include "core/fxcrt/fx_bidi.h"
dsinclaira52ab742016-09-29 13:59:29 -070013#include "core/fxcrt/fx_memory.h"
tsepeza9caab92016-12-14 05:57:10 -080014#include "third_party/base/ptr_util.h"
Dan Sinclair68eefa62017-08-30 12:16:16 -040015#include "xfa/fde/cfde_texteditengine.h"
npm4b91a2d2016-11-21 15:19:44 -080016#include "xfa/fgas/font/cfgas_gefont.h"
Dan Sinclair994acdc2017-04-18 13:56:39 -040017#include "xfa/fgas/layout/cfx_linebreak.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040018
tsepez215507d2016-06-09 19:05:47 -070019namespace {
20
Dan Sinclair812e96c2017-03-13 16:43:37 -040021bool IsCtrlCode(wchar_t ch) {
Dan Sinclairfc9b9882017-03-07 09:18:18 -050022 uint32_t dwRet = (FX_GetUnicodeProperties(ch) & FX_CHARTYPEBITSMASK);
23 return dwRet == FX_CHARTYPE_Tab || dwRet == FX_CHARTYPE_Control;
24}
25
tsepez215507d2016-06-09 19:05:47 -070026} // namespace
27
Dan Sinclair52c73c22017-03-09 13:27:29 -050028CFX_TxtBreak::CFX_TxtBreak()
Dan Sinclaire533b932017-03-16 11:47:20 -040029 : CFX_Break(FX_LAYOUTSTYLE_None),
Dan Sinclair9e9bab62017-03-09 16:59:12 -050030 m_iAlignment(CFX_TxtLineAlignment_Left),
Dan Sinclair2a6482c2017-03-20 14:51:17 -040031 m_iCombWidth(360000) {}
weili1b4f6b32016-08-04 16:37:48 -070032
dan sinclair6fcea1f2017-03-13 13:06:05 -040033CFX_TxtBreak::~CFX_TxtBreak() {}
weili1b4f6b32016-08-04 16:37:48 -070034
Dan Sinclair05df0752017-03-14 14:43:42 -040035void CFX_TxtBreak::SetLineWidth(float fLineWidth) {
Dan Sinclair1770c022016-03-14 14:14:16 -040036 m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f);
dsinclair43854a52016-04-27 12:26:00 -070037 ASSERT(m_iLineWidth >= 20000);
Dan Sinclair1770c022016-03-14 14:14:16 -040038}
weili1b4f6b32016-08-04 16:37:48 -070039
Dan Sinclair1770c022016-03-14 14:14:16 -040040void CFX_TxtBreak::SetAlignment(int32_t iAlignment) {
Dan Sinclair9e9bab62017-03-09 16:59:12 -050041 ASSERT(iAlignment >= CFX_TxtLineAlignment_Left &&
42 iAlignment <= CFX_TxtLineAlignment_Justified);
Dan Sinclair1770c022016-03-14 14:14:16 -040043 m_iAlignment = iAlignment;
Dan Sinclair1770c022016-03-14 14:14:16 -040044}
weili1b4f6b32016-08-04 16:37:48 -070045
Dan Sinclair05df0752017-03-14 14:43:42 -040046void CFX_TxtBreak::SetCombWidth(float fCombWidth) {
Dan Sinclair1770c022016-03-14 14:14:16 -040047 m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f);
48}
weili1b4f6b32016-08-04 16:37:48 -070049
Dan Sinclairdb0cc522017-03-16 11:48:04 -040050void CFX_TxtBreak::AppendChar_Combination(CFX_Char* pCurChar) {
Lei Zhang04f73602017-08-01 14:00:19 -070051 wchar_t wch = pCurChar->char_code();
Dan Sinclair812e96c2017-03-13 16:43:37 -040052 wchar_t wForm;
Dan Sinclair1770c022016-03-14 14:14:16 -040053 int32_t iCharWidth = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -040054 pCurChar->m_iCharWidth = -1;
55 if (m_bCombText) {
56 iCharWidth = m_iCombWidth;
57 } else {
Dan Sinclair068d3442017-03-13 10:15:36 -040058 wForm = wch;
Dan Sinclair5c529e62017-03-21 11:31:25 -040059 CFX_Char* pLastChar = GetLastChar(0, false, false);
Dan Sinclair068d3442017-03-13 10:15:36 -040060 if (pLastChar &&
61 (pLastChar->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicShadda) == 0) {
62 bool bShadda = false;
63 if (wch == 0x0651) {
Lei Zhang04f73602017-08-01 14:00:19 -070064 wchar_t wLast = pLastChar->char_code();
Dan Sinclair068d3442017-03-13 10:15:36 -040065 if (wLast >= 0x064C && wLast <= 0x0650) {
66 wForm = FX_GetArabicFromShaddaTable(wLast);
67 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -040068 }
Dan Sinclair068d3442017-03-13 10:15:36 -040069 } else if (wch >= 0x064C && wch <= 0x0650) {
Lei Zhang04f73602017-08-01 14:00:19 -070070 if (pLastChar->char_code() == 0x0651) {
Dan Sinclair068d3442017-03-13 10:15:36 -040071 wForm = FX_GetArabicFromShaddaTable(wch);
72 bShadda = true;
Dan Sinclair52c73c22017-03-09 13:27:29 -050073 }
Dan Sinclair1770c022016-03-14 14:14:16 -040074 }
Dan Sinclair068d3442017-03-13 10:15:36 -040075 if (bShadda) {
76 pLastChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
77 pLastChar->m_iCharWidth = 0;
78 pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
79 }
Dan Sinclair1770c022016-03-14 14:14:16 -040080 }
Dan Sinclair068d3442017-03-13 10:15:36 -040081 if (!m_pFont->GetCharWidth(wForm, iCharWidth, false))
82 iCharWidth = 0;
83
Dan Sinclair1770c022016-03-14 14:14:16 -040084 iCharWidth *= m_iFontSize;
Dan Sinclaire533b932017-03-16 11:47:20 -040085 iCharWidth = iCharWidth * m_iHorizontalScale / 100;
Dan Sinclair1770c022016-03-14 14:14:16 -040086 }
87 pCurChar->m_iCharWidth = -iCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -040088}
weili1b4f6b32016-08-04 16:37:48 -070089
Dan Sinclairdb0cc522017-03-16 11:48:04 -040090void CFX_TxtBreak::AppendChar_Tab(CFX_Char* pCurChar) {
weilia2c06e42016-05-20 17:09:48 -070091 m_eCharType = FX_CHARTYPE_Tab;
Dan Sinclair1770c022016-03-14 14:14:16 -040092}
weili1b4f6b32016-08-04 16:37:48 -070093
Dan Sinclair893822a2017-03-13 15:32:07 -040094CFX_BreakType CFX_TxtBreak::AppendChar_Control(CFX_Char* pCurChar) {
weilia2c06e42016-05-20 17:09:48 -070095 m_eCharType = FX_CHARTYPE_Control;
Dan Sinclairc36fe072017-03-09 16:58:12 -050096 CFX_BreakType dwRet = CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -040097 if (!m_bSingleLine) {
Lei Zhang04f73602017-08-01 14:00:19 -070098 wchar_t wch = pCurChar->char_code();
Dan Sinclair1770c022016-03-14 14:14:16 -040099 switch (wch) {
100 case L'\v':
101 case 0x2028:
Dan Sinclairc36fe072017-03-09 16:58:12 -0500102 dwRet = CFX_BreakType::Line;
Dan Sinclair1770c022016-03-14 14:14:16 -0400103 break;
104 case L'\f':
Dan Sinclairc36fe072017-03-09 16:58:12 -0500105 dwRet = CFX_BreakType::Page;
Dan Sinclair1770c022016-03-14 14:14:16 -0400106 break;
107 case 0x2029:
Dan Sinclairc36fe072017-03-09 16:58:12 -0500108 dwRet = CFX_BreakType::Paragraph;
Dan Sinclair1770c022016-03-14 14:14:16 -0400109 break;
110 default:
Dan Sinclaire533b932017-03-16 11:47:20 -0400111 if (wch == m_wParagraphBreakChar)
Dan Sinclairc36fe072017-03-09 16:58:12 -0500112 dwRet = CFX_BreakType::Paragraph;
Dan Sinclair1770c022016-03-14 14:14:16 -0400113 break;
114 }
Dan Sinclairc36fe072017-03-09 16:58:12 -0500115 if (dwRet != CFX_BreakType::None)
Dan Sinclair1770c022016-03-14 14:14:16 -0400116 dwRet = EndBreak(dwRet);
Dan Sinclair1770c022016-03-14 14:14:16 -0400117 }
118 return dwRet;
119}
weili1b4f6b32016-08-04 16:37:48 -0700120
Dan Sinclair893822a2017-03-13 15:32:07 -0400121CFX_BreakType CFX_TxtBreak::AppendChar_Arabic(CFX_Char* pCurChar) {
weilia2c06e42016-05-20 17:09:48 -0700122 FX_CHARTYPE chartype = pCurChar->GetCharType();
Dan Sinclair1770c022016-03-14 14:14:16 -0400123 int32_t& iLineWidth = m_pCurLine->m_iWidth;
Dan Sinclair812e96c2017-03-13 16:43:37 -0400124 wchar_t wForm;
Dan Sinclair1770c022016-03-14 14:14:16 -0400125 int32_t iCharWidth = 0;
Dan Sinclair893822a2017-03-13 15:32:07 -0400126 CFX_Char* pLastChar = nullptr;
tsepezd19e9122016-11-02 15:43:18 -0700127 bool bAlef = false;
weilia2c06e42016-05-20 17:09:48 -0700128 if (!m_bCombText && m_eCharType >= FX_CHARTYPE_ArabicAlef &&
129 m_eCharType <= FX_CHARTYPE_ArabicDistortion) {
Dan Sinclair5c529e62017-03-21 11:31:25 -0400130 pLastChar = GetLastChar(1, true, false);
dsinclair85d1f2c2016-06-23 12:40:16 -0700131 if (pLastChar) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400132 iCharWidth = pLastChar->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500133 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400134 iLineWidth -= iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500135
Dan Sinclair5c529e62017-03-21 11:31:25 -0400136 CFX_Char* pPrevChar = GetLastChar(2, true, false);
tsepeze00f75c2016-05-06 13:15:46 -0700137 wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar);
Dan Sinclair1770c022016-03-14 14:14:16 -0400138 bAlef = (wForm == 0xFEFF &&
139 pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef);
Dan Sinclair068d3442017-03-13 10:15:36 -0400140 m_pFont->GetCharWidth(wForm, iCharWidth, false);
Dan Sinclair17f31182017-03-01 09:31:51 -0500141
142 if (wForm == 0xFEFF)
Dan Sinclair1770c022016-03-14 14:14:16 -0400143 iCharWidth = m_iDefChar;
Dan Sinclair17f31182017-03-01 09:31:51 -0500144
Dan Sinclair1770c022016-03-14 14:14:16 -0400145 iCharWidth *= m_iFontSize;
Dan Sinclaire533b932017-03-16 11:47:20 -0400146 iCharWidth = iCharWidth * m_iHorizontalScale / 100;
Dan Sinclair1770c022016-03-14 14:14:16 -0400147 pLastChar->m_iCharWidth = iCharWidth;
148 iLineWidth += iCharWidth;
149 iCharWidth = 0;
150 }
151 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500152
weilia2c06e42016-05-20 17:09:48 -0700153 m_eCharType = chartype;
dsinclair85d1f2c2016-06-23 12:40:16 -0700154 wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar,
155 nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400156 if (m_bCombText) {
157 iCharWidth = m_iCombWidth;
158 } else {
Dan Sinclair068d3442017-03-13 10:15:36 -0400159 m_pFont->GetCharWidth(wForm, iCharWidth, false);
Dan Sinclair17f31182017-03-01 09:31:51 -0500160
161 if (wForm == 0xFEFF)
Dan Sinclair1770c022016-03-14 14:14:16 -0400162 iCharWidth = m_iDefChar;
Dan Sinclair17f31182017-03-01 09:31:51 -0500163
Dan Sinclair1770c022016-03-14 14:14:16 -0400164 iCharWidth *= m_iFontSize;
Dan Sinclaire533b932017-03-16 11:47:20 -0400165 iCharWidth = iCharWidth * m_iHorizontalScale / 100;
Dan Sinclair1770c022016-03-14 14:14:16 -0400166 }
167 pCurChar->m_iCharWidth = iCharWidth;
168 iLineWidth += iCharWidth;
169 m_pCurLine->m_iArabicChars++;
Dan Sinclair17f31182017-03-01 09:31:51 -0500170 if (!m_bSingleLine && iLineWidth > m_iLineWidth + m_iTolerance)
Dan Sinclairc36fe072017-03-09 16:58:12 -0500171 return EndBreak(CFX_BreakType::Line);
172 return CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400173}
weili1b4f6b32016-08-04 16:37:48 -0700174
Dan Sinclair893822a2017-03-13 15:32:07 -0400175CFX_BreakType CFX_TxtBreak::AppendChar_Others(CFX_Char* pCurChar) {
weilia2c06e42016-05-20 17:09:48 -0700176 FX_CHARTYPE chartype = pCurChar->GetCharType();
Dan Sinclair1770c022016-03-14 14:14:16 -0400177 int32_t& iLineWidth = m_pCurLine->m_iWidth;
178 int32_t iCharWidth = 0;
weilia2c06e42016-05-20 17:09:48 -0700179 m_eCharType = chartype;
Lei Zhang04f73602017-08-01 14:00:19 -0700180 wchar_t wch = pCurChar->char_code();
Dan Sinclair812e96c2017-03-13 16:43:37 -0400181 wchar_t wForm = wch;
Dan Sinclair17f31182017-03-01 09:31:51 -0500182
Dan Sinclair1770c022016-03-14 14:14:16 -0400183 if (m_bCombText) {
184 iCharWidth = m_iCombWidth;
185 } else {
Dan Sinclair068d3442017-03-13 10:15:36 -0400186 if (!m_pFont->GetCharWidth(wForm, iCharWidth, false))
Dan Sinclair1770c022016-03-14 14:14:16 -0400187 iCharWidth = m_iDefChar;
Dan Sinclair17f31182017-03-01 09:31:51 -0500188
Dan Sinclair1770c022016-03-14 14:14:16 -0400189 iCharWidth *= m_iFontSize;
Dan Sinclaire533b932017-03-16 11:47:20 -0400190 iCharWidth = iCharWidth * m_iHorizontalScale / 100;
Dan Sinclair1770c022016-03-14 14:14:16 -0400191 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500192
Dan Sinclair1770c022016-03-14 14:14:16 -0400193 iCharWidth += m_iCharSpace;
194 pCurChar->m_iCharWidth = iCharWidth;
195 iLineWidth += iCharWidth;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500196 if (!m_bSingleLine && chartype != FX_CHARTYPE_Space &&
197 iLineWidth > m_iLineWidth + m_iTolerance) {
Dan Sinclairc36fe072017-03-09 16:58:12 -0500198 return EndBreak(CFX_BreakType::Line);
Dan Sinclair52c73c22017-03-09 13:27:29 -0500199 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500200
Dan Sinclairc36fe072017-03-09 16:58:12 -0500201 return CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400202}
tsepez215507d2016-06-09 19:05:47 -0700203
Dan Sinclair812e96c2017-03-13 16:43:37 -0400204CFX_BreakType CFX_TxtBreak::AppendChar(wchar_t wch) {
Tom Sepez740bcd82017-09-01 12:40:05 -0700205 uint32_t dwProps = FX_GetUnicodeProperties(wch);
weilia2c06e42016-05-20 17:09:48 -0700206 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
Lei Zhang04f73602017-08-01 14:00:19 -0700207 m_pCurLine->m_LineChars.emplace_back(wch, dwProps, m_iHorizontalScale,
208 m_iVerticalScale);
Dan Sinclair893822a2017-03-13 15:32:07 -0400209 CFX_Char* pCurChar = &m_pCurLine->m_LineChars.back();
Lei Zhang04f73602017-08-01 14:00:19 -0700210 pCurChar->m_dwCharStyles = m_iAlignment | (1 << 8);
Dan Sinclair1c97fd12017-03-09 16:58:55 -0500211
Dan Sinclairc36fe072017-03-09 16:58:12 -0500212 CFX_BreakType dwRet1 = CFX_BreakType::None;
weilia2c06e42016-05-20 17:09:48 -0700213 if (chartype != FX_CHARTYPE_Combination &&
Dan Sinclair17f31182017-03-01 09:31:51 -0500214 GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) &&
215 m_eCharType != FX_CHARTYPE_Unknown &&
216 m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine &&
217 (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) {
Dan Sinclairc36fe072017-03-09 16:58:12 -0500218 dwRet1 = EndBreak(CFX_BreakType::Line);
Dan Sinclair17f31182017-03-01 09:31:51 -0500219 int32_t iCount = m_pCurLine->CountChars();
220 if (iCount > 0)
Dan Sinclair52c73c22017-03-09 13:27:29 -0500221 pCurChar = &m_pCurLine->m_LineChars[iCount - 1];
Dan Sinclair1770c022016-03-14 14:14:16 -0400222 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500223
Dan Sinclairdb0cc522017-03-16 11:48:04 -0400224 CFX_BreakType dwRet2 = CFX_BreakType::None;
Dan Sinclair68eefa62017-08-30 12:16:16 -0400225 if (wch == m_wParagraphBreakChar) {
226 // This is handled in AppendChar_Control, but it seems like \n and \r
227 // don't get matched as control characters so we go into AppendChar_other
228 // and never detect the new paragraph ...
229 dwRet2 = CFX_BreakType::Paragraph;
230 } else {
231 switch (chartype) {
232 case FX_CHARTYPE_Tab:
233 AppendChar_Tab(pCurChar);
234 break;
235 case FX_CHARTYPE_Control:
236 dwRet2 = AppendChar_Control(pCurChar);
237 break;
238 case FX_CHARTYPE_Combination:
239 AppendChar_Combination(pCurChar);
240 break;
241 case FX_CHARTYPE_ArabicAlef:
242 case FX_CHARTYPE_ArabicSpecial:
243 case FX_CHARTYPE_ArabicDistortion:
244 case FX_CHARTYPE_ArabicNormal:
245 case FX_CHARTYPE_ArabicForm:
246 case FX_CHARTYPE_Arabic:
247 dwRet2 = AppendChar_Arabic(pCurChar);
248 break;
249 case FX_CHARTYPE_Unknown:
250 case FX_CHARTYPE_Space:
251 case FX_CHARTYPE_Numeric:
252 case FX_CHARTYPE_Normal:
253 default:
254 dwRet2 = AppendChar_Others(pCurChar);
255 break;
256 }
Dan Sinclairdb0cc522017-03-16 11:48:04 -0400257 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400258 return std::max(dwRet1, dwRet2);
259}
weili1b4f6b32016-08-04 16:37:48 -0700260
Dan Sinclair893822a2017-03-13 15:32:07 -0400261bool CFX_TxtBreak::EndBreak_SplitLine(CFX_BreakLine* pNextLine,
262 bool bAllChars) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400263 int32_t iCount = m_pCurLine->CountChars();
tsepezd19e9122016-11-02 15:43:18 -0700264 bool bDone = false;
Dan Sinclair893822a2017-03-13 15:32:07 -0400265 CFX_Char* pTC;
Dan Sinclair1770c022016-03-14 14:14:16 -0400266 if (!m_bSingleLine && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance) {
Dan Sinclair893822a2017-03-13 15:32:07 -0400267 pTC = m_pCurLine->GetChar(iCount - 1);
Dan Sinclair1770c022016-03-14 14:14:16 -0400268 switch (pTC->GetCharType()) {
269 case FX_CHARTYPE_Tab:
270 case FX_CHARTYPE_Control:
Dan Sinclair1770c022016-03-14 14:14:16 -0400271 case FX_CHARTYPE_Space:
Dan Sinclair1770c022016-03-14 14:14:16 -0400272 break;
273 default:
Dan Sinclair52c73c22017-03-09 13:27:29 -0500274 SplitTextLine(m_pCurLine, pNextLine, bAllChars);
tsepezd19e9122016-11-02 15:43:18 -0700275 bDone = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400276 break;
277 }
278 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500279
Dan Sinclair1770c022016-03-14 14:14:16 -0400280 iCount = m_pCurLine->CountChars();
Dan Sinclair893822a2017-03-13 15:32:07 -0400281 CFX_BreakPiece tp;
Dan Sinclair1770c022016-03-14 14:14:16 -0400282 if (bAllChars && !bDone) {
283 int32_t iEndPos = m_pCurLine->m_iWidth;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500284 GetBreakPos(m_pCurLine->m_LineChars, iEndPos, bAllChars, true);
Dan Sinclair1770c022016-03-14 14:14:16 -0400285 }
tsepezd19e9122016-11-02 15:43:18 -0700286 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400287}
weili1b4f6b32016-08-04 16:37:48 -0700288
Tom Sepez4a211142017-03-01 14:41:25 -0800289void CFX_TxtBreak::EndBreak_BidiLine(std::deque<FX_TPO>* tpos,
Dan Sinclairc36fe072017-03-09 16:58:12 -0500290 CFX_BreakType dwStatus) {
Dan Sinclair893822a2017-03-13 15:32:07 -0400291 CFX_BreakPiece tp;
Dan Sinclair1770c022016-03-14 14:14:16 -0400292 FX_TPO tpo;
Dan Sinclair893822a2017-03-13 15:32:07 -0400293 CFX_Char* pTC;
Dan Sinclair17f31182017-03-01 09:31:51 -0500294 int32_t i;
295 int32_t j;
Dan Sinclair893822a2017-03-13 15:32:07 -0400296 std::vector<CFX_Char>& chars = m_pCurLine->m_LineChars;
Dan Sinclair1770c022016-03-14 14:14:16 -0400297 int32_t iCount = m_pCurLine->CountChars();
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400298 bool bDone = m_pCurLine->m_iArabicChars > 0;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500299 if (bDone) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400300 int32_t iBidiNum = 0;
301 for (i = 0; i < iCount; i++) {
tsepez33316fc2017-01-24 12:17:40 -0800302 pTC = &chars[i];
Dan Sinclair1770c022016-03-14 14:14:16 -0400303 pTC->m_iBidiPos = i;
Dan Sinclair17f31182017-03-01 09:31:51 -0500304 if (pTC->GetCharType() != FX_CHARTYPE_Control)
Dan Sinclair1770c022016-03-14 14:14:16 -0400305 iBidiNum = i;
Dan Sinclair17f31182017-03-01 09:31:51 -0500306 if (i == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400307 pTC->m_iBidiLevel = 1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400308 }
Dan Sinclair42059a32017-03-15 12:22:48 -0400309 FX_BidiLine(&chars, iBidiNum + 1);
Dan Sinclair1770c022016-03-14 14:14:16 -0400310 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500311
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400312 if (bDone) {
Dan Sinclairc36fe072017-03-09 16:58:12 -0500313 tp.m_dwStatus = CFX_BreakType::Piece;
Dan Sinclair1770c022016-03-14 14:14:16 -0400314 tp.m_iStartPos = m_pCurLine->m_iStart;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500315 tp.m_pChars = &m_pCurLine->m_LineChars;
Dan Sinclair17f31182017-03-01 09:31:51 -0500316 int32_t iBidiLevel = -1;
317 int32_t iCharWidth;
318 i = 0;
319 j = -1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400320 while (i < iCount) {
tsepez33316fc2017-01-24 12:17:40 -0800321 pTC = &chars[i];
Dan Sinclair1770c022016-03-14 14:14:16 -0400322 if (iBidiLevel < 0) {
323 iBidiLevel = pTC->m_iBidiLevel;
324 tp.m_iWidth = 0;
325 tp.m_iBidiLevel = iBidiLevel;
326 tp.m_iBidiPos = pTC->m_iBidiOrder;
327 tp.m_dwCharStyles = pTC->m_dwCharStyles;
Lei Zhang04f73602017-08-01 14:00:19 -0700328 tp.m_iHorizontalScale = pTC->horizonal_scale();
329 tp.m_iVerticalScale = pTC->vertical_scale();
Dan Sinclairc36fe072017-03-09 16:58:12 -0500330 tp.m_dwStatus = CFX_BreakType::Piece;
Dan Sinclair1770c022016-03-14 14:14:16 -0400331 }
Dan Sinclairc36fe072017-03-09 16:58:12 -0500332 if (iBidiLevel != pTC->m_iBidiLevel ||
333 pTC->m_dwStatus != CFX_BreakType::None) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400334 if (iBidiLevel == pTC->m_iBidiLevel) {
335 tp.m_dwStatus = pTC->m_dwStatus;
336 iCharWidth = pTC->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500337 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400338 tp.m_iWidth += iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500339
Dan Sinclair1770c022016-03-14 14:14:16 -0400340 i++;
341 }
342 tp.m_iChars = i - tp.m_iStartChar;
dan sinclair6fcea1f2017-03-13 13:06:05 -0400343 m_pCurLine->m_LinePieces.push_back(tp);
Dan Sinclair1770c022016-03-14 14:14:16 -0400344 tp.m_iStartPos += tp.m_iWidth;
345 tp.m_iStartChar = i;
346 tpo.index = ++j;
347 tpo.pos = tp.m_iBidiPos;
Tom Sepez4a211142017-03-01 14:41:25 -0800348 tpos->push_back(tpo);
Dan Sinclair1770c022016-03-14 14:14:16 -0400349 iBidiLevel = -1;
350 } else {
351 iCharWidth = pTC->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500352 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400353 tp.m_iWidth += iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500354
Dan Sinclair1770c022016-03-14 14:14:16 -0400355 i++;
356 }
357 }
358 if (i > tp.m_iStartChar) {
359 tp.m_dwStatus = dwStatus;
360 tp.m_iChars = i - tp.m_iStartChar;
dan sinclair6fcea1f2017-03-13 13:06:05 -0400361 m_pCurLine->m_LinePieces.push_back(tp);
Dan Sinclair1770c022016-03-14 14:14:16 -0400362 tpo.index = ++j;
363 tpo.pos = tp.m_iBidiPos;
Tom Sepez4a211142017-03-01 14:41:25 -0800364 tpos->push_back(tpo);
Dan Sinclair1770c022016-03-14 14:14:16 -0400365 }
366 if (j > -1) {
367 if (j > 0) {
Tom Sepez4a211142017-03-01 14:41:25 -0800368 std::sort(tpos->begin(), tpos->end());
Dan Sinclair1770c022016-03-14 14:14:16 -0400369 int32_t iStartPos = 0;
370 for (i = 0; i <= j; i++) {
Tom Sepez4a211142017-03-01 14:41:25 -0800371 tpo = (*tpos)[i];
Dan Sinclair893822a2017-03-13 15:32:07 -0400372 CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index];
Dan Sinclair1770c022016-03-14 14:14:16 -0400373 ttp.m_iStartPos = iStartPos;
374 iStartPos += ttp.m_iWidth;
375 }
376 }
dan sinclair6fcea1f2017-03-13 13:06:05 -0400377 m_pCurLine->m_LinePieces[j].m_dwStatus = dwStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400378 }
379 } else {
380 tp.m_dwStatus = dwStatus;
381 tp.m_iStartPos = m_pCurLine->m_iStart;
382 tp.m_iWidth = m_pCurLine->m_iWidth;
383 tp.m_iStartChar = 0;
384 tp.m_iChars = iCount;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500385 tp.m_pChars = &m_pCurLine->m_LineChars;
tsepez33316fc2017-01-24 12:17:40 -0800386 pTC = &chars[0];
Dan Sinclair1770c022016-03-14 14:14:16 -0400387 tp.m_dwCharStyles = pTC->m_dwCharStyles;
Lei Zhang04f73602017-08-01 14:00:19 -0700388 tp.m_iHorizontalScale = pTC->horizonal_scale();
389 tp.m_iVerticalScale = pTC->vertical_scale();
dan sinclair6fcea1f2017-03-13 13:06:05 -0400390 m_pCurLine->m_LinePieces.push_back(tp);
Tom Sepez4a211142017-03-01 14:41:25 -0800391 tpos->push_back({0, 0});
Dan Sinclair1770c022016-03-14 14:14:16 -0400392 }
393}
weili1b4f6b32016-08-04 16:37:48 -0700394
Tom Sepez4a211142017-03-01 14:41:25 -0800395void CFX_TxtBreak::EndBreak_Alignment(const std::deque<FX_TPO>& tpos,
tsepezd19e9122016-11-02 15:43:18 -0700396 bool bAllChars,
Dan Sinclairc36fe072017-03-09 16:58:12 -0500397 CFX_BreakType dwStatus) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500398 int32_t iNetWidth = m_pCurLine->m_iWidth;
399 int32_t iGapChars = 0;
tsepezd19e9122016-11-02 15:43:18 -0700400 bool bFind = false;
dan sinclair6fcea1f2017-03-13 13:06:05 -0400401 for (auto it = tpos.rbegin(); it != tpos.rend(); ++it) {
Dan Sinclair893822a2017-03-13 15:32:07 -0400402 CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it->index];
Dan Sinclair17f31182017-03-01 09:31:51 -0500403 if (!bFind)
Dan Sinclair1770c022016-03-14 14:14:16 -0400404 iNetWidth = ttp.GetEndPos();
Dan Sinclair17f31182017-03-01 09:31:51 -0500405
tsepezd19e9122016-11-02 15:43:18 -0700406 bool bArabic = FX_IsOdd(ttp.m_iBidiLevel);
dan sinclair6fcea1f2017-03-13 13:06:05 -0400407 int32_t j = bArabic ? 0 : ttp.m_iChars - 1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400408 while (j > -1 && j < ttp.m_iChars) {
Dan Sinclair893822a2017-03-13 15:32:07 -0400409 const CFX_Char* pTC = ttp.GetChar(j);
410 if (pTC->m_nBreakType == FX_LBT_DIRECT_BRK)
Dan Sinclair1770c022016-03-14 14:14:16 -0400411 iGapChars++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400412 if (!bFind || !bAllChars) {
Dan Sinclair893822a2017-03-13 15:32:07 -0400413 FX_CHARTYPE chartype = pTC->GetCharType();
weilia2c06e42016-05-20 17:09:48 -0700414 if (chartype == FX_CHARTYPE_Space || chartype == FX_CHARTYPE_Control) {
Dan Sinclair893822a2017-03-13 15:32:07 -0400415 if (!bFind && bAllChars && pTC->m_iCharWidth > 0)
416 iNetWidth -= pTC->m_iCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -0400417 } else {
tsepezd19e9122016-11-02 15:43:18 -0700418 bFind = true;
Dan Sinclair17f31182017-03-01 09:31:51 -0500419 if (!bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400420 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400421 }
422 }
423 j += bArabic ? 1 : -1;
424 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500425 if (!bAllChars && bFind)
Dan Sinclair1770c022016-03-14 14:14:16 -0400426 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400427 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500428
Dan Sinclair1770c022016-03-14 14:14:16 -0400429 int32_t iOffset = m_iLineWidth - iNetWidth;
Dan Sinclair2a6482c2017-03-20 14:51:17 -0400430 if (iGapChars > 0 && m_iAlignment & CFX_TxtLineAlignment_Justified &&
Dan Sinclair9e9bab62017-03-09 16:59:12 -0500431 dwStatus != CFX_BreakType::Paragraph) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400432 int32_t iStart = -1;
dan sinclair6fcea1f2017-03-13 13:06:05 -0400433 for (auto& tpo : tpos) {
Dan Sinclair893822a2017-03-13 15:32:07 -0400434 CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index];
Dan Sinclair17f31182017-03-01 09:31:51 -0500435 if (iStart < -1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400436 iStart = ttp.m_iStartPos;
Dan Sinclair17f31182017-03-01 09:31:51 -0500437 else
Dan Sinclair1770c022016-03-14 14:14:16 -0400438 ttp.m_iStartPos = iStart;
Dan Sinclair17f31182017-03-01 09:31:51 -0500439
dan sinclair6fcea1f2017-03-13 13:06:05 -0400440 for (int32_t j = 0; j < ttp.m_iChars; j++) {
Dan Sinclair893822a2017-03-13 15:32:07 -0400441 CFX_Char* pTC = ttp.GetChar(j);
442 if (pTC->m_nBreakType != FX_LBT_DIRECT_BRK || pTC->m_iCharWidth < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400443 continue;
Dan Sinclair17f31182017-03-01 09:31:51 -0500444
445 int32_t k = iOffset / iGapChars;
Dan Sinclair893822a2017-03-13 15:32:07 -0400446 pTC->m_iCharWidth += k;
Dan Sinclair1770c022016-03-14 14:14:16 -0400447 ttp.m_iWidth += k;
448 iOffset -= k;
449 iGapChars--;
Dan Sinclair17f31182017-03-01 09:31:51 -0500450 if (iGapChars < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400451 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400452 }
453 iStart += ttp.m_iWidth;
454 }
Dan Sinclair2a6482c2017-03-20 14:51:17 -0400455 } else if (m_iAlignment & CFX_TxtLineAlignment_Center ||
456 m_iAlignment & CFX_TxtLineAlignment_Right) {
457 if (m_iAlignment & CFX_TxtLineAlignment_Center &&
458 !(m_iAlignment & CFX_TxtLineAlignment_Right)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400459 iOffset /= 2;
Dan Sinclair9e9bab62017-03-09 16:59:12 -0500460 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400461 if (iOffset > 0) {
dan sinclair6fcea1f2017-03-13 13:06:05 -0400462 for (auto& ttp : m_pCurLine->m_LinePieces)
Dan Sinclair1770c022016-03-14 14:14:16 -0400463 ttp.m_iStartPos += iOffset;
Dan Sinclair1770c022016-03-14 14:14:16 -0400464 }
465 }
466}
weili1b4f6b32016-08-04 16:37:48 -0700467
Dan Sinclairc36fe072017-03-09 16:58:12 -0500468CFX_BreakType CFX_TxtBreak::EndBreak(CFX_BreakType dwStatus) {
469 ASSERT(dwStatus != CFX_BreakType::None);
dan sinclair6fcea1f2017-03-13 13:06:05 -0400470
471 if (!m_pCurLine->m_LinePieces.empty()) {
Dan Sinclairc36fe072017-03-09 16:58:12 -0500472 if (dwStatus != CFX_BreakType::Piece)
dan sinclair6fcea1f2017-03-13 13:06:05 -0400473 m_pCurLine->m_LinePieces.back().m_dwStatus = dwStatus;
474 return m_pCurLine->m_LinePieces.back().m_dwStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400475 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500476
Dan Sinclair5c529e62017-03-21 11:31:25 -0400477 if (HasLine()) {
Dan Sinclaire533b932017-03-16 11:47:20 -0400478 if (!m_Line[m_iReadyLineIndex].m_LinePieces.empty()) {
dan sinclair6fcea1f2017-03-13 13:06:05 -0400479 if (dwStatus != CFX_BreakType::Piece)
Dan Sinclaire533b932017-03-16 11:47:20 -0400480 m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus = dwStatus;
481 return m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus;
dan sinclair6fcea1f2017-03-13 13:06:05 -0400482 }
483 return CFX_BreakType::None;
484 }
485
486 int32_t iCount = m_pCurLine->CountChars();
487 if (iCount < 1)
488 return CFX_BreakType::None;
489
Dan Sinclair893822a2017-03-13 15:32:07 -0400490 m_pCurLine->GetChar(iCount - 1)->m_dwStatus = dwStatus;
dan sinclair6fcea1f2017-03-13 13:06:05 -0400491 if (dwStatus == CFX_BreakType::Piece)
492 return dwStatus;
493
Dan Sinclaire533b932017-03-16 11:47:20 -0400494 m_iReadyLineIndex = m_pCurLine == &m_Line[0] ? 0 : 1;
495 CFX_BreakLine* pNextLine = &m_Line[1 - m_iReadyLineIndex];
Dan Sinclair2a6482c2017-03-20 14:51:17 -0400496 bool bAllChars = m_iAlignment > CFX_TxtLineAlignment_Right;
Dan Sinclairc36fe072017-03-09 16:58:12 -0500497 if (!EndBreak_SplitLine(pNextLine, bAllChars)) {
Tom Sepez4a211142017-03-01 14:41:25 -0800498 std::deque<FX_TPO> tpos;
499 EndBreak_BidiLine(&tpos, dwStatus);
Dan Sinclair2a6482c2017-03-20 14:51:17 -0400500 if (m_iAlignment > CFX_TxtLineAlignment_Left)
Dan Sinclair17f31182017-03-01 09:31:51 -0500501 EndBreak_Alignment(tpos, bAllChars, dwStatus);
Dan Sinclair1770c022016-03-14 14:14:16 -0400502 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500503
Dan Sinclair1770c022016-03-14 14:14:16 -0400504 m_pCurLine = pNextLine;
Dan Sinclair5c529e62017-03-21 11:31:25 -0400505 CFX_Char* pTC = GetLastChar(0, false, false);
weilia2c06e42016-05-20 17:09:48 -0700506 m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown;
Dan Sinclair2a6482c2017-03-20 14:51:17 -0400507
Dan Sinclair1770c022016-03-14 14:14:16 -0400508 return dwStatus;
509}
weili1b4f6b32016-08-04 16:37:48 -0700510
Dan Sinclair893822a2017-03-13 15:32:07 -0400511int32_t CFX_TxtBreak::GetBreakPos(std::vector<CFX_Char>& ca,
Dan Sinclair1770c022016-03-14 14:14:16 -0400512 int32_t& iEndPos,
tsepezd19e9122016-11-02 15:43:18 -0700513 bool bAllChars,
514 bool bOnlyBrk) {
tsepez33316fc2017-01-24 12:17:40 -0800515 int32_t iLength = pdfium::CollectionSize<int32_t>(ca) - 1;
Dan Sinclair17f31182017-03-01 09:31:51 -0500516 if (iLength < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400517 return iLength;
Dan Sinclair17f31182017-03-01 09:31:51 -0500518
519 int32_t iBreak = -1;
520 int32_t iBreakPos = -1;
521 int32_t iIndirect = -1;
522 int32_t iIndirectPos = -1;
523 int32_t iLast = -1;
524 int32_t iLastPos = -1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400525 if (m_bSingleLine || iEndPos <= m_iLineWidth) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500526 if (!bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400527 return iLength;
Dan Sinclair17f31182017-03-01 09:31:51 -0500528
Dan Sinclair1770c022016-03-14 14:14:16 -0400529 iBreak = iLength;
530 iBreakPos = iEndPos;
531 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500532
Dan Sinclair1770c022016-03-14 14:14:16 -0400533 FX_LINEBREAKTYPE eType;
Dan Sinclair17f31182017-03-01 09:31:51 -0500534 uint32_t nCodeProp;
535 uint32_t nCur;
536 uint32_t nNext;
tsepez33316fc2017-01-24 12:17:40 -0800537 CFX_Char* pCur = &ca[iLength--];
Dan Sinclair17f31182017-03-01 09:31:51 -0500538 if (bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400539 pCur->m_nBreakType = FX_LBT_UNKNOWN;
Dan Sinclair17f31182017-03-01 09:31:51 -0500540
Lei Zhang04f73602017-08-01 14:00:19 -0700541 nCodeProp = pCur->char_props();
Dan Sinclair1770c022016-03-14 14:14:16 -0400542 nNext = nCodeProp & 0x003F;
543 int32_t iCharWidth = pCur->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500544 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400545 iEndPos -= iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500546
Dan Sinclair1770c022016-03-14 14:14:16 -0400547 while (iLength >= 0) {
tsepez33316fc2017-01-24 12:17:40 -0800548 pCur = &ca[iLength];
Lei Zhang04f73602017-08-01 14:00:19 -0700549 nCodeProp = pCur->char_props();
Dan Sinclair1770c022016-03-14 14:14:16 -0400550 nCur = nCodeProp & 0x003F;
Dan Sinclair47a90b82017-08-31 14:53:44 -0400551 if (nNext == kBreakPropertySpace)
Lei Zhang04f73602017-08-01 14:00:19 -0700552 eType = FX_LBT_PROHIBITED_BRK;
553 else
554 eType = gs_FX_LineBreak_PairTable[nCur][nNext];
Dan Sinclair17f31182017-03-01 09:31:51 -0500555 if (bAllChars)
556 pCur->m_nBreakType = static_cast<uint8_t>(eType);
Dan Sinclair1770c022016-03-14 14:14:16 -0400557 if (!bOnlyBrk) {
Dan Sinclair47a90b82017-08-31 14:53:44 -0400558 if (m_bSingleLine || iEndPos <= m_iLineWidth ||
559 nCur == kBreakPropertySpace) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400560 if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) {
561 iBreak = iLength;
562 iBreakPos = iEndPos;
Dan Sinclair17f31182017-03-01 09:31:51 -0500563 if (!bAllChars)
Dan Sinclair1770c022016-03-14 14:14:16 -0400564 return iLength;
Dan Sinclair1770c022016-03-14 14:14:16 -0400565 } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) {
566 iIndirect = iLength;
567 iIndirectPos = iEndPos;
568 }
569 if (iLast < 0) {
570 iLast = iLength;
571 iLastPos = iEndPos;
572 }
573 }
574 iCharWidth = pCur->m_iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500575 if (iCharWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400576 iEndPos -= iCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -0400577 }
578 nNext = nCodeProp & 0x003F;
579 iLength--;
580 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500581 if (bOnlyBrk)
Dan Sinclair1770c022016-03-14 14:14:16 -0400582 return 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400583 if (iBreak > -1) {
584 iEndPos = iBreakPos;
585 return iBreak;
586 }
587 if (iIndirect > -1) {
588 iEndPos = iIndirectPos;
589 return iIndirect;
590 }
591 if (iLast > -1) {
592 iEndPos = iLastPos;
593 return iLast;
594 }
595 return 0;
596}
weili1b4f6b32016-08-04 16:37:48 -0700597
Dan Sinclair893822a2017-03-13 15:32:07 -0400598void CFX_TxtBreak::SplitTextLine(CFX_BreakLine* pCurLine,
599 CFX_BreakLine* pNextLine,
tsepezd19e9122016-11-02 15:43:18 -0700600 bool bAllChars) {
dsinclair85d1f2c2016-06-23 12:40:16 -0700601 ASSERT(pCurLine && pNextLine);
Dan Sinclair1770c022016-03-14 14:14:16 -0400602 int32_t iCount = pCurLine->CountChars();
Dan Sinclair17f31182017-03-01 09:31:51 -0500603 if (iCount < 2)
Dan Sinclair1770c022016-03-14 14:14:16 -0400604 return;
Dan Sinclair17f31182017-03-01 09:31:51 -0500605
Dan Sinclair1770c022016-03-14 14:14:16 -0400606 int32_t iEndPos = pCurLine->m_iWidth;
Dan Sinclair893822a2017-03-13 15:32:07 -0400607 std::vector<CFX_Char>& curChars = pCurLine->m_LineChars;
tsepezd19e9122016-11-02 15:43:18 -0700608 int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false);
Dan Sinclair17f31182017-03-01 09:31:51 -0500609 if (iCharPos < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400610 iCharPos = 0;
Dan Sinclair17f31182017-03-01 09:31:51 -0500611
Dan Sinclair1770c022016-03-14 14:14:16 -0400612 iCharPos++;
613 if (iCharPos >= iCount) {
dan sinclair6fcea1f2017-03-13 13:06:05 -0400614 pNextLine->Clear();
tsepez33316fc2017-01-24 12:17:40 -0800615 CFX_Char* pTC = &curChars[iCharPos - 1];
Dan Sinclair1770c022016-03-14 14:14:16 -0400616 pTC->m_nBreakType = FX_LBT_UNKNOWN;
617 return;
618 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500619
Dan Sinclair52c73c22017-03-09 13:27:29 -0500620 pNextLine->m_LineChars =
Dan Sinclair893822a2017-03-13 15:32:07 -0400621 std::vector<CFX_Char>(curChars.begin() + iCharPos, curChars.end());
tsepez33316fc2017-01-24 12:17:40 -0800622 curChars.erase(curChars.begin() + iCharPos, curChars.end());
Dan Sinclair1770c022016-03-14 14:14:16 -0400623 pCurLine->m_iWidth = iEndPos;
Dan Sinclair893822a2017-03-13 15:32:07 -0400624 CFX_Char* pTC = &curChars[iCharPos - 1];
Dan Sinclair1770c022016-03-14 14:14:16 -0400625 pTC->m_nBreakType = FX_LBT_UNKNOWN;
Dan Sinclair52c73c22017-03-09 13:27:29 -0500626 iCount = pdfium::CollectionSize<int>(pNextLine->m_LineChars);
tsepez33316fc2017-01-24 12:17:40 -0800627 int32_t iWidth = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400628 for (int32_t i = 0; i < iCount; i++) {
Dan Sinclair52c73c22017-03-09 13:27:29 -0500629 if (pNextLine->m_LineChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400630 pCurLine->m_iArabicChars--;
631 pNextLine->m_iArabicChars++;
632 }
Dan Sinclair52c73c22017-03-09 13:27:29 -0500633 iWidth += std::max(0, pNextLine->m_LineChars[i].m_iCharWidth);
Dan Sinclairc36fe072017-03-09 16:58:12 -0500634 pNextLine->m_LineChars[i].m_dwStatus = CFX_BreakType::None;
Dan Sinclair1770c022016-03-14 14:14:16 -0400635 }
636 pNextLine->m_iWidth = iWidth;
637}
weili1b4f6b32016-08-04 16:37:48 -0700638
Dan Sinclair1770c022016-03-14 14:14:16 -0400639struct FX_FORMCHAR {
Tom Sepez62a70f92016-03-21 15:00:20 -0700640 uint16_t wch;
641 uint16_t wForm;
Dan Sinclair1770c022016-03-14 14:14:16 -0400642 int32_t iWidth;
643};
644
645int32_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun,
Dan Sinclair171cb272017-08-15 09:43:07 -0400646 FXTEXT_CHARPOS* pCharPos) const {
Dan Sinclair17f31182017-03-01 09:31:51 -0500647 if (!pTxtRun || pTxtRun->iLength < 1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400648 return 0;
Dan Sinclair17f31182017-03-01 09:31:51 -0500649
Dan Sinclair68eefa62017-08-30 12:16:16 -0400650 CFDE_TextEditEngine* pEngine = pTxtRun->pEdtEngine;
Dan Sinclair812e96c2017-03-13 16:43:37 -0400651 const wchar_t* pStr = pTxtRun->wsStr.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -0400652 int32_t* pWidths = pTxtRun->pWidths;
653 int32_t iLength = pTxtRun->iLength - 1;
tsepeze6477992017-01-05 12:57:00 -0800654 CFX_RetainPtr<CFGAS_GEFont> pFont = pTxtRun->pFont;
tsepez736f28a2016-03-25 14:19:51 -0700655 uint32_t dwStyles = pTxtRun->dwStyles;
Dan Sinclair1770c022016-03-14 14:14:16 -0400656 CFX_RectF rtText(*pTxtRun->pRect);
tsepezd19e9122016-11-02 15:43:18 -0700657 bool bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
Dan Sinclair05df0752017-03-14 14:43:42 -0400658 float fFontSize = pTxtRun->fFontSize;
Dan Sinclair1770c022016-03-14 14:14:16 -0400659 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
660 int32_t iAscent = pFont->GetAscent();
661 int32_t iDescent = pFont->GetDescent();
662 int32_t iMaxHeight = iAscent - iDescent;
Dan Sinclair05df0752017-03-14 14:43:42 -0400663 float fFontHeight = fFontSize;
664 float fAscent = fFontHeight * (float)iAscent / (float)iMaxHeight;
665 float fX = rtText.left;
666 float fY;
667 float fCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -0400668 int32_t iHorScale = pTxtRun->iHorizontalScale;
669 int32_t iVerScale = pTxtRun->iVerticalScale;
tsepezd19e9122016-11-02 15:43:18 -0700670 bool bSkipSpace = pTxtRun->bSkipSpace;
Dan Sinclair1770c022016-03-14 14:14:16 -0400671 FX_FORMCHAR formChars[3];
Dan Sinclair05df0752017-03-14 14:43:42 -0400672 float fYBase;
Dan Sinclair17f31182017-03-01 09:31:51 -0500673
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400674 if (bRTLPiece)
675 fX = rtText.right();
Dan Sinclair17f31182017-03-01 09:31:51 -0500676
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400677 fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f;
678 fY = fYBase + fAscent;
Dan Sinclair17f31182017-03-01 09:31:51 -0500679
weili038aa532016-05-20 15:38:29 -0700680 int32_t iCount = 0;
681 int32_t iNext = 0;
Dan Sinclair812e96c2017-03-13 16:43:37 -0400682 wchar_t wPrev = 0xFEFF;
683 wchar_t wNext = 0xFEFF;
684 wchar_t wForm = 0xFEFF;
685 wchar_t wLast = 0xFEFF;
tsepezd19e9122016-11-02 15:43:18 -0700686 bool bShadda = false;
687 bool bLam = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400688 for (int32_t i = 0; i <= iLength; i++) {
weili038aa532016-05-20 15:38:29 -0700689 int32_t iWidth;
Dan Sinclair812e96c2017-03-13 16:43:37 -0400690 wchar_t wch;
Dan Sinclair68eefa62017-08-30 12:16:16 -0400691 if (pEngine) {
692 wch = pEngine->GetChar(i);
693 iWidth = pEngine->GetWidthOfChar(i);
Dan Sinclair1770c022016-03-14 14:14:16 -0400694 } else {
695 wch = *pStr++;
696 iWidth = *pWidths++;
697 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500698
weili038aa532016-05-20 15:38:29 -0700699 uint32_t dwProps = FX_GetUnicodeProperties(wch);
weilia2c06e42016-05-20 17:09:48 -0700700 FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps);
701 if (chartype == FX_CHARTYPE_ArabicAlef && iWidth == 0) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400702 wPrev = 0xFEFF;
703 wLast = wch;
704 continue;
705 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500706
weilia2c06e42016-05-20 17:09:48 -0700707 if (chartype >= FX_CHARTYPE_ArabicAlef) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400708 if (i < iLength) {
Dan Sinclair68eefa62017-08-30 12:16:16 -0400709 if (pEngine) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400710 iNext = i + 1;
711 while (iNext <= iLength) {
Dan Sinclair68eefa62017-08-30 12:16:16 -0400712 wNext = pEngine->GetChar(iNext);
Dan Sinclair1770c022016-03-14 14:14:16 -0400713 dwProps = FX_GetUnicodeProperties(wNext);
Dan Sinclair17f31182017-03-01 09:31:51 -0500714 if ((dwProps & FX_CHARTYPEBITSMASK) != FX_CHARTYPE_Combination)
Dan Sinclair1770c022016-03-14 14:14:16 -0400715 break;
Dan Sinclair17f31182017-03-01 09:31:51 -0500716
Dan Sinclair1770c022016-03-14 14:14:16 -0400717 iNext++;
718 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500719 if (iNext > iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -0400720 wNext = 0xFEFF;
Dan Sinclair1770c022016-03-14 14:14:16 -0400721 } else {
722 int32_t j = -1;
723 do {
724 j++;
Dan Sinclair17f31182017-03-01 09:31:51 -0500725 if (i + j >= iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -0400726 break;
Dan Sinclair17f31182017-03-01 09:31:51 -0500727
Dan Sinclair1770c022016-03-14 14:14:16 -0400728 wNext = pStr[j];
729 dwProps = FX_GetUnicodeProperties(wNext);
730 } while ((dwProps & FX_CHARTYPEBITSMASK) == FX_CHARTYPE_Combination);
Dan Sinclair17f31182017-03-01 09:31:51 -0500731 if (i + j >= iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -0400732 wNext = 0xFEFF;
Dan Sinclair1770c022016-03-14 14:14:16 -0400733 }
734 } else {
735 wNext = 0xFEFF;
736 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500737
tsepeze00f75c2016-05-06 13:15:46 -0700738 wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext);
Dan Sinclair1770c022016-03-14 14:14:16 -0400739 bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647);
weilia2c06e42016-05-20 17:09:48 -0700740 } else if (chartype == FX_CHARTYPE_Combination) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400741 wForm = wch;
742 if (wch >= 0x064C && wch <= 0x0651) {
743 if (bShadda) {
744 wForm = 0xFEFF;
tsepezd19e9122016-11-02 15:43:18 -0700745 bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400746 } else {
747 wNext = 0xFEFF;
Dan Sinclair68eefa62017-08-30 12:16:16 -0400748 if (pEngine) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400749 iNext = i + 1;
Dan Sinclair17f31182017-03-01 09:31:51 -0500750 if (iNext <= iLength)
Dan Sinclair68eefa62017-08-30 12:16:16 -0400751 wNext = pEngine->GetChar(iNext);
Dan Sinclair1770c022016-03-14 14:14:16 -0400752 } else {
Dan Sinclair17f31182017-03-01 09:31:51 -0500753 if (i < iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -0400754 wNext = *pStr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400755 }
756 if (wch == 0x0651) {
757 if (wNext >= 0x064C && wNext <= 0x0650) {
758 wForm = FX_GetArabicFromShaddaTable(wNext);
tsepezd19e9122016-11-02 15:43:18 -0700759 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400760 }
761 } else {
762 if (wNext == 0x0651) {
763 wForm = FX_GetArabicFromShaddaTable(wch);
tsepezd19e9122016-11-02 15:43:18 -0700764 bShadda = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400765 }
766 }
767 }
768 } else {
tsepezd19e9122016-11-02 15:43:18 -0700769 bShadda = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400770 }
weilia2c06e42016-05-20 17:09:48 -0700771 } else if (chartype == FX_CHARTYPE_Numeric) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400772 wForm = wch;
Dan Sinclair1770c022016-03-14 14:14:16 -0400773 } else if (wch == L'.') {
774 wForm = wch;
Dan Sinclair1770c022016-03-14 14:14:16 -0400775 } else if (wch == L',') {
776 wForm = wch;
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400777 } else if (bRTLPiece) {
Lei Zhang672a1722017-07-27 13:47:27 -0700778 wForm = FX_GetMirrorChar(wch, dwProps);
Dan Sinclair1770c022016-03-14 14:14:16 -0400779 } else {
780 wForm = wch;
781 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500782 if (chartype != FX_CHARTYPE_Combination)
tsepezd19e9122016-11-02 15:43:18 -0700783 bShadda = false;
Dan Sinclair17f31182017-03-01 09:31:51 -0500784 if (chartype < FX_CHARTYPE_ArabicAlef)
tsepezd19e9122016-11-02 15:43:18 -0700785 bLam = false;
Dan Sinclair17f31182017-03-01 09:31:51 -0500786
Dan Sinclair1770c022016-03-14 14:14:16 -0400787 dwProps = FX_GetUnicodeProperties(wForm);
tsepezd19e9122016-11-02 15:43:18 -0700788 bool bEmptyChar =
weilia2c06e42016-05-20 17:09:48 -0700789 (chartype >= FX_CHARTYPE_Tab && chartype <= FX_CHARTYPE_Control);
Dan Sinclair17f31182017-03-01 09:31:51 -0500790 if (wForm == 0xFEFF)
tsepezd19e9122016-11-02 15:43:18 -0700791 bEmptyChar = true;
Dan Sinclair17f31182017-03-01 09:31:51 -0500792
weili038aa532016-05-20 15:38:29 -0700793 int32_t iForms = bLam ? 3 : 1;
Dan Sinclair1770c022016-03-14 14:14:16 -0400794 iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms;
dsinclair85d1f2c2016-06-23 12:40:16 -0700795 if (!pCharPos) {
Dan Sinclair17f31182017-03-01 09:31:51 -0500796 if (iWidth > 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400797 wPrev = wch;
Dan Sinclair1770c022016-03-14 14:14:16 -0400798 wLast = wch;
799 continue;
800 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500801
weili038aa532016-05-20 15:38:29 -0700802 int32_t iCharWidth = iWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500803 if (iCharWidth < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -0400804 iCharWidth = -iCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500805
Dan Sinclair1770c022016-03-14 14:14:16 -0400806 iCharWidth /= iFontSize;
807 formChars[0].wch = wch;
808 formChars[0].wForm = wForm;
809 formChars[0].iWidth = iCharWidth;
810 if (bLam) {
811 formChars[1].wForm = 0x0651;
812 iCharWidth = 0;
tsepezd19e9122016-11-02 15:43:18 -0700813 pFont->GetCharWidth(0x0651, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400814 formChars[1].iWidth = iCharWidth;
815 formChars[2].wForm = 0x0670;
816 iCharWidth = 0;
tsepezd19e9122016-11-02 15:43:18 -0700817 pFont->GetCharWidth(0x0670, iCharWidth, false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400818 formChars[2].iWidth = iCharWidth;
819 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500820
Dan Sinclair1770c022016-03-14 14:14:16 -0400821 for (int32_t j = 0; j < iForms; j++) {
Dan Sinclair812e96c2017-03-13 16:43:37 -0400822 wForm = (wchar_t)formChars[j].wForm;
Dan Sinclair1770c022016-03-14 14:14:16 -0400823 iCharWidth = formChars[j].iWidth;
824 if (j > 0) {
weilia2c06e42016-05-20 17:09:48 -0700825 chartype = FX_CHARTYPE_Combination;
Dan Sinclair1770c022016-03-14 14:14:16 -0400826 wch = wForm;
Dan Sinclair812e96c2017-03-13 16:43:37 -0400827 wLast = (wchar_t)formChars[j - 1].wForm;
Dan Sinclair1770c022016-03-14 14:14:16 -0400828 }
829 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
Dan Sinclair171cb272017-08-15 09:43:07 -0400830 pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wForm, false);
thestigec51ac32016-06-20 10:38:52 -0700831#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
Dan Sinclair1770c022016-03-14 14:14:16 -0400832 pCharPos->m_ExtGID = pCharPos->m_GlyphIndex;
thestigec51ac32016-06-20 10:38:52 -0700833#endif
Dan Sinclair1770c022016-03-14 14:14:16 -0400834 pCharPos->m_FontCharWidth = iCharWidth;
Dan Sinclair1770c022016-03-14 14:14:16 -0400835 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500836
Dan Sinclair1770c022016-03-14 14:14:16 -0400837 fCharWidth = fFontSize * iCharWidth / 1000.0f;
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400838 if (bRTLPiece && chartype != FX_CHARTYPE_Combination)
839 fX -= fCharWidth;
840
Dan Sinclair1770c022016-03-14 14:14:16 -0400841 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
Dan Sinclair2c02fae2017-02-16 13:42:11 -0500842 pCharPos->m_Origin = CFX_PointF(fX, fY);
Dan Sinclair68eefa62017-08-30 12:16:16 -0400843
Dan Sinclaire533b932017-03-16 11:47:20 -0400844 if ((dwStyles & FX_LAYOUTSTYLE_CombText) != 0) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400845 int32_t iFormWidth = iCharWidth;
tsepezd19e9122016-11-02 15:43:18 -0700846 pFont->GetCharWidth(wForm, iFormWidth, false);
Dan Sinclair05df0752017-03-14 14:43:42 -0400847 float fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f;
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400848 pCharPos->m_Origin.x += fOffset;
Dan Sinclair1770c022016-03-14 14:14:16 -0400849 }
Dan Sinclair2c02fae2017-02-16 13:42:11 -0500850
weilia2c06e42016-05-20 17:09:48 -0700851 if (chartype == FX_CHARTYPE_Combination) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400852 CFX_Rect rtBBox;
tsepez6fd07ef2017-01-06 09:48:18 -0800853 if (pFont->GetCharBBox(wForm, &rtBBox, false)) {
Dan Sinclair2c02fae2017-02-16 13:42:11 -0500854 pCharPos->m_Origin.y =
Dan Sinclair1770c022016-03-14 14:14:16 -0400855 fYBase + fFontSize -
Dan Sinclair05df0752017-03-14 14:43:42 -0400856 fFontSize * (float)rtBBox.height / (float)iMaxHeight;
Dan Sinclair1770c022016-03-14 14:14:16 -0400857 }
858 if (wForm == wch && wLast != 0xFEFF) {
tsepez736f28a2016-03-25 14:19:51 -0700859 uint32_t dwLastProps = FX_GetUnicodeProperties(wLast);
Dan Sinclair1770c022016-03-14 14:14:16 -0400860 if ((dwLastProps & FX_CHARTYPEBITSMASK) ==
861 FX_CHARTYPE_Combination) {
weilidb444d22016-06-02 15:48:15 -0700862 CFX_Rect rtBox;
Dan Sinclair2c02fae2017-02-16 13:42:11 -0500863 if (pFont->GetCharBBox(wLast, &rtBox, false))
864 pCharPos->m_Origin.y -= fFontSize * rtBox.height / iMaxHeight;
Dan Sinclair1770c022016-03-14 14:14:16 -0400865 }
866 }
867 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400868 }
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400869 if (!bRTLPiece && chartype != FX_CHARTYPE_Combination)
870 fX += fCharWidth;
Dan Sinclair17f31182017-03-01 09:31:51 -0500871
Dan Sinclair1770c022016-03-14 14:14:16 -0400872 if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
tsepezd19e9122016-11-02 15:43:18 -0700873 pCharPos->m_bGlyphAdjust = true;
Dan Sinclair068d3442017-03-13 10:15:36 -0400874 pCharPos->m_AdjustMatrix[0] = -1;
875 pCharPos->m_AdjustMatrix[1] = 0;
876 pCharPos->m_AdjustMatrix[2] = 0;
877 pCharPos->m_AdjustMatrix[3] = 1;
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400878
Dan Sinclair1770c022016-03-14 14:14:16 -0400879 if (iHorScale != 100 || iVerScale != 100) {
880 pCharPos->m_AdjustMatrix[0] =
881 pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f;
882 pCharPos->m_AdjustMatrix[1] =
883 pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f;
884 pCharPos->m_AdjustMatrix[2] =
885 pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f;
886 pCharPos->m_AdjustMatrix[3] =
887 pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f;
888 }
889 pCharPos++;
890 }
891 }
Dan Sinclair17f31182017-03-01 09:31:51 -0500892 if (iWidth > 0)
Dan Sinclair812e96c2017-03-13 16:43:37 -0400893 wPrev = static_cast<wchar_t>(formChars[0].wch);
Dan Sinclair1770c022016-03-14 14:14:16 -0400894 wLast = wch;
895 }
896 return iCount;
897}
weili1b4f6b32016-08-04 16:37:48 -0700898
Tom Sepezc803cbc2017-03-02 12:21:15 -0800899std::vector<CFX_RectF> CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun,
900 bool bCharBBox) const {
tsepeze6477992017-01-05 12:57:00 -0800901 if (!pTxtRun || pTxtRun->iLength < 1)
Tom Sepezc803cbc2017-03-02 12:21:15 -0800902 return std::vector<CFX_RectF>();
tsepeze6477992017-01-05 12:57:00 -0800903
Dan Sinclair68eefa62017-08-30 12:16:16 -0400904 CFDE_TextEditEngine* pEngine = pTxtRun->pEdtEngine;
Dan Sinclair812e96c2017-03-13 16:43:37 -0400905 const wchar_t* pStr = pTxtRun->wsStr.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -0400906 int32_t* pWidths = pTxtRun->pWidths;
907 int32_t iLength = pTxtRun->iLength;
908 CFX_RectF rect(*pTxtRun->pRect);
Dan Sinclair05df0752017-03-14 14:43:42 -0400909 float fFontSize = pTxtRun->fFontSize;
Dan Sinclair1770c022016-03-14 14:14:16 -0400910 int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
Dan Sinclair05df0752017-03-14 14:43:42 -0400911 float fScale = fFontSize / 1000.0f;
tsepeze6477992017-01-05 12:57:00 -0800912 CFX_RetainPtr<CFGAS_GEFont> pFont = pTxtRun->pFont;
913 if (!pFont)
tsepezd19e9122016-11-02 15:43:18 -0700914 bCharBBox = false;
tsepeze6477992017-01-05 12:57:00 -0800915
Dan Sinclair1770c022016-03-14 14:14:16 -0400916 CFX_Rect bbox;
tsepeze6477992017-01-05 12:57:00 -0800917 if (bCharBBox)
tsepez6fd07ef2017-01-06 09:48:18 -0800918 bCharBBox = pFont->GetBBox(&bbox);
tsepeze6477992017-01-05 12:57:00 -0800919
Dan Sinclair05df0752017-03-14 14:43:42 -0400920 float fLeft = std::max(0.0f, bbox.left * fScale);
Dan Sinclair669a4182017-04-03 14:51:45 -0400921 float fHeight = fabs(bbox.height * fScale);
Tom Sepezc803cbc2017-03-02 12:21:15 -0800922 bool bRTLPiece = !!(pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel);
Dan Sinclaire533b932017-03-16 11:47:20 -0400923 bool bSingleLine = !!(pTxtRun->dwStyles & FX_LAYOUTSTYLE_SingleLine);
924 bool bCombText = !!(pTxtRun->dwStyles & FX_LAYOUTSTYLE_CombText);
Dan Sinclair812e96c2017-03-13 16:43:37 -0400925 wchar_t wch;
Dan Sinclair1770c022016-03-14 14:14:16 -0400926 int32_t iCharSize;
Dan Sinclair05df0752017-03-14 14:43:42 -0400927 float fCharSize;
928 float fStart = bRTLPiece ? rect.right() : rect.left;
Dan Sinclair17f31182017-03-01 09:31:51 -0500929
Tom Sepezc803cbc2017-03-02 12:21:15 -0800930 std::vector<CFX_RectF> rtArray(iLength);
Dan Sinclair1770c022016-03-14 14:14:16 -0400931 for (int32_t i = 0; i < iLength; i++) {
Dan Sinclair68eefa62017-08-30 12:16:16 -0400932 if (pEngine) {
933 wch = pEngine->GetChar(i);
934 iCharSize = pEngine->GetWidthOfChar(i);
Dan Sinclair1770c022016-03-14 14:14:16 -0400935 } else {
936 wch = *pStr++;
937 iCharSize = *pWidths++;
938 }
Dan Sinclair05df0752017-03-14 14:43:42 -0400939 fCharSize = static_cast<float>(iCharSize) / 20000.0f;
Dan Sinclairfc9b9882017-03-07 09:18:18 -0500940 bool bRet = (!bSingleLine && IsCtrlCode(wch));
Dan Sinclair1770c022016-03-14 14:14:16 -0400941 if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 ||
Dan Sinclair9342b332017-08-16 17:26:23 -0400942 wch == L'\n')) {
tsepezd19e9122016-11-02 15:43:18 -0700943 bRet = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400944 }
945 if (bRet) {
946 iCharSize = iFontSize * 500;
947 fCharSize = fFontSize / 2.0f;
948 }
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400949 rect.left = fStart;
950 if (bRTLPiece) {
951 rect.left -= fCharSize;
952 fStart -= fCharSize;
Dan Sinclair1770c022016-03-14 14:14:16 -0400953 } else {
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400954 fStart += fCharSize;
Dan Sinclair1770c022016-03-14 14:14:16 -0400955 }
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400956 rect.width = fCharSize;
Dan Sinclair17f31182017-03-01 09:31:51 -0500957
Dan Sinclair1770c022016-03-14 14:14:16 -0400958 if (bCharBBox && !bRet) {
959 int32_t iCharWidth = 1000;
thestig2c065322016-09-26 14:16:43 -0700960 pFont->GetCharWidth(wch, iCharWidth, false);
Dan Sinclair05df0752017-03-14 14:43:42 -0400961 float fRTLeft = 0, fCharWidth = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400962 if (iCharWidth > 0) {
963 fCharWidth = iCharWidth * fScale;
964 fRTLeft = fLeft;
Dan Sinclair17f31182017-03-01 09:31:51 -0500965 if (bCombText)
Dan Sinclair1770c022016-03-14 14:14:16 -0400966 fRTLeft = (rect.width - fCharWidth) / 2.0f;
Dan Sinclair1770c022016-03-14 14:14:16 -0400967 }
968 CFX_RectF rtBBoxF;
Dan Sinclaira5a3de92017-03-13 10:14:21 -0400969 rtBBoxF.left = rect.left + fRTLeft;
970 rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f;
971 rtBBoxF.width = fCharWidth;
972 rtBBoxF.height = fHeight;
973 rtBBoxF.top = std::max(rtBBoxF.top, 0.0f);
Tom Sepezc803cbc2017-03-02 12:21:15 -0800974 rtArray[i] = rtBBoxF;
Dan Sinclair1770c022016-03-14 14:14:16 -0400975 continue;
976 }
Tom Sepezc803cbc2017-03-02 12:21:15 -0800977 rtArray[i] = rect;
Dan Sinclair1770c022016-03-14 14:14:16 -0400978 }
Tom Sepezc803cbc2017-03-02 12:21:15 -0800979 return rtArray;
Dan Sinclair1770c022016-03-14 14:14:16 -0400980}
weilieec3a362016-06-18 06:25:37 -0700981
982FX_TXTRUN::FX_TXTRUN()
Dan Sinclair68eefa62017-08-30 12:16:16 -0400983 : pEdtEngine(nullptr),
weilieec3a362016-06-18 06:25:37 -0700984 pIdentity(nullptr),
985 pWidths(nullptr),
986 iLength(0),
987 pFont(nullptr),
988 fFontSize(12),
989 dwStyles(0),
990 iHorizontalScale(100),
991 iVerticalScale(100),
weilieec3a362016-06-18 06:25:37 -0700992 dwCharStyles(0),
993 pRect(nullptr),
tsepezd19e9122016-11-02 15:43:18 -0700994 bSkipSpace(true) {}
weilieec3a362016-06-18 06:25:37 -0700995
996FX_TXTRUN::~FX_TXTRUN() {}
997
998FX_TXTRUN::FX_TXTRUN(const FX_TXTRUN& other) = default;