summaryrefslogtreecommitdiff
path: root/xfa/src/fgas/layout
diff options
context:
space:
mode:
authorDan Sinclair <dsinclair@chromium.org>2016-03-09 13:49:00 -0500
committerDan Sinclair <dsinclair@chromium.org>2016-03-09 13:49:00 -0500
commit9332e0c2fced598a632e3bbe905b6f63b1f5b06b (patch)
treea8957a09cb34ecd28afcd6ebbed309d9c60e4644 /xfa/src/fgas/layout
parent8388037a5c58d60043b11c03a8efe78c54c65a4b (diff)
downloadpdfium-9332e0c2fced598a632e3bbe905b6f63b1f5b06b.tar.xz
Cleanup the xfa/src/fgas directory.
This CL moves the code from xfa/src/fgas/src up one level. It then takes the headers in xfa/src/fgas/include and moves them to their correct folder. The src/ and include/ directories are then removed. In some cases, when moving from include/ there was another header with the same name. Those headers were either folded together, or the content of the conflicting folder moved to an anonymous namespace in the cpp file as they were not used anywhere else. Files with duplicate names as core/src/crt were renamed to be fgas_ instead of fx_. (e.g. fgas_system.h, fgas_memory.h, fgas_stream.h) R=tsepez@chromium.org Review URL: https://codereview.chromium.org/1776303002 .
Diffstat (limited to 'xfa/src/fgas/layout')
-rw-r--r--xfa/src/fgas/layout/fgas_linebreak.cpp320
-rw-r--r--xfa/src/fgas/layout/fgas_linebreak.h40
-rw-r--r--xfa/src/fgas/layout/fgas_rtfbreak.cpp1691
-rw-r--r--xfa/src/fgas/layout/fgas_rtfbreak.h237
-rw-r--r--xfa/src/fgas/layout/fgas_textbreak.cpp1824
-rw-r--r--xfa/src/fgas/layout/fgas_textbreak.h222
-rw-r--r--xfa/src/fgas/layout/fgas_unicode.cpp117
-rw-r--r--xfa/src/fgas/layout/fgas_unicode.h47
8 files changed, 4498 insertions, 0 deletions
diff --git a/xfa/src/fgas/layout/fgas_linebreak.cpp b/xfa/src/fgas/layout/fgas_linebreak.cpp
new file mode 100644
index 0000000000..b43b8007b4
--- /dev/null
+++ b/xfa/src/fgas/layout/fgas_linebreak.cpp
@@ -0,0 +1,320 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/layout/fgas_linebreak.h"
+
+#include "core/include/fxcrt/fx_ucd.h"
+
+const FX_LINEBREAKTYPE gs_FX_LineBreak_PairTable[64][32] = {
+ {FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBPB, FX_LBPB, FX_LBPB, FX_LBCP, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBPB, FX_LBPB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBPB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBPB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBIB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBDB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBPB,
+ FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBPB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBPB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB,
+ FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB,
+ FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB,
+ FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN,
+ FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+};
+
+void FX_GetLineBreakPositions(const FX_WCHAR* pwsText,
+ FX_LINEBREAKTYPE* pBrkType,
+ int32_t iLength) {
+ if (iLength < 2) {
+ return;
+ }
+ FX_DWORD dwCur, dwNext;
+ FX_WCHAR wch;
+ wch = *pwsText++;
+ dwCur = kTextLayoutCodeProperties[(FX_WORD)wch] & 0x003F;
+ iLength--;
+ for (int32_t i = 0; i < iLength; i++) {
+ wch = *pwsText++;
+ dwNext = kTextLayoutCodeProperties[(FX_WORD)wch] & 0x003F;
+ if (dwNext == FX_CBP_SP) {
+ pBrkType[i] = FX_LBT_PROHIBITED_BRK;
+ } else {
+ pBrkType[i] = *((const FX_LINEBREAKTYPE*)gs_FX_LineBreak_PairTable +
+ (dwCur << 5) + dwNext);
+ }
+ dwCur = dwNext;
+ }
+ pBrkType[iLength] = FX_LBT_INDIRECT_BRK;
+}
+void FX_GetLineBreakPositions(const FX_WCHAR* pwsText,
+ int32_t iLength,
+ CFX_Int32MassArray& bp) {
+ if (iLength < 2) {
+ return;
+ }
+ FX_LINEBREAKTYPE eType;
+ FX_DWORD dwCur, dwNext;
+ FX_WCHAR wch;
+ wch = *pwsText++;
+ dwCur = kTextLayoutCodeProperties[(FX_WORD)wch] & 0x003F;
+ iLength--;
+ for (int32_t i = 0; i < iLength; i++) {
+ wch = *pwsText++;
+ dwNext = kTextLayoutCodeProperties[(FX_WORD)wch] & 0x003F;
+ if (dwNext == FX_CBP_SP) {
+ eType = FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE*)gs_FX_LineBreak_PairTable +
+ (dwCur << 5) + dwNext);
+ }
+ if (eType == FX_LBT_DIRECT_BRK) {
+ bp.Add(i);
+ }
+ dwCur = dwNext;
+ }
+}
diff --git a/xfa/src/fgas/layout/fgas_linebreak.h b/xfa/src/fgas/layout/fgas_linebreak.h
new file mode 100644
index 0000000000..7b91124bc2
--- /dev/null
+++ b/xfa/src/fgas/layout/fgas_linebreak.h
@@ -0,0 +1,40 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_LAYOUT_FGAS_LINEBREAK_H_
+#define XFA_SRC_FGAS_LAYOUT_FGAS_LINEBREAK_H_
+
+#include "core/include/fxcrt/fx_system.h"
+#include "xfa/src/fgas/crt/fgas_utils.h"
+
+enum FX_LINEBREAKTYPE {
+ FX_LBT_UNKNOWN = 0x00,
+ FX_LBT_DIRECT_BRK = 0x1A,
+ FX_LBT_INDIRECT_BRK = 0x2B,
+ FX_LBT_COM_INDIRECT_BRK = 0x3C,
+ FX_LBT_COM_PROHIBITED_BRK = 0x4D,
+ FX_LBT_PROHIBITED_BRK = 0x5E,
+ FX_LBT_HANGUL_SPACE_BRK = 0x6F,
+};
+
+#define FX_LBUN FX_LBT_UNKNOWN
+#define FX_LBDB FX_LBT_DIRECT_BRK
+#define FX_LBIB FX_LBT_INDIRECT_BRK
+#define FX_LBCB FX_LBT_COM_INDIRECT_BRK
+#define FX_LBCP FX_LBT_COM_PROHIBITED_BRK
+#define FX_LBPB FX_LBT_PROHIBITED_BRK
+#define FX_LBHS FX_LBT_HANGUL_SPACE_BRK
+
+extern const FX_LINEBREAKTYPE gs_FX_LineBreak_PairTable[64][32];
+
+void FX_GetLineBreakPositions(const FX_WCHAR* pwsText,
+ FX_LINEBREAKTYPE* pBrkType,
+ int32_t iLength);
+void FX_GetLineBreakPositions(const FX_WCHAR* pwsText,
+ int32_t iLength,
+ CFX_Int32MassArray& bp);
+
+#endif // XFA_SRC_FGAS_LAYOUT_FGAS_LINEBREAK_H_
diff --git a/xfa/src/fgas/layout/fgas_rtfbreak.cpp b/xfa/src/fgas/layout/fgas_rtfbreak.cpp
new file mode 100644
index 0000000000..7e4ab4c08c
--- /dev/null
+++ b/xfa/src/fgas/layout/fgas_rtfbreak.cpp
@@ -0,0 +1,1691 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/layout/fgas_rtfbreak.h"
+
+#include <algorithm>
+
+#include "core/include/fxcrt/fx_arb.h"
+#include "xfa/src/fgas/layout/fgas_linebreak.h"
+#include "xfa/src/fgas/layout/fgas_unicode.h"
+
+namespace {
+
+class CFX_RTFLine {
+ public:
+ CFX_RTFLine()
+ : m_LinePieces(16),
+ m_iStart(0),
+ m_iWidth(0),
+ m_iArabicChars(0),
+ m_iMBCSChars(0) {}
+ ~CFX_RTFLine() { RemoveAll(); }
+ int32_t CountChars() const { return m_LineChars.GetSize(); }
+ CFX_RTFChar& GetChar(int32_t index) {
+ FXSYS_assert(index > -1 && index < m_LineChars.GetSize());
+ return *m_LineChars.GetDataPtr(index);
+ }
+ CFX_RTFChar* GetCharPtr(int32_t index) {
+ FXSYS_assert(index > -1 && index < m_LineChars.GetSize());
+ return m_LineChars.GetDataPtr(index);
+ }
+ int32_t CountPieces() const { return m_LinePieces.GetSize(); }
+ CFX_RTFPiece& GetPiece(int32_t index) const {
+ FXSYS_assert(index > -1 && index < m_LinePieces.GetSize());
+ return m_LinePieces.GetAt(index);
+ }
+ CFX_RTFPiece* GetPiecePtr(int32_t index) const {
+ FXSYS_assert(index > -1 && index < m_LinePieces.GetSize());
+ return m_LinePieces.GetPtrAt(index);
+ }
+ int32_t GetLineEnd() const { return m_iStart + m_iWidth; }
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE) {
+ CFX_RTFChar* pChar;
+ IFX_Unknown* pUnknown;
+ int32_t iCount = m_LineChars.GetSize();
+ for (int32_t i = 0; i < iCount; i++) {
+ pChar = m_LineChars.GetDataPtr(i);
+ if ((pUnknown = pChar->m_pUserData) != NULL) {
+ pUnknown->Release();
+ }
+ }
+ m_LineChars.RemoveAll();
+ m_LinePieces.RemoveAll(bLeaveMemory);
+ m_iWidth = 0;
+ m_iArabicChars = 0;
+ m_iMBCSChars = 0;
+ }
+ CFX_RTFCharArray m_LineChars;
+ CFX_RTFPieceArray m_LinePieces;
+ int32_t m_iStart;
+ int32_t m_iWidth;
+ int32_t m_iArabicChars;
+ int32_t m_iMBCSChars;
+};
+
+class CFX_RTFBreak : public IFX_RTFBreak {
+ public:
+ CFX_RTFBreak(FX_DWORD dwPolicies);
+ ~CFX_RTFBreak();
+ void Release() override { delete this; }
+ void SetLineBoundary(FX_FLOAT fLineStart, FX_FLOAT fLineEnd) override;
+ void SetLineStartPos(FX_FLOAT fLinePos) override;
+ FX_DWORD GetLayoutStyles() const override { return m_dwLayoutStyles; }
+ void SetLayoutStyles(FX_DWORD dwLayoutStyles) override;
+ void SetFont(IFX_Font* pFont) override;
+ void SetFontSize(FX_FLOAT fFontSize) override;
+ void SetTabWidth(FX_FLOAT fTabWidth) override;
+ void AddPositionedTab(FX_FLOAT fTabPos) override;
+ void SetPositionedTabs(const CFX_FloatArray& tabs) override;
+ void ClearPositionedTabs() override;
+ void SetDefaultChar(FX_WCHAR wch) override;
+ void SetLineBreakChar(FX_WCHAR wch) override;
+ void SetLineBreakTolerance(FX_FLOAT fTolerance) override;
+ void SetHorizontalScale(int32_t iScale) override;
+ void SetVerticalScale(int32_t iScale) override;
+ void SetCharRotation(int32_t iCharRotation) override;
+ void SetCharSpace(FX_FLOAT fCharSpace) override;
+ void SetWordSpace(FX_BOOL bDefault, FX_FLOAT fWordSpace) override;
+ void SetReadingOrder(FX_BOOL bRTL = FALSE) override;
+ void SetAlignment(int32_t iAlignment = FX_RTFLINEALIGNMENT_Left) override;
+ void SetUserData(IFX_Unknown* pUserData) override;
+ FX_DWORD AppendChar(FX_WCHAR wch) override;
+ FX_DWORD EndBreak(FX_DWORD dwStatus = FX_RTFBREAK_PieceBreak) override;
+ int32_t CountBreakPieces() const override;
+ const CFX_RTFPiece* GetBreakPiece(int32_t index) const override;
+ void GetLineRect(CFX_RectF& rect) const override;
+ void ClearBreakPieces() override;
+ void Reset() override;
+ int32_t GetDisplayPos(
+ const FX_RTFTEXTOBJ* pText,
+ FXTEXT_CHARPOS* pCharPos,
+ FX_BOOL bCharCode = FALSE,
+ CFX_WideString* pWSForms = NULL,
+ FX_AdjustCharDisplayPos pAdjustPos = NULL) const override;
+ int32_t GetCharRects(const FX_RTFTEXTOBJ* pText,
+ CFX_RectFArray& rtArray,
+ FX_BOOL bCharBBox = FALSE) const override;
+ FX_DWORD AppendChar_CharCode(FX_WCHAR wch);
+ FX_DWORD AppendChar_Combination(CFX_RTFChar* pCurChar, int32_t iRotation);
+ FX_DWORD AppendChar_Tab(CFX_RTFChar* pCurChar, int32_t iRotation);
+ FX_DWORD AppendChar_Control(CFX_RTFChar* pCurChar, int32_t iRotation);
+ FX_DWORD AppendChar_Arabic(CFX_RTFChar* pCurChar, int32_t iRotation);
+ FX_DWORD AppendChar_Others(CFX_RTFChar* pCurChar, int32_t iRotation);
+
+ protected:
+ FX_DWORD m_dwPolicies;
+ IFX_ArabicChar* m_pArabicChar;
+ int32_t m_iBoundaryStart;
+ int32_t m_iBoundaryEnd;
+ FX_DWORD m_dwLayoutStyles;
+ FX_BOOL m_bPagination;
+ FX_BOOL m_bVertical;
+ FX_BOOL m_bSingleLine;
+ FX_BOOL m_bCharCode;
+ IFX_Font* m_pFont;
+ int32_t m_iFontHeight;
+ int32_t m_iFontSize;
+ int32_t m_iTabWidth;
+ CFX_Int32Array m_PositionedTabs;
+ FX_BOOL m_bOrphanLine;
+ FX_WCHAR m_wDefChar;
+ int32_t m_iDefChar;
+ FX_WCHAR m_wLineBreakChar;
+ int32_t m_iHorizontalScale;
+ int32_t m_iVerticalScale;
+ int32_t m_iLineRotation;
+ int32_t m_iCharRotation;
+ int32_t m_iRotation;
+ int32_t m_iCharSpace;
+ FX_BOOL m_bWordSpace;
+ int32_t m_iWordSpace;
+ FX_BOOL m_bRTL;
+ int32_t m_iAlignment;
+ IFX_Unknown* m_pUserData;
+ FX_DWORD m_dwCharType;
+ FX_DWORD m_dwIdentity;
+ CFX_RTFLine m_RTFLine1;
+ CFX_RTFLine m_RTFLine2;
+ CFX_RTFLine* m_pCurLine;
+ int32_t m_iReady;
+ int32_t m_iTolerance;
+ int32_t GetLineRotation(FX_DWORD dwStyles) const;
+ void SetBreakStatus();
+ CFX_RTFChar* GetLastChar(int32_t index) const;
+ CFX_RTFLine* GetRTFLine(FX_BOOL bReady) const;
+ CFX_RTFPieceArray* GetRTFPieces(FX_BOOL bReady) const;
+ FX_DWORD GetUnifiedCharType(FX_DWORD dwType) const;
+ int32_t GetLastPositionedTab() const;
+ FX_BOOL GetPositionedTab(int32_t& iTabPos) const;
+ int32_t GetBreakPos(CFX_RTFCharArray& tca,
+ int32_t& iEndPos,
+ FX_BOOL bAllChars = FALSE,
+ FX_BOOL bOnlyBrk = FALSE);
+ void SplitTextLine(CFX_RTFLine* pCurLine,
+ CFX_RTFLine* pNextLine,
+ FX_BOOL bAllChars = FALSE);
+ FX_BOOL EndBreak_SplitLine(CFX_RTFLine* pNextLine,
+ FX_BOOL bAllChars,
+ FX_DWORD dwStatus);
+ void EndBreak_BidiLine(CFX_TPOArray& tpos, FX_DWORD dwStatus);
+ void EndBreak_Alignment(CFX_TPOArray& tpos,
+ FX_BOOL bAllChars,
+ FX_DWORD dwStatus);
+};
+
+} // namespace
+
+IFX_RTFBreak* IFX_RTFBreak::Create(FX_DWORD dwPolicies) {
+ return new CFX_RTFBreak(dwPolicies);
+}
+CFX_RTFBreak::CFX_RTFBreak(FX_DWORD dwPolicies)
+ : m_dwPolicies(dwPolicies),
+ m_pArabicChar(NULL),
+ m_iBoundaryStart(0),
+ m_iBoundaryEnd(2000000),
+ m_dwLayoutStyles(0),
+ m_bPagination(FALSE),
+ m_bVertical(FALSE),
+ m_bSingleLine(FALSE),
+ m_bCharCode(FALSE),
+ m_pFont(NULL),
+ m_iFontHeight(240),
+ m_iFontSize(240),
+ m_iTabWidth(720000),
+ m_PositionedTabs(),
+ m_bOrphanLine(FALSE),
+ m_wDefChar(0xFEFF),
+ m_iDefChar(0),
+ m_wLineBreakChar(L'\n'),
+ m_iHorizontalScale(100),
+ m_iVerticalScale(100),
+ m_iLineRotation(0),
+ m_iCharRotation(0),
+ m_iRotation(0),
+ m_iCharSpace(0),
+ m_bWordSpace(FALSE),
+ m_iWordSpace(0),
+ m_bRTL(FALSE),
+ m_iAlignment(FX_RTFLINEALIGNMENT_Left),
+ m_pUserData(NULL),
+ m_dwCharType(0),
+ m_dwIdentity(0),
+ m_RTFLine1(),
+ m_RTFLine2(),
+ m_pCurLine(NULL),
+ m_iReady(0),
+ m_iTolerance(0) {
+ m_pArabicChar = IFX_ArabicChar::Create();
+ m_pCurLine = &m_RTFLine1;
+}
+CFX_RTFBreak::~CFX_RTFBreak() {
+ Reset();
+ m_PositionedTabs.RemoveAll();
+ m_pArabicChar->Release();
+ if (m_pUserData != NULL) {
+ m_pUserData->Release();
+ }
+}
+void CFX_RTFBreak::SetLineBoundary(FX_FLOAT fLineStart, FX_FLOAT fLineEnd) {
+ if (fLineStart > fLineEnd)
+ return;
+ m_iBoundaryStart = FXSYS_round(fLineStart * 20000.0f);
+ m_iBoundaryEnd = FXSYS_round(fLineEnd * 20000.0f);
+ m_pCurLine->m_iStart = std::min(m_pCurLine->m_iStart, m_iBoundaryEnd);
+ m_pCurLine->m_iStart = std::max(m_pCurLine->m_iStart, m_iBoundaryStart);
+}
+void CFX_RTFBreak::SetLineStartPos(FX_FLOAT fLinePos) {
+ int32_t iLinePos = FXSYS_round(fLinePos * 20000.0f);
+ iLinePos = std::min(iLinePos, m_iBoundaryEnd);
+ iLinePos = std::max(iLinePos, m_iBoundaryStart);
+ m_pCurLine->m_iStart = iLinePos;
+}
+void CFX_RTFBreak::SetLayoutStyles(FX_DWORD dwLayoutStyles) {
+ if (m_dwLayoutStyles == dwLayoutStyles) {
+ return;
+ }
+ SetBreakStatus();
+ m_dwLayoutStyles = dwLayoutStyles;
+ m_bPagination = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_Pagination) != 0;
+ m_bVertical = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_VerticalChars) != 0;
+ m_bSingleLine = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_SingleLine) != 0;
+ m_bCharCode = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_MBCSCode) != 0;
+ m_iLineRotation = GetLineRotation(m_dwLayoutStyles);
+ m_iRotation = m_iLineRotation + m_iCharRotation;
+ m_iRotation %= 4;
+}
+void CFX_RTFBreak::SetFont(IFX_Font* pFont) {
+ if (pFont == NULL) {
+ return;
+ }
+ if (m_pFont == pFont) {
+ return;
+ }
+ SetBreakStatus();
+ m_pFont = pFont;
+ m_iDefChar = 0;
+ if (m_pFont != NULL) {
+ m_iFontHeight = m_iFontSize;
+ if (m_wDefChar != 0xFEFF) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ m_iDefChar *= m_iFontSize;
+ }
+ }
+}
+void CFX_RTFBreak::SetFontSize(FX_FLOAT fFontSize) {
+ int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
+ if (m_iFontSize == iFontSize) {
+ return;
+ }
+ SetBreakStatus();
+ m_iFontSize = iFontSize;
+ m_iDefChar = 0;
+ if (m_pFont != NULL) {
+ m_iFontHeight = m_iFontSize;
+ if (m_wDefChar != 0xFEFF) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ m_iDefChar *= m_iFontSize;
+ }
+ }
+}
+void CFX_RTFBreak::SetTabWidth(FX_FLOAT fTabWidth) {
+ m_iTabWidth = FXSYS_round(fTabWidth * 20000.0f);
+}
+void CFX_RTFBreak::AddPositionedTab(FX_FLOAT fTabPos) {
+ int32_t iLineEnd = m_iBoundaryEnd;
+ int32_t iTabPos = FXSYS_round(fTabPos * 20000.0f) + m_iBoundaryStart;
+ if (iTabPos > iLineEnd) {
+ iTabPos = iLineEnd;
+ }
+ if (m_PositionedTabs.Find(iTabPos, 0) > -1) {
+ return;
+ }
+ int32_t iCount = m_PositionedTabs.GetSize();
+ int32_t iFind = 0;
+ for (; iFind < iCount; iFind++) {
+ if (m_PositionedTabs[iFind] > iTabPos) {
+ break;
+ }
+ }
+ m_PositionedTabs.InsertAt(iFind, iTabPos);
+ if (m_dwPolicies & FX_RTFBREAKPOLICY_OrphanPositionedTab) {
+ m_bOrphanLine = GetLastPositionedTab() >= iLineEnd;
+ } else {
+ m_bOrphanLine = FALSE;
+ }
+}
+void CFX_RTFBreak::SetPositionedTabs(const CFX_FloatArray& tabs) {
+ m_PositionedTabs.RemoveAll();
+ int32_t iCount = tabs.GetSize();
+ m_PositionedTabs.SetSize(iCount);
+ int32_t iLineEnd = m_iBoundaryEnd;
+ int32_t iTabPos;
+ for (int32_t i = 0; i < iCount; i++) {
+ iTabPos = FXSYS_round(tabs[i] * 20000.0f) + m_iBoundaryStart;
+ if (iTabPos > iLineEnd) {
+ iTabPos = iLineEnd;
+ }
+ m_PositionedTabs[i] = iTabPos;
+ }
+ if (m_dwPolicies & FX_RTFBREAKPOLICY_OrphanPositionedTab) {
+ m_bOrphanLine = GetLastPositionedTab() >= iLineEnd;
+ } else {
+ m_bOrphanLine = FALSE;
+ }
+}
+void CFX_RTFBreak::ClearPositionedTabs() {
+ m_PositionedTabs.RemoveAll();
+ m_bOrphanLine = FALSE;
+}
+void CFX_RTFBreak::SetDefaultChar(FX_WCHAR wch) {
+ m_wDefChar = wch;
+ m_iDefChar = 0;
+ if (m_wDefChar != 0xFEFF && m_pFont != NULL) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ if (m_iDefChar < 0) {
+ m_iDefChar = 0;
+ } else {
+ m_iDefChar *= m_iFontSize;
+ }
+ }
+}
+void CFX_RTFBreak::SetLineBreakChar(FX_WCHAR wch) {
+ if (wch != L'\r' && wch != L'\n') {
+ return;
+ }
+ m_wLineBreakChar = wch;
+}
+void CFX_RTFBreak::SetLineBreakTolerance(FX_FLOAT fTolerance) {
+ m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
+}
+void CFX_RTFBreak::SetHorizontalScale(int32_t iScale) {
+ if (iScale < 0) {
+ iScale = 0;
+ }
+ if (m_iHorizontalScale == iScale) {
+ return;
+ }
+ SetBreakStatus();
+ m_iHorizontalScale = iScale;
+}
+void CFX_RTFBreak::SetVerticalScale(int32_t iScale) {
+ if (iScale < 0) {
+ iScale = 0;
+ }
+ if (m_iVerticalScale == iScale) {
+ return;
+ }
+ SetBreakStatus();
+ m_iVerticalScale = iScale;
+}
+void CFX_RTFBreak::SetCharRotation(int32_t iCharRotation) {
+ if (iCharRotation < 0) {
+ iCharRotation += (-iCharRotation / 4 + 1) * 4;
+ } else if (iCharRotation > 3) {
+ iCharRotation -= (iCharRotation / 4) * 4;
+ }
+ if (m_iCharRotation == iCharRotation) {
+ return;
+ }
+ SetBreakStatus();
+ m_iCharRotation = iCharRotation;
+ m_iRotation = m_iLineRotation + m_iCharRotation;
+ m_iRotation %= 4;
+}
+void CFX_RTFBreak::SetCharSpace(FX_FLOAT fCharSpace) {
+ m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
+}
+void CFX_RTFBreak::SetWordSpace(FX_BOOL bDefault, FX_FLOAT fWordSpace) {
+ m_bWordSpace = !bDefault;
+ m_iWordSpace = FXSYS_round(fWordSpace * 20000.0f);
+}
+void CFX_RTFBreak::SetReadingOrder(FX_BOOL bRTL) {
+ m_bRTL = bRTL;
+}
+void CFX_RTFBreak::SetAlignment(int32_t iAlignment) {
+ FXSYS_assert(iAlignment >= FX_RTFLINEALIGNMENT_Left &&
+ iAlignment <= FX_RTFLINEALIGNMENT_Distributed);
+ m_iAlignment = iAlignment;
+}
+void CFX_RTFBreak::SetUserData(IFX_Unknown* pUserData) {
+ if (m_pUserData == pUserData) {
+ return;
+ }
+ SetBreakStatus();
+ if (m_pUserData != NULL) {
+ m_pUserData->Release();
+ }
+ m_pUserData = pUserData;
+ if (m_pUserData != NULL) {
+ m_pUserData->AddRef();
+ }
+}
+static const int32_t gs_FX_RTFLineRotations[8] = {0, 3, 1, 0, 2, 1, 3, 2};
+int32_t CFX_RTFBreak::GetLineRotation(FX_DWORD dwStyles) const {
+ return gs_FX_RTFLineRotations[(dwStyles & 0x0E) >> 1];
+}
+void CFX_RTFBreak::SetBreakStatus() {
+ m_dwIdentity++;
+ int32_t iCount = m_pCurLine->CountChars();
+ if (iCount < 1) {
+ return;
+ }
+ CFX_RTFChar& tc = m_pCurLine->GetChar(iCount - 1);
+ if (tc.m_dwStatus == 0) {
+ tc.m_dwStatus = FX_RTFBREAK_PieceBreak;
+ }
+}
+CFX_RTFChar* CFX_RTFBreak::GetLastChar(int32_t index) const {
+ CFX_RTFCharArray& tca = m_pCurLine->m_LineChars;
+ int32_t iCount = tca.GetSize();
+ if (index < 0 || index >= iCount) {
+ return NULL;
+ }
+ CFX_RTFChar* pTC;
+ int32_t iStart = iCount - 1;
+ while (iStart > -1) {
+ pTC = tca.GetDataPtr(iStart--);
+ if (pTC->m_iCharWidth >= 0 ||
+ pTC->GetCharType() != FX_CHARTYPE_Combination) {
+ if (--index < 0) {
+ return pTC;
+ }
+ }
+ }
+ return NULL;
+}
+CFX_RTFLine* CFX_RTFBreak::GetRTFLine(FX_BOOL bReady) const {
+ if (bReady) {
+ if (m_iReady == 1) {
+ return (CFX_RTFLine*)&m_RTFLine1;
+ } else if (m_iReady == 2) {
+ return (CFX_RTFLine*)&m_RTFLine2;
+ } else {
+ return NULL;
+ }
+ }
+ FXSYS_assert(m_pCurLine != NULL);
+ return m_pCurLine;
+}
+CFX_RTFPieceArray* CFX_RTFBreak::GetRTFPieces(FX_BOOL bReady) const {
+ CFX_RTFLine* pRTFLine = GetRTFLine(bReady);
+ if (pRTFLine == NULL) {
+ return NULL;
+ }
+ return &pRTFLine->m_LinePieces;
+}
+inline FX_DWORD CFX_RTFBreak::GetUnifiedCharType(FX_DWORD dwType) const {
+ return dwType >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : dwType;
+}
+int32_t CFX_RTFBreak::GetLastPositionedTab() const {
+ int32_t iCount = m_PositionedTabs.GetSize();
+ if (iCount < 1) {
+ return m_iBoundaryStart;
+ }
+ return m_PositionedTabs[iCount - 1];
+}
+FX_BOOL CFX_RTFBreak::GetPositionedTab(int32_t& iTabPos) const {
+ int32_t iCount = m_PositionedTabs.GetSize();
+ for (int32_t i = 0; i < iCount; i++) {
+ if (m_PositionedTabs[i] > iTabPos) {
+ iTabPos = m_PositionedTabs[i];
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+typedef FX_DWORD (CFX_RTFBreak::*FX_RTFBreak_LPFAppendChar)(
+ CFX_RTFChar* pCurChar,
+ int32_t iRotation);
+static const FX_RTFBreak_LPFAppendChar g_FX_RTFBreak_lpfAppendChar[16] = {
+ &CFX_RTFBreak::AppendChar_Others, &CFX_RTFBreak::AppendChar_Tab,
+ &CFX_RTFBreak::AppendChar_Others, &CFX_RTFBreak::AppendChar_Control,
+ &CFX_RTFBreak::AppendChar_Combination, &CFX_RTFBreak::AppendChar_Others,
+ &CFX_RTFBreak::AppendChar_Others, &CFX_RTFBreak::AppendChar_Arabic,
+ &CFX_RTFBreak::AppendChar_Arabic, &CFX_RTFBreak::AppendChar_Arabic,
+ &CFX_RTFBreak::AppendChar_Arabic, &CFX_RTFBreak::AppendChar_Arabic,
+ &CFX_RTFBreak::AppendChar_Arabic, &CFX_RTFBreak::AppendChar_Others,
+ &CFX_RTFBreak::AppendChar_Others, &CFX_RTFBreak::AppendChar_Others,
+};
+FX_DWORD CFX_RTFBreak::AppendChar(FX_WCHAR wch) {
+ FXSYS_assert(m_pFont != NULL && m_pCurLine != NULL && m_pArabicChar != NULL);
+ if (m_bCharCode) {
+ return AppendChar_CharCode(wch);
+ }
+ FX_DWORD dwProps = kTextLayoutCodeProperties[(FX_WORD)wch];
+ FX_DWORD dwType = (dwProps & FX_CHARTYPEBITSMASK);
+ CFX_RTFCharArray& tca = m_pCurLine->m_LineChars;
+ CFX_RTFChar* pCurChar = tca.AddSpace();
+ pCurChar->m_dwStatus = 0;
+ pCurChar->m_wCharCode = wch;
+ pCurChar->m_dwCharProps = dwProps;
+ pCurChar->m_dwCharStyles = 0;
+ pCurChar->m_dwLayoutStyles = 0;
+ pCurChar->m_iFontSize = m_iFontSize;
+ pCurChar->m_iFontHeight = m_iFontHeight;
+ pCurChar->m_iHorizontalScale = m_iHorizontalScale;
+ pCurChar->m_iVertialScale = m_iVerticalScale;
+ pCurChar->m_nRotation = m_iCharRotation;
+ pCurChar->m_iCharWidth = 0;
+ pCurChar->m_dwIdentity = m_dwIdentity;
+ if (m_pUserData != NULL) {
+ m_pUserData->AddRef();
+ }
+ pCurChar->m_pUserData = m_pUserData;
+ FX_DWORD dwRet1 = FX_RTFBREAK_None;
+ if (dwType != FX_CHARTYPE_Combination &&
+ GetUnifiedCharType(m_dwCharType) != GetUnifiedCharType(dwType)) {
+ if (!m_bSingleLine && !m_bOrphanLine && m_dwCharType > 0 &&
+ m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) {
+ if (m_dwCharType != FX_CHARTYPE_Space || dwType != FX_CHARTYPE_Control) {
+ dwRet1 = EndBreak(FX_RTFBREAK_LineBreak);
+ int32_t iCount = m_pCurLine->CountChars();
+ if (iCount > 0) {
+ pCurChar = m_pCurLine->m_LineChars.GetDataPtr(iCount - 1);
+ }
+ }
+ }
+ }
+ int32_t iRotation = m_iRotation;
+ if (m_bVertical && (dwProps & 0x8000) != 0) {
+ iRotation = (iRotation + 1) % 4;
+ }
+ FX_DWORD dwRet2 =
+ (this->*g_FX_RTFBreak_lpfAppendChar[dwType >> FX_CHARTYPEBITS])(
+ pCurChar, iRotation);
+ m_dwCharType = dwType;
+ return std::max(dwRet1, dwRet2);
+}
+FX_DWORD CFX_RTFBreak::AppendChar_CharCode(FX_WCHAR wch) {
+ FXSYS_assert(m_pFont != NULL && m_pCurLine != NULL);
+ FXSYS_assert(m_bCharCode);
+ m_pCurLine->m_iMBCSChars++;
+ CFX_RTFCharArray& tca = m_pCurLine->m_LineChars;
+ CFX_RTFChar* pCurChar = tca.AddSpace();
+ pCurChar->m_dwStatus = 0;
+ pCurChar->m_wCharCode = wch;
+ pCurChar->m_dwCharProps = 0;
+ pCurChar->m_dwCharStyles = 0;
+ pCurChar->m_dwLayoutStyles = m_dwLayoutStyles;
+ pCurChar->m_iFontSize = m_iFontSize;
+ pCurChar->m_iFontHeight = m_iFontHeight;
+ pCurChar->m_iHorizontalScale = m_iHorizontalScale;
+ pCurChar->m_iVertialScale = m_iVerticalScale;
+ pCurChar->m_nRotation = m_iCharRotation;
+ pCurChar->m_iCharWidth = 0;
+ pCurChar->m_dwIdentity = m_dwIdentity;
+ if (m_pUserData != NULL) {
+ m_pUserData->AddRef();
+ }
+ pCurChar->m_pUserData = m_pUserData;
+ int32_t iCharWidth = 0;
+ if (m_bVertical != FX_IsOdd(m_iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ if (!m_pFont->GetCharWidth(wch, iCharWidth, TRUE)) {
+ iCharWidth = m_iDefChar;
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorizontalScale / 100;
+ iCharWidth += m_iCharSpace;
+ pCurChar->m_iCharWidth = iCharWidth;
+ m_pCurLine->m_iWidth += iCharWidth;
+ m_dwCharType = 0;
+ if (!m_bSingleLine &&
+ m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) {
+ return EndBreak(FX_RTFBREAK_LineBreak);
+ }
+ return FX_RTFBREAK_None;
+}
+FX_DWORD CFX_RTFBreak::AppendChar_Combination(CFX_RTFChar* pCurChar,
+ int32_t iRotation) {
+ int32_t iCharWidth = 0;
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ if (!m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth,
+ m_bCharCode)) {
+ iCharWidth = 0;
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorizontalScale / 100;
+ CFX_RTFChar* pLastChar = GetLastChar(0);
+ if (pLastChar != NULL && pLastChar->GetCharType() > FX_CHARTYPE_Combination) {
+ iCharWidth = -iCharWidth;
+ } else {
+ m_dwCharType = FX_CHARTYPE_Combination;
+ }
+ pCurChar->m_iCharWidth = iCharWidth;
+ if (iCharWidth > 0) {
+ m_pCurLine->m_iWidth += iCharWidth;
+ }
+ return FX_RTFBREAK_None;
+}
+FX_DWORD CFX_RTFBreak::AppendChar_Tab(CFX_RTFChar* pCurChar,
+ int32_t iRotation) {
+ if (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_ExpandTab) {
+ FX_BOOL bBreak = FALSE;
+ if ((m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0) {
+ bBreak = (m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance);
+ }
+ int32_t& iLineWidth = m_pCurLine->m_iWidth;
+ int32_t iCharWidth = iLineWidth;
+ if (GetPositionedTab(iCharWidth)) {
+ iCharWidth -= iLineWidth;
+ } else {
+ iCharWidth = m_iTabWidth * (iLineWidth / m_iTabWidth + 1) - iLineWidth;
+ }
+ pCurChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ if (!m_bSingleLine && !m_bOrphanLine && bBreak) {
+ return EndBreak(FX_RTFBREAK_LineBreak);
+ }
+ }
+ return FX_RTFBREAK_None;
+}
+FX_DWORD CFX_RTFBreak::AppendChar_Control(CFX_RTFChar* pCurChar,
+ int32_t iRotation) {
+ FX_DWORD dwRet2 = FX_RTFBREAK_None;
+ if (!m_bSingleLine) {
+ switch (pCurChar->m_wCharCode) {
+ case L'\v':
+ case 0x2028:
+ dwRet2 = FX_RTFBREAK_LineBreak;
+ break;
+ case L'\f':
+ dwRet2 = FX_RTFBREAK_PageBreak;
+ break;
+ case 0x2029:
+ dwRet2 = FX_RTFBREAK_ParagraphBreak;
+ break;
+ default:
+ if (pCurChar->m_wCharCode == m_wLineBreakChar) {
+ dwRet2 = FX_RTFBREAK_ParagraphBreak;
+ }
+ break;
+ }
+ if (dwRet2 != FX_RTFBREAK_None) {
+ dwRet2 = EndBreak(dwRet2);
+ }
+ }
+ return dwRet2;
+}
+FX_DWORD CFX_RTFBreak::AppendChar_Arabic(CFX_RTFChar* pCurChar,
+ int32_t iRotation) {
+ CFX_RTFChar* pLastChar = NULL;
+ int32_t& iLineWidth = m_pCurLine->m_iWidth;
+ int32_t iCharWidth = 0;
+ FX_WCHAR wForm;
+ FX_BOOL bAlef = FALSE;
+ if (m_dwCharType >= FX_CHARTYPE_ArabicAlef &&
+ m_dwCharType <= FX_CHARTYPE_ArabicDistortion) {
+ pLastChar = GetLastChar(1);
+ if (pLastChar != NULL) {
+ iLineWidth -= pLastChar->m_iCharWidth;
+ CFX_RTFChar* pPrevChar = GetLastChar(2);
+ wForm = m_pArabicChar->GetFormChar(pLastChar, pPrevChar, pCurChar);
+ bAlef = (wForm == 0xFEFF &&
+ pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef);
+ int32_t iLastRotation = pLastChar->m_nRotation + m_iLineRotation;
+ if (m_bVertical && (pLastChar->m_dwCharProps & 0x8000) != 0) {
+ iLastRotation++;
+ }
+ if (m_bVertical != FX_IsOdd(iLastRotation)) {
+ iCharWidth = 1000;
+ } else {
+ if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode)) {
+ if (!m_pFont->GetCharWidth(pLastChar->m_wCharCode, iCharWidth,
+ m_bCharCode)) {
+ iCharWidth = m_iDefChar;
+ }
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorizontalScale / 100;
+ pLastChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ iCharWidth = 0;
+ }
+ }
+ wForm =
+ m_pArabicChar->GetFormChar(pCurChar, (bAlef ? NULL : pLastChar), NULL);
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode) &&
+ !m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth,
+ m_bCharCode)) {
+ iCharWidth = m_iDefChar;
+ }
+
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorizontalScale / 100;
+ pCurChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ m_pCurLine->m_iArabicChars++;
+ if (!m_bSingleLine && !m_bOrphanLine &&
+ m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) {
+ return EndBreak(FX_RTFBREAK_LineBreak);
+ }
+ return FX_RTFBREAK_None;
+}
+FX_DWORD CFX_RTFBreak::AppendChar_Others(CFX_RTFChar* pCurChar,
+ int32_t iRotation) {
+ FX_DWORD dwType = (pCurChar->m_dwCharProps & FX_CHARTYPEBITSMASK);
+ FX_WCHAR wForm;
+ if (dwType == FX_CHARTYPE_Numeric) {
+ if (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_ArabicNumber) {
+ wForm = pCurChar->m_wCharCode + 0x0630;
+ } else {
+ wForm = pCurChar->m_wCharCode;
+ }
+ } else if (m_bRTL || m_bVertical) {
+ wForm = FX_GetMirrorChar(pCurChar->m_wCharCode, pCurChar->m_dwCharProps,
+ m_bRTL, m_bVertical);
+ } else {
+ wForm = pCurChar->m_wCharCode;
+ }
+ int32_t iCharWidth = 0;
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode)) {
+ iCharWidth = m_iDefChar;
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorizontalScale / 100;
+ iCharWidth += m_iCharSpace;
+ if (dwType == FX_CHARTYPE_Space && m_bWordSpace) {
+ iCharWidth += m_iWordSpace;
+ }
+ pCurChar->m_iCharWidth = iCharWidth;
+ m_pCurLine->m_iWidth += iCharWidth;
+ FX_BOOL bBreak = (dwType != FX_CHARTYPE_Space ||
+ (m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0);
+ if (!m_bSingleLine && !m_bOrphanLine && bBreak &&
+ m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) {
+ return EndBreak(FX_RTFBREAK_LineBreak);
+ }
+ return FX_RTFBREAK_None;
+}
+FX_DWORD CFX_RTFBreak::EndBreak(FX_DWORD dwStatus) {
+ FXSYS_assert(dwStatus >= FX_RTFBREAK_PieceBreak &&
+ dwStatus <= FX_RTFBREAK_PageBreak);
+ m_dwIdentity++;
+ CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
+ int32_t iCount = pCurPieces->GetSize();
+ if (iCount > 0) {
+ CFX_RTFPiece* pLastPiece = pCurPieces->GetPtrAt(--iCount);
+ if (dwStatus > FX_RTFBREAK_PieceBreak) {
+ pLastPiece->m_dwStatus = dwStatus;
+ } else {
+ dwStatus = pLastPiece->m_dwStatus;
+ }
+ return dwStatus;
+ } else {
+ CFX_RTFLine* pLastLine = GetRTFLine(TRUE);
+ if (pLastLine != NULL) {
+ pCurPieces = &pLastLine->m_LinePieces;
+ iCount = pCurPieces->GetSize();
+ if (iCount-- > 0) {
+ CFX_RTFPiece* pLastPiece = pCurPieces->GetPtrAt(iCount);
+ if (dwStatus > FX_RTFBREAK_PieceBreak) {
+ pLastPiece->m_dwStatus = dwStatus;
+ } else {
+ dwStatus = pLastPiece->m_dwStatus;
+ }
+ return dwStatus;
+ }
+ return FX_RTFBREAK_None;
+ }
+ iCount = m_pCurLine->CountChars();
+ if (iCount < 1) {
+ return FX_RTFBREAK_None;
+ }
+ CFX_RTFChar& tc = m_pCurLine->GetChar(iCount - 1);
+ tc.m_dwStatus = dwStatus;
+ if (dwStatus <= FX_RTFBREAK_PieceBreak) {
+ return dwStatus;
+ }
+ }
+ m_iReady = (m_pCurLine == &m_RTFLine1) ? 1 : 2;
+ CFX_RTFLine* pNextLine =
+ (m_pCurLine == &m_RTFLine1) ? &m_RTFLine2 : &m_RTFLine1;
+ FX_BOOL bAllChars = (m_iAlignment > FX_RTFLINEALIGNMENT_Right);
+ CFX_TPOArray tpos;
+ if (EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) {
+ goto EndBreak_Ret;
+ }
+ if (!m_bCharCode) {
+ EndBreak_BidiLine(tpos, dwStatus);
+ }
+ if (!m_bPagination && m_iAlignment > FX_RTFLINEALIGNMENT_Left) {
+ EndBreak_Alignment(tpos, bAllChars, dwStatus);
+ }
+EndBreak_Ret:
+ m_pCurLine = pNextLine;
+ m_pCurLine->m_iStart = m_iBoundaryStart;
+ CFX_RTFChar* pTC = GetLastChar(0);
+ m_dwCharType = pTC == NULL ? 0 : pTC->GetCharType();
+ return dwStatus;
+}
+FX_BOOL CFX_RTFBreak::EndBreak_SplitLine(CFX_RTFLine* pNextLine,
+ FX_BOOL bAllChars,
+ FX_DWORD dwStatus) {
+ FX_BOOL bDone = FALSE;
+ if (!m_bSingleLine && !m_bOrphanLine &&
+ m_pCurLine->GetLineEnd() > m_iBoundaryEnd + m_iTolerance) {
+ CFX_RTFChar& tc = m_pCurLine->GetChar(m_pCurLine->CountChars() - 1);
+ switch (tc.GetCharType()) {
+ case FX_CHARTYPE_Tab:
+ if ((m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0) {
+ SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
+ bDone = TRUE;
+ }
+ break;
+ case FX_CHARTYPE_Control:
+ break;
+ case FX_CHARTYPE_Space:
+ if ((m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0) {
+ SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
+ bDone = TRUE;
+ }
+ break;
+ default:
+ SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
+ bDone = TRUE;
+ break;
+ }
+ }
+ if (m_bPagination || m_pCurLine->m_iMBCSChars > 0) {
+ const CFX_RTFChar* pCurChars = m_pCurLine->m_LineChars.GetData();
+ const CFX_RTFChar* pTC;
+ CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
+ CFX_RTFPiece tp;
+ tp.m_pChars = &m_pCurLine->m_LineChars;
+ FX_BOOL bNew = TRUE;
+ FX_DWORD dwIdentity = (FX_DWORD)-1;
+ int32_t iLast = m_pCurLine->CountChars() - 1, j = 0;
+ for (int32_t i = 0; i <= iLast;) {
+ pTC = pCurChars + i;
+ if (bNew) {
+ tp.m_iStartChar = i;
+ tp.m_iStartPos += tp.m_iWidth;
+ tp.m_iWidth = 0;
+ tp.m_dwStatus = pTC->m_dwStatus;
+ tp.m_iFontSize = pTC->m_iFontSize;
+ tp.m_iFontHeight = pTC->m_iFontHeight;
+ tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
+ tp.m_iVerticalScale = pTC->m_iVertialScale;
+ tp.m_dwLayoutStyles = pTC->m_dwLayoutStyles;
+ dwIdentity = pTC->m_dwIdentity;
+ tp.m_dwIdentity = dwIdentity;
+ tp.m_pUserData = pTC->m_pUserData;
+ j = i;
+ bNew = FALSE;
+ }
+ if (i == iLast || pTC->m_dwStatus != FX_RTFBREAK_None ||
+ pTC->m_dwIdentity != dwIdentity) {
+ tp.m_iChars = i - j;
+ if (pTC->m_dwIdentity == dwIdentity) {
+ tp.m_dwStatus = pTC->m_dwStatus;
+ tp.m_iWidth += pTC->m_iCharWidth;
+ tp.m_iChars += 1;
+ i++;
+ }
+ pCurPieces->Add(tp);
+ bNew = TRUE;
+ } else {
+ tp.m_iWidth += pTC->m_iCharWidth;
+ i++;
+ }
+ }
+ return TRUE;
+ }
+ if (bAllChars && !bDone) {
+ int32_t iEndPos = m_pCurLine->GetLineEnd();
+ GetBreakPos(m_pCurLine->m_LineChars, iEndPos, bAllChars, TRUE);
+ }
+ return FALSE;
+}
+void CFX_RTFBreak::EndBreak_BidiLine(CFX_TPOArray& tpos, FX_DWORD dwStatus) {
+ FX_TPO tpo;
+ CFX_RTFPiece tp;
+ CFX_RTFChar* pTC;
+ int32_t i, j;
+ CFX_RTFCharArray& chars = m_pCurLine->m_LineChars;
+ int32_t iCount = m_pCurLine->CountChars();
+ FX_BOOL bDone = (!m_bPagination && !m_bCharCode &&
+ (m_pCurLine->m_iArabicChars > 0 || m_bRTL));
+ if (bDone) {
+ int32_t iBidiNum = 0;
+ for (i = 0; i < iCount; i++) {
+ pTC = chars.GetDataPtr(i);
+ pTC->m_iBidiPos = i;
+ if (pTC->GetCharType() != FX_CHARTYPE_Control) {
+ iBidiNum = i;
+ }
+ if (i == 0) {
+ pTC->m_iBidiLevel = 1;
+ }
+ }
+ FX_BidiLine(chars, iBidiNum + 1, m_bRTL ? 1 : 0);
+ } else {
+ for (i = 0; i < iCount; i++) {
+ pTC = chars.GetDataPtr(i);
+ pTC->m_iBidiLevel = 0;
+ pTC->m_iBidiPos = 0;
+ pTC->m_iBidiOrder = 0;
+ }
+ }
+ tp.m_dwStatus = FX_RTFBREAK_PieceBreak;
+ tp.m_iStartPos = m_pCurLine->m_iStart;
+ tp.m_pChars = &chars;
+ CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
+ int32_t iBidiLevel = -1, iCharWidth;
+ FX_DWORD dwIdentity = (FX_DWORD)-1;
+ i = j = 0;
+ while (i < iCount) {
+ pTC = chars.GetDataPtr(i);
+ if (iBidiLevel < 0) {
+ iBidiLevel = pTC->m_iBidiLevel;
+ iCharWidth = pTC->m_iCharWidth;
+ if (iCharWidth < 1) {
+ tp.m_iWidth = 0;
+ } else {
+ tp.m_iWidth = iCharWidth;
+ }
+ tp.m_iBidiLevel = iBidiLevel;
+ tp.m_iBidiPos = pTC->m_iBidiOrder;
+ tp.m_iFontSize = pTC->m_iFontSize;
+ tp.m_iFontHeight = pTC->m_iFontHeight;
+ tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
+ tp.m_iVerticalScale = pTC->m_iVertialScale;
+ dwIdentity = pTC->m_dwIdentity;
+ tp.m_dwIdentity = dwIdentity;
+ tp.m_pUserData = pTC->m_pUserData;
+ tp.m_dwStatus = FX_RTFBREAK_PieceBreak;
+ i++;
+ } else if (iBidiLevel != pTC->m_iBidiLevel ||
+ pTC->m_dwIdentity != dwIdentity) {
+ tp.m_iChars = i - tp.m_iStartChar;
+ pCurPieces->Add(tp);
+ tp.m_iStartPos += tp.m_iWidth;
+ tp.m_iStartChar = i;
+ tpo.index = j++;
+ tpo.pos = tp.m_iBidiPos;
+ tpos.Add(tpo);
+ iBidiLevel = -1;
+ } else {
+ iCharWidth = pTC->m_iCharWidth;
+ if (iCharWidth > 0) {
+ tp.m_iWidth += iCharWidth;
+ }
+ i++;
+ }
+ }
+ if (i > tp.m_iStartChar) {
+ tp.m_dwStatus = dwStatus;
+ tp.m_iChars = i - tp.m_iStartChar;
+ pCurPieces->Add(tp);
+ tpo.index = j;
+ tpo.pos = tp.m_iBidiPos;
+ tpos.Add(tpo);
+ }
+ if (!m_bCharCode) {
+ j = tpos.GetSize() - 1;
+ FX_TEXTLAYOUT_PieceSort(tpos, 0, j);
+ int32_t iStartPos = m_pCurLine->m_iStart;
+ for (i = 0; i <= j; i++) {
+ tpo = tpos.GetAt(i);
+ CFX_RTFPiece& ttp = pCurPieces->GetAt(tpo.index);
+ ttp.m_iStartPos = iStartPos;
+ iStartPos += ttp.m_iWidth;
+ }
+ }
+}
+void CFX_RTFBreak::EndBreak_Alignment(CFX_TPOArray& tpos,
+ FX_BOOL bAllChars,
+ FX_DWORD dwStatus) {
+ CFX_RTFPieceArray* pCurPieces = &m_pCurLine->m_LinePieces;
+ int32_t iNetWidth = m_pCurLine->m_iWidth, iGapChars = 0, iCharWidth;
+ int32_t iCount = pCurPieces->GetSize();
+ FX_BOOL bFind = FALSE;
+ FX_DWORD dwCharType;
+ int32_t i, j;
+ FX_TPO tpo;
+ for (i = iCount - 1; i > -1; i--) {
+ tpo = tpos.GetAt(i);
+ CFX_RTFPiece& ttp = pCurPieces->GetAt(tpo.index);
+ if (!bFind) {
+ iNetWidth = ttp.GetEndPos();
+ }
+ FX_BOOL bArabic = FX_IsOdd(ttp.m_iBidiLevel);
+ j = bArabic ? 0 : ttp.m_iChars - 1;
+ while (j > -1 && j < ttp.m_iChars) {
+ const CFX_RTFChar& tc = ttp.GetChar(j);
+ if (tc.m_nBreakType == FX_LBT_DIRECT_BRK) {
+ iGapChars++;
+ }
+ if (!bFind || !bAllChars) {
+ dwCharType = tc.GetCharType();
+ if (dwCharType == FX_CHARTYPE_Space ||
+ dwCharType == FX_CHARTYPE_Control) {
+ if (!bFind) {
+ iCharWidth = tc.m_iCharWidth;
+ if (bAllChars && iCharWidth > 0) {
+ iNetWidth -= iCharWidth;
+ }
+ }
+ } else {
+ bFind = TRUE;
+ if (!bAllChars) {
+ break;
+ }
+ }
+ }
+ j += bArabic ? 1 : -1;
+ }
+ if (!bAllChars && bFind) {
+ break;
+ }
+ }
+ int32_t iOffset = m_iBoundaryEnd - iNetWidth;
+ int32_t iLowerAlignment = (m_iAlignment & FX_RTFLINEALIGNMENT_LowerMask);
+ int32_t iHigherAlignment = (m_iAlignment & FX_RTFLINEALIGNMENT_HigherMask);
+ if (iGapChars > 0 && (iHigherAlignment == FX_RTFLINEALIGNMENT_Distributed ||
+ (iHigherAlignment == FX_RTFLINEALIGNMENT_Justified &&
+ dwStatus != FX_RTFBREAK_ParagraphBreak))) {
+ int32_t iStart = -1;
+ for (i = 0; i < iCount; i++) {
+ tpo = tpos.GetAt(i);
+ CFX_RTFPiece& ttp = pCurPieces->GetAt(tpo.index);
+ if (iStart < 0) {
+ iStart = ttp.m_iStartPos;
+ } else {
+ ttp.m_iStartPos = iStart;
+ }
+ int32_t k;
+ for (j = 0; j < ttp.m_iChars; j++) {
+ CFX_RTFChar& tc = ttp.GetChar(j);
+ if (tc.m_nBreakType != FX_LBT_DIRECT_BRK || tc.m_iCharWidth < 0) {
+ continue;
+ }
+ k = iOffset / iGapChars;
+ tc.m_iCharWidth += k;
+ ttp.m_iWidth += k;
+ iOffset -= k;
+ iGapChars--;
+ if (iGapChars < 1) {
+ break;
+ }
+ }
+ iStart += ttp.m_iWidth;
+ }
+ } else if (iLowerAlignment > FX_RTFLINEALIGNMENT_Left) {
+ if (iLowerAlignment == FX_RTFLINEALIGNMENT_Center) {
+ iOffset /= 2;
+ }
+ if (iOffset > 0) {
+ for (i = 0; i < iCount; i++) {
+ CFX_RTFPiece& ttp = pCurPieces->GetAt(i);
+ ttp.m_iStartPos += iOffset;
+ }
+ }
+ }
+}
+int32_t CFX_RTFBreak::GetBreakPos(CFX_RTFCharArray& tca,
+ int32_t& iEndPos,
+ FX_BOOL bAllChars,
+ FX_BOOL bOnlyBrk) {
+ int32_t iLength = tca.GetSize() - 1;
+ if (iLength < 1) {
+ return iLength;
+ }
+ int32_t iBreak = -1, iBreakPos = -1, iIndirect = -1, iIndirectPos = -1,
+ iLast = -1, iLastPos = -1;
+ if (m_bSingleLine || m_bOrphanLine || iEndPos <= m_iBoundaryEnd) {
+ if (!bAllChars || m_bCharCode) {
+ return iLength;
+ }
+ iBreak = iLength;
+ iBreakPos = iEndPos;
+ }
+ CFX_RTFChar* pCharArray = tca.GetData();
+ if (m_bCharCode) {
+ const CFX_RTFChar* pChar;
+ int32_t iCharWidth;
+ while (iLength > 0) {
+ if (iEndPos <= m_iBoundaryEnd) {
+ break;
+ }
+ pChar = pCharArray + iLength--;
+ iCharWidth = pChar->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iEndPos -= iCharWidth;
+ }
+ }
+ return iLength;
+ }
+ FX_BOOL bSpaceBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0;
+ FX_BOOL bTabBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0;
+ FX_BOOL bNumberBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_NumberBreak) != 0;
+ FX_BOOL bInfixBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_InfixBreak) != 0;
+ FX_LINEBREAKTYPE eType;
+ FX_DWORD nCodeProp, nCur, nNext;
+ CFX_RTFChar* pCur = pCharArray + iLength--;
+ if (bAllChars) {
+ pCur->m_nBreakType = FX_LBT_UNKNOWN;
+ }
+ nCodeProp = pCur->m_dwCharProps;
+ nNext = nCodeProp & 0x003F;
+ int32_t iCharWidth = pCur->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iEndPos -= iCharWidth;
+ }
+ while (iLength >= 0) {
+ pCur = pCharArray + iLength;
+ nCodeProp = pCur->m_dwCharProps;
+ nCur = nCodeProp & 0x003F;
+ FX_BOOL bNeedBreak = FALSE;
+ if (nCur == FX_CBP_SP) {
+ bNeedBreak = !bSpaceBreak;
+ if (nNext == FX_CBP_SP) {
+ eType = bSpaceBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE*)gs_FX_LineBreak_PairTable +
+ (nCur << 5) + nNext);
+ }
+ } else if (nCur == FX_CBP_TB) {
+ bNeedBreak = !bTabBreak;
+ if (nNext == FX_CBP_TB) {
+ eType = bTabBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE*)gs_FX_LineBreak_PairTable +
+ (nCur << 5) + nNext);
+ }
+ } else if (bNumberBreak && nCur == FX_CBP_NU && nNext == FX_CBP_NU) {
+ eType = FX_LBT_DIRECT_BRK;
+ } else if (bInfixBreak && nCur == FX_CBP_IS && nNext == FX_CBP_IS) {
+ eType = FX_LBT_DIRECT_BRK;
+ } else {
+ if (nNext == FX_CBP_SP) {
+ eType = FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE*)gs_FX_LineBreak_PairTable +
+ (nCur << 5) + nNext);
+ }
+ }
+ if (bAllChars) {
+ pCur->m_nBreakType = eType;
+ }
+ if (!bOnlyBrk) {
+ iCharWidth = pCur->m_iCharWidth;
+ FX_BOOL bBreak = FALSE;
+ if (nCur == FX_CBP_TB && bTabBreak) {
+ bBreak = iCharWidth > 0 && iEndPos - iCharWidth <= m_iBoundaryEnd;
+ } else {
+ bBreak = iEndPos <= m_iBoundaryEnd;
+ }
+ if (m_bSingleLine || m_bOrphanLine || bBreak || bNeedBreak) {
+ if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) {
+ iBreak = iLength;
+ iBreakPos = iEndPos;
+ if (!bAllChars) {
+ return iLength;
+ }
+ } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) {
+ iIndirect = iLength;
+ iIndirectPos = iEndPos;
+ }
+ if (iLast < 0) {
+ iLast = iLength;
+ iLastPos = iEndPos;
+ }
+ }
+ if (iCharWidth > 0) {
+ iEndPos -= iCharWidth;
+ }
+ }
+ nNext = nCodeProp & 0x003F;
+ iLength--;
+ }
+ if (bOnlyBrk) {
+ return 0;
+ }
+ if (iBreak > -1) {
+ iEndPos = iBreakPos;
+ return iBreak;
+ }
+ if (iIndirect > -1) {
+ iEndPos = iIndirectPos;
+ return iIndirect;
+ }
+ if (iLast > -1) {
+ iEndPos = iLastPos;
+ return iLast;
+ }
+ return 0;
+}
+void CFX_RTFBreak::SplitTextLine(CFX_RTFLine* pCurLine,
+ CFX_RTFLine* pNextLine,
+ FX_BOOL bAllChars) {
+ FXSYS_assert(pCurLine != NULL && pNextLine != NULL);
+ int32_t iCount = pCurLine->CountChars();
+ if (iCount < 2) {
+ return;
+ }
+ int32_t iEndPos = pCurLine->GetLineEnd();
+ CFX_RTFCharArray& curChars = pCurLine->m_LineChars;
+ int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, FALSE);
+ if (iCharPos < 0) {
+ iCharPos = 0;
+ }
+ iCharPos++;
+ if (iCharPos >= iCount) {
+ pNextLine->RemoveAll(TRUE);
+ CFX_Char* pTC = curChars.GetDataPtr(iCharPos - 1);
+ pTC->m_nBreakType = FX_LBT_UNKNOWN;
+ return;
+ }
+ CFX_RTFCharArray& nextChars = pNextLine->m_LineChars;
+ int cur_size = curChars.GetSize();
+ nextChars.SetSize(cur_size - iCharPos);
+ FXSYS_memcpy(nextChars.GetData(), curChars.GetDataPtr(iCharPos),
+ (cur_size - iCharPos) * sizeof(CFX_RTFChar));
+ iCount -= iCharPos;
+ cur_size = curChars.GetSize();
+ curChars.RemoveAt(cur_size - iCount, iCount);
+ pNextLine->m_iStart = pCurLine->m_iStart;
+ pNextLine->m_iWidth = pCurLine->GetLineEnd() - iEndPos;
+ pCurLine->m_iWidth = iEndPos;
+ CFX_RTFChar* tc = curChars.GetDataPtr(iCharPos - 1);
+ tc->m_nBreakType = FX_LBT_UNKNOWN;
+ iCount = nextChars.GetSize();
+ CFX_RTFChar* pNextChars = nextChars.GetData();
+ for (int32_t i = 0; i < iCount; i++) {
+ CFX_RTFChar* tc = pNextChars + i;
+ if (tc->GetCharType() >= FX_CHARTYPE_ArabicAlef) {
+ pCurLine->m_iArabicChars--;
+ pNextLine->m_iArabicChars++;
+ }
+ if (tc->m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_MBCSCode) {
+ pCurLine->m_iMBCSChars--;
+ pNextLine->m_iMBCSChars++;
+ }
+ tc->m_dwStatus = 0;
+ }
+}
+int32_t CFX_RTFBreak::CountBreakPieces() const {
+ CFX_RTFPieceArray* pRTFPieces = GetRTFPieces(TRUE);
+ if (pRTFPieces == NULL) {
+ return 0;
+ }
+ return pRTFPieces->GetSize();
+}
+const CFX_RTFPiece* CFX_RTFBreak::GetBreakPiece(int32_t index) const {
+ CFX_RTFPieceArray* pRTFPieces = GetRTFPieces(TRUE);
+ if (pRTFPieces == NULL) {
+ return NULL;
+ }
+ if (index < 0 || index >= pRTFPieces->GetSize()) {
+ return NULL;
+ }
+ return pRTFPieces->GetPtrAt(index);
+}
+void CFX_RTFBreak::GetLineRect(CFX_RectF& rect) const {
+ rect.top = 0;
+ CFX_RTFLine* pRTFLine = GetRTFLine(TRUE);
+ if (pRTFLine == NULL) {
+ rect.left = ((FX_FLOAT)m_iBoundaryStart) / 20000.0f;
+ rect.width = rect.height = 0;
+ return;
+ }
+ rect.left = ((FX_FLOAT)pRTFLine->m_iStart) / 20000.0f;
+ rect.width = ((FX_FLOAT)pRTFLine->m_iWidth) / 20000.0f;
+ CFX_RTFPieceArray& rtfPieces = pRTFLine->m_LinePieces;
+ int32_t iCount = rtfPieces.GetSize();
+ if (iCount < 1) {
+ rect.width = 0;
+ return;
+ }
+ CFX_RTFPiece* pBreakPiece;
+ int32_t iLineHeight = 0, iMax;
+ for (int32_t i = 0; i < iCount; i++) {
+ pBreakPiece = rtfPieces.GetPtrAt(i);
+ int32_t iFontHeight = FXSYS_round(pBreakPiece->m_iFontHeight *
+ pBreakPiece->m_iVerticalScale / 100.0f);
+ iMax = std::max(pBreakPiece->m_iFontSize, iFontHeight);
+ if (i == 0) {
+ iLineHeight = iMax;
+ } else if (iLineHeight < iMax) {
+ iLineHeight = iMax;
+ }
+ }
+ rect.height = ((FX_FLOAT)iLineHeight) / 20.0f;
+}
+void CFX_RTFBreak::ClearBreakPieces() {
+ CFX_RTFLine* pRTFLine = GetRTFLine(TRUE);
+ if (pRTFLine != NULL) {
+ pRTFLine->RemoveAll(TRUE);
+ }
+ m_iReady = 0;
+}
+void CFX_RTFBreak::Reset() {
+ m_dwCharType = 0;
+ m_RTFLine1.RemoveAll(TRUE);
+ m_RTFLine2.RemoveAll(TRUE);
+}
+int32_t CFX_RTFBreak::GetDisplayPos(const FX_RTFTEXTOBJ* pText,
+ FXTEXT_CHARPOS* pCharPos,
+ FX_BOOL bCharCode,
+ CFX_WideString* pWSForms,
+ FX_AdjustCharDisplayPos pAdjustPos) const {
+ if (pText == NULL || pText->iLength < 1) {
+ return 0;
+ }
+ FXSYS_assert(pText->pStr != NULL && pText->pWidths != NULL &&
+ pText->pFont != NULL && pText->pRect != NULL);
+ const FX_WCHAR* pStr = pText->pStr;
+ int32_t* pWidths = pText->pWidths;
+ int32_t iLength = pText->iLength - 1;
+ IFX_Font* pFont = pText->pFont;
+ FX_DWORD dwStyles = pText->dwLayoutStyles;
+ CFX_RectF rtText(*pText->pRect);
+ FX_BOOL bRTLPiece = FX_IsOdd(pText->iBidiLevel);
+ FX_FLOAT fFontSize = pText->fFontSize;
+ int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
+ int32_t iAscent = pFont->GetAscent();
+ int32_t iDescent = pFont->GetDescent();
+ int32_t iMaxHeight = iAscent - iDescent;
+ FX_FLOAT fFontHeight = fFontSize;
+ FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight;
+ FX_FLOAT fDescent = fFontHeight * (FX_FLOAT)iDescent / (FX_FLOAT)iMaxHeight;
+ FX_BOOL bVerticalDoc = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalLayout) != 0;
+ FX_BOOL bVerticalChar = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalChars) != 0;
+ FX_BOOL bArabicNumber = (dwStyles & FX_RTFLAYOUTSTYLE_ArabicNumber) != 0;
+ FX_BOOL bMBCSCode = (dwStyles & FX_RTFLAYOUTSTYLE_MBCSCode) != 0;
+ int32_t iRotation = GetLineRotation(dwStyles) + pText->iCharRotation;
+ int32_t iCharRotation;
+ FX_WCHAR wch, wPrev = 0xFEFF, wNext, wForm;
+ int32_t iWidth, iCharWidth, iCharHeight;
+ FX_FLOAT fX, fY, fCharWidth, fCharHeight;
+ int32_t iHorScale = pText->iHorizontalScale;
+ int32_t iVerScale = pText->iVerticalScale;
+ FX_BOOL bEmptyChar;
+ FX_DWORD dwProps, dwCharType;
+ fX = rtText.left;
+ fY = rtText.top;
+ if (bVerticalDoc) {
+ fX += (rtText.width - fFontSize) / 2.0f;
+ if (bRTLPiece) {
+ fY = rtText.bottom();
+ }
+ } else {
+ if (bRTLPiece) {
+ fX = rtText.right();
+ }
+ fY += fAscent;
+ }
+ int32_t iCount = 0;
+ for (int32_t i = 0; i <= iLength; i++) {
+ wch = *pStr++;
+ iWidth = *pWidths++;
+ if (!bMBCSCode) {
+ dwProps = FX_GetUnicodeProperties(wch);
+ dwCharType = (dwProps & FX_CHARTYPEBITSMASK);
+ if (dwCharType == FX_CHARTYPE_ArabicAlef && iWidth == 0) {
+ wPrev = 0xFEFF;
+ continue;
+ }
+ } else {
+ dwProps = 0;
+ dwCharType = 0;
+ }
+ if (iWidth != 0) {
+ iCharWidth = iWidth;
+ if (iCharWidth < 0) {
+ iCharWidth = -iCharWidth;
+ }
+ if (!bMBCSCode) {
+ bEmptyChar = (dwCharType >= FX_CHARTYPE_Tab &&
+ dwCharType <= FX_CHARTYPE_Control);
+ } else {
+ bEmptyChar = FALSE;
+ }
+ if (!bEmptyChar) {
+ iCount++;
+ }
+ if (pCharPos != NULL) {
+ iCharWidth /= iFontSize;
+ wForm = wch;
+ if (!bMBCSCode) {
+ if (dwCharType >= FX_CHARTYPE_ArabicAlef) {
+ if (i < iLength) {
+ wNext = *pStr;
+ if (*pWidths < 0) {
+ if (i + 1 < iLength) {
+ wNext = pStr[1];
+ }
+ }
+ } else {
+ wNext = 0xFEFF;
+ }
+ wForm = m_pArabicChar->GetFormChar(wch, wPrev, wNext);
+ } else if (bRTLPiece || bVerticalChar) {
+ wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, bVerticalChar);
+ } else if (dwCharType == FX_CHARTYPE_Numeric && bArabicNumber) {
+ wForm = wch + 0x0630;
+ }
+ dwProps = FX_GetUnicodeProperties(wForm);
+ }
+ iCharRotation = iRotation;
+ if (!bMBCSCode && bVerticalChar && (dwProps & 0x8000) != 0) {
+ iCharRotation++;
+ iCharRotation %= 4;
+ }
+ if (!bEmptyChar) {
+ if (bCharCode) {
+ pCharPos->m_GlyphIndex = wch;
+ } else {
+ pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wForm, bMBCSCode);
+ if (pCharPos->m_GlyphIndex == 0xFFFF) {
+ pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wch, bMBCSCode);
+ }
+ }
+ pCharPos->m_ExtGID = pCharPos->m_GlyphIndex;
+ pCharPos->m_FontCharWidth = iCharWidth;
+ if (pWSForms) {
+ *pWSForms += wForm;
+ }
+ }
+ if (bVerticalDoc) {
+ iCharHeight = iCharWidth;
+ iCharWidth = 1000;
+ } else {
+ iCharHeight = 1000;
+ }
+ fCharWidth = fFontSize * iCharWidth / 1000.0f;
+ fCharHeight = fFontSize * iCharHeight / 1000.0f;
+ if (!bMBCSCode && bRTLPiece && dwCharType != FX_CHARTYPE_Combination) {
+ if (bVerticalDoc) {
+ fY -= fCharHeight;
+ } else {
+ fX -= fCharWidth;
+ }
+ }
+ if (!bEmptyChar) {
+ CFX_PointF ptOffset;
+ FX_BOOL bAdjusted = FALSE;
+ if (pAdjustPos) {
+ bAdjusted = pAdjustPos(wForm, bMBCSCode, pFont, fFontSize,
+ bVerticalChar, ptOffset);
+ }
+ if (!pAdjustPos && bVerticalChar && (dwProps & 0x00010000) != 0) {
+ CFX_Rect rtBBox;
+ rtBBox.Reset();
+ if (pFont->GetCharBBox(wForm, rtBBox, bMBCSCode)) {
+ ptOffset.x = fFontSize * (850 - rtBBox.right()) / 1000.0f;
+ ptOffset.y = fFontSize * (1000 - rtBBox.height) / 2000.0f;
+ }
+ }
+ pCharPos->m_OriginX = fX + ptOffset.x;
+ pCharPos->m_OriginY = fY - ptOffset.y;
+ }
+ if (!bRTLPiece && dwCharType != FX_CHARTYPE_Combination) {
+ if (bVerticalDoc) {
+ fY += fCharHeight;
+ } else {
+ fX += fCharWidth;
+ }
+ }
+ if (!bEmptyChar) {
+ pCharPos->m_bGlyphAdjust = TRUE;
+ if (bVerticalDoc) {
+ if (iCharRotation == 0) {
+ pCharPos->m_AdjustMatrix[0] = -1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = 1;
+ pCharPos->m_OriginY += fAscent * iVerScale / 100.0f;
+ } else if (iCharRotation == 1) {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = -1;
+ pCharPos->m_AdjustMatrix[2] = -1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX -=
+ fDescent + fAscent * iVerScale / 100.0f - fAscent;
+ } else if (iCharRotation == 2) {
+ pCharPos->m_AdjustMatrix[0] = 1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = -1;
+ pCharPos->m_OriginX += fCharWidth;
+ pCharPos->m_OriginY += fAscent;
+ } else {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = 1;
+ pCharPos->m_AdjustMatrix[2] = 1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX += fAscent;
+ pCharPos->m_OriginY += fCharWidth;
+ }
+ } else {
+ if (iCharRotation == 0) {
+ pCharPos->m_AdjustMatrix[0] = -1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = 1;
+ pCharPos->m_OriginY += fAscent * iVerScale / 100.0f - fAscent;
+ } else if (iCharRotation == 1) {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = -1;
+ pCharPos->m_AdjustMatrix[2] = -1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX -= fDescent;
+ pCharPos->m_OriginY -= fAscent + fDescent;
+ } else if (iCharRotation == 2) {
+ pCharPos->m_AdjustMatrix[0] = 1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = -1;
+ pCharPos->m_OriginX += fCharWidth;
+ pCharPos->m_OriginY -= fAscent;
+ } else {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = 1;
+ pCharPos->m_AdjustMatrix[2] = 1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX += fAscent * iVerScale / 100.0f;
+ }
+ }
+ if (iHorScale != 100 || iVerScale != 100) {
+ pCharPos->m_AdjustMatrix[0] =
+ pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f;
+ pCharPos->m_AdjustMatrix[1] =
+ pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f;
+ pCharPos->m_AdjustMatrix[2] =
+ pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f;
+ pCharPos->m_AdjustMatrix[3] =
+ pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f;
+ }
+ pCharPos++;
+ }
+ }
+ }
+ if (iWidth > 0) {
+ wPrev = wch;
+ }
+ }
+ return iCount;
+}
+int32_t CFX_RTFBreak::GetCharRects(const FX_RTFTEXTOBJ* pText,
+ CFX_RectFArray& rtArray,
+ FX_BOOL bCharBBox) const {
+ if (pText == NULL || pText->iLength < 1) {
+ return 0;
+ }
+ FXSYS_assert(pText->pStr != NULL && pText->pWidths != NULL &&
+ pText->pFont != NULL && pText->pRect != NULL);
+ const FX_WCHAR* pStr = pText->pStr;
+ int32_t* pWidths = pText->pWidths;
+ int32_t iLength = pText->iLength;
+ CFX_RectF rect(*pText->pRect);
+ FX_BOOL bRTLPiece = FX_IsOdd(pText->iBidiLevel);
+ FX_FLOAT fFontSize = pText->fFontSize;
+ int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
+ FX_FLOAT fScale = fFontSize / 1000.0f;
+ IFX_Font* pFont = pText->pFont;
+ if (pFont == NULL) {
+ bCharBBox = FALSE;
+ }
+ CFX_Rect bbox;
+ bbox.Set(0, 0, 0, 0);
+ if (bCharBBox) {
+ bCharBBox = pFont->GetBBox(bbox);
+ }
+ FX_FLOAT fLeft = std::max(0.0f, bbox.left * fScale);
+ FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale);
+ rtArray.RemoveAll();
+ rtArray.SetSize(iLength);
+ FX_DWORD dwStyles = pText->dwLayoutStyles;
+ FX_BOOL bVertical = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalLayout) != 0;
+ FX_BOOL bSingleLine = (dwStyles & FX_RTFLAYOUTSTYLE_SingleLine) != 0;
+ FX_BOOL bCombText = (dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
+ FX_WCHAR wch, wLineBreakChar = pText->wLineBreakChar;
+ int32_t iCharSize;
+ FX_FLOAT fCharSize, fStart;
+ if (bVertical) {
+ fStart = bRTLPiece ? rect.bottom() : rect.top;
+ } else {
+ fStart = bRTLPiece ? rect.right() : rect.left;
+ }
+ for (int32_t i = 0; i < iLength; i++) {
+ wch = *pStr++;
+ iCharSize = *pWidths++;
+ fCharSize = (FX_FLOAT)iCharSize / 20000.0f;
+ FX_BOOL bRet = (!bSingleLine && FX_IsCtrlCode(wch));
+ if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 ||
+ (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) {
+ bRet = FALSE;
+ }
+ if (bRet) {
+ iCharSize = iFontSize * 500;
+ fCharSize = fFontSize / 2.0f;
+ }
+ if (bVertical) {
+ rect.top = fStart;
+ if (bRTLPiece) {
+ rect.top -= fCharSize;
+ fStart -= fCharSize;
+ } else {
+ fStart += fCharSize;
+ }
+ rect.height = fCharSize;
+ } else {
+ rect.left = fStart;
+ if (bRTLPiece) {
+ rect.left -= fCharSize;
+ fStart -= fCharSize;
+ } else {
+ fStart += fCharSize;
+ }
+ rect.width = fCharSize;
+ }
+ if (bCharBBox && !bRet) {
+ int32_t iCharWidth = 1000;
+ pFont->GetCharWidth(wch, iCharWidth);
+ FX_FLOAT fRTLeft = 0, fCharWidth = 0;
+ if (iCharWidth > 0) {
+ fCharWidth = iCharWidth * fScale;
+ fRTLeft = fLeft;
+ if (bCombText) {
+ fRTLeft = (rect.width - fCharWidth) / 2.0f;
+ }
+ }
+ CFX_RectF rtBBoxF;
+ if (bVertical) {
+ rtBBoxF.top = rect.left + fRTLeft;
+ rtBBoxF.left = rect.top + (rect.height - fHeight) / 2.0f;
+ rtBBoxF.height = fCharWidth;
+ rtBBoxF.width = fHeight;
+ rtBBoxF.left = std::max(rtBBoxF.left, 0.0f);
+ } else {
+ rtBBoxF.left = rect.left + fRTLeft;
+ rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f;
+ rtBBoxF.width = fCharWidth;
+ rtBBoxF.height = fHeight;
+ rtBBoxF.top = std::max(rtBBoxF.top, 0.0f);
+ }
+ rtArray.SetAt(i, rtBBoxF);
+ continue;
+ }
+ rtArray.SetAt(i, rect);
+ }
+ return iLength;
+}
diff --git a/xfa/src/fgas/layout/fgas_rtfbreak.h b/xfa/src/fgas/layout/fgas_rtfbreak.h
new file mode 100644
index 0000000000..24cf2e32cb
--- /dev/null
+++ b/xfa/src/fgas/layout/fgas_rtfbreak.h
@@ -0,0 +1,237 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_LAYOUT_FGAS_RTFBREAK_H_
+#define XFA_SRC_FGAS_LAYOUT_FGAS_RTFBREAK_H_
+
+#include "core/include/fxcrt/fx_ucd.h"
+#include "core/include/fxge/fx_ge.h"
+#include "xfa/src/fgas/crt/fgas_memory.h"
+#include "xfa/src/fgas/crt/fgas_utils.h"
+#include "xfa/src/fgas/layout/fgas_textbreak.h"
+#include "xfa/src/fgas/layout/fgas_unicode.h"
+
+class IFX_Unknown;
+class IFX_Font;
+
+#define FX_RTFBREAKPOLICY_None 0x00
+#define FX_RTFBREAKPOLICY_SpaceBreak 0x01
+#define FX_RTFBREAKPOLICY_NumberBreak 0x02
+#define FX_RTFBREAKPOLICY_InfixBreak 0x04
+#define FX_RTFBREAKPOLICY_TabBreak 0x08
+#define FX_RTFBREAKPOLICY_OrphanPositionedTab 0x10
+#define FX_RTFBREAK_None 0x00
+#define FX_RTFBREAK_PieceBreak 0x01
+#define FX_RTFBREAK_LineBreak 0x02
+#define FX_RTFBREAK_ParagraphBreak 0x03
+#define FX_RTFBREAK_PageBreak 0x04
+#define FX_RTFLAYOUTSTYLE_Pagination 0x01
+#define FX_RTFLAYOUTSTYLE_VerticalLayout 0x02
+#define FX_RTFLAYOUTSTYLE_VerticalChars 0x04
+#define FX_RTFLAYOUTSTYLE_LineDirection 0x08
+#define FX_RTFLAYOUTSTYLE_ExpandTab 0x10
+#define FX_RTFLAYOUTSTYLE_ArabicNumber 0x20
+#define FX_RTFLAYOUTSTYLE_SingleLine 0x40
+#define FX_RTFLAYOUTSTYLE_MBCSCode 0x80
+#define FX_RTFCHARSTYLE_Alignment 0x000F
+#define FX_RTFCHARSTYLE_ArabicNumber 0x0010
+#define FX_RTFCHARSTYLE_ArabicShadda 0x0020
+#define FX_RTFCHARSTYLE_OddBidiLevel 0x0040
+#define FX_RTFCHARSTYLE_RTLReadingOrder 0x0080
+#define FX_RTFCHARSTYLE_ArabicContext 0x0300
+#define FX_RTFCHARSTYLE_ArabicIndic 0x0400
+#define FX_RTFCHARSTYLE_ArabicComma 0x0800
+#define FX_RTFLINEALIGNMENT_Left 0
+#define FX_RTFLINEALIGNMENT_Center 1
+#define FX_RTFLINEALIGNMENT_Right 2
+#define FX_RTFLINEALIGNMENT_Justified (1 << 2)
+#define FX_RTFLINEALIGNMENT_Distributed (2 << 2)
+#define FX_RTFLINEALIGNMENT_JustifiedLeft \
+ (FX_RTFLINEALIGNMENT_Left | FX_RTFLINEALIGNMENT_Justified)
+#define FX_RTFLINEALIGNMENT_JustifiedCenter \
+ (FX_RTFLINEALIGNMENT_Center | FX_RTFLINEALIGNMENT_Justified)
+#define FX_RTFLINEALIGNMENT_JustifiedRight \
+ (FX_RTFLINEALIGNMENT_Right | FX_RTFLINEALIGNMENT_Justified)
+#define FX_RTFLINEALIGNMENT_DistributedLeft \
+ (FX_RTFLINEALIGNMENT_Left | FX_RTFLINEALIGNMENT_Distributed)
+#define FX_RTFLINEALIGNMENT_DistributedCenter \
+ (FX_RTFLINEALIGNMENT_Center | FX_RTFLINEALIGNMENT_Distributed)
+#define FX_RTFLINEALIGNMENT_DistributedRight \
+ (FX_RTFLINEALIGNMENT_Right | FX_RTFLINEALIGNMENT_Distributed)
+#define FX_RTFLINEALIGNMENT_LowerMask 0x03
+#define FX_RTFLINEALIGNMENT_HigherMask 0x0C
+
+struct FX_RTFTEXTOBJ {
+ FX_RTFTEXTOBJ() {
+ pStr = NULL;
+ pWidths = NULL;
+ iLength = 0;
+ pFont = NULL;
+ fFontSize = 12.0f;
+ dwLayoutStyles = 0;
+ iCharRotation = 0;
+ iBidiLevel = 0;
+ pRect = NULL;
+ wLineBreakChar = L'\n';
+ iHorizontalScale = 100;
+ iVerticalScale = 100;
+ }
+
+ const FX_WCHAR* pStr;
+ int32_t* pWidths;
+ int32_t iLength;
+ IFX_Font* pFont;
+ FX_FLOAT fFontSize;
+ FX_DWORD dwLayoutStyles;
+ int32_t iCharRotation;
+ int32_t iBidiLevel;
+ const CFX_RectF* pRect;
+ FX_WCHAR wLineBreakChar;
+ int32_t iHorizontalScale;
+ int32_t iVerticalScale;
+};
+
+class CFX_RTFPiece : public CFX_Target {
+ public:
+ CFX_RTFPiece()
+ : m_dwStatus(FX_RTFBREAK_PieceBreak),
+ m_iStartPos(0),
+ m_iWidth(-1),
+ m_iStartChar(0),
+ m_iChars(0),
+ m_iBidiLevel(0),
+ m_iBidiPos(0),
+ m_iFontSize(0),
+ m_iFontHeight(0),
+ m_iHorizontalScale(100),
+ m_iVerticalScale(100),
+ m_dwLayoutStyles(0),
+ m_dwIdentity(0),
+ m_pChars(NULL),
+ m_pUserData(NULL) {}
+ ~CFX_RTFPiece() { Reset(); }
+ void AppendChar(const CFX_RTFChar& tc) {
+ FXSYS_assert(m_pChars != NULL);
+ m_pChars->Add(tc);
+ if (m_iWidth < 0) {
+ m_iWidth = tc.m_iCharWidth;
+ } else {
+ m_iWidth += tc.m_iCharWidth;
+ }
+ m_iChars++;
+ }
+ int32_t GetEndPos() const {
+ return m_iWidth < 0 ? m_iStartPos : m_iStartPos + m_iWidth;
+ }
+ int32_t GetLength() const { return m_iChars; }
+ int32_t GetEndChar() const { return m_iStartChar + m_iChars; }
+ CFX_RTFChar& GetChar(int32_t index) {
+ FXSYS_assert(index > -1 && index < m_iChars && m_pChars != NULL);
+ return *m_pChars->GetDataPtr(m_iStartChar + index);
+ }
+ CFX_RTFChar* GetCharPtr(int32_t index) const {
+ FXSYS_assert(index > -1 && index < m_iChars && m_pChars != NULL);
+ return m_pChars->GetDataPtr(m_iStartChar + index);
+ }
+ void GetString(FX_WCHAR* pText) const {
+ FXSYS_assert(pText != NULL);
+ int32_t iEndChar = m_iStartChar + m_iChars;
+ CFX_RTFChar* pChar;
+ for (int32_t i = m_iStartChar; i < iEndChar; i++) {
+ pChar = m_pChars->GetDataPtr(i);
+ *pText++ = (FX_WCHAR)pChar->m_wCharCode;
+ }
+ }
+ void GetString(CFX_WideString& wsText) const {
+ FX_WCHAR* pText = wsText.GetBuffer(m_iChars);
+ GetString(pText);
+ wsText.ReleaseBuffer(m_iChars);
+ }
+ void GetWidths(int32_t* pWidths) const {
+ FXSYS_assert(pWidths != NULL);
+ int32_t iEndChar = m_iStartChar + m_iChars;
+ CFX_RTFChar* pChar;
+ for (int32_t i = m_iStartChar; i < iEndChar; i++) {
+ pChar = m_pChars->GetDataPtr(i);
+ *pWidths++ = pChar->m_iCharWidth;
+ }
+ }
+ void Reset() {
+ m_dwStatus = FX_RTFBREAK_PieceBreak;
+ if (m_iWidth > -1) {
+ m_iStartPos += m_iWidth;
+ }
+ m_iWidth = -1;
+ m_iStartChar += m_iChars;
+ m_iChars = 0;
+ m_iBidiLevel = 0;
+ m_iBidiPos = 0;
+ m_iHorizontalScale = 100;
+ m_iVerticalScale = 100;
+ }
+ FX_DWORD m_dwStatus;
+ int32_t m_iStartPos;
+ int32_t m_iWidth;
+ int32_t m_iStartChar;
+ int32_t m_iChars;
+ int32_t m_iBidiLevel;
+ int32_t m_iBidiPos;
+ int32_t m_iFontSize;
+ int32_t m_iFontHeight;
+ int32_t m_iHorizontalScale;
+ int32_t m_iVerticalScale;
+ FX_DWORD m_dwLayoutStyles;
+ FX_DWORD m_dwIdentity;
+ CFX_RTFCharArray* m_pChars;
+ IFX_Unknown* m_pUserData;
+};
+typedef CFX_BaseArrayTemplate<CFX_RTFPiece> CFX_RTFPieceArray;
+
+class IFX_RTFBreak {
+ public:
+ static IFX_RTFBreak* Create(FX_DWORD dwPolicies);
+ virtual ~IFX_RTFBreak() {}
+ virtual void Release() = 0;
+ virtual void SetLineBoundary(FX_FLOAT fLineStart, FX_FLOAT fLineEnd) = 0;
+ virtual void SetLineStartPos(FX_FLOAT fLinePos) = 0;
+ virtual FX_DWORD GetLayoutStyles() const = 0;
+ virtual void SetLayoutStyles(FX_DWORD dwLayoutStyles) = 0;
+ virtual void SetFont(IFX_Font* pFont) = 0;
+ virtual void SetFontSize(FX_FLOAT fFontSize) = 0;
+ virtual void SetTabWidth(FX_FLOAT fTabWidth) = 0;
+ virtual void AddPositionedTab(FX_FLOAT fTabPos) = 0;
+ virtual void SetPositionedTabs(const CFX_FloatArray& tabs) = 0;
+ virtual void ClearPositionedTabs() = 0;
+ virtual void SetDefaultChar(FX_WCHAR wch) = 0;
+ virtual void SetLineBreakChar(FX_WCHAR wch) = 0;
+ virtual void SetLineBreakTolerance(FX_FLOAT fTolerance) = 0;
+ virtual void SetHorizontalScale(int32_t iScale) = 0;
+ virtual void SetVerticalScale(int32_t iScale) = 0;
+ virtual void SetCharRotation(int32_t iCharRotation) = 0;
+ virtual void SetCharSpace(FX_FLOAT fCharSpace) = 0;
+ virtual void SetWordSpace(FX_BOOL bDefault, FX_FLOAT fWordSpace) = 0;
+ virtual void SetReadingOrder(FX_BOOL bRTL = FALSE) = 0;
+ virtual void SetAlignment(int32_t iAlignment = FX_RTFLINEALIGNMENT_Left) = 0;
+ virtual void SetUserData(IFX_Unknown* pUserData) = 0;
+ virtual FX_DWORD AppendChar(FX_WCHAR wch) = 0;
+ virtual FX_DWORD EndBreak(FX_DWORD dwStatus = FX_RTFBREAK_PieceBreak) = 0;
+ virtual int32_t CountBreakPieces() const = 0;
+ virtual const CFX_RTFPiece* GetBreakPiece(int32_t index) const = 0;
+ virtual void GetLineRect(CFX_RectF& rect) const = 0;
+ virtual void ClearBreakPieces() = 0;
+ virtual void Reset() = 0;
+ virtual int32_t GetDisplayPos(
+ const FX_RTFTEXTOBJ* pText,
+ FXTEXT_CHARPOS* pCharPos,
+ FX_BOOL bCharCode = FALSE,
+ CFX_WideString* pWSForms = NULL,
+ FX_AdjustCharDisplayPos pAdjustPos = NULL) const = 0;
+ virtual int32_t GetCharRects(const FX_RTFTEXTOBJ* pText,
+ CFX_RectFArray& rtArray,
+ FX_BOOL bCharBBox = FALSE) const = 0;
+};
+
+#endif // XFA_SRC_FGAS_LAYOUT_FGAS_RTFBREAK_H_
diff --git a/xfa/src/fgas/layout/fgas_textbreak.cpp b/xfa/src/fgas/layout/fgas_textbreak.cpp
new file mode 100644
index 0000000000..af7be50a51
--- /dev/null
+++ b/xfa/src/fgas/layout/fgas_textbreak.cpp
@@ -0,0 +1,1824 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/layout/fgas_textbreak.h"
+
+#include <algorithm>
+
+#include "core/include/fxcrt/fx_arb.h"
+#include "core/include/fxcrt/fx_memory.h"
+#include "xfa/src/fgas/layout/fgas_linebreak.h"
+#include "xfa/src/fgas/layout/fgas_unicode.h"
+
+namespace {
+
+class CFX_TxtLine {
+ public:
+ CFX_TxtLine(int32_t iBlockSize)
+ : m_iStart(0), m_iWidth(0), m_iArabicChars(0) {
+ m_pLineChars = new CFX_TxtCharArray;
+ m_pLinePieces = new CFX_TxtPieceArray(16);
+ }
+ ~CFX_TxtLine() {
+ RemoveAll();
+ delete m_pLineChars;
+ delete m_pLinePieces;
+ }
+ int32_t CountChars() const { return m_pLineChars->GetSize(); }
+ CFX_TxtChar* GetCharPtr(int32_t index) const {
+ FXSYS_assert(index > -1 && index < m_pLineChars->GetSize());
+ return m_pLineChars->GetDataPtr(index);
+ }
+ int32_t CountPieces() const { return m_pLinePieces->GetSize(); }
+ CFX_TxtPiece* GetPiecePtr(int32_t index) const {
+ FXSYS_assert(index > -1 && index < m_pLinePieces->GetSize());
+ return m_pLinePieces->GetPtrAt(index);
+ }
+ void GetString(CFX_WideString& wsStr) const {
+ int32_t iCount = m_pLineChars->GetSize();
+ FX_WCHAR* pBuf = wsStr.GetBuffer(iCount);
+ CFX_Char* pChar;
+ for (int32_t i = 0; i < iCount; i++) {
+ pChar = m_pLineChars->GetDataPtr(i);
+ *pBuf++ = (FX_WCHAR)pChar->m_wCharCode;
+ }
+ wsStr.ReleaseBuffer(iCount);
+ }
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE) {
+ m_pLineChars->RemoveAll();
+ m_pLinePieces->RemoveAll(bLeaveMemory);
+ m_iWidth = 0;
+ m_iArabicChars = 0;
+ }
+ CFX_TxtCharArray* m_pLineChars;
+ CFX_TxtPieceArray* m_pLinePieces;
+ int32_t m_iStart;
+ int32_t m_iWidth;
+ int32_t m_iArabicChars;
+};
+
+class CFX_TxtBreak : public IFX_TxtBreak {
+ public:
+ CFX_TxtBreak(FX_DWORD dwPolicies);
+ ~CFX_TxtBreak();
+ virtual void Release() { delete this; }
+ virtual void SetLineWidth(FX_FLOAT fLineWidth);
+ virtual void SetLinePos(FX_FLOAT fLinePos);
+ virtual FX_DWORD GetLayoutStyles() const { return m_dwLayoutStyles; }
+ virtual void SetLayoutStyles(FX_DWORD dwLayoutStyles);
+ virtual void SetFont(IFX_Font* pFont);
+ virtual void SetFontSize(FX_FLOAT fFontSize);
+ virtual void SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant);
+ virtual void SetDefaultChar(FX_WCHAR wch);
+ virtual void SetParagraphBreakChar(FX_WCHAR wch);
+ virtual void SetLineBreakTolerance(FX_FLOAT fTolerance);
+ virtual void SetHorizontalScale(int32_t iScale);
+ virtual void SetVerticalScale(int32_t iScale);
+ virtual void SetCharRotation(int32_t iCharRotation);
+ virtual void SetCharSpace(FX_FLOAT fCharSpace);
+ virtual void SetAlignment(int32_t iAlignment);
+ virtual FX_DWORD GetContextCharStyles() const;
+ virtual void SetContextCharStyles(FX_DWORD dwCharStyles);
+ virtual void SetCombWidth(FX_FLOAT fCombWidth);
+ virtual void SetUserData(void* pUserData);
+ virtual FX_DWORD AppendChar(FX_WCHAR wch);
+ virtual FX_DWORD EndBreak(FX_DWORD dwStatus = FX_TXTBREAK_PieceBreak);
+ virtual int32_t CountBreakChars() const;
+ virtual int32_t CountBreakPieces() const;
+ virtual const CFX_TxtPiece* GetBreakPiece(int32_t index) const;
+ virtual void ClearBreakPieces();
+ virtual void Reset();
+ virtual int32_t GetDisplayPos(
+ const FX_TXTRUN* pTxtRun,
+ FXTEXT_CHARPOS* pCharPos,
+ FX_BOOL bCharCode = FALSE,
+ CFX_WideString* pWSForms = NULL,
+ FX_AdjustCharDisplayPos pAdjustPos = NULL) const;
+ virtual int32_t GetCharRects(const FX_TXTRUN* pTxtRun,
+ CFX_RectFArray& rtArray,
+ FX_BOOL bCharBBox = FALSE) const;
+ void AppendChar_PageLoad(CFX_Char* pCurChar, FX_DWORD dwProps);
+ FX_DWORD AppendChar_Combination(CFX_Char* pCurChar, int32_t iRotation);
+ FX_DWORD AppendChar_Tab(CFX_Char* pCurChar, int32_t iRotation);
+ FX_DWORD AppendChar_Control(CFX_Char* pCurChar, int32_t iRotation);
+ FX_DWORD AppendChar_Arabic(CFX_Char* pCurChar, int32_t iRotation);
+ FX_DWORD AppendChar_Others(CFX_Char* pCurChar, int32_t iRotation);
+
+ protected:
+ FX_DWORD m_dwPolicies;
+ FX_BOOL m_bPagination;
+ IFX_ArabicChar* m_pArabicChar;
+ int32_t m_iLineWidth;
+ FX_DWORD m_dwLayoutStyles;
+ FX_BOOL m_bVertical;
+ FX_BOOL m_bArabicContext;
+ FX_BOOL m_bArabicShapes;
+ FX_BOOL m_bRTL;
+ FX_BOOL m_bSingleLine;
+ FX_BOOL m_bCombText;
+ int32_t m_iArabicContext;
+ int32_t m_iCurArabicContext;
+ IFX_Font* m_pFont;
+ int32_t m_iFontSize;
+ FX_BOOL m_bEquidistant;
+ int32_t m_iTabWidth;
+ FX_WCHAR m_wDefChar;
+ FX_WCHAR m_wParagBreakChar;
+ int32_t m_iDefChar;
+ int32_t m_iLineRotation;
+ int32_t m_iCharRotation;
+ int32_t m_iRotation;
+ int32_t m_iAlignment;
+ FX_DWORD m_dwContextCharStyles;
+ int32_t m_iCombWidth;
+ void* m_pUserData;
+ FX_DWORD m_dwCharType;
+ FX_BOOL m_bCurRTL;
+ int32_t m_iCurAlignment;
+ FX_BOOL m_bArabicNumber;
+ FX_BOOL m_bArabicComma;
+ CFX_TxtLine* m_pTxtLine1;
+ CFX_TxtLine* m_pTxtLine2;
+ CFX_TxtLine* m_pCurLine;
+ int32_t m_iReady;
+ int32_t m_iTolerance;
+ int32_t m_iHorScale;
+ int32_t m_iVerScale;
+ int32_t m_iCharSpace;
+ void SetBreakStatus();
+ int32_t GetLineRotation(FX_DWORD dwStyles) const;
+ CFX_TxtChar* GetLastChar(int32_t index, FX_BOOL bOmitChar = TRUE) const;
+ CFX_TxtLine* GetTxtLine(FX_BOOL bReady) const;
+ CFX_TxtPieceArray* GetTxtPieces(FX_BOOL bReady) const;
+ FX_DWORD GetUnifiedCharType(FX_DWORD dwType) const;
+ void ResetArabicContext();
+ void ResetContextCharStyles();
+ void EndBreak_UpdateArabicShapes();
+ FX_BOOL EndBreak_SplitLine(CFX_TxtLine* pNextLine,
+ FX_BOOL bAllChars,
+ FX_DWORD dwStatus);
+ void EndBreak_BidiLine(CFX_TPOArray& tpos, FX_DWORD dwStatus);
+ void EndBreak_Alignment(CFX_TPOArray& tpos,
+ FX_BOOL bAllChars,
+ FX_DWORD dwStatus);
+ int32_t GetBreakPos(CFX_TxtCharArray& ca,
+ int32_t& iEndPos,
+ FX_BOOL bAllChars = FALSE,
+ FX_BOOL bOnlyBrk = FALSE);
+ void SplitTextLine(CFX_TxtLine* pCurLine,
+ CFX_TxtLine* pNextLine,
+ FX_BOOL bAllChars = FALSE);
+};
+
+} // namespace
+
+extern const FX_LINEBREAKTYPE gs_FX_LineBreak_PairTable[64][32];
+IFX_TxtBreak* IFX_TxtBreak::Create(FX_DWORD dwPolicies) {
+ return new CFX_TxtBreak(dwPolicies);
+}
+CFX_TxtBreak::CFX_TxtBreak(FX_DWORD dwPolicies)
+ : m_dwPolicies(dwPolicies),
+ m_pArabicChar(NULL),
+ m_iLineWidth(2000000),
+ m_dwLayoutStyles(0),
+ m_bVertical(FALSE),
+ m_bArabicContext(FALSE),
+ m_bArabicShapes(FALSE),
+ m_bRTL(FALSE),
+ m_bSingleLine(FALSE),
+ m_bCombText(FALSE),
+ m_iArabicContext(1),
+ m_iCurArabicContext(1),
+ m_pFont(NULL),
+ m_iFontSize(240),
+ m_bEquidistant(TRUE),
+ m_iTabWidth(720000),
+ m_wDefChar(0xFEFF),
+ m_wParagBreakChar(L'\n'),
+ m_iDefChar(0),
+ m_iLineRotation(0),
+ m_iCharRotation(0),
+ m_iRotation(0),
+ m_iAlignment(FX_TXTLINEALIGNMENT_Left),
+ m_dwContextCharStyles(0),
+ m_iCombWidth(360000),
+ m_pUserData(NULL),
+ m_dwCharType(0),
+ m_bArabicNumber(FALSE),
+ m_bArabicComma(FALSE),
+ m_pCurLine(NULL),
+ m_iReady(0),
+ m_iTolerance(0),
+ m_iHorScale(100),
+ m_iVerScale(100),
+ m_iCharSpace(0) {
+ m_bPagination = (m_dwPolicies & FX_TXTBREAKPOLICY_Pagination) != 0;
+ m_pArabicChar = IFX_ArabicChar::Create();
+ if (m_bPagination) {
+ m_pTxtLine1 = new CFX_TxtLine(sizeof(CFX_Char));
+ m_pTxtLine2 = new CFX_TxtLine(sizeof(CFX_Char));
+ } else {
+ m_pTxtLine1 = new CFX_TxtLine(sizeof(CFX_TxtChar));
+ m_pTxtLine2 = new CFX_TxtLine(sizeof(CFX_TxtChar));
+ }
+ m_pCurLine = m_pTxtLine1;
+ ResetArabicContext();
+}
+CFX_TxtBreak::~CFX_TxtBreak() {
+ Reset();
+ delete m_pTxtLine1;
+ delete m_pTxtLine2;
+ m_pArabicChar->Release();
+}
+void CFX_TxtBreak::SetLineWidth(FX_FLOAT fLineWidth) {
+ m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f);
+ FXSYS_assert(m_iLineWidth >= 20000);
+}
+void CFX_TxtBreak::SetLinePos(FX_FLOAT fLinePos) {
+ int32_t iLinePos = FXSYS_round(fLinePos * 20000.0f);
+ if (iLinePos < 0) {
+ iLinePos = 0;
+ }
+ if (iLinePos > m_iLineWidth) {
+ iLinePos = m_iLineWidth;
+ }
+ m_pCurLine->m_iStart = iLinePos;
+ m_pCurLine->m_iWidth += iLinePos;
+}
+void CFX_TxtBreak::SetLayoutStyles(FX_DWORD dwLayoutStyles) {
+ m_dwLayoutStyles = dwLayoutStyles;
+ m_bVertical = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0;
+ m_bArabicContext = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ArabicContext) != 0;
+ m_bArabicShapes = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ArabicShapes) != 0;
+ m_bRTL = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_RTLReadingOrder) != 0;
+ m_bSingleLine = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
+ m_bCombText = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
+ ResetArabicContext();
+ m_iLineRotation = GetLineRotation(m_dwLayoutStyles);
+ m_iRotation = m_iLineRotation + m_iCharRotation;
+ m_iRotation %= 4;
+}
+void CFX_TxtBreak::SetFont(IFX_Font* pFont) {
+ if (pFont == NULL) {
+ return;
+ }
+ if (m_pFont == pFont) {
+ return;
+ }
+ SetBreakStatus();
+ m_pFont = pFont;
+ m_iDefChar = 0;
+ if (m_wDefChar != 0xFEFF && m_pFont != NULL) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ m_iDefChar *= m_iFontSize;
+ }
+}
+void CFX_TxtBreak::SetFontSize(FX_FLOAT fFontSize) {
+ int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
+ if (m_iFontSize == iFontSize) {
+ return;
+ }
+ SetBreakStatus();
+ m_iFontSize = iFontSize;
+ m_iDefChar = 0;
+ if (m_wDefChar != 0xFEFF && m_pFont != NULL) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ m_iDefChar *= m_iFontSize;
+ }
+}
+void CFX_TxtBreak::SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant) {
+ m_iTabWidth = FXSYS_round(fTabWidth * 20000.0f);
+ if (m_iTabWidth < FX_TXTBREAK_MinimumTabWidth) {
+ m_iTabWidth = FX_TXTBREAK_MinimumTabWidth;
+ }
+ m_bEquidistant = bEquidistant;
+}
+void CFX_TxtBreak::SetDefaultChar(FX_WCHAR wch) {
+ m_wDefChar = wch;
+ m_iDefChar = 0;
+ if (m_wDefChar != 0xFEFF && m_pFont != NULL) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ if (m_iDefChar < 0) {
+ m_iDefChar = 0;
+ } else {
+ m_iDefChar *= m_iFontSize;
+ }
+ }
+}
+void CFX_TxtBreak::SetParagraphBreakChar(FX_WCHAR wch) {
+ if (wch != L'\r' && wch != L'\n') {
+ return;
+ }
+ m_wParagBreakChar = wch;
+}
+void CFX_TxtBreak::SetLineBreakTolerance(FX_FLOAT fTolerance) {
+ m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
+}
+void CFX_TxtBreak::SetCharRotation(int32_t iCharRotation) {
+ if (iCharRotation < 0) {
+ iCharRotation += (-iCharRotation / 4 + 1) * 4;
+ } else if (iCharRotation > 3) {
+ iCharRotation -= (iCharRotation / 4) * 4;
+ }
+ if (m_iCharRotation == iCharRotation) {
+ return;
+ }
+ SetBreakStatus();
+ m_iCharRotation = iCharRotation;
+ m_iRotation = m_iLineRotation + m_iCharRotation;
+ m_iRotation %= 4;
+}
+void CFX_TxtBreak::SetAlignment(int32_t iAlignment) {
+ FXSYS_assert(iAlignment >= FX_TXTLINEALIGNMENT_Left &&
+ iAlignment <= FX_TXTLINEALIGNMENT_Distributed);
+ m_iAlignment = iAlignment;
+ ResetArabicContext();
+}
+void CFX_TxtBreak::ResetContextCharStyles() {
+ m_dwContextCharStyles = m_bArabicContext ? m_iCurAlignment : m_iAlignment;
+ if (m_bArabicNumber) {
+ m_dwContextCharStyles |= FX_TXTCHARSTYLE_ArabicNumber;
+ }
+ if (m_bArabicComma) {
+ m_dwContextCharStyles |= FX_TXTCHARSTYLE_ArabicComma;
+ }
+ if ((m_bArabicContext && m_bCurRTL) || (!m_bArabicContext && m_bRTL)) {
+ m_dwContextCharStyles |= FX_TXTCHARSTYLE_RTLReadingOrder;
+ }
+ m_dwContextCharStyles |= (m_iArabicContext << 8);
+}
+FX_DWORD CFX_TxtBreak::GetContextCharStyles() const {
+ return m_dwContextCharStyles;
+}
+void CFX_TxtBreak::SetContextCharStyles(FX_DWORD dwCharStyles) {
+ m_iCurAlignment = dwCharStyles & 0x0F;
+ m_bArabicNumber = (dwCharStyles & FX_TXTCHARSTYLE_ArabicNumber) != 0;
+ m_bArabicComma = (dwCharStyles & FX_TXTCHARSTYLE_ArabicComma) != 0;
+ m_bCurRTL = (dwCharStyles & FX_TXTCHARSTYLE_RTLReadingOrder) != 0;
+ m_iCurArabicContext = m_iArabicContext = ((dwCharStyles & 0x0300) >> 8);
+ ResetContextCharStyles();
+}
+void CFX_TxtBreak::SetCombWidth(FX_FLOAT fCombWidth) {
+ m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f);
+}
+void CFX_TxtBreak::SetUserData(void* pUserData) {
+ if (m_pUserData == pUserData) {
+ return;
+ }
+ SetBreakStatus();
+ m_pUserData = pUserData;
+}
+void CFX_TxtBreak::SetBreakStatus() {
+ if (m_bPagination) {
+ return;
+ }
+ int32_t iCount = m_pCurLine->CountChars();
+ if (iCount < 1) {
+ return;
+ }
+ CFX_TxtChar* pTC = (CFX_TxtChar*)m_pCurLine->GetCharPtr(iCount - 1);
+ if (pTC->m_dwStatus == 0) {
+ pTC->m_dwStatus = FX_TXTBREAK_PieceBreak;
+ }
+}
+void CFX_TxtBreak::SetHorizontalScale(int32_t iScale) {
+ if (iScale < 0) {
+ iScale = 0;
+ }
+ if (iScale == m_iHorScale) {
+ return;
+ }
+ SetBreakStatus();
+ m_iHorScale = iScale;
+}
+void CFX_TxtBreak::SetVerticalScale(int32_t iScale) {
+ if (iScale < 0) {
+ iScale = 0;
+ }
+ if (iScale == m_iHorScale) {
+ return;
+ }
+ SetBreakStatus();
+ m_iVerScale = iScale;
+}
+void CFX_TxtBreak::SetCharSpace(FX_FLOAT fCharSpace) {
+ m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
+}
+static const int32_t gs_FX_TxtLineRotations[8] = {0, 3, 1, 0, 2, 1, 3, 2};
+int32_t CFX_TxtBreak::GetLineRotation(FX_DWORD dwStyles) const {
+ return gs_FX_TxtLineRotations[(dwStyles & 0x0E) >> 1];
+}
+CFX_TxtChar* CFX_TxtBreak::GetLastChar(int32_t index, FX_BOOL bOmitChar) const {
+ CFX_TxtCharArray& ca = *m_pCurLine->m_pLineChars;
+ int32_t iCount = ca.GetSize();
+ if (index < 0 || index >= iCount) {
+ return NULL;
+ }
+ CFX_TxtChar* pTC;
+ int32_t iStart = iCount - 1;
+ while (iStart > -1) {
+ pTC = ca.GetDataPtr(iStart--);
+ if (bOmitChar && pTC->GetCharType() == FX_CHARTYPE_Combination) {
+ continue;
+ }
+ if (--index < 0) {
+ return pTC;
+ }
+ }
+ return NULL;
+}
+CFX_TxtLine* CFX_TxtBreak::GetTxtLine(FX_BOOL bReady) const {
+ if (!bReady) {
+ return m_pCurLine;
+ }
+ if (m_iReady == 1) {
+ return m_pTxtLine1;
+ } else if (m_iReady == 2) {
+ return m_pTxtLine2;
+ } else {
+ return NULL;
+ }
+}
+CFX_TxtPieceArray* CFX_TxtBreak::GetTxtPieces(FX_BOOL bReady) const {
+ CFX_TxtLine* pTxtLine = GetTxtLine(bReady);
+ if (pTxtLine == NULL) {
+ return NULL;
+ }
+ return pTxtLine->m_pLinePieces;
+}
+inline FX_DWORD CFX_TxtBreak::GetUnifiedCharType(FX_DWORD dwType) const {
+ return dwType >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : dwType;
+}
+void CFX_TxtBreak::ResetArabicContext() {
+ if (m_bArabicContext) {
+ m_bCurRTL = m_iCurArabicContext > 1;
+ m_iCurAlignment = m_iCurArabicContext > 1 ? FX_TXTLINEALIGNMENT_Right
+ : FX_TXTLINEALIGNMENT_Left;
+ m_iCurAlignment |= (m_iAlignment & FX_TXTLINEALIGNMENT_HigherMask);
+ m_bArabicNumber = m_iArabicContext >= 1 && m_bArabicShapes;
+ } else {
+ if (m_bPagination) {
+ m_bCurRTL = FALSE;
+ m_iCurAlignment = 0;
+ } else {
+ m_bCurRTL = m_bRTL;
+ m_iCurAlignment = m_iAlignment;
+ }
+ if (m_bRTL) {
+ m_bArabicNumber = m_iArabicContext >= 1;
+ } else {
+ m_bArabicNumber = m_iArabicContext > 1;
+ }
+ m_bArabicNumber = m_bArabicNumber && m_bArabicShapes;
+ }
+ m_bArabicComma = m_bArabicNumber;
+ ResetContextCharStyles();
+}
+void CFX_TxtBreak::AppendChar_PageLoad(CFX_Char* pCurChar, FX_DWORD dwProps) {
+ if (!m_bPagination) {
+ ((CFX_TxtChar*)pCurChar)->m_dwStatus = 0;
+ ((CFX_TxtChar*)pCurChar)->m_pUserData = m_pUserData;
+ }
+ if (m_bArabicContext || m_bArabicShapes) {
+ int32_t iBidiCls = (dwProps & FX_BIDICLASSBITSMASK) >> FX_BIDICLASSBITS;
+ int32_t iArabicContext =
+ (iBidiCls == FX_BIDICLASS_R || iBidiCls == FX_BIDICLASS_AL)
+ ? 2
+ : ((iBidiCls == FX_BIDICLASS_L || iBidiCls == FX_BIDICLASS_S) ? 0
+ : 1);
+ if (iArabicContext != m_iArabicContext && iArabicContext != 1) {
+ m_iArabicContext = iArabicContext;
+ if (m_iCurArabicContext == 1) {
+ m_iCurArabicContext = iArabicContext;
+ }
+ ResetArabicContext();
+ if (!m_bPagination) {
+ CFX_TxtChar* pLastChar = (CFX_TxtChar*)GetLastChar(1, FALSE);
+ if (pLastChar != NULL && pLastChar->m_dwStatus < 1) {
+ pLastChar->m_dwStatus = FX_TXTBREAK_PieceBreak;
+ }
+ }
+ }
+ }
+ pCurChar->m_dwCharStyles = m_dwContextCharStyles;
+}
+FX_DWORD CFX_TxtBreak::AppendChar_Combination(CFX_Char* pCurChar,
+ int32_t iRotation) {
+ FXSYS_assert(pCurChar != NULL);
+ FX_WCHAR wch = pCurChar->m_wCharCode;
+ FX_WCHAR wForm;
+ int32_t iCharWidth = 0;
+ CFX_Char* pLastChar;
+ pCurChar->m_iCharWidth = -1;
+ if (m_bCombText) {
+ iCharWidth = m_iCombWidth;
+ } else {
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ wForm = wch;
+ if (!m_bPagination) {
+ pLastChar = GetLastChar(0, FALSE);
+ if (pLastChar != NULL &&
+ (((CFX_TxtChar*)pLastChar)->m_dwCharStyles &
+ FX_TXTCHARSTYLE_ArabicShadda) == 0) {
+ FX_BOOL bShadda = FALSE;
+ if (wch == 0x0651) {
+ FX_WCHAR wLast = pLastChar->m_wCharCode;
+ if (wLast >= 0x064C && wLast <= 0x0650) {
+ wForm = FX_GetArabicFromShaddaTable(wLast);
+ bShadda = TRUE;
+ }
+ } else if (wch >= 0x064C && wch <= 0x0650) {
+ if (pLastChar->m_wCharCode == 0x0651) {
+ wForm = FX_GetArabicFromShaddaTable(wch);
+ bShadda = TRUE;
+ }
+ }
+ if (bShadda) {
+ ((CFX_TxtChar*)pLastChar)->m_dwCharStyles |=
+ FX_TXTCHARSTYLE_ArabicShadda;
+ ((CFX_TxtChar*)pLastChar)->m_iCharWidth = 0;
+ ((CFX_TxtChar*)pCurChar)->m_dwCharStyles |=
+ FX_TXTCHARSTYLE_ArabicShadda;
+ }
+ }
+ }
+ if (!m_pFont->GetCharWidth(wForm, iCharWidth, FALSE)) {
+ iCharWidth = 0;
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorScale / 100;
+ }
+ pCurChar->m_iCharWidth = -iCharWidth;
+ return FX_TXTBREAK_None;
+}
+FX_DWORD CFX_TxtBreak::AppendChar_Tab(CFX_Char* pCurChar, int32_t iRotation) {
+ m_dwCharType = FX_CHARTYPE_Tab;
+ if ((m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ExpandTab) == 0) {
+ return FX_TXTBREAK_None;
+ }
+ int32_t& iLineWidth = m_pCurLine->m_iWidth;
+ int32_t iCharWidth;
+ if (m_bCombText) {
+ iCharWidth = m_iCombWidth;
+ } else {
+ if (m_bEquidistant) {
+ iCharWidth = iLineWidth;
+ iCharWidth = m_iTabWidth * (iCharWidth / m_iTabWidth + 1) - iCharWidth;
+ if (iCharWidth < FX_TXTBREAK_MinimumTabWidth) {
+ iCharWidth += m_iTabWidth;
+ }
+ } else {
+ iCharWidth = m_iTabWidth;
+ }
+ }
+ pCurChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ if (!m_bSingleLine && iLineWidth >= m_iLineWidth + m_iTolerance) {
+ return EndBreak(FX_TXTBREAK_LineBreak);
+ }
+ return FX_TXTBREAK_None;
+}
+FX_DWORD CFX_TxtBreak::AppendChar_Control(CFX_Char* pCurChar,
+ int32_t iRotation) {
+ m_dwCharType = FX_CHARTYPE_Control;
+ FX_DWORD dwRet = FX_TXTBREAK_None;
+ if (!m_bSingleLine) {
+ FX_WCHAR wch = pCurChar->m_wCharCode;
+ switch (wch) {
+ case L'\v':
+ case 0x2028:
+ dwRet = FX_TXTBREAK_LineBreak;
+ break;
+ case L'\f':
+ dwRet = FX_TXTBREAK_PageBreak;
+ break;
+ case 0x2029:
+ dwRet = FX_TXTBREAK_ParagraphBreak;
+ break;
+ default:
+ if (wch == m_wParagBreakChar) {
+ dwRet = FX_TXTBREAK_ParagraphBreak;
+ }
+ break;
+ }
+ if (dwRet != FX_TXTBREAK_None) {
+ dwRet = EndBreak(dwRet);
+ }
+ }
+ return dwRet;
+}
+FX_DWORD CFX_TxtBreak::AppendChar_Arabic(CFX_Char* pCurChar,
+ int32_t iRotation) {
+ FX_DWORD dwType = (pCurChar->m_dwCharProps & FX_CHARTYPEBITSMASK);
+ int32_t& iLineWidth = m_pCurLine->m_iWidth;
+ FX_WCHAR wForm;
+ int32_t iCharWidth = 0;
+ CFX_Char* pLastChar = NULL;
+ FX_BOOL bAlef = FALSE;
+ if (!m_bCombText && m_dwCharType >= FX_CHARTYPE_ArabicAlef &&
+ m_dwCharType <= FX_CHARTYPE_ArabicDistortion) {
+ pLastChar = GetLastChar(1);
+ if (pLastChar != NULL) {
+ iCharWidth = pLastChar->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iLineWidth -= iCharWidth;
+ }
+ CFX_Char* pPrevChar = GetLastChar(2);
+ wForm = m_pArabicChar->GetFormChar(pLastChar, pPrevChar, pCurChar);
+ bAlef = (wForm == 0xFEFF &&
+ pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef);
+ int32_t iLastRotation = pLastChar->m_nRotation + m_iLineRotation;
+ if (m_bVertical && (pLastChar->m_dwCharProps & 0x8000) != 0) {
+ iLastRotation++;
+ }
+ if (m_bVertical != FX_IsOdd(iLastRotation)) {
+ iCharWidth = 1000;
+ } else {
+ m_pFont->GetCharWidth(wForm, iCharWidth, FALSE);
+ }
+ if (wForm == 0xFEFF) {
+ iCharWidth = m_iDefChar;
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorScale / 100;
+ pLastChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ iCharWidth = 0;
+ }
+ }
+ m_dwCharType = dwType;
+ wForm = m_pArabicChar->GetFormChar(pCurChar, bAlef ? NULL : pLastChar, NULL);
+ if (m_bCombText) {
+ iCharWidth = m_iCombWidth;
+ } else {
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ m_pFont->GetCharWidth(wForm, iCharWidth, FALSE);
+ }
+ if (wForm == 0xFEFF) {
+ iCharWidth = m_iDefChar;
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorScale / 100;
+ }
+ pCurChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ m_pCurLine->m_iArabicChars++;
+ if (!m_bSingleLine && iLineWidth > m_iLineWidth + m_iTolerance) {
+ return EndBreak(FX_TXTBREAK_LineBreak);
+ }
+ return FX_TXTBREAK_None;
+}
+FX_DWORD CFX_TxtBreak::AppendChar_Others(CFX_Char* pCurChar,
+ int32_t iRotation) {
+ FX_DWORD dwProps = pCurChar->m_dwCharProps;
+ FX_DWORD dwType = (dwProps & FX_CHARTYPEBITSMASK);
+ int32_t& iLineWidth = m_pCurLine->m_iWidth;
+ int32_t iCharWidth = 0;
+ m_dwCharType = dwType;
+ FX_WCHAR wch = pCurChar->m_wCharCode;
+ FX_WCHAR wForm = wch;
+ if (dwType == FX_CHARTYPE_Numeric) {
+ if (m_bArabicNumber) {
+ wForm = wch + 0x0630;
+ pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicIndic;
+ }
+ } else if (wch == L',') {
+ if (m_bArabicShapes && m_iCurArabicContext > 0) {
+ wForm = 0x060C;
+ pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicComma;
+ }
+ } else if (m_bCurRTL || m_bVertical) {
+ wForm = FX_GetMirrorChar(wch, dwProps, m_bCurRTL, m_bVertical);
+ }
+ if (m_bCombText) {
+ iCharWidth = m_iCombWidth;
+ } else {
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, FALSE)) {
+ iCharWidth = m_iDefChar;
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorScale / 100;
+ }
+ iCharWidth += m_iCharSpace;
+ pCurChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ FX_BOOL bBreak = (dwType != FX_CHARTYPE_Space ||
+ (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0);
+ if (!m_bSingleLine && bBreak && iLineWidth > m_iLineWidth + m_iTolerance) {
+ return EndBreak(FX_TXTBREAK_LineBreak);
+ }
+ return FX_TXTBREAK_None;
+}
+typedef FX_DWORD (CFX_TxtBreak::*FX_TxtBreak_LPFAppendChar)(CFX_Char* pCurChar,
+ int32_t iRotation);
+static const FX_TxtBreak_LPFAppendChar g_FX_TxtBreak_lpfAppendChar[16] = {
+ &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Tab,
+ &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Control,
+ &CFX_TxtBreak::AppendChar_Combination, &CFX_TxtBreak::AppendChar_Others,
+ &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Arabic,
+ &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Arabic,
+ &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Arabic,
+ &CFX_TxtBreak::AppendChar_Arabic, &CFX_TxtBreak::AppendChar_Others,
+ &CFX_TxtBreak::AppendChar_Others, &CFX_TxtBreak::AppendChar_Others,
+};
+FX_DWORD CFX_TxtBreak::AppendChar(FX_WCHAR wch) {
+ FX_DWORD dwProps = kTextLayoutCodeProperties[(FX_WORD)wch];
+ FX_DWORD dwType = (dwProps & FX_CHARTYPEBITSMASK);
+ CFX_TxtChar* pCurChar = m_pCurLine->m_pLineChars->AddSpace();
+ pCurChar->m_wCharCode = (FX_WORD)wch;
+ pCurChar->m_nRotation = m_iCharRotation;
+ pCurChar->m_dwCharProps = dwProps;
+ pCurChar->m_dwCharStyles = 0;
+ pCurChar->m_iCharWidth = 0;
+ pCurChar->m_iHorizontalScale = m_iHorScale;
+ pCurChar->m_iVertialScale = m_iVerScale;
+ pCurChar->m_dwStatus = 0;
+ pCurChar->m_iBidiClass = 0;
+ pCurChar->m_iBidiLevel = 0;
+ pCurChar->m_iBidiPos = 0;
+ pCurChar->m_iBidiOrder = 0;
+ pCurChar->m_pUserData = NULL;
+ AppendChar_PageLoad(pCurChar, dwProps);
+ FX_DWORD dwRet1 = FX_TXTBREAK_None;
+ if (dwType != FX_CHARTYPE_Combination &&
+ GetUnifiedCharType(m_dwCharType) != GetUnifiedCharType(dwType)) {
+ if (m_dwCharType > 0 &&
+ m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine) {
+ if (m_dwCharType != FX_CHARTYPE_Space || dwType != FX_CHARTYPE_Control) {
+ dwRet1 = EndBreak(FX_TXTBREAK_LineBreak);
+ int32_t iCount = m_pCurLine->CountChars();
+ if (iCount > 0) {
+ pCurChar = m_pCurLine->m_pLineChars->GetDataPtr(iCount - 1);
+ }
+ }
+ }
+ }
+ int32_t iRotation = m_iRotation;
+ if (m_bVertical && (dwProps & 0x8000) != 0) {
+ iRotation = (iRotation + 1) % 4;
+ }
+ FX_DWORD dwRet2 =
+ (this->*g_FX_TxtBreak_lpfAppendChar[dwType >> FX_CHARTYPEBITS])(
+ pCurChar, iRotation);
+ return std::max(dwRet1, dwRet2);
+}
+void CFX_TxtBreak::EndBreak_UpdateArabicShapes() {
+ FXSYS_assert(m_bArabicShapes);
+ int32_t iCount = m_pCurLine->CountChars();
+ if (iCount < 2) {
+ return;
+ }
+ int32_t& iLineWidth = m_pCurLine->m_iWidth;
+ CFX_Char *pCur, *pNext;
+ pCur = m_pCurLine->GetCharPtr(0);
+ FX_BOOL bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
+ pCur = m_pCurLine->GetCharPtr(1);
+ FX_WCHAR wch, wForm;
+ FX_BOOL bNextNum;
+ int32_t i = 1, iCharWidth, iRotation;
+ do {
+ i++;
+ if (i < iCount) {
+ pNext = m_pCurLine->GetCharPtr(i);
+ bNextNum = (pNext->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
+ } else {
+ pNext = NULL;
+ bNextNum = FALSE;
+ }
+ wch = pCur->m_wCharCode;
+ if (wch == L'.') {
+ if (bPrevNum && bNextNum) {
+ iRotation = m_iRotation;
+ if (m_bVertical && (pCur->m_dwCharProps & 0x8000) != 0) {
+ iRotation = ((iRotation + 1) & 0x03);
+ }
+ wForm = wch == L'.' ? 0x066B : 0x066C;
+ iLineWidth -= pCur->m_iCharWidth;
+ if (m_bCombText) {
+ iCharWidth = m_iCombWidth;
+ } else {
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, FALSE)) {
+ iCharWidth = m_iDefChar;
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorScale / 100;
+ }
+ pCur->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ }
+ }
+ bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
+ pCur = pNext;
+ } while (i < iCount);
+}
+FX_BOOL CFX_TxtBreak::EndBreak_SplitLine(CFX_TxtLine* pNextLine,
+ FX_BOOL bAllChars,
+ FX_DWORD dwStatus) {
+ int32_t iCount = m_pCurLine->CountChars();
+ FX_BOOL bDone = FALSE;
+ CFX_Char* pTC;
+ if (!m_bSingleLine && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance) {
+ pTC = m_pCurLine->GetCharPtr(iCount - 1);
+ switch (pTC->GetCharType()) {
+ case FX_CHARTYPE_Tab:
+ case FX_CHARTYPE_Control:
+ break;
+ case FX_CHARTYPE_Space:
+ if ((m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0) {
+ SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
+ bDone = TRUE;
+ }
+ break;
+ default:
+ SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
+ bDone = TRUE;
+ break;
+ }
+ }
+ iCount = m_pCurLine->CountChars();
+ CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces;
+ CFX_TxtPiece tp;
+ if (m_bPagination) {
+ tp.m_dwStatus = dwStatus;
+ tp.m_iStartPos = m_pCurLine->m_iStart;
+ tp.m_iWidth = m_pCurLine->m_iWidth;
+ tp.m_iStartChar = 0;
+ tp.m_iChars = iCount;
+ tp.m_pChars = m_pCurLine->m_pLineChars;
+ tp.m_pUserData = m_pUserData;
+ pTC = m_pCurLine->GetCharPtr(0);
+ tp.m_dwCharStyles = pTC->m_dwCharStyles;
+ tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
+ tp.m_iVerticalScale = pTC->m_iVertialScale;
+ pCurPieces->Add(tp);
+ m_pCurLine = pNextLine;
+ m_dwCharType = 0;
+ return TRUE;
+ }
+ if (bAllChars && !bDone) {
+ int32_t iEndPos = m_pCurLine->m_iWidth;
+ GetBreakPos(*m_pCurLine->m_pLineChars, iEndPos, bAllChars, TRUE);
+ }
+ return FALSE;
+}
+void CFX_TxtBreak::EndBreak_BidiLine(CFX_TPOArray& tpos, FX_DWORD dwStatus) {
+ CFX_TxtPiece tp;
+ FX_TPO tpo;
+ CFX_TxtChar* pTC;
+ int32_t i, j;
+ CFX_TxtCharArray& chars = *m_pCurLine->m_pLineChars;
+ int32_t iCount = m_pCurLine->CountChars();
+ FX_BOOL bDone = (m_pCurLine->m_iArabicChars > 0 || m_bCurRTL);
+ if (!m_bPagination && bDone) {
+ int32_t iBidiNum = 0;
+ for (i = 0; i < iCount; i++) {
+ pTC = chars.GetDataPtr(i);
+ pTC->m_iBidiPos = i;
+ if (pTC->GetCharType() != FX_CHARTYPE_Control) {
+ iBidiNum = i;
+ }
+ if (i == 0) {
+ pTC->m_iBidiLevel = 1;
+ }
+ }
+ FX_BidiLine(chars, iBidiNum + 1, m_bCurRTL ? 1 : 0);
+ }
+ CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces;
+ if (!m_bPagination &&
+ (bDone || (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_MutipleFormat) != 0)) {
+ tp.m_dwStatus = FX_TXTBREAK_PieceBreak;
+ tp.m_iStartPos = m_pCurLine->m_iStart;
+ tp.m_pChars = m_pCurLine->m_pLineChars;
+ int32_t iBidiLevel = -1, iCharWidth;
+ i = 0, j = -1;
+ while (i < iCount) {
+ pTC = chars.GetDataPtr(i);
+ if (iBidiLevel < 0) {
+ iBidiLevel = pTC->m_iBidiLevel;
+ tp.m_iWidth = 0;
+ tp.m_iBidiLevel = iBidiLevel;
+ tp.m_iBidiPos = pTC->m_iBidiOrder;
+ tp.m_dwCharStyles = pTC->m_dwCharStyles;
+ tp.m_pUserData = pTC->m_pUserData;
+ tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
+ tp.m_iVerticalScale = pTC->m_iVertialScale;
+ tp.m_dwStatus = FX_TXTBREAK_PieceBreak;
+ }
+ if (iBidiLevel != pTC->m_iBidiLevel || pTC->m_dwStatus != 0) {
+ if (iBidiLevel == pTC->m_iBidiLevel) {
+ tp.m_dwStatus = pTC->m_dwStatus;
+ iCharWidth = pTC->m_iCharWidth;
+ if (iCharWidth > 0) {
+ tp.m_iWidth += iCharWidth;
+ }
+ i++;
+ }
+ tp.m_iChars = i - tp.m_iStartChar;
+ pCurPieces->Add(tp);
+ tp.m_iStartPos += tp.m_iWidth;
+ tp.m_iStartChar = i;
+ tpo.index = ++j;
+ tpo.pos = tp.m_iBidiPos;
+ tpos.Add(tpo);
+ iBidiLevel = -1;
+ } else {
+ iCharWidth = pTC->m_iCharWidth;
+ if (iCharWidth > 0) {
+ tp.m_iWidth += iCharWidth;
+ }
+ i++;
+ }
+ }
+ if (i > tp.m_iStartChar) {
+ tp.m_dwStatus = dwStatus;
+ tp.m_iChars = i - tp.m_iStartChar;
+ pCurPieces->Add(tp);
+ tpo.index = ++j;
+ tpo.pos = tp.m_iBidiPos;
+ tpos.Add(tpo);
+ }
+ if (j > -1) {
+ if (j > 0) {
+ FX_TEXTLAYOUT_PieceSort(tpos, 0, j);
+ int32_t iStartPos = 0;
+ for (i = 0; i <= j; i++) {
+ tpo = tpos.GetAt(i);
+ CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
+ ttp.m_iStartPos = iStartPos;
+ iStartPos += ttp.m_iWidth;
+ }
+ }
+ CFX_TxtPiece& ttp = pCurPieces->GetAt(j);
+ ttp.m_dwStatus = dwStatus;
+ }
+ } else {
+ tp.m_dwStatus = dwStatus;
+ tp.m_iStartPos = m_pCurLine->m_iStart;
+ tp.m_iWidth = m_pCurLine->m_iWidth;
+ tp.m_iStartChar = 0;
+ tp.m_iChars = iCount;
+ tp.m_pChars = m_pCurLine->m_pLineChars;
+ tp.m_pUserData = m_pUserData;
+ pTC = chars.GetDataPtr(0);
+ tp.m_dwCharStyles = pTC->m_dwCharStyles;
+ tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
+ tp.m_iVerticalScale = pTC->m_iVertialScale;
+ pCurPieces->Add(tp);
+ tpo.index = 0;
+ tpo.pos = 0;
+ tpos.Add(tpo);
+ }
+}
+void CFX_TxtBreak::EndBreak_Alignment(CFX_TPOArray& tpos,
+ FX_BOOL bAllChars,
+ FX_DWORD dwStatus) {
+ int32_t iNetWidth = m_pCurLine->m_iWidth, iGapChars = 0, iCharWidth;
+ CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces;
+ int32_t i, j, iCount = pCurPieces->GetSize();
+ FX_BOOL bFind = FALSE;
+ FX_TPO tpo;
+ CFX_TxtChar* pTC;
+ FX_DWORD dwCharType;
+ for (i = iCount - 1; i > -1; i--) {
+ tpo = tpos.GetAt(i);
+ CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
+ if (!bFind) {
+ iNetWidth = ttp.GetEndPos();
+ }
+ FX_BOOL bArabic = FX_IsOdd(ttp.m_iBidiLevel);
+ j = bArabic ? 0 : ttp.m_iChars - 1;
+ while (j > -1 && j < ttp.m_iChars) {
+ pTC = ttp.GetCharPtr(j);
+ if (pTC->m_nBreakType == FX_LBT_DIRECT_BRK) {
+ iGapChars++;
+ }
+ if (!bFind || !bAllChars) {
+ dwCharType = pTC->GetCharType();
+ if (dwCharType == FX_CHARTYPE_Space ||
+ dwCharType == FX_CHARTYPE_Control) {
+ if (!bFind) {
+ iCharWidth = pTC->m_iCharWidth;
+ if (bAllChars && iCharWidth > 0) {
+ iNetWidth -= iCharWidth;
+ }
+ }
+ } else {
+ bFind = TRUE;
+ if (!bAllChars) {
+ break;
+ }
+ }
+ }
+ j += bArabic ? 1 : -1;
+ }
+ if (!bAllChars && bFind) {
+ break;
+ }
+ }
+ int32_t iOffset = m_iLineWidth - iNetWidth;
+ int32_t iLowerAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_LowerMask);
+ int32_t iHigherAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_HigherMask);
+ if (iGapChars > 0 && (iHigherAlignment == FX_TXTLINEALIGNMENT_Distributed ||
+ (iHigherAlignment == FX_TXTLINEALIGNMENT_Justified &&
+ dwStatus != FX_TXTBREAK_ParagraphBreak))) {
+ int32_t iStart = -1;
+ for (i = 0; i < iCount; i++) {
+ tpo = tpos.GetAt(i);
+ CFX_TxtPiece& ttp = pCurPieces->GetAt(tpo.index);
+ if (iStart < -1) {
+ iStart = ttp.m_iStartPos;
+ } else {
+ ttp.m_iStartPos = iStart;
+ }
+ int32_t k;
+ for (j = 0; j < ttp.m_iChars; j++) {
+ pTC = ttp.GetCharPtr(j);
+ if (pTC->m_nBreakType != FX_LBT_DIRECT_BRK || pTC->m_iCharWidth < 0) {
+ continue;
+ }
+ k = iOffset / iGapChars;
+ pTC->m_iCharWidth += k;
+ ttp.m_iWidth += k;
+ iOffset -= k;
+ iGapChars--;
+ if (iGapChars < 1) {
+ break;
+ }
+ }
+ iStart += ttp.m_iWidth;
+ }
+ } else if (iLowerAlignment > FX_TXTLINEALIGNMENT_Left) {
+ if (iLowerAlignment == FX_TXTLINEALIGNMENT_Center) {
+ iOffset /= 2;
+ }
+ if (iOffset > 0) {
+ for (i = 0; i < iCount; i++) {
+ CFX_TxtPiece& ttp = pCurPieces->GetAt(i);
+ ttp.m_iStartPos += iOffset;
+ }
+ }
+ }
+}
+FX_DWORD CFX_TxtBreak::EndBreak(FX_DWORD dwStatus) {
+ FXSYS_assert(dwStatus >= FX_TXTBREAK_PieceBreak &&
+ dwStatus <= FX_TXTBREAK_PageBreak);
+ CFX_TxtPieceArray* pCurPieces = m_pCurLine->m_pLinePieces;
+ int32_t iCount = pCurPieces->GetSize();
+ if (iCount > 0) {
+ CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(--iCount);
+ if (dwStatus > FX_TXTBREAK_PieceBreak) {
+ pLastPiece->m_dwStatus = dwStatus;
+ } else {
+ dwStatus = pLastPiece->m_dwStatus;
+ }
+ return dwStatus;
+ } else {
+ CFX_TxtLine* pLastLine = GetTxtLine(TRUE);
+ if (pLastLine != NULL) {
+ pCurPieces = pLastLine->m_pLinePieces;
+ iCount = pCurPieces->GetSize();
+ if (iCount-- > 0) {
+ CFX_TxtPiece* pLastPiece = pCurPieces->GetPtrAt(iCount);
+ if (dwStatus > FX_TXTBREAK_PieceBreak) {
+ pLastPiece->m_dwStatus = dwStatus;
+ } else {
+ dwStatus = pLastPiece->m_dwStatus;
+ }
+ return dwStatus;
+ }
+ return FX_TXTBREAK_None;
+ }
+ iCount = m_pCurLine->CountChars();
+ if (iCount < 1) {
+ return FX_TXTBREAK_None;
+ }
+ if (!m_bPagination) {
+ CFX_TxtChar* pTC = m_pCurLine->GetCharPtr(iCount - 1);
+ pTC->m_dwStatus = dwStatus;
+ }
+ if (dwStatus <= FX_TXTBREAK_PieceBreak) {
+ return dwStatus;
+ }
+ }
+ m_iReady = (m_pCurLine == m_pTxtLine1) ? 1 : 2;
+ CFX_TxtLine* pNextLine =
+ (m_pCurLine == m_pTxtLine1) ? m_pTxtLine2 : m_pTxtLine1;
+ FX_BOOL bAllChars = (m_iCurAlignment > FX_TXTLINEALIGNMENT_Right);
+ CFX_TPOArray tpos;
+ CFX_Char* pTC;
+ if (m_bArabicShapes) {
+ EndBreak_UpdateArabicShapes();
+ }
+ if (EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) {
+ goto EndBreak_Ret;
+ }
+ EndBreak_BidiLine(tpos, dwStatus);
+ if (!m_bPagination && m_iCurAlignment > FX_TXTLINEALIGNMENT_Left) {
+ EndBreak_Alignment(tpos, bAllChars, dwStatus);
+ }
+EndBreak_Ret:
+ m_pCurLine = pNextLine;
+ pTC = GetLastChar(0, FALSE);
+ m_dwCharType = pTC == NULL ? 0 : pTC->GetCharType();
+ if (dwStatus == FX_TXTBREAK_ParagraphBreak) {
+ m_iArabicContext = m_iCurArabicContext = 1;
+ ResetArabicContext();
+ }
+ return dwStatus;
+}
+int32_t CFX_TxtBreak::GetBreakPos(CFX_TxtCharArray& ca,
+ int32_t& iEndPos,
+ FX_BOOL bAllChars,
+ FX_BOOL bOnlyBrk) {
+ int32_t iLength = ca.GetSize() - 1;
+ if (iLength < 1) {
+ return iLength;
+ }
+ int32_t iBreak = -1, iBreakPos = -1, iIndirect = -1, iIndirectPos = -1,
+ iLast = -1, iLastPos = -1;
+ if (m_bSingleLine || iEndPos <= m_iLineWidth) {
+ if (!bAllChars) {
+ return iLength;
+ }
+ iBreak = iLength;
+ iBreakPos = iEndPos;
+ }
+ FX_BOOL bSpaceBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0;
+ FX_BOOL bNumberBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_NumberBreak) != 0;
+ FX_LINEBREAKTYPE eType;
+ FX_DWORD nCodeProp, nCur, nNext;
+ CFX_Char* pCur = ca.GetDataPtr(iLength--);
+ if (bAllChars) {
+ pCur->m_nBreakType = FX_LBT_UNKNOWN;
+ }
+ nCodeProp = pCur->m_dwCharProps;
+ nNext = nCodeProp & 0x003F;
+ int32_t iCharWidth = pCur->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iEndPos -= iCharWidth;
+ }
+ while (iLength >= 0) {
+ pCur = ca.GetDataPtr(iLength);
+ nCodeProp = pCur->m_dwCharProps;
+ nCur = nCodeProp & 0x003F;
+ if (nCur == FX_CBP_SP) {
+ if (nNext == FX_CBP_SP) {
+ eType = bSpaceBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE*)gs_FX_LineBreak_PairTable +
+ (nCur << 5) + nNext);
+ }
+ } else if (bNumberBreak && nCur == FX_CBP_NU && nNext == FX_CBP_NU) {
+ eType = FX_LBT_DIRECT_BRK;
+ } else {
+ if (nNext == FX_CBP_SP) {
+ eType = FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE*)gs_FX_LineBreak_PairTable +
+ (nCur << 5) + nNext);
+ }
+ }
+ if (bAllChars) {
+ pCur->m_nBreakType = (uint8_t)eType;
+ }
+ if (!bOnlyBrk) {
+ if (m_bSingleLine || iEndPos <= m_iLineWidth ||
+ (nCur == FX_CBP_SP && !bSpaceBreak)) {
+ if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) {
+ iBreak = iLength;
+ iBreakPos = iEndPos;
+ if (!bAllChars) {
+ return iLength;
+ }
+ } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) {
+ iIndirect = iLength;
+ iIndirectPos = iEndPos;
+ }
+ if (iLast < 0) {
+ iLast = iLength;
+ iLastPos = iEndPos;
+ }
+ }
+ iCharWidth = pCur->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iEndPos -= iCharWidth;
+ }
+ }
+ nNext = nCodeProp & 0x003F;
+ iLength--;
+ }
+ if (bOnlyBrk) {
+ return 0;
+ }
+ if (iBreak > -1) {
+ iEndPos = iBreakPos;
+ return iBreak;
+ }
+ if (iIndirect > -1) {
+ iEndPos = iIndirectPos;
+ return iIndirect;
+ }
+ if (iLast > -1) {
+ iEndPos = iLastPos;
+ return iLast;
+ }
+ return 0;
+}
+void CFX_TxtBreak::SplitTextLine(CFX_TxtLine* pCurLine,
+ CFX_TxtLine* pNextLine,
+ FX_BOOL bAllChars) {
+ FXSYS_assert(pCurLine != NULL && pNextLine != NULL);
+ int32_t iCount = pCurLine->CountChars();
+ if (iCount < 2) {
+ return;
+ }
+ int32_t iEndPos = pCurLine->m_iWidth;
+ CFX_TxtCharArray& curChars = *pCurLine->m_pLineChars;
+ int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, FALSE);
+ if (iCharPos < 0) {
+ iCharPos = 0;
+ }
+ iCharPos++;
+ if (iCharPos >= iCount) {
+ pNextLine->RemoveAll(TRUE);
+ CFX_Char* pTC = curChars.GetDataPtr(iCharPos - 1);
+ pTC->m_nBreakType = FX_LBT_UNKNOWN;
+ return;
+ }
+ CFX_TxtCharArray& nextChars = *pNextLine->m_pLineChars;
+ int cur_size = curChars.GetSize();
+ nextChars.SetSize(cur_size - iCharPos);
+ FXSYS_memcpy(nextChars.GetData(), curChars.GetDataPtr(iCharPos),
+ (cur_size - iCharPos) * sizeof(CFX_TxtChar));
+ iCount -= iCharPos;
+ cur_size = curChars.GetSize();
+ curChars.RemoveAt(cur_size - iCount, iCount);
+ pCurLine->m_iWidth = iEndPos;
+ CFX_TxtChar* pTC = curChars.GetDataPtr(iCharPos - 1);
+ pTC->m_nBreakType = FX_LBT_UNKNOWN;
+ iCount = nextChars.GetSize();
+ int32_t iCharWidth, iWidth = 0;
+ for (int32_t i = 0; i < iCount; i++) {
+ pTC = nextChars.GetDataPtr(i);
+ if (pTC->GetCharType() >= FX_CHARTYPE_ArabicAlef) {
+ pCurLine->m_iArabicChars--;
+ pNextLine->m_iArabicChars++;
+ }
+ iCharWidth = pTC->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iWidth += iCharWidth;
+ }
+ if (m_bPagination) {
+ continue;
+ }
+ pTC->m_dwStatus = 0;
+ }
+ pNextLine->m_iWidth = iWidth;
+}
+int32_t CFX_TxtBreak::CountBreakChars() const {
+ CFX_TxtLine* pTxtLine = GetTxtLine(TRUE);
+ return pTxtLine == NULL ? 0 : pTxtLine->CountChars();
+}
+int32_t CFX_TxtBreak::CountBreakPieces() const {
+ CFX_TxtPieceArray* pTxtPieces = GetTxtPieces(TRUE);
+ if (pTxtPieces == NULL) {
+ return 0;
+ }
+ return pTxtPieces->GetSize();
+}
+const CFX_TxtPiece* CFX_TxtBreak::GetBreakPiece(int32_t index) const {
+ CFX_TxtPieceArray* pTxtPieces = GetTxtPieces(TRUE);
+ if (pTxtPieces == NULL) {
+ return NULL;
+ }
+ if (index < 0 || index >= pTxtPieces->GetSize()) {
+ return NULL;
+ }
+ return pTxtPieces->GetPtrAt(index);
+}
+void CFX_TxtBreak::ClearBreakPieces() {
+ CFX_TxtLine* pTxtLine = GetTxtLine(TRUE);
+ if (pTxtLine != NULL) {
+ pTxtLine->RemoveAll(TRUE);
+ }
+ m_iReady = 0;
+}
+void CFX_TxtBreak::Reset() {
+ m_dwCharType = 0;
+ m_iArabicContext = m_iCurArabicContext = 1;
+ ResetArabicContext();
+ m_pTxtLine1->RemoveAll(TRUE);
+ m_pTxtLine2->RemoveAll(TRUE);
+}
+
+struct FX_FORMCHAR {
+ FX_WORD wch;
+ FX_WORD wForm;
+ int32_t iWidth;
+};
+
+int32_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun,
+ FXTEXT_CHARPOS* pCharPos,
+ FX_BOOL bCharCode,
+ CFX_WideString* pWSForms,
+ FX_AdjustCharDisplayPos pAdjustPos) const {
+ if (pTxtRun == NULL || pTxtRun->iLength < 1) {
+ return 0;
+ }
+ IFX_TxtAccess* pAccess = pTxtRun->pAccess;
+ void* pIdentity = pTxtRun->pIdentity;
+ const FX_WCHAR* pStr = pTxtRun->pStr;
+ int32_t* pWidths = pTxtRun->pWidths;
+ int32_t iLength = pTxtRun->iLength - 1;
+ IFX_Font* pFont = pTxtRun->pFont;
+ FX_DWORD dwStyles = pTxtRun->dwStyles;
+ CFX_RectF rtText(*pTxtRun->pRect);
+ FX_BOOL bRTLPiece =
+ (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
+ FX_BOOL bArabicNumber =
+ (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicNumber) != 0;
+ FX_BOOL bArabicComma =
+ (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicComma) != 0;
+ FX_FLOAT fFontSize = pTxtRun->fFontSize;
+ int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
+ int32_t iAscent = pFont->GetAscent();
+ int32_t iDescent = pFont->GetDescent();
+ int32_t iMaxHeight = iAscent - iDescent;
+ FX_FLOAT fFontHeight = fFontSize;
+ FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight;
+ FX_FLOAT fDescent = fFontHeight * (FX_FLOAT)iDescent / (FX_FLOAT)iMaxHeight;
+ FX_BOOL bVerticalDoc = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0;
+ FX_BOOL bVerticalChar = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0;
+ int32_t iRotation = GetLineRotation(dwStyles) + pTxtRun->iCharRotation;
+ int32_t iCharRotation;
+ FX_WCHAR wch, wPrev = 0xFEFF, wNext, wForm, wLast = 0xFEFF;
+ int32_t iWidth, iCharWidth, iCharHeight;
+ FX_FLOAT fX, fY, fCharWidth, fCharHeight;
+ int32_t iHorScale = pTxtRun->iHorizontalScale;
+ int32_t iVerScale = pTxtRun->iVerticalScale;
+ FX_BOOL bSkipSpace = pTxtRun->bSkipSpace;
+ FX_BOOL bEmptyChar, bShadda = FALSE, bLam = FALSE;
+ FX_DWORD dwProps, dwCharType;
+ FX_FORMCHAR formChars[3];
+ FX_FLOAT fYBase;
+ fX = rtText.left;
+ if (bVerticalDoc) {
+ fX += (rtText.width - fFontSize) / 2.0f;
+ fYBase = bRTLPiece ? rtText.bottom() : rtText.top;
+ fY = fYBase;
+ } else {
+ if (bRTLPiece) {
+ fX = rtText.right();
+ }
+ fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f;
+ fY = fYBase + fAscent;
+ }
+ int32_t iCount = 0, iNext, iForms;
+ for (int32_t i = 0; i <= iLength; i++) {
+ if (pAccess != NULL) {
+ wch = pAccess->GetChar(pIdentity, i);
+ iWidth = pAccess->GetWidth(pIdentity, i);
+ } else {
+ wch = *pStr++;
+ iWidth = *pWidths++;
+ }
+ dwProps = FX_GetUnicodeProperties(wch);
+ dwCharType = (dwProps & FX_CHARTYPEBITSMASK);
+ if (dwCharType == FX_CHARTYPE_ArabicAlef && iWidth == 0) {
+ wPrev = 0xFEFF;
+ wLast = wch;
+ continue;
+ }
+ if (dwCharType >= FX_CHARTYPE_ArabicAlef) {
+ if (i < iLength) {
+ if (pAccess != NULL) {
+ iNext = i + 1;
+ while (iNext <= iLength) {
+ wNext = pAccess->GetChar(pIdentity, iNext);
+ dwProps = FX_GetUnicodeProperties(wNext);
+ if ((dwProps & FX_CHARTYPEBITSMASK) != FX_CHARTYPE_Combination) {
+ break;
+ }
+ iNext++;
+ }
+ if (iNext > iLength) {
+ wNext = 0xFEFF;
+ }
+ } else {
+ int32_t j = -1;
+ do {
+ j++;
+ if (i + j >= iLength) {
+ break;
+ }
+ wNext = pStr[j];
+ dwProps = FX_GetUnicodeProperties(wNext);
+ } while ((dwProps & FX_CHARTYPEBITSMASK) == FX_CHARTYPE_Combination);
+ if (i + j >= iLength) {
+ wNext = 0xFEFF;
+ }
+ }
+ } else {
+ wNext = 0xFEFF;
+ }
+ wForm = m_pArabicChar->GetFormChar(wch, wPrev, wNext);
+ bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647);
+ } else if (dwCharType == FX_CHARTYPE_Combination) {
+ wForm = wch;
+ if (wch >= 0x064C && wch <= 0x0651) {
+ if (bShadda) {
+ wForm = 0xFEFF;
+ bShadda = FALSE;
+ } else {
+ wNext = 0xFEFF;
+ if (pAccess != NULL) {
+ iNext = i + 1;
+ if (iNext <= iLength) {
+ wNext = pAccess->GetChar(pIdentity, iNext);
+ }
+ } else {
+ if (i < iLength) {
+ wNext = *pStr;
+ }
+ }
+ if (wch == 0x0651) {
+ if (wNext >= 0x064C && wNext <= 0x0650) {
+ wForm = FX_GetArabicFromShaddaTable(wNext);
+ bShadda = TRUE;
+ }
+ } else {
+ if (wNext == 0x0651) {
+ wForm = FX_GetArabicFromShaddaTable(wch);
+ bShadda = TRUE;
+ }
+ }
+ }
+ } else {
+ bShadda = FALSE;
+ }
+ } else if (dwCharType == FX_CHARTYPE_Numeric) {
+ wForm = wch;
+ if (bArabicNumber) {
+ wForm += 0x0630;
+ }
+ } else if (wch == L'.') {
+ wForm = wch;
+ if (bArabicNumber) {
+ wNext = 0xFEFF;
+ if (pAccess != NULL) {
+ iNext = i + 1;
+ if (iNext <= iLength) {
+ wNext = pAccess->GetChar(pIdentity, iNext);
+ }
+ } else {
+ if (i < iLength) {
+ wNext = *pStr;
+ }
+ }
+ if (wNext >= L'0' && wNext <= L'9') {
+ wForm = 0x066B;
+ }
+ }
+ } else if (wch == L',') {
+ wForm = wch;
+ if (bArabicComma) {
+ wForm = 0x060C;
+ }
+ } else if (bRTLPiece || bVerticalChar) {
+ wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, bVerticalChar);
+ } else {
+ wForm = wch;
+ }
+ if (dwCharType != FX_CHARTYPE_Combination) {
+ bShadda = FALSE;
+ }
+ if (dwCharType < FX_CHARTYPE_ArabicAlef) {
+ bLam = FALSE;
+ }
+ dwProps = FX_GetUnicodeProperties(wForm);
+ iCharRotation = iRotation;
+ if (bVerticalChar && (dwProps & 0x8000) != 0) {
+ iCharRotation++;
+ }
+ iCharRotation %= 4;
+ bEmptyChar =
+ (dwCharType >= FX_CHARTYPE_Tab && dwCharType <= FX_CHARTYPE_Control);
+ if (wForm == 0xFEFF) {
+ bEmptyChar = TRUE;
+ }
+ iForms = bLam ? 3 : 1;
+ iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms;
+ if (pCharPos == NULL) {
+ if (iWidth > 0) {
+ wPrev = wch;
+ }
+ wLast = wch;
+ continue;
+ }
+ iCharWidth = iWidth;
+ if (iCharWidth < 0) {
+ iCharWidth = -iCharWidth;
+ }
+ iCharWidth /= iFontSize;
+ formChars[0].wch = wch;
+ formChars[0].wForm = wForm;
+ formChars[0].iWidth = iCharWidth;
+ if (bLam) {
+ formChars[1].wForm = 0x0651;
+ iCharWidth = 0;
+ pFont->GetCharWidth(0x0651, iCharWidth, FALSE);
+ formChars[1].iWidth = iCharWidth;
+ formChars[2].wForm = 0x0670;
+ iCharWidth = 0;
+ pFont->GetCharWidth(0x0670, iCharWidth, FALSE);
+ formChars[2].iWidth = iCharWidth;
+ }
+ for (int32_t j = 0; j < iForms; j++) {
+ wForm = (FX_WCHAR)formChars[j].wForm;
+ iCharWidth = formChars[j].iWidth;
+ if (j > 0) {
+ dwCharType = FX_CHARTYPE_Combination;
+ wch = wForm;
+ wLast = (FX_WCHAR)formChars[j - 1].wForm;
+ }
+ if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
+ pCharPos->m_GlyphIndex =
+ bCharCode ? wch : pFont->GetGlyphIndex(wForm, FALSE);
+ pCharPos->m_ExtGID = pCharPos->m_GlyphIndex;
+ pCharPos->m_FontCharWidth = iCharWidth;
+ if (pWSForms) {
+ *pWSForms += wForm;
+ }
+ }
+ if (bVerticalDoc) {
+ iCharHeight = iCharWidth;
+ iCharWidth = 1000;
+ } else {
+ iCharHeight = 1000;
+ }
+ fCharWidth = fFontSize * iCharWidth / 1000.0f;
+ fCharHeight = fFontSize * iCharHeight / 1000.0f;
+ if (bRTLPiece && dwCharType != FX_CHARTYPE_Combination) {
+ if (bVerticalDoc) {
+ fY -= fCharHeight;
+ } else {
+ fX -= fCharWidth;
+ }
+ }
+ if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
+ pCharPos->m_OriginX = fX;
+ pCharPos->m_OriginY = fY;
+ if ((dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0) {
+ int32_t iFormWidth = iCharWidth;
+ pFont->GetCharWidth(wForm, iFormWidth, FALSE);
+ FX_FLOAT fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f;
+ if (bVerticalDoc) {
+ pCharPos->m_OriginY += fOffset;
+ } else {
+ pCharPos->m_OriginX += fOffset;
+ }
+ }
+ if (dwCharType == FX_CHARTYPE_Combination) {
+ CFX_Rect rtBBox;
+ rtBBox.Reset();
+ if (pFont->GetCharBBox(wForm, rtBBox, FALSE)) {
+ pCharPos->m_OriginY =
+ fYBase + fFontSize -
+ fFontSize * (FX_FLOAT)rtBBox.height / (FX_FLOAT)iMaxHeight;
+ }
+ if (wForm == wch && wLast != 0xFEFF) {
+ FX_DWORD dwLastProps = FX_GetUnicodeProperties(wLast);
+ if ((dwLastProps & FX_CHARTYPEBITSMASK) ==
+ FX_CHARTYPE_Combination) {
+ CFX_Rect rtBBox;
+ rtBBox.Reset();
+ if (pFont->GetCharBBox(wLast, rtBBox, FALSE)) {
+ pCharPos->m_OriginY -= fFontSize * rtBBox.height / iMaxHeight;
+ }
+ }
+ }
+ }
+ CFX_PointF ptOffset;
+ FX_BOOL bAdjusted = FALSE;
+ if (pAdjustPos) {
+ bAdjusted = pAdjustPos(wForm, bCharCode, pFont, fFontSize,
+ bVerticalChar, ptOffset);
+ }
+ if (!bAdjusted && bVerticalChar && (dwProps & 0x00010000) != 0) {
+ CFX_Rect rtBBox;
+ rtBBox.Reset();
+ if (pFont->GetCharBBox(wForm, rtBBox, FALSE)) {
+ ptOffset.x = fFontSize * (850 - rtBBox.right()) / iMaxHeight;
+ ptOffset.y = fFontSize * (iAscent - rtBBox.top - 150) / iMaxHeight;
+ }
+ }
+ pCharPos->m_OriginX += ptOffset.x;
+ pCharPos->m_OriginY -= ptOffset.y;
+ }
+ if (!bRTLPiece && dwCharType != FX_CHARTYPE_Combination) {
+ if (bVerticalDoc) {
+ fY += fCharHeight;
+ } else {
+ fX += fCharWidth;
+ }
+ }
+ if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
+ pCharPos->m_bGlyphAdjust = TRUE;
+ if (bVerticalDoc) {
+ if (iCharRotation == 0) {
+ pCharPos->m_AdjustMatrix[0] = -1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = 1;
+ pCharPos->m_OriginY += fAscent;
+ } else if (iCharRotation == 1) {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = -1;
+ pCharPos->m_AdjustMatrix[2] = -1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX -= fDescent;
+ } else if (iCharRotation == 2) {
+ pCharPos->m_AdjustMatrix[0] = 1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = -1;
+ pCharPos->m_OriginX += fCharWidth;
+ pCharPos->m_OriginY += fAscent;
+ } else {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = 1;
+ pCharPos->m_AdjustMatrix[2] = 1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX += fAscent;
+ }
+ } else {
+ if (iCharRotation == 0) {
+ pCharPos->m_AdjustMatrix[0] = -1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = 1;
+ } else if (iCharRotation == 1) {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = -1;
+ pCharPos->m_AdjustMatrix[2] = -1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX -= fDescent;
+ pCharPos->m_OriginY -= fAscent + fDescent;
+ } else if (iCharRotation == 2) {
+ pCharPos->m_AdjustMatrix[0] = 1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = -1;
+ pCharPos->m_OriginX += fCharWidth;
+ pCharPos->m_OriginY -= fAscent;
+ } else {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = 1;
+ pCharPos->m_AdjustMatrix[2] = 1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX += fAscent;
+ }
+ }
+ if (iHorScale != 100 || iVerScale != 100) {
+ pCharPos->m_AdjustMatrix[0] =
+ pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f;
+ pCharPos->m_AdjustMatrix[1] =
+ pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f;
+ pCharPos->m_AdjustMatrix[2] =
+ pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f;
+ pCharPos->m_AdjustMatrix[3] =
+ pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f;
+ }
+ pCharPos++;
+ }
+ }
+ if (iWidth > 0) {
+ wPrev = (FX_WCHAR)formChars[0].wch;
+ }
+ wLast = wch;
+ }
+ return iCount;
+}
+int32_t CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun,
+ CFX_RectFArray& rtArray,
+ FX_BOOL bCharBBox) const {
+ if (pTxtRun == NULL || pTxtRun->iLength < 1) {
+ return 0;
+ }
+ IFX_TxtAccess* pAccess = pTxtRun->pAccess;
+ void* pIdentity = pTxtRun->pIdentity;
+ const FX_WCHAR* pStr = pTxtRun->pStr;
+ int32_t* pWidths = pTxtRun->pWidths;
+ int32_t iLength = pTxtRun->iLength;
+ CFX_RectF rect(*pTxtRun->pRect);
+ FX_BOOL bRTLPiece =
+ (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
+ FX_FLOAT fFontSize = pTxtRun->fFontSize;
+ int32_t iFontSize = FXSYS_round(fFontSize * 20.0f);
+ FX_FLOAT fScale = fFontSize / 1000.0f;
+ IFX_Font* pFont = pTxtRun->pFont;
+ if (pFont == NULL) {
+ bCharBBox = FALSE;
+ }
+ CFX_Rect bbox;
+ bbox.Set(0, 0, 0, 0);
+ if (bCharBBox) {
+ bCharBBox = pFont->GetBBox(bbox);
+ }
+ FX_FLOAT fLeft = std::max(0.0f, bbox.left * fScale);
+ FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale);
+ rtArray.RemoveAll();
+ rtArray.SetSize(iLength);
+ FX_BOOL bVertical =
+ (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0;
+ FX_BOOL bSingleLine = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
+ FX_BOOL bCombText = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
+ FX_WCHAR wch, wLineBreakChar = pTxtRun->wLineBreakChar;
+ int32_t iCharSize;
+ FX_FLOAT fCharSize, fStart;
+ if (bVertical) {
+ fStart = bRTLPiece ? rect.bottom() : rect.top;
+ } else {
+ fStart = bRTLPiece ? rect.right() : rect.left;
+ }
+ for (int32_t i = 0; i < iLength; i++) {
+ if (pAccess != NULL) {
+ wch = pAccess->GetChar(pIdentity, i);
+ iCharSize = pAccess->GetWidth(pIdentity, i);
+ } else {
+ wch = *pStr++;
+ iCharSize = *pWidths++;
+ }
+ fCharSize = (FX_FLOAT)iCharSize / 20000.0f;
+ FX_BOOL bRet = (!bSingleLine && FX_IsCtrlCode(wch));
+ if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 ||
+ (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) {
+ bRet = FALSE;
+ }
+ if (bRet) {
+ iCharSize = iFontSize * 500;
+ fCharSize = fFontSize / 2.0f;
+ }
+ if (bVertical) {
+ rect.top = fStart;
+ if (bRTLPiece) {
+ rect.top -= fCharSize;
+ fStart -= fCharSize;
+ } else {
+ fStart += fCharSize;
+ }
+ rect.height = fCharSize;
+ } else {
+ rect.left = fStart;
+ if (bRTLPiece) {
+ rect.left -= fCharSize;
+ fStart -= fCharSize;
+ } else {
+ fStart += fCharSize;
+ }
+ rect.width = fCharSize;
+ }
+ if (bCharBBox && !bRet) {
+ int32_t iCharWidth = 1000;
+ pFont->GetCharWidth(wch, iCharWidth);
+ FX_FLOAT fRTLeft = 0, fCharWidth = 0;
+ if (iCharWidth > 0) {
+ fCharWidth = iCharWidth * fScale;
+ fRTLeft = fLeft;
+ if (bCombText) {
+ fRTLeft = (rect.width - fCharWidth) / 2.0f;
+ }
+ }
+ CFX_RectF rtBBoxF;
+ if (bVertical) {
+ rtBBoxF.top = rect.left + fRTLeft;
+ rtBBoxF.left = rect.top + (rect.height - fHeight) / 2.0f;
+ rtBBoxF.height = fCharWidth;
+ rtBBoxF.width = fHeight;
+ rtBBoxF.left = std::max(rtBBoxF.left, 0.0f);
+ } else {
+ rtBBoxF.left = rect.left + fRTLeft;
+ rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f;
+ rtBBoxF.width = fCharWidth;
+ rtBBoxF.height = fHeight;
+ rtBBoxF.top = std::max(rtBBoxF.top, 0.0f);
+ }
+ rtArray.SetAt(i, rtBBoxF);
+ continue;
+ }
+ rtArray.SetAt(i, rect);
+ }
+ return iLength;
+}
diff --git a/xfa/src/fgas/layout/fgas_textbreak.h b/xfa/src/fgas/layout/fgas_textbreak.h
new file mode 100644
index 0000000000..65fba720d5
--- /dev/null
+++ b/xfa/src/fgas/layout/fgas_textbreak.h
@@ -0,0 +1,222 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_LAYOUT_FGAS_TEXTBREAK_H_
+#define XFA_SRC_FGAS_LAYOUT_FGAS_TEXTBREAK_H_
+
+#include "core/include/fxcrt/fx_ucd.h"
+#include "core/include/fxge/fx_ge.h"
+#include "xfa/src/fgas/crt/fgas_utils.h"
+#include "xfa/src/fgas/layout/fgas_unicode.h"
+
+class IFX_Font;
+class CFX_Char;
+class IFX_TxtAccess;
+class CFX_TxtChar;
+class CFX_TxtPiece;
+class IFX_TxtBreak;
+
+#define FX_TXTBREAKPOLICY_None 0x00
+#define FX_TXTBREAKPOLICY_Pagination 0x01
+#define FX_TXTBREAKPOLICY_SpaceBreak 0x02
+#define FX_TXTBREAKPOLICY_NumberBreak 0x04
+#define FX_TXTBREAK_None 0x00
+#define FX_TXTBREAK_PieceBreak 0x01
+#define FX_TXTBREAK_LineBreak 0x02
+#define FX_TXTBREAK_ParagraphBreak 0x03
+#define FX_TXTBREAK_PageBreak 0x04
+#define FX_TXTBREAK_ControlChar 0x10
+#define FX_TXTBREAK_BreakChar 0x20
+#define FX_TXTBREAK_UnknownChar 0x40
+#define FX_TXTBREAK_RemoveChar 0x80
+#define FX_TXTLAYOUTSTYLE_MutipleFormat 0x0001
+#define FX_TXTLAYOUTSTYLE_VerticalLayout 0x0002
+#define FX_TXTLAYOUTSTYLE_VerticalChars 0x0004
+#define FX_TXTLAYOUTSTYLE_ReverseLine 0x0008
+#define FX_TXTLAYOUTSTYLE_ArabicContext 0x0010
+#define FX_TXTLAYOUTSTYLE_ArabicShapes 0x0020
+#define FX_TXTLAYOUTSTYLE_RTLReadingOrder 0x0040
+#define FX_TXTLAYOUTSTYLE_ExpandTab 0x0100
+#define FX_TXTLAYOUTSTYLE_SingleLine 0x0200
+#define FX_TXTLAYOUTSTYLE_CombText 0x0400
+#define FX_TXTCHARSTYLE_Alignment 0x000F
+#define FX_TXTCHARSTYLE_ArabicNumber 0x0010
+#define FX_TXTCHARSTYLE_ArabicShadda 0x0020
+#define FX_TXTCHARSTYLE_OddBidiLevel 0x0040
+#define FX_TXTCHARSTYLE_RTLReadingOrder 0x0080
+#define FX_TXTCHARSTYLE_ArabicContext 0x0300
+#define FX_TXTCHARSTYLE_ArabicIndic 0x0400
+#define FX_TXTCHARSTYLE_ArabicComma 0x0800
+#define FX_TXTLINEALIGNMENT_Left 0
+#define FX_TXTLINEALIGNMENT_Center 1
+#define FX_TXTLINEALIGNMENT_Right 2
+#define FX_TXTLINEALIGNMENT_Justified (1 << 2)
+#define FX_TXTLINEALIGNMENT_Distributed (2 << 2)
+#define FX_TXTLINEALIGNMENT_JustifiedLeft \
+ (FX_TXTLINEALIGNMENT_Left | FX_TXTLINEALIGNMENT_Justified)
+#define FX_TXTLINEALIGNMENT_JustifiedCenter \
+ (FX_TXTLINEALIGNMENT_Center | FX_TXTLINEALIGNMENT_Justified)
+#define FX_TXTLINEALIGNMENT_JustifiedRight \
+ (FX_TXTLINEALIGNMENT_Right | FX_TXTLINEALIGNMENT_Justified)
+#define FX_TXTLINEALIGNMENT_DistributedLeft \
+ (FX_TXTLINEALIGNMENT_Left | FX_TXTLINEALIGNMENT_Distributed)
+#define FX_TXTLINEALIGNMENT_DistributedCenter \
+ (FX_TXTLINEALIGNMENT_Center | FX_TXTLINEALIGNMENT_Distributed)
+#define FX_TXTLINEALIGNMENT_DistributedRight \
+ (FX_TXTLINEALIGNMENT_Right | FX_TXTLINEALIGNMENT_Distributed)
+#define FX_TXTLINEALIGNMENT_LowerMask 0x03
+#define FX_TXTLINEALIGNMENT_HigherMask 0x0C
+#define FX_TXTBREAK_MinimumTabWidth 160000
+
+class IFX_TxtAccess {
+ public:
+ virtual ~IFX_TxtAccess() {}
+ virtual FX_WCHAR GetChar(void* pIdentity, int32_t index) const = 0;
+ virtual int32_t GetWidth(void* pIdentity, int32_t index) const = 0;
+};
+
+struct FX_TXTRUN {
+ FX_TXTRUN() {
+ pAccess = NULL;
+ pIdentity = NULL;
+ pStr = NULL;
+ pWidths = NULL;
+ iLength = 0;
+ pFont = NULL;
+ fFontSize = 12;
+ dwStyles = 0;
+ iHorizontalScale = 100;
+ iVerticalScale = 100;
+ iCharRotation = 0;
+ dwCharStyles = 0;
+ pRect = NULL;
+ wLineBreakChar = L'\n';
+ bSkipSpace = TRUE;
+ }
+
+ IFX_TxtAccess* pAccess;
+ void* pIdentity;
+ const FX_WCHAR* pStr;
+ int32_t* pWidths;
+ int32_t iLength;
+ IFX_Font* pFont;
+ FX_FLOAT fFontSize;
+ FX_DWORD dwStyles;
+ int32_t iHorizontalScale;
+ int32_t iVerticalScale;
+ int32_t iCharRotation;
+ FX_DWORD dwCharStyles;
+ const CFX_RectF* pRect;
+ FX_WCHAR wLineBreakChar;
+ FX_BOOL bSkipSpace;
+};
+
+class CFX_TxtPiece : public CFX_Target {
+ public:
+ CFX_TxtPiece()
+ : m_dwStatus(FX_TXTBREAK_PieceBreak),
+ m_iStartPos(0),
+ m_iWidth(-1),
+ m_iStartChar(0),
+ m_iChars(0),
+ m_iBidiLevel(0),
+ m_iBidiPos(0),
+ m_iHorizontalScale(100),
+ m_iVerticalScale(100),
+ m_dwCharStyles(0),
+ m_pChars(NULL),
+ m_pUserData(NULL) {}
+ int32_t GetEndPos() const {
+ return m_iWidth < 0 ? m_iStartPos : m_iStartPos + m_iWidth;
+ }
+ int32_t GetLength() const { return m_iChars; }
+ int32_t GetEndChar() const { return m_iStartChar + m_iChars; }
+ CFX_TxtChar* GetCharPtr(int32_t index) const {
+ FXSYS_assert(index > -1 && index < m_iChars && m_pChars != NULL);
+ return m_pChars->GetDataPtr(m_iStartChar + index);
+ }
+ void GetString(FX_WCHAR* pText) const {
+ FXSYS_assert(pText != NULL);
+ int32_t iEndChar = m_iStartChar + m_iChars;
+ CFX_Char* pChar;
+ for (int32_t i = m_iStartChar; i < iEndChar; i++) {
+ pChar = m_pChars->GetDataPtr(i);
+ *pText++ = (FX_WCHAR)pChar->m_wCharCode;
+ }
+ }
+
+ void GetString(CFX_WideString& wsText) const {
+ FX_WCHAR* pText = wsText.GetBuffer(m_iChars);
+ GetString(pText);
+ wsText.ReleaseBuffer(m_iChars);
+ }
+ void GetWidths(int32_t* pWidths) const {
+ FXSYS_assert(pWidths != NULL);
+ int32_t iEndChar = m_iStartChar + m_iChars;
+ CFX_Char* pChar;
+ for (int32_t i = m_iStartChar; i < iEndChar; i++) {
+ pChar = m_pChars->GetDataPtr(i);
+ *pWidths++ = pChar->m_iCharWidth;
+ }
+ }
+ FX_DWORD m_dwStatus;
+ int32_t m_iStartPos;
+ int32_t m_iWidth;
+ int32_t m_iStartChar;
+ int32_t m_iChars;
+ int32_t m_iBidiLevel;
+ int32_t m_iBidiPos;
+ int32_t m_iHorizontalScale;
+ int32_t m_iVerticalScale;
+ FX_DWORD m_dwCharStyles;
+ CFX_TxtCharArray* m_pChars;
+ void* m_pUserData;
+};
+typedef CFX_BaseArrayTemplate<CFX_TxtPiece> CFX_TxtPieceArray;
+
+class IFX_TxtBreak {
+ public:
+ static IFX_TxtBreak* Create(FX_DWORD dwPolicies);
+ virtual ~IFX_TxtBreak() {}
+ virtual void Release() = 0;
+ virtual void SetLineWidth(FX_FLOAT fLineWidth) = 0;
+ virtual void SetLinePos(FX_FLOAT fLinePos) = 0;
+ virtual FX_DWORD GetLayoutStyles() const = 0;
+ virtual void SetLayoutStyles(FX_DWORD dwLayoutStyles) = 0;
+ virtual void SetFont(IFX_Font* pFont) = 0;
+ virtual void SetFontSize(FX_FLOAT fFontSize) = 0;
+ virtual void SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant) = 0;
+ virtual void SetDefaultChar(FX_WCHAR wch) = 0;
+ virtual void SetParagraphBreakChar(FX_WCHAR wch) = 0;
+ virtual void SetLineBreakTolerance(FX_FLOAT fTolerance) = 0;
+ virtual void SetHorizontalScale(int32_t iScale) = 0;
+ virtual void SetVerticalScale(int32_t iScale) = 0;
+ virtual void SetCharRotation(int32_t iCharRotation) = 0;
+ virtual void SetCharSpace(FX_FLOAT fCharSpace) = 0;
+ virtual void SetAlignment(int32_t iAlignment) = 0;
+ virtual FX_DWORD GetContextCharStyles() const = 0;
+ virtual void SetContextCharStyles(FX_DWORD dwCharStyles) = 0;
+ virtual void SetCombWidth(FX_FLOAT fCombWidth) = 0;
+ virtual void SetUserData(void* pUserData) = 0;
+ virtual FX_DWORD AppendChar(FX_WCHAR wch) = 0;
+ virtual FX_DWORD EndBreak(FX_DWORD dwStatus = FX_TXTBREAK_PieceBreak) = 0;
+ virtual int32_t CountBreakChars() const = 0;
+ virtual int32_t CountBreakPieces() const = 0;
+ virtual const CFX_TxtPiece* GetBreakPiece(int32_t index) const = 0;
+ virtual void ClearBreakPieces() = 0;
+ virtual void Reset() = 0;
+ virtual int32_t GetDisplayPos(
+ const FX_TXTRUN* pTxtRun,
+ FXTEXT_CHARPOS* pCharPos,
+ FX_BOOL bCharCode = FALSE,
+ CFX_WideString* pWSForms = NULL,
+ FX_AdjustCharDisplayPos pAdjustPos = NULL) const = 0;
+ virtual int32_t GetCharRects(const FX_TXTRUN* pTxtRun,
+ CFX_RectFArray& rtArray,
+ FX_BOOL bCharBBox = FALSE) const = 0;
+};
+
+#endif // XFA_SRC_FGAS_LAYOUT_FGAS_TEXTBREAK_H_
diff --git a/xfa/src/fgas/layout/fgas_unicode.cpp b/xfa/src/fgas/layout/fgas_unicode.cpp
new file mode 100644
index 0000000000..f463d753b5
--- /dev/null
+++ b/xfa/src/fgas/layout/fgas_unicode.cpp
@@ -0,0 +1,117 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/layout/fgas_unicode.h"
+
+void FX_TEXTLAYOUT_PieceSort(CFX_TPOArray& tpos, int32_t iStart, int32_t iEnd) {
+ FXSYS_assert(iStart > -1 && iStart < tpos.GetSize());
+ FXSYS_assert(iEnd > -1 && iEnd < tpos.GetSize());
+ if (iStart >= iEnd) {
+ return;
+ }
+ int32_t i = iStart, j = iEnd;
+ FX_TPO *pCur = tpos.GetPtrAt(iStart), *pSort;
+ int32_t v = pCur->pos;
+ while (i < j) {
+ while (j > i) {
+ pSort = tpos.GetPtrAt(j);
+ if (pSort->pos < v) {
+ FX_TPO t = *pSort;
+ *pSort = *pCur;
+ *pCur = t;
+ pCur = pSort;
+ break;
+ }
+ j--;
+ }
+ while (i < j) {
+ pSort = tpos.GetPtrAt(i);
+ if (pSort->pos > v) {
+ FX_TPO t = *pSort;
+ *pSort = *pCur;
+ *pCur = t;
+ pCur = pSort;
+ break;
+ }
+ i++;
+ }
+ }
+ i--, j++;
+ if (iStart < i) {
+ FX_TEXTLAYOUT_PieceSort(tpos, iStart, i);
+ }
+ if (j < iEnd) {
+ FX_TEXTLAYOUT_PieceSort(tpos, j, iEnd);
+ }
+}
+static const FX_JAPCHARPROPERTYEX gs_FX_JapCharPropertysEx[] = {
+ {0x3001, 0x13}, {0x3002, 0x13}, {0x3041, 0x23}, {0x3043, 0x23},
+ {0x3045, 0x23}, {0x3047, 0x23}, {0x3049, 0x23}, {0x3063, 0x23},
+ {0x3083, 0x23}, {0x3085, 0x23}, {0x3087, 0x23}, {0x308E, 0x23},
+ {0x3095, 0x23}, {0x3096, 0x23}, {0x30A1, 0x23}, {0x30A3, 0x23},
+ {0x30A5, 0x23}, {0x30A7, 0x23}, {0x30A9, 0x23}, {0x30C3, 0x23},
+ {0x30E3, 0x23}, {0x30E5, 0x23}, {0x30E7, 0x23}, {0x30EE, 0x23},
+ {0x30F5, 0x23}, {0x30F6, 0x23}, {0x30FB, 0x22}, {0x31F0, 0x23},
+ {0x31F1, 0x23}, {0x31F2, 0x23}, {0x31F3, 0x23}, {0x31F4, 0x23},
+ {0x31F5, 0x23}, {0x31F6, 0x23}, {0x31F7, 0x23}, {0x31F8, 0x23},
+ {0x31F9, 0x23}, {0x31FA, 0x23}, {0x31FB, 0x23}, {0x31FC, 0x23},
+ {0x31FD, 0x23}, {0x31FE, 0x23}, {0x31FF, 0x23},
+};
+const FX_JAPCHARPROPERTYEX* FX_GetJapCharPropertyEx(FX_WCHAR wch) {
+ int32_t iStart = 0;
+ int32_t iEnd =
+ sizeof(gs_FX_JapCharPropertysEx) / sizeof(FX_JAPCHARPROPERTYEX);
+ while (iStart <= iEnd) {
+ int32_t iMid = (iStart + iEnd) / 2;
+ FX_WCHAR wJapChar = gs_FX_JapCharPropertysEx[iMid].wChar;
+ if (wch == wJapChar) {
+ return gs_FX_JapCharPropertysEx + iMid;
+ } else if (wch < wJapChar) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ }
+ return NULL;
+}
+FX_BOOL FX_AdjustJapCharDisplayPos(FX_WCHAR wch,
+ FX_BOOL bMBCSCode,
+ IFX_Font* pFont,
+ FX_FLOAT fFontSize,
+ FX_BOOL bVertical,
+ CFX_PointF& ptOffset) {
+ if (pFont == NULL || !bVertical) {
+ return FALSE;
+ }
+ if (wch < 0x3001 || wch > 0x31FF) {
+ return FALSE;
+ }
+ const FX_JAPCHARPROPERTYEX* pJapChar = FX_GetJapCharPropertyEx(wch);
+ if (pJapChar == NULL) {
+ return FALSE;
+ }
+ CFX_Rect rtBBox;
+ rtBBox.Reset();
+ if (pFont->GetCharBBox(wch, rtBBox, bMBCSCode)) {
+ switch (pJapChar->uAlign & 0xF0) {
+ case FX_JAPCHARPROPERTYEX_Top:
+ ptOffset.y = fFontSize * (1000 - rtBBox.height) / 1200.0f;
+ break;
+ case FX_JAPCHARPROPERTYEX_Middle:
+ ptOffset.y = fFontSize * (1000 - rtBBox.height) / 6000.0f;
+ break;
+ }
+ switch (pJapChar->uAlign & 0x0F) {
+ case FX_JAPCHARPROPERTYEX_Center:
+ ptOffset.x = fFontSize * (600 - rtBBox.right()) / 1000.0f;
+ break;
+ case FX_JAPCHARPROPERTYEX_Right:
+ ptOffset.x = fFontSize * (950 - rtBBox.right()) / 1000.0f;
+ break;
+ }
+ }
+ return TRUE;
+}
diff --git a/xfa/src/fgas/layout/fgas_unicode.h b/xfa/src/fgas/layout/fgas_unicode.h
new file mode 100644
index 0000000000..f25da87e96
--- /dev/null
+++ b/xfa/src/fgas/layout/fgas_unicode.h
@@ -0,0 +1,47 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_LAYOUT_FGAS_UNICODE_H_
+#define XFA_SRC_FGAS_LAYOUT_FGAS_UNICODE_H_
+
+#include "xfa/src/fgas/font/fgas_font.h"
+#include "xfa/src/fgas/crt/fgas_utils.h"
+
+#define FX_JAPCHARPROPERTYEX_Left 0x01
+#define FX_JAPCHARPROPERTYEX_Center 0x02
+#define FX_JAPCHARPROPERTYEX_Right 0x03
+#define FX_JAPCHARPROPERTYEX_Top 0x10
+#define FX_JAPCHARPROPERTYEX_Middle 0x20
+#define FX_JAPCHARPROPERTYEX_Bottom 0x30
+
+struct FX_TPO {
+ int32_t index;
+ int32_t pos;
+};
+typedef CFX_MassArrayTemplate<FX_TPO> CFX_TPOArray;
+
+void FX_TEXTLAYOUT_PieceSort(CFX_TPOArray& tpos, int32_t iStart, int32_t iEnd);
+
+struct FX_JAPCHARPROPERTYEX {
+ FX_WCHAR wChar;
+ uint8_t uAlign;
+};
+
+const FX_JAPCHARPROPERTYEX* FX_GetJapCharPropertyEx(FX_WCHAR wch);
+typedef FX_BOOL (*FX_AdjustCharDisplayPos)(FX_WCHAR wch,
+ FX_BOOL bMBCSCode,
+ IFX_Font* pFont,
+ FX_FLOAT fFontSize,
+ FX_BOOL bVertical,
+ CFX_PointF& ptOffset);
+FX_BOOL FX_AdjustJapCharDisplayPos(FX_WCHAR wch,
+ FX_BOOL bMBCSCode,
+ IFX_Font* pFont,
+ FX_FLOAT fFontSize,
+ FX_BOOL bVertical,
+ CFX_PointF& ptOffset);
+
+#endif // XFA_SRC_FGAS_LAYOUT_FGAS_UNICODE_H_