From 994acdc1a31015674e786d24cc37d08dfae6d863 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Tue, 18 Apr 2017 13:56:39 -0400 Subject: Rename text break files to match class names. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL renames several fgas/layout files to match the class names contained in the files. Change-Id: Ib4feaa902618e577261e51dbac743cb4cb500ea1 Reviewed-on: https://pdfium-review.googlesource.com/4290 Commit-Queue: dsinclair Reviewed-by: Tom Sepez Reviewed-by: Nicolás Peña --- BUILD.gn | 14 +- xfa/fde/cfde_textout.cpp | 2 +- xfa/fde/cfde_txtedtengine.cpp | 2 +- xfa/fde/cfde_txtedtpage.cpp | 2 +- xfa/fde/cfde_txtedtparag.cpp | 2 +- xfa/fde/cfde_txtedttextset.cpp | 2 +- xfa/fgas/layout/cfx_linebreak.cpp | 268 ++++++++ xfa/fgas/layout/cfx_linebreak.h | 32 + xfa/fgas/layout/cfx_rtfbreak.cpp | 790 +++++++++++++++++++++ xfa/fgas/layout/cfx_rtfbreak.h | 98 +++ xfa/fgas/layout/cfx_rtfbreak_unittest.cpp | 87 +++ xfa/fgas/layout/cfx_txtbreak.cpp | 1027 +++++++++++++++++++++++++++ xfa/fgas/layout/cfx_txtbreak.h | 102 +++ xfa/fgas/layout/fgas_linebreak.cpp | 268 -------- xfa/fgas/layout/fgas_linebreak.h | 32 - xfa/fgas/layout/fgas_rtfbreak.cpp | 790 --------------------- xfa/fgas/layout/fgas_rtfbreak.h | 98 --- xfa/fgas/layout/fgas_rtfbreak_unittest.cpp | 87 --- xfa/fgas/layout/fgas_textbreak.cpp | 1028 ---------------------------- xfa/fgas/layout/fgas_textbreak.h | 102 --- xfa/fxfa/app/cxfa_textlayout.h | 2 +- 21 files changed, 2417 insertions(+), 2418 deletions(-) create mode 100644 xfa/fgas/layout/cfx_linebreak.cpp create mode 100644 xfa/fgas/layout/cfx_linebreak.h create mode 100644 xfa/fgas/layout/cfx_rtfbreak.cpp create mode 100644 xfa/fgas/layout/cfx_rtfbreak.h create mode 100644 xfa/fgas/layout/cfx_rtfbreak_unittest.cpp create mode 100644 xfa/fgas/layout/cfx_txtbreak.cpp create mode 100644 xfa/fgas/layout/cfx_txtbreak.h delete mode 100644 xfa/fgas/layout/fgas_linebreak.cpp delete mode 100644 xfa/fgas/layout/fgas_linebreak.h delete mode 100644 xfa/fgas/layout/fgas_rtfbreak.cpp delete mode 100644 xfa/fgas/layout/fgas_rtfbreak.h delete mode 100644 xfa/fgas/layout/fgas_rtfbreak_unittest.cpp delete mode 100644 xfa/fgas/layout/fgas_textbreak.cpp delete mode 100644 xfa/fgas/layout/fgas_textbreak.h diff --git a/BUILD.gn b/BUILD.gn index 9c370c258b..1246a7bca0 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1444,12 +1444,12 @@ if (pdf_enable_xfa) { "xfa/fgas/layout/cfx_breakline.h", "xfa/fgas/layout/cfx_breakpiece.cpp", "xfa/fgas/layout/cfx_breakpiece.h", - "xfa/fgas/layout/fgas_linebreak.cpp", - "xfa/fgas/layout/fgas_linebreak.h", - "xfa/fgas/layout/fgas_rtfbreak.cpp", - "xfa/fgas/layout/fgas_rtfbreak.h", - "xfa/fgas/layout/fgas_textbreak.cpp", - "xfa/fgas/layout/fgas_textbreak.h", + "xfa/fgas/layout/cfx_linebreak.cpp", + "xfa/fgas/layout/cfx_linebreak.h", + "xfa/fgas/layout/cfx_rtfbreak.cpp", + "xfa/fgas/layout/cfx_rtfbreak.h", + "xfa/fgas/layout/cfx_txtbreak.cpp", + "xfa/fgas/layout/cfx_txtbreak.h", "xfa/fwl/cfwl_app.cpp", "xfa/fwl/cfwl_app.h", "xfa/fwl/cfwl_barcode.cpp", @@ -1894,7 +1894,7 @@ test("pdfium_unittests") { "xfa/fde/css/cfde_cssstylesheet_unittest.cpp", "xfa/fde/css/cfde_cssvaluelistparser_unittest.cpp", "xfa/fde/xml/cfde_xmlsyntaxparser_unittest.cpp", - "xfa/fgas/layout/fgas_rtfbreak_unittest.cpp", + "xfa/fgas/layout/cfx_rtfbreak_unittest.cpp", "xfa/fxfa/app/cxfa_textparser_unittest.cpp", "xfa/fxfa/cxfa_ffapp_unittest.cpp", "xfa/fxfa/fm2js/xfa_simpleexpression_unittest.cpp", diff --git a/xfa/fde/cfde_textout.cpp b/xfa/fde/cfde_textout.cpp index b85bfef3f6..d5706dd497 100644 --- a/xfa/fde/cfde_textout.cpp +++ b/xfa/fde/cfde_textout.cpp @@ -16,7 +16,7 @@ #include "xfa/fde/cfde_path.h" #include "xfa/fde/cfde_pen.h" #include "xfa/fde/cfde_renderdevice.h" -#include "xfa/fgas/layout/fgas_textbreak.h" +#include "xfa/fgas/layout/cfx_txtbreak.h" FDE_TTOPIECE::FDE_TTOPIECE() = default; diff --git a/xfa/fde/cfde_txtedtengine.cpp b/xfa/fde/cfde_txtedtengine.cpp index 86a501559f..84aafed433 100644 --- a/xfa/fde/cfde_txtedtengine.cpp +++ b/xfa/fde/cfde_txtedtengine.cpp @@ -17,7 +17,7 @@ #include "xfa/fde/cfde_txtedtdorecord_insert.h" #include "xfa/fde/cfde_txtedtpage.h" #include "xfa/fde/cfde_txtedtparag.h" -#include "xfa/fgas/layout/fgas_textbreak.h" +#include "xfa/fgas/layout/cfx_txtbreak.h" #include "xfa/fwl/cfwl_edit.h" namespace { diff --git a/xfa/fde/cfde_txtedtpage.cpp b/xfa/fde/cfde_txtedtpage.cpp index 5bd731f8f5..faf52316c8 100644 --- a/xfa/fde/cfde_txtedtpage.cpp +++ b/xfa/fde/cfde_txtedtpage.cpp @@ -16,7 +16,7 @@ #include "xfa/fde/cfde_txtedtparag.h" #include "xfa/fde/cfde_txtedttextset.h" #include "xfa/fde/ifde_txtedtengine.h" -#include "xfa/fgas/layout/fgas_textbreak.h" +#include "xfa/fgas/layout/cfx_txtbreak.h" namespace { diff --git a/xfa/fde/cfde_txtedtparag.cpp b/xfa/fde/cfde_txtedtparag.cpp index bcacc66695..c6b13007c9 100644 --- a/xfa/fde/cfde_txtedtparag.cpp +++ b/xfa/fde/cfde_txtedtparag.cpp @@ -15,7 +15,7 @@ #include "xfa/fde/cfde_txtedtbuf.h" #include "xfa/fde/cfde_txtedtengine.h" #include "xfa/fde/ifde_txtedtengine.h" -#include "xfa/fgas/layout/fgas_textbreak.h" +#include "xfa/fgas/layout/cfx_txtbreak.h" CFDE_TxtEdtParag::CFDE_TxtEdtParag(CFDE_TxtEdtEngine* pEngine) : m_nCharStart(0), diff --git a/xfa/fde/cfde_txtedttextset.cpp b/xfa/fde/cfde_txtedttextset.cpp index ff7b39bb9f..dd68d42618 100644 --- a/xfa/fde/cfde_txtedttextset.cpp +++ b/xfa/fde/cfde_txtedttextset.cpp @@ -9,7 +9,7 @@ #include "xfa/fde/cfde_txtedtengine.h" #include "xfa/fde/cfde_txtedtpage.h" #include "xfa/fgas/font/cfgas_gefont.h" -#include "xfa/fgas/layout/fgas_textbreak.h" +#include "xfa/fgas/layout/cfx_txtbreak.h" CFDE_TxtEdtTextSet::CFDE_TxtEdtTextSet(CFDE_TxtEdtPage* pPage) : m_pPage(pPage) {} diff --git a/xfa/fgas/layout/cfx_linebreak.cpp b/xfa/fgas/layout/cfx_linebreak.cpp new file mode 100644 index 0000000000..9531bc55b0 --- /dev/null +++ b/xfa/fgas/layout/cfx_linebreak.cpp @@ -0,0 +1,268 @@ +// 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/fgas/layout/cfx_linebreak.h" + +#include "core/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}, +}; diff --git a/xfa/fgas/layout/cfx_linebreak.h b/xfa/fgas/layout/cfx_linebreak.h new file mode 100644 index 0000000000..8ba022e71e --- /dev/null +++ b/xfa/fgas/layout/cfx_linebreak.h @@ -0,0 +1,32 @@ +// 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_FGAS_LAYOUT_CFX_LINEBREAK_H_ +#define XFA_FGAS_LAYOUT_CFX_LINEBREAK_H_ + +#include "core/fxcrt/fx_system.h" + +enum FX_LINEBREAKTYPE : uint8_t { + 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]; + +#endif // XFA_FGAS_LAYOUT_CFX_LINEBREAK_H_ diff --git a/xfa/fgas/layout/cfx_rtfbreak.cpp b/xfa/fgas/layout/cfx_rtfbreak.cpp new file mode 100644 index 0000000000..9acc082d8e --- /dev/null +++ b/xfa/fgas/layout/cfx_rtfbreak.cpp @@ -0,0 +1,790 @@ +// 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/fgas/layout/cfx_rtfbreak.h" + +#include + +#include "core/fxcrt/fx_arabic.h" +#include "third_party/base/stl_util.h" +#include "xfa/fgas/font/cfgas_gefont.h" +#include "xfa/fgas/layout/cfx_linebreak.h" + +CFX_RTFBreak::CFX_RTFBreak(uint32_t dwLayoutStyles) + : CFX_Break(dwLayoutStyles), + m_bPagination(false), + m_iAlignment(CFX_RTFLineAlignment::Left), + m_pUserData(nullptr) { + SetBreakStatus(); + m_bPagination = !!(m_dwLayoutStyles & FX_LAYOUTSTYLE_Pagination); +} + +CFX_RTFBreak::~CFX_RTFBreak() {} + +void CFX_RTFBreak::SetLineStartPos(float fLinePos) { + int32_t iLinePos = FXSYS_round(fLinePos * 20000.0f); + iLinePos = std::min(iLinePos, m_iLineWidth); + iLinePos = std::max(iLinePos, m_iLineStart); + m_pCurLine->m_iStart = iLinePos; +} + +void CFX_RTFBreak::AddPositionedTab(float fTabPos) { + int32_t iTabPos = + std::min(FXSYS_round(fTabPos * 20000.0f) + m_iLineStart, m_iLineWidth); + auto it = std::lower_bound(m_PositionedTabs.begin(), m_PositionedTabs.end(), + iTabPos); + if (it != m_PositionedTabs.end() && *it == iTabPos) + return; + m_PositionedTabs.insert(it, iTabPos); +} + +void CFX_RTFBreak::SetUserData(const CFX_RetainPtr& pUserData) { + if (m_pUserData == pUserData) + return; + + SetBreakStatus(); + m_pUserData = pUserData; +} + +int32_t CFX_RTFBreak::GetLastPositionedTab() const { + return m_PositionedTabs.empty() ? m_iLineStart : m_PositionedTabs.back(); +} + +bool CFX_RTFBreak::GetPositionedTab(int32_t* iTabPos) const { + auto it = std::upper_bound(m_PositionedTabs.begin(), m_PositionedTabs.end(), + *iTabPos); + if (it == m_PositionedTabs.end()) + return false; + + *iTabPos = *it; + return true; +} + +CFX_BreakType CFX_RTFBreak::AppendChar(wchar_t wch) { + ASSERT(m_pFont && m_pCurLine); + + uint32_t dwProps = kTextLayoutCodeProperties[static_cast(wch)]; + FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); + m_pCurLine->m_LineChars.emplace_back(); + + CFX_Char* pCurChar = &m_pCurLine->m_LineChars.back(); + pCurChar->m_dwStatus = CFX_BreakType::None; + pCurChar->m_wCharCode = wch; + pCurChar->m_dwCharProps = dwProps; + pCurChar->m_iFontSize = m_iFontSize; + pCurChar->m_iHorizontalScale = m_iHorizontalScale; + pCurChar->m_iVerticalScale = m_iVerticalScale; + pCurChar->m_iCharWidth = 0; + pCurChar->m_dwIdentity = m_dwIdentity; + pCurChar->m_pUserData = m_pUserData; + + CFX_BreakType dwRet1 = CFX_BreakType::None; + if (chartype != FX_CHARTYPE_Combination && + GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) && + m_eCharType != FX_CHARTYPE_Unknown && + m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance && + (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) { + dwRet1 = EndBreak(CFX_BreakType::Line); + int32_t iCount = m_pCurLine->CountChars(); + if (iCount > 0) + pCurChar = &m_pCurLine->m_LineChars[iCount - 1]; + } + + CFX_BreakType dwRet2 = CFX_BreakType::None; + switch (chartype) { + case FX_CHARTYPE_Tab: + AppendChar_Tab(pCurChar); + break; + case FX_CHARTYPE_Control: + dwRet2 = AppendChar_Control(pCurChar); + break; + case FX_CHARTYPE_Combination: + AppendChar_Combination(pCurChar); + break; + case FX_CHARTYPE_ArabicAlef: + case FX_CHARTYPE_ArabicSpecial: + case FX_CHARTYPE_ArabicDistortion: + case FX_CHARTYPE_ArabicNormal: + case FX_CHARTYPE_ArabicForm: + case FX_CHARTYPE_Arabic: + dwRet2 = AppendChar_Arabic(pCurChar); + break; + case FX_CHARTYPE_Unknown: + case FX_CHARTYPE_Space: + case FX_CHARTYPE_Numeric: + case FX_CHARTYPE_Normal: + default: + dwRet2 = AppendChar_Others(pCurChar); + break; + } + + m_eCharType = chartype; + return std::max(dwRet1, dwRet2); +} + +void CFX_RTFBreak::AppendChar_Combination(CFX_Char* pCurChar) { + int32_t iCharWidth = 0; + if (!m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth, false)) + iCharWidth = 0; + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + CFX_Char* pLastChar = GetLastChar(0, false, true); + if (pLastChar && pLastChar->GetCharType() > FX_CHARTYPE_Combination) + iCharWidth = -iCharWidth; + else + m_eCharType = FX_CHARTYPE_Combination; + + pCurChar->m_iCharWidth = iCharWidth; + if (iCharWidth > 0) + m_pCurLine->m_iWidth += iCharWidth; +} + +void CFX_RTFBreak::AppendChar_Tab(CFX_Char* pCurChar) { + if (!(m_dwLayoutStyles & FX_LAYOUTSTYLE_ExpandTab)) + return; + + 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; +} + +CFX_BreakType CFX_RTFBreak::AppendChar_Control(CFX_Char* pCurChar) { + CFX_BreakType dwRet2 = CFX_BreakType::None; + switch (pCurChar->m_wCharCode) { + case L'\v': + case 0x2028: + dwRet2 = CFX_BreakType::Line; + break; + case L'\f': + dwRet2 = CFX_BreakType::Page; + break; + case 0x2029: + dwRet2 = CFX_BreakType::Paragraph; + break; + default: + if (pCurChar->m_wCharCode == m_wParagraphBreakChar) + dwRet2 = CFX_BreakType::Paragraph; + break; + } + if (dwRet2 != CFX_BreakType::None) + dwRet2 = EndBreak(dwRet2); + + return dwRet2; +} + +CFX_BreakType CFX_RTFBreak::AppendChar_Arabic(CFX_Char* pCurChar) { + CFX_Char* pLastChar = nullptr; + int32_t iCharWidth = 0; + wchar_t wForm; + bool bAlef = false; + if (m_eCharType >= FX_CHARTYPE_ArabicAlef && + m_eCharType <= FX_CHARTYPE_ArabicDistortion) { + pLastChar = GetLastChar(1, false, true); + if (pLastChar) { + m_pCurLine->m_iWidth -= pLastChar->m_iCharWidth; + CFX_Char* pPrevChar = GetLastChar(2, false, true); + wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar); + bAlef = (wForm == 0xFEFF && + pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef); + if (!m_pFont->GetCharWidth(wForm, iCharWidth, false) && + !m_pFont->GetCharWidth(pLastChar->m_wCharCode, iCharWidth, false)) { + iCharWidth = m_iDefChar; + } + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + pLastChar->m_iCharWidth = iCharWidth; + m_pCurLine->m_iWidth += iCharWidth; + iCharWidth = 0; + } + } + + wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar, + nullptr); + if (!m_pFont->GetCharWidth(wForm, iCharWidth, false) && + !m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth, false)) { + iCharWidth = m_iDefChar; + } + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + pCurChar->m_iCharWidth = iCharWidth; + m_pCurLine->m_iWidth += iCharWidth; + m_pCurLine->m_iArabicChars++; + + if (m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance) + return EndBreak(CFX_BreakType::Line); + return CFX_BreakType::None; +} + +CFX_BreakType CFX_RTFBreak::AppendChar_Others(CFX_Char* pCurChar) { + FX_CHARTYPE chartype = pCurChar->GetCharType(); + wchar_t wForm = pCurChar->m_wCharCode; + int32_t iCharWidth = 0; + if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) + iCharWidth = m_iDefChar; + + iCharWidth *= m_iFontSize; + iCharWidth *= m_iHorizontalScale / 100; + iCharWidth += m_iCharSpace; + + pCurChar->m_iCharWidth = iCharWidth; + m_pCurLine->m_iWidth += iCharWidth; + if (chartype != FX_CHARTYPE_Space && + m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance) { + return EndBreak(CFX_BreakType::Line); + } + return CFX_BreakType::None; +} + +CFX_BreakType CFX_RTFBreak::EndBreak(CFX_BreakType dwStatus) { + ASSERT(dwStatus != CFX_BreakType::None); + + ++m_dwIdentity; + if (!m_pCurLine->m_LinePieces.empty()) { + if (dwStatus != CFX_BreakType::Piece) + m_pCurLine->m_LinePieces.back().m_dwStatus = dwStatus; + return m_pCurLine->m_LinePieces.back().m_dwStatus; + } + + if (HasLine()) { + if (!m_Line[m_iReadyLineIndex].m_LinePieces.empty()) { + if (dwStatus != CFX_BreakType::Piece) + m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus = dwStatus; + return m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus; + } + return CFX_BreakType::None; + } + + int32_t iCount = m_pCurLine->CountChars(); + if (iCount < 1) + return CFX_BreakType::None; + + CFX_Char* tc = m_pCurLine->GetChar(iCount - 1); + tc->m_dwStatus = dwStatus; + if (dwStatus == CFX_BreakType::Piece) + return dwStatus; + + m_iReadyLineIndex = m_pCurLine == &m_Line[0] ? 0 : 1; + CFX_BreakLine* pNextLine = &m_Line[1 - m_iReadyLineIndex]; + bool bAllChars = m_iAlignment == CFX_RTFLineAlignment::Justified || + m_iAlignment == CFX_RTFLineAlignment::Distributed; + + if (!EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) { + std::deque tpos; + EndBreak_BidiLine(&tpos, dwStatus); + if (!m_bPagination && m_iAlignment != CFX_RTFLineAlignment::Left) + EndBreak_Alignment(tpos, bAllChars, dwStatus); + } + m_pCurLine = pNextLine; + m_pCurLine->m_iStart = m_iLineStart; + + CFX_Char* pTC = GetLastChar(0, false, true); + m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown; + return dwStatus; +} + +bool CFX_RTFBreak::EndBreak_SplitLine(CFX_BreakLine* pNextLine, + bool bAllChars, + CFX_BreakType dwStatus) { + bool bDone = false; + if (m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance) { + const CFX_Char* tc = m_pCurLine->GetChar(m_pCurLine->CountChars() - 1); + switch (tc->GetCharType()) { + case FX_CHARTYPE_Tab: + case FX_CHARTYPE_Control: + case FX_CHARTYPE_Space: + break; + default: + SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars); + bDone = true; + break; + } + } + + if (!m_bPagination) { + if (bAllChars && !bDone) { + int32_t endPos = m_pCurLine->GetLineEnd(); + GetBreakPos(m_pCurLine->m_LineChars, endPos, bAllChars, true); + } + return false; + } + + const CFX_Char* pCurChars = m_pCurLine->m_LineChars.data(); + CFX_BreakPiece tp; + tp.m_pChars = &m_pCurLine->m_LineChars; + bool bNew = true; + uint32_t dwIdentity = static_cast(-1); + int32_t iLast = m_pCurLine->CountChars() - 1; + int32_t j = 0; + for (int32_t i = 0; i <= iLast;) { + const CFX_Char* 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_iHorizontalScale = pTC->m_iHorizontalScale; + tp.m_iVerticalScale = pTC->m_iVerticalScale; + dwIdentity = pTC->m_dwIdentity; + tp.m_dwIdentity = dwIdentity; + tp.m_pUserData = pTC->m_pUserData; + j = i; + bNew = false; + } + + if (i == iLast || pTC->m_dwStatus != CFX_BreakType::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; + } + m_pCurLine->m_LinePieces.push_back(tp); + bNew = true; + } else { + tp.m_iWidth += pTC->m_iCharWidth; + ++i; + } + } + return true; +} + +void CFX_RTFBreak::EndBreak_BidiLine(std::deque* tpos, + CFX_BreakType dwStatus) { + CFX_Char* pTC; + std::vector& chars = m_pCurLine->m_LineChars; + int32_t iCount = m_pCurLine->CountChars(); + if (!m_bPagination && m_pCurLine->m_iArabicChars > 0) { + int32_t iBidiNum = 0; + for (int32_t i = 0; i < iCount; ++i) { + pTC = &chars[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); + } else { + for (int32_t i = 0; i < iCount; ++i) { + pTC = &chars[i]; + pTC->m_iBidiLevel = 0; + pTC->m_iBidiPos = 0; + pTC->m_iBidiOrder = 0; + } + } + + CFX_BreakPiece tp; + tp.m_dwStatus = CFX_BreakType::Piece; + tp.m_iStartPos = m_pCurLine->m_iStart; + tp.m_pChars = &chars; + + int32_t iBidiLevel = -1; + int32_t iCharWidth; + FX_TPO tpo; + uint32_t dwIdentity = static_cast(-1); + int32_t i = 0; + int32_t j = 0; + while (i < iCount) { + pTC = &chars[i]; + if (iBidiLevel < 0) { + iBidiLevel = pTC->m_iBidiLevel; + iCharWidth = pTC->m_iCharWidth; + tp.m_iWidth = iCharWidth < 1 ? 0 : iCharWidth; + tp.m_iBidiLevel = iBidiLevel; + tp.m_iBidiPos = pTC->m_iBidiOrder; + tp.m_iFontSize = pTC->m_iFontSize; + tp.m_iHorizontalScale = pTC->m_iHorizontalScale; + tp.m_iVerticalScale = pTC->m_iVerticalScale; + dwIdentity = pTC->m_dwIdentity; + tp.m_dwIdentity = dwIdentity; + tp.m_pUserData = pTC->m_pUserData; + tp.m_dwStatus = CFX_BreakType::Piece; + ++i; + } else if (iBidiLevel != pTC->m_iBidiLevel || + pTC->m_dwIdentity != dwIdentity) { + tp.m_iChars = i - tp.m_iStartChar; + m_pCurLine->m_LinePieces.push_back(tp); + + tp.m_iStartPos += tp.m_iWidth; + tp.m_iStartChar = i; + tpo.index = j++; + tpo.pos = tp.m_iBidiPos; + tpos->push_back(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; + m_pCurLine->m_LinePieces.push_back(tp); + + tpo.index = j; + tpo.pos = tp.m_iBidiPos; + tpos->push_back(tpo); + } + + std::sort(tpos->begin(), tpos->end()); + int32_t iStartPos = m_pCurLine->m_iStart; + for (const auto& it : *tpos) { + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it.index]; + ttp.m_iStartPos = iStartPos; + iStartPos += ttp.m_iWidth; + } +} + +void CFX_RTFBreak::EndBreak_Alignment(const std::deque& tpos, + bool bAllChars, + CFX_BreakType dwStatus) { + int32_t iNetWidth = m_pCurLine->m_iWidth; + int32_t iGapChars = 0; + bool bFind = false; + for (auto it = tpos.rbegin(); it != tpos.rend(); it++) { + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it->index]; + if (!bFind) + iNetWidth = ttp.GetEndPos(); + + bool bArabic = FX_IsOdd(ttp.m_iBidiLevel); + int32_t j = bArabic ? 0 : ttp.m_iChars - 1; + while (j > -1 && j < ttp.m_iChars) { + const CFX_Char* tc = ttp.GetChar(j); + if (tc->m_nBreakType == FX_LBT_DIRECT_BRK) + ++iGapChars; + + if (!bFind || !bAllChars) { + uint32_t dwCharType = tc->GetCharType(); + if (dwCharType == FX_CHARTYPE_Space || + dwCharType == FX_CHARTYPE_Control) { + if (!bFind) { + int32_t 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_iLineWidth - iNetWidth; + if (iGapChars > 0 && (m_iAlignment == CFX_RTFLineAlignment::Distributed || + (m_iAlignment == CFX_RTFLineAlignment::Justified && + dwStatus != CFX_BreakType::Paragraph))) { + int32_t iStart = -1; + for (const auto& tpo : tpos) { + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index]; + if (iStart < 0) + iStart = ttp.m_iStartPos; + else + ttp.m_iStartPos = iStart; + + for (int32_t j = 0; j < ttp.m_iChars; ++j) { + CFX_Char* tc = ttp.GetChar(j); + if (tc->m_nBreakType != FX_LBT_DIRECT_BRK || tc->m_iCharWidth < 0) + continue; + + int32_t k = iOffset / iGapChars; + tc->m_iCharWidth += k; + ttp.m_iWidth += k; + iOffset -= k; + --iGapChars; + if (iGapChars < 1) + break; + } + iStart += ttp.m_iWidth; + } + } else if (m_iAlignment == CFX_RTFLineAlignment::Right || + m_iAlignment == CFX_RTFLineAlignment::Center) { + if (m_iAlignment == CFX_RTFLineAlignment::Center) + iOffset /= 2; + if (iOffset > 0) { + for (auto& ttp : m_pCurLine->m_LinePieces) + ttp.m_iStartPos += iOffset; + } + } +} + +int32_t CFX_RTFBreak::GetBreakPos(std::vector& tca, + int32_t& iEndPos, + bool bAllChars, + bool bOnlyBrk) { + int32_t iLength = pdfium::CollectionSize(tca) - 1; + if (iLength < 1) + return iLength; + + int32_t iBreak = -1; + int32_t iBreakPos = -1; + int32_t iIndirect = -1; + int32_t iIndirectPos = -1; + int32_t iLast = -1; + int32_t iLastPos = -1; + if (iEndPos <= m_iLineWidth) { + if (!bAllChars) + return iLength; + + iBreak = iLength; + iBreakPos = iEndPos; + } + + CFX_Char* pCharArray = tca.data(); + CFX_Char* pCur = pCharArray + iLength; + --iLength; + if (bAllChars) + pCur->m_nBreakType = FX_LBT_UNKNOWN; + + uint32_t nCodeProp = pCur->m_dwCharProps; + uint32_t nNext = nCodeProp & 0x003F; + int32_t iCharWidth = pCur->m_iCharWidth; + if (iCharWidth > 0) + iEndPos -= iCharWidth; + + while (iLength >= 0) { + pCur = pCharArray + iLength; + nCodeProp = pCur->m_dwCharProps; + uint32_t nCur = nCodeProp & 0x003F; + bool bNeedBreak = false; + FX_LINEBREAKTYPE eType; + if (nCur == FX_CBP_TB) { + bNeedBreak = true; + eType = nNext == FX_CBP_TB ? FX_LBT_PROHIBITED_BRK + : gs_FX_LineBreak_PairTable[nCur][nNext]; + } else { + if (nCur == FX_CBP_SP) + bNeedBreak = true; + + eType = nNext == FX_CBP_SP ? FX_LBT_PROHIBITED_BRK + : gs_FX_LineBreak_PairTable[nCur][nNext]; + } + if (bAllChars) + pCur->m_nBreakType = eType; + + if (!bOnlyBrk) { + iCharWidth = pCur->m_iCharWidth; + if (iEndPos <= m_iLineWidth || 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_BreakLine* pCurLine, + CFX_BreakLine* pNextLine, + bool bAllChars) { + ASSERT(pCurLine && pNextLine); + int32_t iCount = pCurLine->CountChars(); + if (iCount < 2) + return; + + int32_t iEndPos = pCurLine->GetLineEnd(); + std::vector& curChars = pCurLine->m_LineChars; + int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false); + if (iCharPos < 0) + iCharPos = 0; + + ++iCharPos; + if (iCharPos >= iCount) { + pNextLine->Clear(); + curChars[iCharPos - 1].m_nBreakType = FX_LBT_UNKNOWN; + return; + } + + pNextLine->m_LineChars = + std::vector(curChars.begin() + iCharPos, curChars.end()); + curChars.erase(curChars.begin() + iCharPos, curChars.end()); + pNextLine->m_iStart = pCurLine->m_iStart; + pNextLine->m_iWidth = pCurLine->GetLineEnd() - iEndPos; + pCurLine->m_iWidth = iEndPos; + curChars[iCharPos - 1].m_nBreakType = FX_LBT_UNKNOWN; + + for (size_t i = 0; i < pNextLine->m_LineChars.size(); ++i) { + if (pNextLine->m_LineChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) { + pCurLine->m_iArabicChars--; + pNextLine->m_iArabicChars++; + } + pNextLine->m_LineChars[i].m_dwStatus = CFX_BreakType::None; + } +} + +int32_t CFX_RTFBreak::GetDisplayPos(const FX_RTFTEXTOBJ* pText, + FXTEXT_CHARPOS* pCharPos, + bool bCharCode) const { + if (!pText || pText->iLength < 1) + return 0; + + ASSERT(pText->pFont && pText->pRect); + + CFX_RetainPtr pFont = pText->pFont; + CFX_RectF rtText(*pText->pRect); + bool bRTLPiece = FX_IsOdd(pText->iBidiLevel); + 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; + float fFontHeight = fFontSize; + float fAscent = fFontHeight * static_cast(iAscent) / + static_cast(iMaxHeight); + wchar_t wPrev = 0xFEFF; + wchar_t wNext; + float fX = rtText.left; + int32_t iHorScale = pText->iHorizontalScale; + int32_t iVerScale = pText->iVerticalScale; + if (bRTLPiece) + fX = rtText.right(); + + float fY = rtText.top + fAscent; + int32_t iCount = 0; + for (int32_t i = 0; i < pText->iLength; ++i) { + wchar_t wch = pText->pStr[i]; + int32_t iWidth = pText->pWidths[i]; + uint32_t dwProps = FX_GetUnicodeProperties(wch); + uint32_t dwCharType = (dwProps & FX_CHARTYPEBITSMASK); + if (iWidth == 0) { + if (dwCharType == FX_CHARTYPE_ArabicAlef) + wPrev = 0xFEFF; + continue; + } + + int32_t iCharWidth = abs(iWidth); + bool bEmptyChar = + (dwCharType >= FX_CHARTYPE_Tab && dwCharType <= FX_CHARTYPE_Control); + if (!bEmptyChar) + ++iCount; + + if (pCharPos) { + iCharWidth /= iFontSize; + wchar_t wForm = wch; + if (dwCharType >= FX_CHARTYPE_ArabicAlef) { + if (i + 1 < pText->iLength) { + wNext = pText->pStr[i + 1]; + if (pText->pWidths[i + 1] < 0 && i + 2 < pText->iLength) + wNext = pText->pStr[i + 2]; + } else { + wNext = 0xFEFF; + } + wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext); + } else if (bRTLPiece) { + wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, false); + } + dwProps = FX_GetUnicodeProperties(wForm); + + if (!bEmptyChar) { + if (bCharCode) { + pCharPos->m_GlyphIndex = wch; + } else { + pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wForm, false); + if (pCharPos->m_GlyphIndex == 0xFFFF) + pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wch, false); + } +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + pCharPos->m_ExtGID = pCharPos->m_GlyphIndex; +#endif + pCharPos->m_FontCharWidth = iCharWidth; + } + + float fCharWidth = fFontSize * iCharWidth / 1000.0f; + if (bRTLPiece && dwCharType != FX_CHARTYPE_Combination) + fX -= fCharWidth; + + if (!bEmptyChar) + pCharPos->m_Origin = CFX_PointF(fX, fY); + if (!bRTLPiece && dwCharType != FX_CHARTYPE_Combination) + fX += fCharWidth; + + if (!bEmptyChar) { + pCharPos->m_bGlyphAdjust = true; + pCharPos->m_AdjustMatrix[0] = -1; + pCharPos->m_AdjustMatrix[1] = 0; + pCharPos->m_AdjustMatrix[2] = 0; + pCharPos->m_AdjustMatrix[3] = 1; + pCharPos->m_Origin.y += fAscent * iVerScale / 100.0f; + pCharPos->m_Origin.y -= 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 = wch; + } + return iCount; +} + +FX_RTFTEXTOBJ::FX_RTFTEXTOBJ() + : pFont(nullptr), + pRect(nullptr), + wLineBreakChar(L'\n'), + fFontSize(12.0f), + iLength(0), + iBidiLevel(0), + iHorizontalScale(100), + iVerticalScale(100) {} + +FX_RTFTEXTOBJ::~FX_RTFTEXTOBJ() {} diff --git a/xfa/fgas/layout/cfx_rtfbreak.h b/xfa/fgas/layout/cfx_rtfbreak.h new file mode 100644 index 0000000000..28adaa5d41 --- /dev/null +++ b/xfa/fgas/layout/cfx_rtfbreak.h @@ -0,0 +1,98 @@ +// 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_FGAS_LAYOUT_CFX_RTFBREAK_H_ +#define XFA_FGAS_LAYOUT_CFX_RTFBREAK_H_ + +#include +#include + +#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/fx_basic.h" +#include "core/fxcrt/fx_coordinates.h" +#include "core/fxcrt/fx_ucd.h" +#include "core/fxge/cfx_renderdevice.h" +#include "xfa/fgas/layout/cfx_break.h" + +class CFGAS_GEFont; + +enum class CFX_RTFLineAlignment { + Left = 0, + Center, + Right, + Justified, + Distributed +}; + +struct FX_RTFTEXTOBJ { + FX_RTFTEXTOBJ(); + ~FX_RTFTEXTOBJ(); + + CFX_WideString pStr; + std::vector pWidths; + CFX_RetainPtr pFont; + const CFX_RectF* pRect; + wchar_t wLineBreakChar; + float fFontSize; + int32_t iLength; + int32_t iBidiLevel; + int32_t iHorizontalScale; + int32_t iVerticalScale; +}; + +class CFX_RTFBreak : public CFX_Break { + public: + explicit CFX_RTFBreak(uint32_t dwLayoutStyles); + ~CFX_RTFBreak() override; + + void SetLineStartPos(float fLinePos); + + void SetAlignment(CFX_RTFLineAlignment align) { m_iAlignment = align; } + void SetUserData(const CFX_RetainPtr& pUserData); + + void AddPositionedTab(float fTabPos); + + CFX_BreakType EndBreak(CFX_BreakType dwStatus); + + int32_t GetDisplayPos(const FX_RTFTEXTOBJ* pText, + FXTEXT_CHARPOS* pCharPos, + bool bCharCode) const; + + CFX_BreakType AppendChar(wchar_t wch); + + CFX_BreakLine* GetCurrentLineForTesting() const { return m_pCurLine; } + + private: + void AppendChar_Combination(CFX_Char* pCurChar); + void AppendChar_Tab(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Control(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Arabic(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Others(CFX_Char* pCurChar); + int32_t GetLastPositionedTab() const; + bool GetPositionedTab(int32_t* iTabPos) const; + + int32_t GetBreakPos(std::vector& tca, + int32_t& iEndPos, + bool bAllChars, + bool bOnlyBrk); + void SplitTextLine(CFX_BreakLine* pCurLine, + CFX_BreakLine* pNextLine, + bool bAllChars); + bool EndBreak_SplitLine(CFX_BreakLine* pNextLine, + bool bAllChars, + CFX_BreakType dwStatus); + void EndBreak_BidiLine(std::deque* tpos, CFX_BreakType dwStatus); + void EndBreak_Alignment(const std::deque& tpos, + bool bAllChars, + CFX_BreakType dwStatus); + + bool m_bPagination; + std::vector m_PositionedTabs; + CFX_RTFLineAlignment m_iAlignment; + CFX_RetainPtr m_pUserData; +}; + +#endif // XFA_FGAS_LAYOUT_CFX_RTFBREAK_H_ diff --git a/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp b/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp new file mode 100644 index 0000000000..c8ffc4eb33 --- /dev/null +++ b/xfa/fgas/layout/cfx_rtfbreak_unittest.cpp @@ -0,0 +1,87 @@ +// Copyright 2017 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/fgas/layout/cfx_rtfbreak.h" + +#include + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fgas/font/cfgas_fontmgr.h" +#include "xfa/fgas/font/cfgas_gefont.h" + +class CFX_RTFBreakTest : public testing::Test { + public: + void SetUp() override { + CFX_GEModule::Get()->GetFontMgr()->SetSystemFontInfo( + IFX_SystemFontInfo::CreateDefault(nullptr)); + +#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ + font_mgr_ = CFGAS_FontMgr::Create(FX_GetDefFontEnumerator()); +#else + font_source_ = pdfium::MakeUnique(); + font_mgr_ = CFGAS_FontMgr::Create(font_source_.get()); +#endif + + font_ = CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0, font_mgr_.get()); + ASSERT(font_.Get() != nullptr); + } + + std::unique_ptr CreateBreak(int32_t args) { + auto b = pdfium::MakeUnique(args); + b->SetFont(font_); + return b; + } + + private: + std::unique_ptr font_mgr_; + CFX_RetainPtr font_; + +#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ + std::unique_ptr font_source_; +#endif +}; + +// As soon as you get one of the control characters the break is complete +// and must be consumed before you get any more characters .... + +TEST_F(CFX_RTFBreakTest, AddChars) { + auto b = CreateBreak(FX_LAYOUTSTYLE_ExpandTab); + + CFX_WideString str(L"Input String."); + for (const auto& c : str) + EXPECT_EQ(CFX_BreakType::None, b->AppendChar(c)); + + EXPECT_EQ(CFX_BreakType::Paragraph, b->AppendChar(L'\n')); + ASSERT_EQ(1, b->CountBreakPieces()); + EXPECT_EQ(str + L"\n", b->GetBreakPieceUnstable(0)->GetString()); + + b->ClearBreakPieces(); + b->Reset(); + EXPECT_EQ(0, b->GetCurrentLineForTesting()->GetLineEnd()); + + str = L"Second str."; + for (const auto& c : str) + EXPECT_EQ(CFX_BreakType::None, b->AppendChar(c)); + + // Force the end of the break at the end of the string. + b->EndBreak(CFX_BreakType::Paragraph); + ASSERT_EQ(1, b->CountBreakPieces()); + EXPECT_EQ(str, b->GetBreakPieceUnstable(0)->GetString()); +} + +TEST_F(CFX_RTFBreakTest, ControlCharacters) { + auto b = CreateBreak(FX_LAYOUTSTYLE_ExpandTab); + EXPECT_EQ(CFX_BreakType::Line, b->AppendChar(L'\v')); + EXPECT_EQ(CFX_BreakType::Page, b->AppendChar(L'\f')); + // 0x2029 is the Paragraph Separator unicode character. + EXPECT_EQ(CFX_BreakType::Paragraph, b->AppendChar(0x2029)); + EXPECT_EQ(CFX_BreakType::Paragraph, b->AppendChar(L'\n')); + + ASSERT_EQ(1, b->CountBreakPieces()); + EXPECT_EQ(L"\v", b->GetBreakPieceUnstable(0)->GetString()); +} diff --git a/xfa/fgas/layout/cfx_txtbreak.cpp b/xfa/fgas/layout/cfx_txtbreak.cpp new file mode 100644 index 0000000000..e898a22991 --- /dev/null +++ b/xfa/fgas/layout/cfx_txtbreak.cpp @@ -0,0 +1,1027 @@ +// 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/fgas/layout/cfx_txtbreak.h" + +#include + +#include "core/fxcrt/fx_arabic.h" +#include "core/fxcrt/fx_memory.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fgas/font/cfgas_gefont.h" +#include "xfa/fgas/layout/cfx_linebreak.h" + +namespace { + +bool IsCtrlCode(wchar_t ch) { + uint32_t dwRet = (FX_GetUnicodeProperties(ch) & FX_CHARTYPEBITSMASK); + return dwRet == FX_CHARTYPE_Tab || dwRet == FX_CHARTYPE_Control; +} + +} // namespace + +CFX_TxtBreak::CFX_TxtBreak() + : CFX_Break(FX_LAYOUTSTYLE_None), + m_iAlignment(CFX_TxtLineAlignment_Left), + m_iCombWidth(360000) {} + +CFX_TxtBreak::~CFX_TxtBreak() {} + +void CFX_TxtBreak::SetLineWidth(float fLineWidth) { + m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f); + ASSERT(m_iLineWidth >= 20000); +} + +void CFX_TxtBreak::SetAlignment(int32_t iAlignment) { + ASSERT(iAlignment >= CFX_TxtLineAlignment_Left && + iAlignment <= CFX_TxtLineAlignment_Justified); + m_iAlignment = iAlignment; +} + +void CFX_TxtBreak::SetCombWidth(float fCombWidth) { + m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f); +} + +void CFX_TxtBreak::AppendChar_PageLoad(CFX_Char* pCurChar, uint32_t dwProps) { + pCurChar->m_dwStatus = CFX_BreakType::None; + pCurChar->m_dwCharStyles = m_iAlignment | (1 << 8); +} + +void CFX_TxtBreak::AppendChar_Combination(CFX_Char* pCurChar) { + wchar_t wch = pCurChar->m_wCharCode; + wchar_t wForm; + int32_t iCharWidth = 0; + pCurChar->m_iCharWidth = -1; + if (m_bCombText) { + iCharWidth = m_iCombWidth; + } else { + wForm = wch; + CFX_Char* pLastChar = GetLastChar(0, false, false); + if (pLastChar && + (pLastChar->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicShadda) == 0) { + bool bShadda = false; + if (wch == 0x0651) { + wchar_t 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) { + pLastChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda; + pLastChar->m_iCharWidth = 0; + pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda; + } + } + if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) + iCharWidth = 0; + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + } + pCurChar->m_iCharWidth = -iCharWidth; +} + +void CFX_TxtBreak::AppendChar_Tab(CFX_Char* pCurChar) { + m_eCharType = FX_CHARTYPE_Tab; +} + +CFX_BreakType CFX_TxtBreak::AppendChar_Control(CFX_Char* pCurChar) { + m_eCharType = FX_CHARTYPE_Control; + CFX_BreakType dwRet = CFX_BreakType::None; + if (!m_bSingleLine) { + wchar_t wch = pCurChar->m_wCharCode; + switch (wch) { + case L'\v': + case 0x2028: + dwRet = CFX_BreakType::Line; + break; + case L'\f': + dwRet = CFX_BreakType::Page; + break; + case 0x2029: + dwRet = CFX_BreakType::Paragraph; + break; + default: + if (wch == m_wParagraphBreakChar) + dwRet = CFX_BreakType::Paragraph; + break; + } + if (dwRet != CFX_BreakType::None) + dwRet = EndBreak(dwRet); + } + return dwRet; +} + +CFX_BreakType CFX_TxtBreak::AppendChar_Arabic(CFX_Char* pCurChar) { + FX_CHARTYPE chartype = pCurChar->GetCharType(); + int32_t& iLineWidth = m_pCurLine->m_iWidth; + wchar_t wForm; + int32_t iCharWidth = 0; + CFX_Char* pLastChar = nullptr; + bool bAlef = false; + if (!m_bCombText && m_eCharType >= FX_CHARTYPE_ArabicAlef && + m_eCharType <= FX_CHARTYPE_ArabicDistortion) { + pLastChar = GetLastChar(1, true, false); + if (pLastChar) { + iCharWidth = pLastChar->m_iCharWidth; + if (iCharWidth > 0) + iLineWidth -= iCharWidth; + + CFX_Char* pPrevChar = GetLastChar(2, true, false); + wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar); + bAlef = (wForm == 0xFEFF && + pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef); + m_pFont->GetCharWidth(wForm, iCharWidth, false); + + if (wForm == 0xFEFF) + iCharWidth = m_iDefChar; + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + pLastChar->m_iCharWidth = iCharWidth; + iLineWidth += iCharWidth; + iCharWidth = 0; + } + } + + m_eCharType = chartype; + wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar, + nullptr); + if (m_bCombText) { + iCharWidth = m_iCombWidth; + } else { + m_pFont->GetCharWidth(wForm, iCharWidth, false); + + if (wForm == 0xFEFF) + iCharWidth = m_iDefChar; + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + } + pCurChar->m_iCharWidth = iCharWidth; + iLineWidth += iCharWidth; + m_pCurLine->m_iArabicChars++; + if (!m_bSingleLine && iLineWidth > m_iLineWidth + m_iTolerance) + return EndBreak(CFX_BreakType::Line); + return CFX_BreakType::None; +} + +CFX_BreakType CFX_TxtBreak::AppendChar_Others(CFX_Char* pCurChar) { + FX_CHARTYPE chartype = pCurChar->GetCharType(); + int32_t& iLineWidth = m_pCurLine->m_iWidth; + int32_t iCharWidth = 0; + m_eCharType = chartype; + wchar_t wch = pCurChar->m_wCharCode; + wchar_t wForm = wch; + + if (m_bCombText) { + iCharWidth = m_iCombWidth; + } else { + if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) + iCharWidth = m_iDefChar; + + iCharWidth *= m_iFontSize; + iCharWidth = iCharWidth * m_iHorizontalScale / 100; + } + + iCharWidth += m_iCharSpace; + pCurChar->m_iCharWidth = iCharWidth; + iLineWidth += iCharWidth; + if (!m_bSingleLine && chartype != FX_CHARTYPE_Space && + iLineWidth > m_iLineWidth + m_iTolerance) { + return EndBreak(CFX_BreakType::Line); + } + + return CFX_BreakType::None; +} + +CFX_BreakType CFX_TxtBreak::AppendChar(wchar_t wch) { + uint32_t dwProps = kTextLayoutCodeProperties[static_cast(wch)]; + FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); + m_pCurLine->m_LineChars.emplace_back(); + + CFX_Char* pCurChar = &m_pCurLine->m_LineChars.back(); + pCurChar->m_wCharCode = static_cast(wch); + pCurChar->m_dwCharProps = dwProps; + pCurChar->m_dwCharStyles = 0; + pCurChar->m_iCharWidth = 0; + pCurChar->m_iHorizontalScale = m_iHorizontalScale; + pCurChar->m_iVerticalScale = m_iVerticalScale; + pCurChar->m_dwStatus = CFX_BreakType::None; + pCurChar->m_iBidiClass = 0; + pCurChar->m_iBidiLevel = 0; + pCurChar->m_iBidiPos = 0; + pCurChar->m_iBidiOrder = 0; + + AppendChar_PageLoad(pCurChar, dwProps); + CFX_BreakType dwRet1 = CFX_BreakType::None; + if (chartype != FX_CHARTYPE_Combination && + GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) && + m_eCharType != FX_CHARTYPE_Unknown && + m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine && + (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) { + dwRet1 = EndBreak(CFX_BreakType::Line); + int32_t iCount = m_pCurLine->CountChars(); + if (iCount > 0) + pCurChar = &m_pCurLine->m_LineChars[iCount - 1]; + } + + CFX_BreakType dwRet2 = CFX_BreakType::None; + switch (chartype) { + case FX_CHARTYPE_Tab: + AppendChar_Tab(pCurChar); + break; + case FX_CHARTYPE_Control: + dwRet2 = AppendChar_Control(pCurChar); + break; + case FX_CHARTYPE_Combination: + AppendChar_Combination(pCurChar); + break; + case FX_CHARTYPE_ArabicAlef: + case FX_CHARTYPE_ArabicSpecial: + case FX_CHARTYPE_ArabicDistortion: + case FX_CHARTYPE_ArabicNormal: + case FX_CHARTYPE_ArabicForm: + case FX_CHARTYPE_Arabic: + dwRet2 = AppendChar_Arabic(pCurChar); + break; + case FX_CHARTYPE_Unknown: + case FX_CHARTYPE_Space: + case FX_CHARTYPE_Numeric: + case FX_CHARTYPE_Normal: + default: + dwRet2 = AppendChar_Others(pCurChar); + break; + } + + return std::max(dwRet1, dwRet2); +} + +bool CFX_TxtBreak::EndBreak_SplitLine(CFX_BreakLine* pNextLine, + bool bAllChars) { + int32_t iCount = m_pCurLine->CountChars(); + bool bDone = false; + CFX_Char* pTC; + if (!m_bSingleLine && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance) { + pTC = m_pCurLine->GetChar(iCount - 1); + switch (pTC->GetCharType()) { + case FX_CHARTYPE_Tab: + case FX_CHARTYPE_Control: + case FX_CHARTYPE_Space: + break; + default: + SplitTextLine(m_pCurLine, pNextLine, bAllChars); + bDone = true; + break; + } + } + + iCount = m_pCurLine->CountChars(); + CFX_BreakPiece tp; + if (bAllChars && !bDone) { + int32_t iEndPos = m_pCurLine->m_iWidth; + GetBreakPos(m_pCurLine->m_LineChars, iEndPos, bAllChars, true); + } + return false; +} + +void CFX_TxtBreak::EndBreak_BidiLine(std::deque* tpos, + CFX_BreakType dwStatus) { + CFX_BreakPiece tp; + FX_TPO tpo; + CFX_Char* pTC; + int32_t i; + int32_t j; + std::vector& chars = m_pCurLine->m_LineChars; + int32_t iCount = m_pCurLine->CountChars(); + bool bDone = m_pCurLine->m_iArabicChars > 0; + if (bDone) { + int32_t iBidiNum = 0; + for (i = 0; i < iCount; i++) { + pTC = &chars[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); + } + + if (bDone) { + tp.m_dwStatus = CFX_BreakType::Piece; + tp.m_iStartPos = m_pCurLine->m_iStart; + tp.m_pChars = &m_pCurLine->m_LineChars; + int32_t iBidiLevel = -1; + int32_t iCharWidth; + i = 0; + j = -1; + while (i < iCount) { + pTC = &chars[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_iHorizontalScale = pTC->m_iHorizontalScale; + tp.m_iVerticalScale = pTC->m_iVerticalScale; + tp.m_dwStatus = CFX_BreakType::Piece; + } + if (iBidiLevel != pTC->m_iBidiLevel || + pTC->m_dwStatus != CFX_BreakType::None) { + 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; + m_pCurLine->m_LinePieces.push_back(tp); + tp.m_iStartPos += tp.m_iWidth; + tp.m_iStartChar = i; + tpo.index = ++j; + tpo.pos = tp.m_iBidiPos; + tpos->push_back(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; + m_pCurLine->m_LinePieces.push_back(tp); + tpo.index = ++j; + tpo.pos = tp.m_iBidiPos; + tpos->push_back(tpo); + } + if (j > -1) { + if (j > 0) { + std::sort(tpos->begin(), tpos->end()); + int32_t iStartPos = 0; + for (i = 0; i <= j; i++) { + tpo = (*tpos)[i]; + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index]; + ttp.m_iStartPos = iStartPos; + iStartPos += ttp.m_iWidth; + } + } + m_pCurLine->m_LinePieces[j].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_LineChars; + pTC = &chars[0]; + tp.m_dwCharStyles = pTC->m_dwCharStyles; + tp.m_iHorizontalScale = pTC->m_iHorizontalScale; + tp.m_iVerticalScale = pTC->m_iVerticalScale; + m_pCurLine->m_LinePieces.push_back(tp); + tpos->push_back({0, 0}); + } +} + +void CFX_TxtBreak::EndBreak_Alignment(const std::deque& tpos, + bool bAllChars, + CFX_BreakType dwStatus) { + int32_t iNetWidth = m_pCurLine->m_iWidth; + int32_t iGapChars = 0; + bool bFind = false; + for (auto it = tpos.rbegin(); it != tpos.rend(); ++it) { + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it->index]; + if (!bFind) + iNetWidth = ttp.GetEndPos(); + + bool bArabic = FX_IsOdd(ttp.m_iBidiLevel); + int32_t j = bArabic ? 0 : ttp.m_iChars - 1; + while (j > -1 && j < ttp.m_iChars) { + const CFX_Char* pTC = ttp.GetChar(j); + if (pTC->m_nBreakType == FX_LBT_DIRECT_BRK) + iGapChars++; + if (!bFind || !bAllChars) { + FX_CHARTYPE chartype = pTC->GetCharType(); + if (chartype == FX_CHARTYPE_Space || chartype == FX_CHARTYPE_Control) { + if (!bFind && bAllChars && pTC->m_iCharWidth > 0) + iNetWidth -= pTC->m_iCharWidth; + } else { + bFind = true; + if (!bAllChars) + break; + } + } + j += bArabic ? 1 : -1; + } + if (!bAllChars && bFind) + break; + } + + int32_t iOffset = m_iLineWidth - iNetWidth; + if (iGapChars > 0 && m_iAlignment & CFX_TxtLineAlignment_Justified && + dwStatus != CFX_BreakType::Paragraph) { + int32_t iStart = -1; + for (auto& tpo : tpos) { + CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index]; + if (iStart < -1) + iStart = ttp.m_iStartPos; + else + ttp.m_iStartPos = iStart; + + for (int32_t j = 0; j < ttp.m_iChars; j++) { + CFX_Char* pTC = ttp.GetChar(j); + if (pTC->m_nBreakType != FX_LBT_DIRECT_BRK || pTC->m_iCharWidth < 0) + continue; + + int32_t k = iOffset / iGapChars; + pTC->m_iCharWidth += k; + ttp.m_iWidth += k; + iOffset -= k; + iGapChars--; + if (iGapChars < 1) + break; + } + iStart += ttp.m_iWidth; + } + } else if (m_iAlignment & CFX_TxtLineAlignment_Center || + m_iAlignment & CFX_TxtLineAlignment_Right) { + if (m_iAlignment & CFX_TxtLineAlignment_Center && + !(m_iAlignment & CFX_TxtLineAlignment_Right)) { + iOffset /= 2; + } + if (iOffset > 0) { + for (auto& ttp : m_pCurLine->m_LinePieces) + ttp.m_iStartPos += iOffset; + } + } +} + +CFX_BreakType CFX_TxtBreak::EndBreak(CFX_BreakType dwStatus) { + ASSERT(dwStatus != CFX_BreakType::None); + + if (!m_pCurLine->m_LinePieces.empty()) { + if (dwStatus != CFX_BreakType::Piece) + m_pCurLine->m_LinePieces.back().m_dwStatus = dwStatus; + return m_pCurLine->m_LinePieces.back().m_dwStatus; + } + + if (HasLine()) { + if (!m_Line[m_iReadyLineIndex].m_LinePieces.empty()) { + if (dwStatus != CFX_BreakType::Piece) + m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus = dwStatus; + return m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus; + } + return CFX_BreakType::None; + } + + int32_t iCount = m_pCurLine->CountChars(); + if (iCount < 1) + return CFX_BreakType::None; + + m_pCurLine->GetChar(iCount - 1)->m_dwStatus = dwStatus; + if (dwStatus == CFX_BreakType::Piece) + return dwStatus; + + m_iReadyLineIndex = m_pCurLine == &m_Line[0] ? 0 : 1; + CFX_BreakLine* pNextLine = &m_Line[1 - m_iReadyLineIndex]; + bool bAllChars = m_iAlignment > CFX_TxtLineAlignment_Right; + if (!EndBreak_SplitLine(pNextLine, bAllChars)) { + std::deque tpos; + EndBreak_BidiLine(&tpos, dwStatus); + if (m_iAlignment > CFX_TxtLineAlignment_Left) + EndBreak_Alignment(tpos, bAllChars, dwStatus); + } + + m_pCurLine = pNextLine; + CFX_Char* pTC = GetLastChar(0, false, false); + m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown; + + return dwStatus; +} + +int32_t CFX_TxtBreak::GetBreakPos(std::vector& ca, + int32_t& iEndPos, + bool bAllChars, + bool bOnlyBrk) { + int32_t iLength = pdfium::CollectionSize(ca) - 1; + if (iLength < 1) + return iLength; + + int32_t iBreak = -1; + int32_t iBreakPos = -1; + int32_t iIndirect = -1; + int32_t iIndirectPos = -1; + int32_t iLast = -1; + int32_t iLastPos = -1; + if (m_bSingleLine || iEndPos <= m_iLineWidth) { + if (!bAllChars) + return iLength; + + iBreak = iLength; + iBreakPos = iEndPos; + } + + FX_LINEBREAKTYPE eType; + uint32_t nCodeProp; + uint32_t nCur; + uint32_t nNext; + CFX_Char* pCur = &ca[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[iLength]; + nCodeProp = pCur->m_dwCharProps; + nCur = nCodeProp & 0x003F; + if (nCur == FX_CBP_SP) { + if (nNext == FX_CBP_SP) + eType = FX_LBT_PROHIBITED_BRK; + else + eType = gs_FX_LineBreak_PairTable[nCur][nNext]; + } else { + if (nNext == FX_CBP_SP) + eType = FX_LBT_PROHIBITED_BRK; + else + eType = gs_FX_LineBreak_PairTable[nCur][nNext]; + } + if (bAllChars) + pCur->m_nBreakType = static_cast(eType); + if (!bOnlyBrk) { + if (m_bSingleLine || iEndPos <= m_iLineWidth || nCur == FX_CBP_SP) { + 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_BreakLine* pCurLine, + CFX_BreakLine* pNextLine, + bool bAllChars) { + ASSERT(pCurLine && pNextLine); + int32_t iCount = pCurLine->CountChars(); + if (iCount < 2) + return; + + int32_t iEndPos = pCurLine->m_iWidth; + std::vector& curChars = pCurLine->m_LineChars; + int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false); + if (iCharPos < 0) + iCharPos = 0; + + iCharPos++; + if (iCharPos >= iCount) { + pNextLine->Clear(); + CFX_Char* pTC = &curChars[iCharPos - 1]; + pTC->m_nBreakType = FX_LBT_UNKNOWN; + return; + } + + pNextLine->m_LineChars = + std::vector(curChars.begin() + iCharPos, curChars.end()); + curChars.erase(curChars.begin() + iCharPos, curChars.end()); + pCurLine->m_iWidth = iEndPos; + CFX_Char* pTC = &curChars[iCharPos - 1]; + pTC->m_nBreakType = FX_LBT_UNKNOWN; + iCount = pdfium::CollectionSize(pNextLine->m_LineChars); + int32_t iWidth = 0; + for (int32_t i = 0; i < iCount; i++) { + if (pNextLine->m_LineChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) { + pCurLine->m_iArabicChars--; + pNextLine->m_iArabicChars++; + } + iWidth += std::max(0, pNextLine->m_LineChars[i].m_iCharWidth); + pNextLine->m_LineChars[i].m_dwStatus = CFX_BreakType::None; + } + pNextLine->m_iWidth = iWidth; +} + +struct FX_FORMCHAR { + uint16_t wch; + uint16_t wForm; + int32_t iWidth; +}; + +int32_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun, + FXTEXT_CHARPOS* pCharPos, + bool bCharCode, + CFX_WideString* pWSForms) const { + if (!pTxtRun || pTxtRun->iLength < 1) + return 0; + + CFDE_TxtEdtPage* pAccess = pTxtRun->pAccess; + const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity; + const wchar_t* pStr = pTxtRun->wsStr.c_str(); + int32_t* pWidths = pTxtRun->pWidths; + int32_t iLength = pTxtRun->iLength - 1; + CFX_RetainPtr pFont = pTxtRun->pFont; + uint32_t dwStyles = pTxtRun->dwStyles; + CFX_RectF rtText(*pTxtRun->pRect); + bool bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0; + 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; + float fFontHeight = fFontSize; + float fAscent = fFontHeight * (float)iAscent / (float)iMaxHeight; + float fX = rtText.left; + float fY; + float fCharWidth; + float fCharHeight; + int32_t iHorScale = pTxtRun->iHorizontalScale; + int32_t iVerScale = pTxtRun->iVerticalScale; + bool bSkipSpace = pTxtRun->bSkipSpace; + FX_FORMCHAR formChars[3]; + float fYBase; + + if (bRTLPiece) + fX = rtText.right(); + + fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f; + fY = fYBase + fAscent; + + int32_t iCount = 0; + int32_t iNext = 0; + wchar_t wPrev = 0xFEFF; + wchar_t wNext = 0xFEFF; + wchar_t wForm = 0xFEFF; + wchar_t wLast = 0xFEFF; + bool bShadda = false; + bool bLam = false; + for (int32_t i = 0; i <= iLength; i++) { + int32_t iWidth; + wchar_t wch; + if (pAccess) { + wch = pAccess->GetChar(pIdentity, i); + iWidth = pAccess->GetWidth(pIdentity, i); + } else { + wch = *pStr++; + iWidth = *pWidths++; + } + + uint32_t dwProps = FX_GetUnicodeProperties(wch); + FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); + if (chartype == FX_CHARTYPE_ArabicAlef && iWidth == 0) { + wPrev = 0xFEFF; + wLast = wch; + continue; + } + + if (chartype >= FX_CHARTYPE_ArabicAlef) { + if (i < iLength) { + if (pAccess) { + 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 = pdfium::arabic::GetFormChar(wch, wPrev, wNext); + bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647); + } else if (chartype == FX_CHARTYPE_Combination) { + wForm = wch; + if (wch >= 0x064C && wch <= 0x0651) { + if (bShadda) { + wForm = 0xFEFF; + bShadda = false; + } else { + wNext = 0xFEFF; + if (pAccess) { + 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 (chartype == FX_CHARTYPE_Numeric) { + wForm = wch; + } else if (wch == L'.') { + wForm = wch; + } else if (wch == L',') { + wForm = wch; + } else if (bRTLPiece) { + wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, false); + } else { + wForm = wch; + } + if (chartype != FX_CHARTYPE_Combination) + bShadda = false; + if (chartype < FX_CHARTYPE_ArabicAlef) + bLam = false; + + dwProps = FX_GetUnicodeProperties(wForm); + bool bEmptyChar = + (chartype >= FX_CHARTYPE_Tab && chartype <= FX_CHARTYPE_Control); + if (wForm == 0xFEFF) + bEmptyChar = true; + + int32_t iForms = bLam ? 3 : 1; + iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms; + if (!pCharPos) { + if (iWidth > 0) + wPrev = wch; + wLast = wch; + continue; + } + + int32_t 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 = (wchar_t)formChars[j].wForm; + iCharWidth = formChars[j].iWidth; + if (j > 0) { + chartype = FX_CHARTYPE_Combination; + wch = wForm; + wLast = (wchar_t)formChars[j - 1].wForm; + } + if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) { + pCharPos->m_GlyphIndex = + bCharCode ? wch : pFont->GetGlyphIndex(wForm, false); +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + pCharPos->m_ExtGID = pCharPos->m_GlyphIndex; +#endif + pCharPos->m_FontCharWidth = iCharWidth; + if (pWSForms) + *pWSForms += wForm; + } + + int32_t iCharHeight = 1000; + + fCharWidth = fFontSize * iCharWidth / 1000.0f; + fCharHeight = fFontSize * iCharHeight / 1000.0f; + if (bRTLPiece && chartype != FX_CHARTYPE_Combination) + fX -= fCharWidth; + + if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) { + pCharPos->m_Origin = CFX_PointF(fX, fY); + if ((dwStyles & FX_LAYOUTSTYLE_CombText) != 0) { + int32_t iFormWidth = iCharWidth; + pFont->GetCharWidth(wForm, iFormWidth, false); + float fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f; + pCharPos->m_Origin.x += fOffset; + } + + if (chartype == FX_CHARTYPE_Combination) { + CFX_Rect rtBBox; + if (pFont->GetCharBBox(wForm, &rtBBox, false)) { + pCharPos->m_Origin.y = + fYBase + fFontSize - + fFontSize * (float)rtBBox.height / (float)iMaxHeight; + } + if (wForm == wch && wLast != 0xFEFF) { + uint32_t dwLastProps = FX_GetUnicodeProperties(wLast); + if ((dwLastProps & FX_CHARTYPEBITSMASK) == + FX_CHARTYPE_Combination) { + CFX_Rect rtBox; + if (pFont->GetCharBBox(wLast, &rtBox, false)) + pCharPos->m_Origin.y -= fFontSize * rtBox.height / iMaxHeight; + } + } + } + CFX_PointF ptOffset; + pCharPos->m_Origin.x += ptOffset.x; + pCharPos->m_Origin.y -= ptOffset.y; + } + if (!bRTLPiece && chartype != FX_CHARTYPE_Combination) + fX += fCharWidth; + + if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) { + pCharPos->m_bGlyphAdjust = true; + pCharPos->m_AdjustMatrix[0] = -1; + pCharPos->m_AdjustMatrix[1] = 0; + pCharPos->m_AdjustMatrix[2] = 0; + pCharPos->m_AdjustMatrix[3] = 1; + + 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 = static_cast(formChars[0].wch); + wLast = wch; + } + return iCount; +} + +std::vector CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun, + bool bCharBBox) const { + if (!pTxtRun || pTxtRun->iLength < 1) + return std::vector(); + + CFDE_TxtEdtPage* pAccess = pTxtRun->pAccess; + const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity; + const wchar_t* pStr = pTxtRun->wsStr.c_str(); + int32_t* pWidths = pTxtRun->pWidths; + int32_t iLength = pTxtRun->iLength; + CFX_RectF rect(*pTxtRun->pRect); + float fFontSize = pTxtRun->fFontSize; + int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); + float fScale = fFontSize / 1000.0f; + CFX_RetainPtr pFont = pTxtRun->pFont; + if (!pFont) + bCharBBox = false; + + CFX_Rect bbox; + if (bCharBBox) + bCharBBox = pFont->GetBBox(&bbox); + + float fLeft = std::max(0.0f, bbox.left * fScale); + float fHeight = fabs(bbox.height * fScale); + bool bRTLPiece = !!(pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel); + bool bSingleLine = !!(pTxtRun->dwStyles & FX_LAYOUTSTYLE_SingleLine); + bool bCombText = !!(pTxtRun->dwStyles & FX_LAYOUTSTYLE_CombText); + wchar_t wch; + wchar_t wLineBreakChar = pTxtRun->wLineBreakChar; + int32_t iCharSize; + float fCharSize; + float fStart = bRTLPiece ? rect.right() : rect.left; + + std::vector rtArray(iLength); + for (int32_t i = 0; i < iLength; i++) { + if (pAccess) { + wch = pAccess->GetChar(pIdentity, i); + iCharSize = pAccess->GetWidth(pIdentity, i); + } else { + wch = *pStr++; + iCharSize = *pWidths++; + } + fCharSize = static_cast(iCharSize) / 20000.0f; + bool bRet = (!bSingleLine && 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; + } + 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, false); + float fRTLeft = 0, fCharWidth = 0; + if (iCharWidth > 0) { + fCharWidth = iCharWidth * fScale; + fRTLeft = fLeft; + if (bCombText) + fRTLeft = (rect.width - fCharWidth) / 2.0f; + } + CFX_RectF rtBBoxF; + 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[i] = rtBBoxF; + continue; + } + rtArray[i] = rect; + } + return rtArray; +} + +FX_TXTRUN::FX_TXTRUN() + : pAccess(nullptr), + pIdentity(nullptr), + pWidths(nullptr), + iLength(0), + pFont(nullptr), + fFontSize(12), + dwStyles(0), + iHorizontalScale(100), + iVerticalScale(100), + dwCharStyles(0), + pRect(nullptr), + wLineBreakChar(L'\n'), + bSkipSpace(true) {} + +FX_TXTRUN::~FX_TXTRUN() {} + +FX_TXTRUN::FX_TXTRUN(const FX_TXTRUN& other) = default; diff --git a/xfa/fgas/layout/cfx_txtbreak.h b/xfa/fgas/layout/cfx_txtbreak.h new file mode 100644 index 0000000000..0f11844453 --- /dev/null +++ b/xfa/fgas/layout/cfx_txtbreak.h @@ -0,0 +1,102 @@ +// 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_FGAS_LAYOUT_CFX_TXTBREAK_H_ +#define XFA_FGAS_LAYOUT_CFX_TXTBREAK_H_ + +#include +#include +#include + +#include "core/fxcrt/cfx_char.h" +#include "core/fxge/cfx_renderdevice.h" +#include "third_party/base/stl_util.h" +#include "xfa/fde/cfde_txtedtpage.h" +#include "xfa/fgas/layout/cfx_break.h" + +class CFGAS_GEFont; +struct FDE_TEXTEDITPIECE; + +#define FX_TXTCHARSTYLE_ArabicShadda 0x0020 +#define FX_TXTCHARSTYLE_OddBidiLevel 0x0040 + +enum CFX_TxtLineAlignment { + CFX_TxtLineAlignment_Left = 0, + CFX_TxtLineAlignment_Center = 1 << 0, + CFX_TxtLineAlignment_Right = 1 << 1, + CFX_TxtLineAlignment_Justified = 1 << 2 +}; + +inline bool CFX_BreakTypeNoneOrPiece(CFX_BreakType type) { + return type == CFX_BreakType::None || type == CFX_BreakType::Piece; +} + +struct FX_TXTRUN { + FX_TXTRUN(); + FX_TXTRUN(const FX_TXTRUN& other); + ~FX_TXTRUN(); + + CFDE_TxtEdtPage* pAccess; + const FDE_TEXTEDITPIECE* pIdentity; + CFX_WideString wsStr; + int32_t* pWidths; + int32_t iLength; + CFX_RetainPtr pFont; + float fFontSize; + uint32_t dwStyles; + int32_t iHorizontalScale; + int32_t iVerticalScale; + uint32_t dwCharStyles; + const CFX_RectF* pRect; + wchar_t wLineBreakChar; + bool bSkipSpace; +}; + +class CFX_TxtBreak : public CFX_Break { + public: + CFX_TxtBreak(); + ~CFX_TxtBreak() override; + + void SetLineWidth(float fLineWidth); + void SetAlignment(int32_t iAlignment); + void SetCombWidth(float fCombWidth); + CFX_BreakType EndBreak(CFX_BreakType dwStatus); + + int32_t GetDisplayPos(const FX_TXTRUN* pTxtRun, + FXTEXT_CHARPOS* pCharPos, + bool bCharCode = false, + CFX_WideString* pWSForms = nullptr) const; + std::vector GetCharRects(const FX_TXTRUN* pTxtRun, + bool bCharBBox = false) const; + CFX_BreakType AppendChar(wchar_t wch); + + private: + void AppendChar_Combination(CFX_Char* pCurChar); + void AppendChar_Tab(CFX_Char* pCurChar); + void AppendChar_PageLoad(CFX_Char* pCurChar, uint32_t dwProps); + CFX_BreakType AppendChar_Control(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Arabic(CFX_Char* pCurChar); + CFX_BreakType AppendChar_Others(CFX_Char* pCurChar); + + void ResetContextCharStyles(); + bool EndBreak_SplitLine(CFX_BreakLine* pNextLine, bool bAllChars); + void EndBreak_BidiLine(std::deque* tpos, CFX_BreakType dwStatus); + void EndBreak_Alignment(const std::deque& tpos, + bool bAllChars, + CFX_BreakType dwStatus); + int32_t GetBreakPos(std::vector& ca, + int32_t& iEndPos, + bool bAllChars = false, + bool bOnlyBrk = false); + void SplitTextLine(CFX_BreakLine* pCurLine, + CFX_BreakLine* pNextLine, + bool bAllChars = false); + + int32_t m_iAlignment; + int32_t m_iCombWidth; +}; + +#endif // XFA_FGAS_LAYOUT_CFX_TXTBREAK_H_ diff --git a/xfa/fgas/layout/fgas_linebreak.cpp b/xfa/fgas/layout/fgas_linebreak.cpp deleted file mode 100644 index 2a9e3be522..0000000000 --- a/xfa/fgas/layout/fgas_linebreak.cpp +++ /dev/null @@ -1,268 +0,0 @@ -// 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/fgas/layout/fgas_linebreak.h" - -#include "core/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}, -}; diff --git a/xfa/fgas/layout/fgas_linebreak.h b/xfa/fgas/layout/fgas_linebreak.h deleted file mode 100644 index 918c2e5caf..0000000000 --- a/xfa/fgas/layout/fgas_linebreak.h +++ /dev/null @@ -1,32 +0,0 @@ -// 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_FGAS_LAYOUT_FGAS_LINEBREAK_H_ -#define XFA_FGAS_LAYOUT_FGAS_LINEBREAK_H_ - -#include "core/fxcrt/fx_system.h" - -enum FX_LINEBREAKTYPE : uint8_t { - 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]; - -#endif // XFA_FGAS_LAYOUT_FGAS_LINEBREAK_H_ diff --git a/xfa/fgas/layout/fgas_rtfbreak.cpp b/xfa/fgas/layout/fgas_rtfbreak.cpp deleted file mode 100644 index 842e729217..0000000000 --- a/xfa/fgas/layout/fgas_rtfbreak.cpp +++ /dev/null @@ -1,790 +0,0 @@ -// 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/fgas/layout/fgas_rtfbreak.h" - -#include - -#include "core/fxcrt/fx_arabic.h" -#include "third_party/base/stl_util.h" -#include "xfa/fgas/font/cfgas_gefont.h" -#include "xfa/fgas/layout/fgas_linebreak.h" - -CFX_RTFBreak::CFX_RTFBreak(uint32_t dwLayoutStyles) - : CFX_Break(dwLayoutStyles), - m_bPagination(false), - m_iAlignment(CFX_RTFLineAlignment::Left), - m_pUserData(nullptr) { - SetBreakStatus(); - m_bPagination = !!(m_dwLayoutStyles & FX_LAYOUTSTYLE_Pagination); -} - -CFX_RTFBreak::~CFX_RTFBreak() {} - -void CFX_RTFBreak::SetLineStartPos(float fLinePos) { - int32_t iLinePos = FXSYS_round(fLinePos * 20000.0f); - iLinePos = std::min(iLinePos, m_iLineWidth); - iLinePos = std::max(iLinePos, m_iLineStart); - m_pCurLine->m_iStart = iLinePos; -} - -void CFX_RTFBreak::AddPositionedTab(float fTabPos) { - int32_t iTabPos = - std::min(FXSYS_round(fTabPos * 20000.0f) + m_iLineStart, m_iLineWidth); - auto it = std::lower_bound(m_PositionedTabs.begin(), m_PositionedTabs.end(), - iTabPos); - if (it != m_PositionedTabs.end() && *it == iTabPos) - return; - m_PositionedTabs.insert(it, iTabPos); -} - -void CFX_RTFBreak::SetUserData(const CFX_RetainPtr& pUserData) { - if (m_pUserData == pUserData) - return; - - SetBreakStatus(); - m_pUserData = pUserData; -} - -int32_t CFX_RTFBreak::GetLastPositionedTab() const { - return m_PositionedTabs.empty() ? m_iLineStart : m_PositionedTabs.back(); -} - -bool CFX_RTFBreak::GetPositionedTab(int32_t* iTabPos) const { - auto it = std::upper_bound(m_PositionedTabs.begin(), m_PositionedTabs.end(), - *iTabPos); - if (it == m_PositionedTabs.end()) - return false; - - *iTabPos = *it; - return true; -} - -CFX_BreakType CFX_RTFBreak::AppendChar(wchar_t wch) { - ASSERT(m_pFont && m_pCurLine); - - uint32_t dwProps = kTextLayoutCodeProperties[static_cast(wch)]; - FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); - m_pCurLine->m_LineChars.emplace_back(); - - CFX_Char* pCurChar = &m_pCurLine->m_LineChars.back(); - pCurChar->m_dwStatus = CFX_BreakType::None; - pCurChar->m_wCharCode = wch; - pCurChar->m_dwCharProps = dwProps; - pCurChar->m_iFontSize = m_iFontSize; - pCurChar->m_iHorizontalScale = m_iHorizontalScale; - pCurChar->m_iVerticalScale = m_iVerticalScale; - pCurChar->m_iCharWidth = 0; - pCurChar->m_dwIdentity = m_dwIdentity; - pCurChar->m_pUserData = m_pUserData; - - CFX_BreakType dwRet1 = CFX_BreakType::None; - if (chartype != FX_CHARTYPE_Combination && - GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) && - m_eCharType != FX_CHARTYPE_Unknown && - m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance && - (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) { - dwRet1 = EndBreak(CFX_BreakType::Line); - int32_t iCount = m_pCurLine->CountChars(); - if (iCount > 0) - pCurChar = &m_pCurLine->m_LineChars[iCount - 1]; - } - - CFX_BreakType dwRet2 = CFX_BreakType::None; - switch (chartype) { - case FX_CHARTYPE_Tab: - AppendChar_Tab(pCurChar); - break; - case FX_CHARTYPE_Control: - dwRet2 = AppendChar_Control(pCurChar); - break; - case FX_CHARTYPE_Combination: - AppendChar_Combination(pCurChar); - break; - case FX_CHARTYPE_ArabicAlef: - case FX_CHARTYPE_ArabicSpecial: - case FX_CHARTYPE_ArabicDistortion: - case FX_CHARTYPE_ArabicNormal: - case FX_CHARTYPE_ArabicForm: - case FX_CHARTYPE_Arabic: - dwRet2 = AppendChar_Arabic(pCurChar); - break; - case FX_CHARTYPE_Unknown: - case FX_CHARTYPE_Space: - case FX_CHARTYPE_Numeric: - case FX_CHARTYPE_Normal: - default: - dwRet2 = AppendChar_Others(pCurChar); - break; - } - - m_eCharType = chartype; - return std::max(dwRet1, dwRet2); -} - -void CFX_RTFBreak::AppendChar_Combination(CFX_Char* pCurChar) { - int32_t iCharWidth = 0; - if (!m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth, false)) - iCharWidth = 0; - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorizontalScale / 100; - CFX_Char* pLastChar = GetLastChar(0, false, true); - if (pLastChar && pLastChar->GetCharType() > FX_CHARTYPE_Combination) - iCharWidth = -iCharWidth; - else - m_eCharType = FX_CHARTYPE_Combination; - - pCurChar->m_iCharWidth = iCharWidth; - if (iCharWidth > 0) - m_pCurLine->m_iWidth += iCharWidth; -} - -void CFX_RTFBreak::AppendChar_Tab(CFX_Char* pCurChar) { - if (!(m_dwLayoutStyles & FX_LAYOUTSTYLE_ExpandTab)) - return; - - 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; -} - -CFX_BreakType CFX_RTFBreak::AppendChar_Control(CFX_Char* pCurChar) { - CFX_BreakType dwRet2 = CFX_BreakType::None; - switch (pCurChar->m_wCharCode) { - case L'\v': - case 0x2028: - dwRet2 = CFX_BreakType::Line; - break; - case L'\f': - dwRet2 = CFX_BreakType::Page; - break; - case 0x2029: - dwRet2 = CFX_BreakType::Paragraph; - break; - default: - if (pCurChar->m_wCharCode == m_wParagraphBreakChar) - dwRet2 = CFX_BreakType::Paragraph; - break; - } - if (dwRet2 != CFX_BreakType::None) - dwRet2 = EndBreak(dwRet2); - - return dwRet2; -} - -CFX_BreakType CFX_RTFBreak::AppendChar_Arabic(CFX_Char* pCurChar) { - CFX_Char* pLastChar = nullptr; - int32_t iCharWidth = 0; - wchar_t wForm; - bool bAlef = false; - if (m_eCharType >= FX_CHARTYPE_ArabicAlef && - m_eCharType <= FX_CHARTYPE_ArabicDistortion) { - pLastChar = GetLastChar(1, false, true); - if (pLastChar) { - m_pCurLine->m_iWidth -= pLastChar->m_iCharWidth; - CFX_Char* pPrevChar = GetLastChar(2, false, true); - wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar); - bAlef = (wForm == 0xFEFF && - pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef); - if (!m_pFont->GetCharWidth(wForm, iCharWidth, false) && - !m_pFont->GetCharWidth(pLastChar->m_wCharCode, iCharWidth, false)) { - iCharWidth = m_iDefChar; - } - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorizontalScale / 100; - pLastChar->m_iCharWidth = iCharWidth; - m_pCurLine->m_iWidth += iCharWidth; - iCharWidth = 0; - } - } - - wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar, - nullptr); - if (!m_pFont->GetCharWidth(wForm, iCharWidth, false) && - !m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth, false)) { - iCharWidth = m_iDefChar; - } - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorizontalScale / 100; - pCurChar->m_iCharWidth = iCharWidth; - m_pCurLine->m_iWidth += iCharWidth; - m_pCurLine->m_iArabicChars++; - - if (m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance) - return EndBreak(CFX_BreakType::Line); - return CFX_BreakType::None; -} - -CFX_BreakType CFX_RTFBreak::AppendChar_Others(CFX_Char* pCurChar) { - FX_CHARTYPE chartype = pCurChar->GetCharType(); - wchar_t wForm = pCurChar->m_wCharCode; - int32_t iCharWidth = 0; - if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) - iCharWidth = m_iDefChar; - - iCharWidth *= m_iFontSize; - iCharWidth *= m_iHorizontalScale / 100; - iCharWidth += m_iCharSpace; - - pCurChar->m_iCharWidth = iCharWidth; - m_pCurLine->m_iWidth += iCharWidth; - if (chartype != FX_CHARTYPE_Space && - m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance) { - return EndBreak(CFX_BreakType::Line); - } - return CFX_BreakType::None; -} - -CFX_BreakType CFX_RTFBreak::EndBreak(CFX_BreakType dwStatus) { - ASSERT(dwStatus != CFX_BreakType::None); - - ++m_dwIdentity; - if (!m_pCurLine->m_LinePieces.empty()) { - if (dwStatus != CFX_BreakType::Piece) - m_pCurLine->m_LinePieces.back().m_dwStatus = dwStatus; - return m_pCurLine->m_LinePieces.back().m_dwStatus; - } - - if (HasLine()) { - if (!m_Line[m_iReadyLineIndex].m_LinePieces.empty()) { - if (dwStatus != CFX_BreakType::Piece) - m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus = dwStatus; - return m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus; - } - return CFX_BreakType::None; - } - - int32_t iCount = m_pCurLine->CountChars(); - if (iCount < 1) - return CFX_BreakType::None; - - CFX_Char* tc = m_pCurLine->GetChar(iCount - 1); - tc->m_dwStatus = dwStatus; - if (dwStatus == CFX_BreakType::Piece) - return dwStatus; - - m_iReadyLineIndex = m_pCurLine == &m_Line[0] ? 0 : 1; - CFX_BreakLine* pNextLine = &m_Line[1 - m_iReadyLineIndex]; - bool bAllChars = m_iAlignment == CFX_RTFLineAlignment::Justified || - m_iAlignment == CFX_RTFLineAlignment::Distributed; - - if (!EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) { - std::deque tpos; - EndBreak_BidiLine(&tpos, dwStatus); - if (!m_bPagination && m_iAlignment != CFX_RTFLineAlignment::Left) - EndBreak_Alignment(tpos, bAllChars, dwStatus); - } - m_pCurLine = pNextLine; - m_pCurLine->m_iStart = m_iLineStart; - - CFX_Char* pTC = GetLastChar(0, false, true); - m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown; - return dwStatus; -} - -bool CFX_RTFBreak::EndBreak_SplitLine(CFX_BreakLine* pNextLine, - bool bAllChars, - CFX_BreakType dwStatus) { - bool bDone = false; - if (m_pCurLine->GetLineEnd() > m_iLineWidth + m_iTolerance) { - const CFX_Char* tc = m_pCurLine->GetChar(m_pCurLine->CountChars() - 1); - switch (tc->GetCharType()) { - case FX_CHARTYPE_Tab: - case FX_CHARTYPE_Control: - case FX_CHARTYPE_Space: - break; - default: - SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars); - bDone = true; - break; - } - } - - if (!m_bPagination) { - if (bAllChars && !bDone) { - int32_t endPos = m_pCurLine->GetLineEnd(); - GetBreakPos(m_pCurLine->m_LineChars, endPos, bAllChars, true); - } - return false; - } - - const CFX_Char* pCurChars = m_pCurLine->m_LineChars.data(); - CFX_BreakPiece tp; - tp.m_pChars = &m_pCurLine->m_LineChars; - bool bNew = true; - uint32_t dwIdentity = static_cast(-1); - int32_t iLast = m_pCurLine->CountChars() - 1; - int32_t j = 0; - for (int32_t i = 0; i <= iLast;) { - const CFX_Char* 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_iHorizontalScale = pTC->m_iHorizontalScale; - tp.m_iVerticalScale = pTC->m_iVerticalScale; - dwIdentity = pTC->m_dwIdentity; - tp.m_dwIdentity = dwIdentity; - tp.m_pUserData = pTC->m_pUserData; - j = i; - bNew = false; - } - - if (i == iLast || pTC->m_dwStatus != CFX_BreakType::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; - } - m_pCurLine->m_LinePieces.push_back(tp); - bNew = true; - } else { - tp.m_iWidth += pTC->m_iCharWidth; - ++i; - } - } - return true; -} - -void CFX_RTFBreak::EndBreak_BidiLine(std::deque* tpos, - CFX_BreakType dwStatus) { - CFX_Char* pTC; - std::vector& chars = m_pCurLine->m_LineChars; - int32_t iCount = m_pCurLine->CountChars(); - if (!m_bPagination && m_pCurLine->m_iArabicChars > 0) { - int32_t iBidiNum = 0; - for (int32_t i = 0; i < iCount; ++i) { - pTC = &chars[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); - } else { - for (int32_t i = 0; i < iCount; ++i) { - pTC = &chars[i]; - pTC->m_iBidiLevel = 0; - pTC->m_iBidiPos = 0; - pTC->m_iBidiOrder = 0; - } - } - - CFX_BreakPiece tp; - tp.m_dwStatus = CFX_BreakType::Piece; - tp.m_iStartPos = m_pCurLine->m_iStart; - tp.m_pChars = &chars; - - int32_t iBidiLevel = -1; - int32_t iCharWidth; - FX_TPO tpo; - uint32_t dwIdentity = static_cast(-1); - int32_t i = 0; - int32_t j = 0; - while (i < iCount) { - pTC = &chars[i]; - if (iBidiLevel < 0) { - iBidiLevel = pTC->m_iBidiLevel; - iCharWidth = pTC->m_iCharWidth; - tp.m_iWidth = iCharWidth < 1 ? 0 : iCharWidth; - tp.m_iBidiLevel = iBidiLevel; - tp.m_iBidiPos = pTC->m_iBidiOrder; - tp.m_iFontSize = pTC->m_iFontSize; - tp.m_iHorizontalScale = pTC->m_iHorizontalScale; - tp.m_iVerticalScale = pTC->m_iVerticalScale; - dwIdentity = pTC->m_dwIdentity; - tp.m_dwIdentity = dwIdentity; - tp.m_pUserData = pTC->m_pUserData; - tp.m_dwStatus = CFX_BreakType::Piece; - ++i; - } else if (iBidiLevel != pTC->m_iBidiLevel || - pTC->m_dwIdentity != dwIdentity) { - tp.m_iChars = i - tp.m_iStartChar; - m_pCurLine->m_LinePieces.push_back(tp); - - tp.m_iStartPos += tp.m_iWidth; - tp.m_iStartChar = i; - tpo.index = j++; - tpo.pos = tp.m_iBidiPos; - tpos->push_back(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; - m_pCurLine->m_LinePieces.push_back(tp); - - tpo.index = j; - tpo.pos = tp.m_iBidiPos; - tpos->push_back(tpo); - } - - std::sort(tpos->begin(), tpos->end()); - int32_t iStartPos = m_pCurLine->m_iStart; - for (const auto& it : *tpos) { - CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it.index]; - ttp.m_iStartPos = iStartPos; - iStartPos += ttp.m_iWidth; - } -} - -void CFX_RTFBreak::EndBreak_Alignment(const std::deque& tpos, - bool bAllChars, - CFX_BreakType dwStatus) { - int32_t iNetWidth = m_pCurLine->m_iWidth; - int32_t iGapChars = 0; - bool bFind = false; - for (auto it = tpos.rbegin(); it != tpos.rend(); it++) { - CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it->index]; - if (!bFind) - iNetWidth = ttp.GetEndPos(); - - bool bArabic = FX_IsOdd(ttp.m_iBidiLevel); - int32_t j = bArabic ? 0 : ttp.m_iChars - 1; - while (j > -1 && j < ttp.m_iChars) { - const CFX_Char* tc = ttp.GetChar(j); - if (tc->m_nBreakType == FX_LBT_DIRECT_BRK) - ++iGapChars; - - if (!bFind || !bAllChars) { - uint32_t dwCharType = tc->GetCharType(); - if (dwCharType == FX_CHARTYPE_Space || - dwCharType == FX_CHARTYPE_Control) { - if (!bFind) { - int32_t 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_iLineWidth - iNetWidth; - if (iGapChars > 0 && (m_iAlignment == CFX_RTFLineAlignment::Distributed || - (m_iAlignment == CFX_RTFLineAlignment::Justified && - dwStatus != CFX_BreakType::Paragraph))) { - int32_t iStart = -1; - for (const auto& tpo : tpos) { - CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index]; - if (iStart < 0) - iStart = ttp.m_iStartPos; - else - ttp.m_iStartPos = iStart; - - for (int32_t j = 0; j < ttp.m_iChars; ++j) { - CFX_Char* tc = ttp.GetChar(j); - if (tc->m_nBreakType != FX_LBT_DIRECT_BRK || tc->m_iCharWidth < 0) - continue; - - int32_t k = iOffset / iGapChars; - tc->m_iCharWidth += k; - ttp.m_iWidth += k; - iOffset -= k; - --iGapChars; - if (iGapChars < 1) - break; - } - iStart += ttp.m_iWidth; - } - } else if (m_iAlignment == CFX_RTFLineAlignment::Right || - m_iAlignment == CFX_RTFLineAlignment::Center) { - if (m_iAlignment == CFX_RTFLineAlignment::Center) - iOffset /= 2; - if (iOffset > 0) { - for (auto& ttp : m_pCurLine->m_LinePieces) - ttp.m_iStartPos += iOffset; - } - } -} - -int32_t CFX_RTFBreak::GetBreakPos(std::vector& tca, - int32_t& iEndPos, - bool bAllChars, - bool bOnlyBrk) { - int32_t iLength = pdfium::CollectionSize(tca) - 1; - if (iLength < 1) - return iLength; - - int32_t iBreak = -1; - int32_t iBreakPos = -1; - int32_t iIndirect = -1; - int32_t iIndirectPos = -1; - int32_t iLast = -1; - int32_t iLastPos = -1; - if (iEndPos <= m_iLineWidth) { - if (!bAllChars) - return iLength; - - iBreak = iLength; - iBreakPos = iEndPos; - } - - CFX_Char* pCharArray = tca.data(); - CFX_Char* pCur = pCharArray + iLength; - --iLength; - if (bAllChars) - pCur->m_nBreakType = FX_LBT_UNKNOWN; - - uint32_t nCodeProp = pCur->m_dwCharProps; - uint32_t nNext = nCodeProp & 0x003F; - int32_t iCharWidth = pCur->m_iCharWidth; - if (iCharWidth > 0) - iEndPos -= iCharWidth; - - while (iLength >= 0) { - pCur = pCharArray + iLength; - nCodeProp = pCur->m_dwCharProps; - uint32_t nCur = nCodeProp & 0x003F; - bool bNeedBreak = false; - FX_LINEBREAKTYPE eType; - if (nCur == FX_CBP_TB) { - bNeedBreak = true; - eType = nNext == FX_CBP_TB ? FX_LBT_PROHIBITED_BRK - : gs_FX_LineBreak_PairTable[nCur][nNext]; - } else { - if (nCur == FX_CBP_SP) - bNeedBreak = true; - - eType = nNext == FX_CBP_SP ? FX_LBT_PROHIBITED_BRK - : gs_FX_LineBreak_PairTable[nCur][nNext]; - } - if (bAllChars) - pCur->m_nBreakType = eType; - - if (!bOnlyBrk) { - iCharWidth = pCur->m_iCharWidth; - if (iEndPos <= m_iLineWidth || 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_BreakLine* pCurLine, - CFX_BreakLine* pNextLine, - bool bAllChars) { - ASSERT(pCurLine && pNextLine); - int32_t iCount = pCurLine->CountChars(); - if (iCount < 2) - return; - - int32_t iEndPos = pCurLine->GetLineEnd(); - std::vector& curChars = pCurLine->m_LineChars; - int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false); - if (iCharPos < 0) - iCharPos = 0; - - ++iCharPos; - if (iCharPos >= iCount) { - pNextLine->Clear(); - curChars[iCharPos - 1].m_nBreakType = FX_LBT_UNKNOWN; - return; - } - - pNextLine->m_LineChars = - std::vector(curChars.begin() + iCharPos, curChars.end()); - curChars.erase(curChars.begin() + iCharPos, curChars.end()); - pNextLine->m_iStart = pCurLine->m_iStart; - pNextLine->m_iWidth = pCurLine->GetLineEnd() - iEndPos; - pCurLine->m_iWidth = iEndPos; - curChars[iCharPos - 1].m_nBreakType = FX_LBT_UNKNOWN; - - for (size_t i = 0; i < pNextLine->m_LineChars.size(); ++i) { - if (pNextLine->m_LineChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) { - pCurLine->m_iArabicChars--; - pNextLine->m_iArabicChars++; - } - pNextLine->m_LineChars[i].m_dwStatus = CFX_BreakType::None; - } -} - -int32_t CFX_RTFBreak::GetDisplayPos(const FX_RTFTEXTOBJ* pText, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode) const { - if (!pText || pText->iLength < 1) - return 0; - - ASSERT(pText->pFont && pText->pRect); - - CFX_RetainPtr pFont = pText->pFont; - CFX_RectF rtText(*pText->pRect); - bool bRTLPiece = FX_IsOdd(pText->iBidiLevel); - 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; - float fFontHeight = fFontSize; - float fAscent = fFontHeight * static_cast(iAscent) / - static_cast(iMaxHeight); - wchar_t wPrev = 0xFEFF; - wchar_t wNext; - float fX = rtText.left; - int32_t iHorScale = pText->iHorizontalScale; - int32_t iVerScale = pText->iVerticalScale; - if (bRTLPiece) - fX = rtText.right(); - - float fY = rtText.top + fAscent; - int32_t iCount = 0; - for (int32_t i = 0; i < pText->iLength; ++i) { - wchar_t wch = pText->pStr[i]; - int32_t iWidth = pText->pWidths[i]; - uint32_t dwProps = FX_GetUnicodeProperties(wch); - uint32_t dwCharType = (dwProps & FX_CHARTYPEBITSMASK); - if (iWidth == 0) { - if (dwCharType == FX_CHARTYPE_ArabicAlef) - wPrev = 0xFEFF; - continue; - } - - int32_t iCharWidth = abs(iWidth); - bool bEmptyChar = - (dwCharType >= FX_CHARTYPE_Tab && dwCharType <= FX_CHARTYPE_Control); - if (!bEmptyChar) - ++iCount; - - if (pCharPos) { - iCharWidth /= iFontSize; - wchar_t wForm = wch; - if (dwCharType >= FX_CHARTYPE_ArabicAlef) { - if (i + 1 < pText->iLength) { - wNext = pText->pStr[i + 1]; - if (pText->pWidths[i + 1] < 0 && i + 2 < pText->iLength) - wNext = pText->pStr[i + 2]; - } else { - wNext = 0xFEFF; - } - wForm = pdfium::arabic::GetFormChar(wch, wPrev, wNext); - } else if (bRTLPiece) { - wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, false); - } - dwProps = FX_GetUnicodeProperties(wForm); - - if (!bEmptyChar) { - if (bCharCode) { - pCharPos->m_GlyphIndex = wch; - } else { - pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wForm, false); - if (pCharPos->m_GlyphIndex == 0xFFFF) - pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wch, false); - } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - pCharPos->m_ExtGID = pCharPos->m_GlyphIndex; -#endif - pCharPos->m_FontCharWidth = iCharWidth; - } - - float fCharWidth = fFontSize * iCharWidth / 1000.0f; - if (bRTLPiece && dwCharType != FX_CHARTYPE_Combination) - fX -= fCharWidth; - - if (!bEmptyChar) - pCharPos->m_Origin = CFX_PointF(fX, fY); - if (!bRTLPiece && dwCharType != FX_CHARTYPE_Combination) - fX += fCharWidth; - - if (!bEmptyChar) { - pCharPos->m_bGlyphAdjust = true; - pCharPos->m_AdjustMatrix[0] = -1; - pCharPos->m_AdjustMatrix[1] = 0; - pCharPos->m_AdjustMatrix[2] = 0; - pCharPos->m_AdjustMatrix[3] = 1; - pCharPos->m_Origin.y += fAscent * iVerScale / 100.0f; - pCharPos->m_Origin.y -= 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 = wch; - } - return iCount; -} - -FX_RTFTEXTOBJ::FX_RTFTEXTOBJ() - : pFont(nullptr), - pRect(nullptr), - wLineBreakChar(L'\n'), - fFontSize(12.0f), - iLength(0), - iBidiLevel(0), - iHorizontalScale(100), - iVerticalScale(100) {} - -FX_RTFTEXTOBJ::~FX_RTFTEXTOBJ() {} diff --git a/xfa/fgas/layout/fgas_rtfbreak.h b/xfa/fgas/layout/fgas_rtfbreak.h deleted file mode 100644 index 7cbd250218..0000000000 --- a/xfa/fgas/layout/fgas_rtfbreak.h +++ /dev/null @@ -1,98 +0,0 @@ -// 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_FGAS_LAYOUT_FGAS_RTFBREAK_H_ -#define XFA_FGAS_LAYOUT_FGAS_RTFBREAK_H_ - -#include -#include - -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/fx_basic.h" -#include "core/fxcrt/fx_coordinates.h" -#include "core/fxcrt/fx_ucd.h" -#include "core/fxge/cfx_renderdevice.h" -#include "xfa/fgas/layout/cfx_break.h" - -class CFGAS_GEFont; - -enum class CFX_RTFLineAlignment { - Left = 0, - Center, - Right, - Justified, - Distributed -}; - -struct FX_RTFTEXTOBJ { - FX_RTFTEXTOBJ(); - ~FX_RTFTEXTOBJ(); - - CFX_WideString pStr; - std::vector pWidths; - CFX_RetainPtr pFont; - const CFX_RectF* pRect; - wchar_t wLineBreakChar; - float fFontSize; - int32_t iLength; - int32_t iBidiLevel; - int32_t iHorizontalScale; - int32_t iVerticalScale; -}; - -class CFX_RTFBreak : public CFX_Break { - public: - explicit CFX_RTFBreak(uint32_t dwLayoutStyles); - ~CFX_RTFBreak() override; - - void SetLineStartPos(float fLinePos); - - void SetAlignment(CFX_RTFLineAlignment align) { m_iAlignment = align; } - void SetUserData(const CFX_RetainPtr& pUserData); - - void AddPositionedTab(float fTabPos); - - CFX_BreakType EndBreak(CFX_BreakType dwStatus); - - int32_t GetDisplayPos(const FX_RTFTEXTOBJ* pText, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode) const; - - CFX_BreakType AppendChar(wchar_t wch); - - CFX_BreakLine* GetCurrentLineForTesting() const { return m_pCurLine; } - - private: - void AppendChar_Combination(CFX_Char* pCurChar); - void AppendChar_Tab(CFX_Char* pCurChar); - CFX_BreakType AppendChar_Control(CFX_Char* pCurChar); - CFX_BreakType AppendChar_Arabic(CFX_Char* pCurChar); - CFX_BreakType AppendChar_Others(CFX_Char* pCurChar); - int32_t GetLastPositionedTab() const; - bool GetPositionedTab(int32_t* iTabPos) const; - - int32_t GetBreakPos(std::vector& tca, - int32_t& iEndPos, - bool bAllChars, - bool bOnlyBrk); - void SplitTextLine(CFX_BreakLine* pCurLine, - CFX_BreakLine* pNextLine, - bool bAllChars); - bool EndBreak_SplitLine(CFX_BreakLine* pNextLine, - bool bAllChars, - CFX_BreakType dwStatus); - void EndBreak_BidiLine(std::deque* tpos, CFX_BreakType dwStatus); - void EndBreak_Alignment(const std::deque& tpos, - bool bAllChars, - CFX_BreakType dwStatus); - - bool m_bPagination; - std::vector m_PositionedTabs; - CFX_RTFLineAlignment m_iAlignment; - CFX_RetainPtr m_pUserData; -}; - -#endif // XFA_FGAS_LAYOUT_FGAS_RTFBREAK_H_ diff --git a/xfa/fgas/layout/fgas_rtfbreak_unittest.cpp b/xfa/fgas/layout/fgas_rtfbreak_unittest.cpp deleted file mode 100644 index cc3c86cadb..0000000000 --- a/xfa/fgas/layout/fgas_rtfbreak_unittest.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2017 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/fgas/layout/fgas_rtfbreak.h" - -#include - -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/test_support.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fgas/font/cfgas_fontmgr.h" -#include "xfa/fgas/font/cfgas_gefont.h" - -class RTFBreakTest : public testing::Test { - public: - void SetUp() override { - CFX_GEModule::Get()->GetFontMgr()->SetSystemFontInfo( - IFX_SystemFontInfo::CreateDefault(nullptr)); - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - font_mgr_ = CFGAS_FontMgr::Create(FX_GetDefFontEnumerator()); -#else - font_source_ = pdfium::MakeUnique(); - font_mgr_ = CFGAS_FontMgr::Create(font_source_.get()); -#endif - - font_ = CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0, font_mgr_.get()); - ASSERT(font_.Get() != nullptr); - } - - std::unique_ptr CreateBreak(int32_t args) { - auto b = pdfium::MakeUnique(args); - b->SetFont(font_); - return b; - } - - private: - std::unique_ptr font_mgr_; - CFX_RetainPtr font_; - -#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ - std::unique_ptr font_source_; -#endif -}; - -// As soon as you get one of the control characters the break is complete -// and must be consumed before you get any more characters .... - -TEST_F(RTFBreakTest, AddChars) { - auto b = CreateBreak(FX_LAYOUTSTYLE_ExpandTab); - - CFX_WideString str(L"Input String."); - for (const auto& c : str) - EXPECT_EQ(CFX_BreakType::None, b->AppendChar(c)); - - EXPECT_EQ(CFX_BreakType::Paragraph, b->AppendChar(L'\n')); - ASSERT_EQ(1, b->CountBreakPieces()); - EXPECT_EQ(str + L"\n", b->GetBreakPieceUnstable(0)->GetString()); - - b->ClearBreakPieces(); - b->Reset(); - EXPECT_EQ(0, b->GetCurrentLineForTesting()->GetLineEnd()); - - str = L"Second str."; - for (const auto& c : str) - EXPECT_EQ(CFX_BreakType::None, b->AppendChar(c)); - - // Force the end of the break at the end of the string. - b->EndBreak(CFX_BreakType::Paragraph); - ASSERT_EQ(1, b->CountBreakPieces()); - EXPECT_EQ(str, b->GetBreakPieceUnstable(0)->GetString()); -} - -TEST_F(RTFBreakTest, ControlCharacters) { - auto b = CreateBreak(FX_LAYOUTSTYLE_ExpandTab); - EXPECT_EQ(CFX_BreakType::Line, b->AppendChar(L'\v')); - EXPECT_EQ(CFX_BreakType::Page, b->AppendChar(L'\f')); - // 0x2029 is the Paragraph Separator unicode character. - EXPECT_EQ(CFX_BreakType::Paragraph, b->AppendChar(0x2029)); - EXPECT_EQ(CFX_BreakType::Paragraph, b->AppendChar(L'\n')); - - ASSERT_EQ(1, b->CountBreakPieces()); - EXPECT_EQ(L"\v", b->GetBreakPieceUnstable(0)->GetString()); -} diff --git a/xfa/fgas/layout/fgas_textbreak.cpp b/xfa/fgas/layout/fgas_textbreak.cpp deleted file mode 100644 index 83a03eed5e..0000000000 --- a/xfa/fgas/layout/fgas_textbreak.cpp +++ /dev/null @@ -1,1028 +0,0 @@ -// 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/fgas/layout/fgas_textbreak.h" - -#include - -#include "core/fxcrt/fx_arabic.h" -#include "core/fxcrt/fx_memory.h" -#include "third_party/base/ptr_util.h" -#include "xfa/fgas/font/cfgas_gefont.h" -#include "xfa/fgas/layout/fgas_linebreak.h" - -namespace { - -bool IsCtrlCode(wchar_t ch) { - uint32_t dwRet = (FX_GetUnicodeProperties(ch) & FX_CHARTYPEBITSMASK); - return dwRet == FX_CHARTYPE_Tab || dwRet == FX_CHARTYPE_Control; -} - -} // namespace - -CFX_TxtBreak::CFX_TxtBreak() - : CFX_Break(FX_LAYOUTSTYLE_None), - m_iAlignment(CFX_TxtLineAlignment_Left), - m_iCombWidth(360000) {} - -CFX_TxtBreak::~CFX_TxtBreak() {} - -void CFX_TxtBreak::SetLineWidth(float fLineWidth) { - m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f); - ASSERT(m_iLineWidth >= 20000); -} - - -void CFX_TxtBreak::SetAlignment(int32_t iAlignment) { - ASSERT(iAlignment >= CFX_TxtLineAlignment_Left && - iAlignment <= CFX_TxtLineAlignment_Justified); - m_iAlignment = iAlignment; -} - -void CFX_TxtBreak::SetCombWidth(float fCombWidth) { - m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f); -} - -void CFX_TxtBreak::AppendChar_PageLoad(CFX_Char* pCurChar, uint32_t dwProps) { - pCurChar->m_dwStatus = CFX_BreakType::None; - pCurChar->m_dwCharStyles = m_iAlignment | (1 << 8); -} - -void CFX_TxtBreak::AppendChar_Combination(CFX_Char* pCurChar) { - wchar_t wch = pCurChar->m_wCharCode; - wchar_t wForm; - int32_t iCharWidth = 0; - pCurChar->m_iCharWidth = -1; - if (m_bCombText) { - iCharWidth = m_iCombWidth; - } else { - wForm = wch; - CFX_Char* pLastChar = GetLastChar(0, false, false); - if (pLastChar && - (pLastChar->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicShadda) == 0) { - bool bShadda = false; - if (wch == 0x0651) { - wchar_t 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) { - pLastChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda; - pLastChar->m_iCharWidth = 0; - pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda; - } - } - if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) - iCharWidth = 0; - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorizontalScale / 100; - } - pCurChar->m_iCharWidth = -iCharWidth; -} - -void CFX_TxtBreak::AppendChar_Tab(CFX_Char* pCurChar) { - m_eCharType = FX_CHARTYPE_Tab; -} - -CFX_BreakType CFX_TxtBreak::AppendChar_Control(CFX_Char* pCurChar) { - m_eCharType = FX_CHARTYPE_Control; - CFX_BreakType dwRet = CFX_BreakType::None; - if (!m_bSingleLine) { - wchar_t wch = pCurChar->m_wCharCode; - switch (wch) { - case L'\v': - case 0x2028: - dwRet = CFX_BreakType::Line; - break; - case L'\f': - dwRet = CFX_BreakType::Page; - break; - case 0x2029: - dwRet = CFX_BreakType::Paragraph; - break; - default: - if (wch == m_wParagraphBreakChar) - dwRet = CFX_BreakType::Paragraph; - break; - } - if (dwRet != CFX_BreakType::None) - dwRet = EndBreak(dwRet); - } - return dwRet; -} - -CFX_BreakType CFX_TxtBreak::AppendChar_Arabic(CFX_Char* pCurChar) { - FX_CHARTYPE chartype = pCurChar->GetCharType(); - int32_t& iLineWidth = m_pCurLine->m_iWidth; - wchar_t wForm; - int32_t iCharWidth = 0; - CFX_Char* pLastChar = nullptr; - bool bAlef = false; - if (!m_bCombText && m_eCharType >= FX_CHARTYPE_ArabicAlef && - m_eCharType <= FX_CHARTYPE_ArabicDistortion) { - pLastChar = GetLastChar(1, true, false); - if (pLastChar) { - iCharWidth = pLastChar->m_iCharWidth; - if (iCharWidth > 0) - iLineWidth -= iCharWidth; - - CFX_Char* pPrevChar = GetLastChar(2, true, false); - wForm = pdfium::arabic::GetFormChar(pLastChar, pPrevChar, pCurChar); - bAlef = (wForm == 0xFEFF && - pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef); - m_pFont->GetCharWidth(wForm, iCharWidth, false); - - if (wForm == 0xFEFF) - iCharWidth = m_iDefChar; - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorizontalScale / 100; - pLastChar->m_iCharWidth = iCharWidth; - iLineWidth += iCharWidth; - iCharWidth = 0; - } - } - - m_eCharType = chartype; - wForm = pdfium::arabic::GetFormChar(pCurChar, bAlef ? nullptr : pLastChar, - nullptr); - if (m_bCombText) { - iCharWidth = m_iCombWidth; - } else { - m_pFont->GetCharWidth(wForm, iCharWidth, false); - - if (wForm == 0xFEFF) - iCharWidth = m_iDefChar; - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorizontalScale / 100; - } - pCurChar->m_iCharWidth = iCharWidth; - iLineWidth += iCharWidth; - m_pCurLine->m_iArabicChars++; - if (!m_bSingleLine && iLineWidth > m_iLineWidth + m_iTolerance) - return EndBreak(CFX_BreakType::Line); - return CFX_BreakType::None; -} - -CFX_BreakType CFX_TxtBreak::AppendChar_Others(CFX_Char* pCurChar) { - FX_CHARTYPE chartype = pCurChar->GetCharType(); - int32_t& iLineWidth = m_pCurLine->m_iWidth; - int32_t iCharWidth = 0; - m_eCharType = chartype; - wchar_t wch = pCurChar->m_wCharCode; - wchar_t wForm = wch; - - if (m_bCombText) { - iCharWidth = m_iCombWidth; - } else { - if (!m_pFont->GetCharWidth(wForm, iCharWidth, false)) - iCharWidth = m_iDefChar; - - iCharWidth *= m_iFontSize; - iCharWidth = iCharWidth * m_iHorizontalScale / 100; - } - - iCharWidth += m_iCharSpace; - pCurChar->m_iCharWidth = iCharWidth; - iLineWidth += iCharWidth; - if (!m_bSingleLine && chartype != FX_CHARTYPE_Space && - iLineWidth > m_iLineWidth + m_iTolerance) { - return EndBreak(CFX_BreakType::Line); - } - - return CFX_BreakType::None; -} - -CFX_BreakType CFX_TxtBreak::AppendChar(wchar_t wch) { - uint32_t dwProps = kTextLayoutCodeProperties[static_cast(wch)]; - FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); - m_pCurLine->m_LineChars.emplace_back(); - - CFX_Char* pCurChar = &m_pCurLine->m_LineChars.back(); - pCurChar->m_wCharCode = static_cast(wch); - pCurChar->m_dwCharProps = dwProps; - pCurChar->m_dwCharStyles = 0; - pCurChar->m_iCharWidth = 0; - pCurChar->m_iHorizontalScale = m_iHorizontalScale; - pCurChar->m_iVerticalScale = m_iVerticalScale; - pCurChar->m_dwStatus = CFX_BreakType::None; - pCurChar->m_iBidiClass = 0; - pCurChar->m_iBidiLevel = 0; - pCurChar->m_iBidiPos = 0; - pCurChar->m_iBidiOrder = 0; - - AppendChar_PageLoad(pCurChar, dwProps); - CFX_BreakType dwRet1 = CFX_BreakType::None; - if (chartype != FX_CHARTYPE_Combination && - GetUnifiedCharType(m_eCharType) != GetUnifiedCharType(chartype) && - m_eCharType != FX_CHARTYPE_Unknown && - m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine && - (m_eCharType != FX_CHARTYPE_Space || chartype != FX_CHARTYPE_Control)) { - dwRet1 = EndBreak(CFX_BreakType::Line); - int32_t iCount = m_pCurLine->CountChars(); - if (iCount > 0) - pCurChar = &m_pCurLine->m_LineChars[iCount - 1]; - } - - CFX_BreakType dwRet2 = CFX_BreakType::None; - switch (chartype) { - case FX_CHARTYPE_Tab: - AppendChar_Tab(pCurChar); - break; - case FX_CHARTYPE_Control: - dwRet2 = AppendChar_Control(pCurChar); - break; - case FX_CHARTYPE_Combination: - AppendChar_Combination(pCurChar); - break; - case FX_CHARTYPE_ArabicAlef: - case FX_CHARTYPE_ArabicSpecial: - case FX_CHARTYPE_ArabicDistortion: - case FX_CHARTYPE_ArabicNormal: - case FX_CHARTYPE_ArabicForm: - case FX_CHARTYPE_Arabic: - dwRet2 = AppendChar_Arabic(pCurChar); - break; - case FX_CHARTYPE_Unknown: - case FX_CHARTYPE_Space: - case FX_CHARTYPE_Numeric: - case FX_CHARTYPE_Normal: - default: - dwRet2 = AppendChar_Others(pCurChar); - break; - } - - return std::max(dwRet1, dwRet2); -} - -bool CFX_TxtBreak::EndBreak_SplitLine(CFX_BreakLine* pNextLine, - bool bAllChars) { - int32_t iCount = m_pCurLine->CountChars(); - bool bDone = false; - CFX_Char* pTC; - if (!m_bSingleLine && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance) { - pTC = m_pCurLine->GetChar(iCount - 1); - switch (pTC->GetCharType()) { - case FX_CHARTYPE_Tab: - case FX_CHARTYPE_Control: - case FX_CHARTYPE_Space: - break; - default: - SplitTextLine(m_pCurLine, pNextLine, bAllChars); - bDone = true; - break; - } - } - - iCount = m_pCurLine->CountChars(); - CFX_BreakPiece tp; - if (bAllChars && !bDone) { - int32_t iEndPos = m_pCurLine->m_iWidth; - GetBreakPos(m_pCurLine->m_LineChars, iEndPos, bAllChars, true); - } - return false; -} - -void CFX_TxtBreak::EndBreak_BidiLine(std::deque* tpos, - CFX_BreakType dwStatus) { - CFX_BreakPiece tp; - FX_TPO tpo; - CFX_Char* pTC; - int32_t i; - int32_t j; - std::vector& chars = m_pCurLine->m_LineChars; - int32_t iCount = m_pCurLine->CountChars(); - bool bDone = m_pCurLine->m_iArabicChars > 0; - if (bDone) { - int32_t iBidiNum = 0; - for (i = 0; i < iCount; i++) { - pTC = &chars[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); - } - - if (bDone) { - tp.m_dwStatus = CFX_BreakType::Piece; - tp.m_iStartPos = m_pCurLine->m_iStart; - tp.m_pChars = &m_pCurLine->m_LineChars; - int32_t iBidiLevel = -1; - int32_t iCharWidth; - i = 0; - j = -1; - while (i < iCount) { - pTC = &chars[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_iHorizontalScale = pTC->m_iHorizontalScale; - tp.m_iVerticalScale = pTC->m_iVerticalScale; - tp.m_dwStatus = CFX_BreakType::Piece; - } - if (iBidiLevel != pTC->m_iBidiLevel || - pTC->m_dwStatus != CFX_BreakType::None) { - 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; - m_pCurLine->m_LinePieces.push_back(tp); - tp.m_iStartPos += tp.m_iWidth; - tp.m_iStartChar = i; - tpo.index = ++j; - tpo.pos = tp.m_iBidiPos; - tpos->push_back(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; - m_pCurLine->m_LinePieces.push_back(tp); - tpo.index = ++j; - tpo.pos = tp.m_iBidiPos; - tpos->push_back(tpo); - } - if (j > -1) { - if (j > 0) { - std::sort(tpos->begin(), tpos->end()); - int32_t iStartPos = 0; - for (i = 0; i <= j; i++) { - tpo = (*tpos)[i]; - CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index]; - ttp.m_iStartPos = iStartPos; - iStartPos += ttp.m_iWidth; - } - } - m_pCurLine->m_LinePieces[j].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_LineChars; - pTC = &chars[0]; - tp.m_dwCharStyles = pTC->m_dwCharStyles; - tp.m_iHorizontalScale = pTC->m_iHorizontalScale; - tp.m_iVerticalScale = pTC->m_iVerticalScale; - m_pCurLine->m_LinePieces.push_back(tp); - tpos->push_back({0, 0}); - } -} - -void CFX_TxtBreak::EndBreak_Alignment(const std::deque& tpos, - bool bAllChars, - CFX_BreakType dwStatus) { - int32_t iNetWidth = m_pCurLine->m_iWidth; - int32_t iGapChars = 0; - bool bFind = false; - for (auto it = tpos.rbegin(); it != tpos.rend(); ++it) { - CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it->index]; - if (!bFind) - iNetWidth = ttp.GetEndPos(); - - bool bArabic = FX_IsOdd(ttp.m_iBidiLevel); - int32_t j = bArabic ? 0 : ttp.m_iChars - 1; - while (j > -1 && j < ttp.m_iChars) { - const CFX_Char* pTC = ttp.GetChar(j); - if (pTC->m_nBreakType == FX_LBT_DIRECT_BRK) - iGapChars++; - if (!bFind || !bAllChars) { - FX_CHARTYPE chartype = pTC->GetCharType(); - if (chartype == FX_CHARTYPE_Space || chartype == FX_CHARTYPE_Control) { - if (!bFind && bAllChars && pTC->m_iCharWidth > 0) - iNetWidth -= pTC->m_iCharWidth; - } else { - bFind = true; - if (!bAllChars) - break; - } - } - j += bArabic ? 1 : -1; - } - if (!bAllChars && bFind) - break; - } - - int32_t iOffset = m_iLineWidth - iNetWidth; - if (iGapChars > 0 && m_iAlignment & CFX_TxtLineAlignment_Justified && - dwStatus != CFX_BreakType::Paragraph) { - int32_t iStart = -1; - for (auto& tpo : tpos) { - CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[tpo.index]; - if (iStart < -1) - iStart = ttp.m_iStartPos; - else - ttp.m_iStartPos = iStart; - - for (int32_t j = 0; j < ttp.m_iChars; j++) { - CFX_Char* pTC = ttp.GetChar(j); - if (pTC->m_nBreakType != FX_LBT_DIRECT_BRK || pTC->m_iCharWidth < 0) - continue; - - int32_t k = iOffset / iGapChars; - pTC->m_iCharWidth += k; - ttp.m_iWidth += k; - iOffset -= k; - iGapChars--; - if (iGapChars < 1) - break; - } - iStart += ttp.m_iWidth; - } - } else if (m_iAlignment & CFX_TxtLineAlignment_Center || - m_iAlignment & CFX_TxtLineAlignment_Right) { - if (m_iAlignment & CFX_TxtLineAlignment_Center && - !(m_iAlignment & CFX_TxtLineAlignment_Right)) { - iOffset /= 2; - } - if (iOffset > 0) { - for (auto& ttp : m_pCurLine->m_LinePieces) - ttp.m_iStartPos += iOffset; - } - } -} - -CFX_BreakType CFX_TxtBreak::EndBreak(CFX_BreakType dwStatus) { - ASSERT(dwStatus != CFX_BreakType::None); - - if (!m_pCurLine->m_LinePieces.empty()) { - if (dwStatus != CFX_BreakType::Piece) - m_pCurLine->m_LinePieces.back().m_dwStatus = dwStatus; - return m_pCurLine->m_LinePieces.back().m_dwStatus; - } - - if (HasLine()) { - if (!m_Line[m_iReadyLineIndex].m_LinePieces.empty()) { - if (dwStatus != CFX_BreakType::Piece) - m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus = dwStatus; - return m_Line[m_iReadyLineIndex].m_LinePieces.back().m_dwStatus; - } - return CFX_BreakType::None; - } - - int32_t iCount = m_pCurLine->CountChars(); - if (iCount < 1) - return CFX_BreakType::None; - - m_pCurLine->GetChar(iCount - 1)->m_dwStatus = dwStatus; - if (dwStatus == CFX_BreakType::Piece) - return dwStatus; - - m_iReadyLineIndex = m_pCurLine == &m_Line[0] ? 0 : 1; - CFX_BreakLine* pNextLine = &m_Line[1 - m_iReadyLineIndex]; - bool bAllChars = m_iAlignment > CFX_TxtLineAlignment_Right; - if (!EndBreak_SplitLine(pNextLine, bAllChars)) { - std::deque tpos; - EndBreak_BidiLine(&tpos, dwStatus); - if (m_iAlignment > CFX_TxtLineAlignment_Left) - EndBreak_Alignment(tpos, bAllChars, dwStatus); - } - - m_pCurLine = pNextLine; - CFX_Char* pTC = GetLastChar(0, false, false); - m_eCharType = pTC ? pTC->GetCharType() : FX_CHARTYPE_Unknown; - - return dwStatus; -} - -int32_t CFX_TxtBreak::GetBreakPos(std::vector& ca, - int32_t& iEndPos, - bool bAllChars, - bool bOnlyBrk) { - int32_t iLength = pdfium::CollectionSize(ca) - 1; - if (iLength < 1) - return iLength; - - int32_t iBreak = -1; - int32_t iBreakPos = -1; - int32_t iIndirect = -1; - int32_t iIndirectPos = -1; - int32_t iLast = -1; - int32_t iLastPos = -1; - if (m_bSingleLine || iEndPos <= m_iLineWidth) { - if (!bAllChars) - return iLength; - - iBreak = iLength; - iBreakPos = iEndPos; - } - - FX_LINEBREAKTYPE eType; - uint32_t nCodeProp; - uint32_t nCur; - uint32_t nNext; - CFX_Char* pCur = &ca[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[iLength]; - nCodeProp = pCur->m_dwCharProps; - nCur = nCodeProp & 0x003F; - if (nCur == FX_CBP_SP) { - if (nNext == FX_CBP_SP) - eType = FX_LBT_PROHIBITED_BRK; - else - eType = gs_FX_LineBreak_PairTable[nCur][nNext]; - } else { - if (nNext == FX_CBP_SP) - eType = FX_LBT_PROHIBITED_BRK; - else - eType = gs_FX_LineBreak_PairTable[nCur][nNext]; - } - if (bAllChars) - pCur->m_nBreakType = static_cast(eType); - if (!bOnlyBrk) { - if (m_bSingleLine || iEndPos <= m_iLineWidth || nCur == FX_CBP_SP) { - 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_BreakLine* pCurLine, - CFX_BreakLine* pNextLine, - bool bAllChars) { - ASSERT(pCurLine && pNextLine); - int32_t iCount = pCurLine->CountChars(); - if (iCount < 2) - return; - - int32_t iEndPos = pCurLine->m_iWidth; - std::vector& curChars = pCurLine->m_LineChars; - int32_t iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, false); - if (iCharPos < 0) - iCharPos = 0; - - iCharPos++; - if (iCharPos >= iCount) { - pNextLine->Clear(); - CFX_Char* pTC = &curChars[iCharPos - 1]; - pTC->m_nBreakType = FX_LBT_UNKNOWN; - return; - } - - pNextLine->m_LineChars = - std::vector(curChars.begin() + iCharPos, curChars.end()); - curChars.erase(curChars.begin() + iCharPos, curChars.end()); - pCurLine->m_iWidth = iEndPos; - CFX_Char* pTC = &curChars[iCharPos - 1]; - pTC->m_nBreakType = FX_LBT_UNKNOWN; - iCount = pdfium::CollectionSize(pNextLine->m_LineChars); - int32_t iWidth = 0; - for (int32_t i = 0; i < iCount; i++) { - if (pNextLine->m_LineChars[i].GetCharType() >= FX_CHARTYPE_ArabicAlef) { - pCurLine->m_iArabicChars--; - pNextLine->m_iArabicChars++; - } - iWidth += std::max(0, pNextLine->m_LineChars[i].m_iCharWidth); - pNextLine->m_LineChars[i].m_dwStatus = CFX_BreakType::None; - } - pNextLine->m_iWidth = iWidth; -} - -struct FX_FORMCHAR { - uint16_t wch; - uint16_t wForm; - int32_t iWidth; -}; - -int32_t CFX_TxtBreak::GetDisplayPos(const FX_TXTRUN* pTxtRun, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode, - CFX_WideString* pWSForms) const { - if (!pTxtRun || pTxtRun->iLength < 1) - return 0; - - CFDE_TxtEdtPage* pAccess = pTxtRun->pAccess; - const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity; - const wchar_t* pStr = pTxtRun->wsStr.c_str(); - int32_t* pWidths = pTxtRun->pWidths; - int32_t iLength = pTxtRun->iLength - 1; - CFX_RetainPtr pFont = pTxtRun->pFont; - uint32_t dwStyles = pTxtRun->dwStyles; - CFX_RectF rtText(*pTxtRun->pRect); - bool bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0; - 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; - float fFontHeight = fFontSize; - float fAscent = fFontHeight * (float)iAscent / (float)iMaxHeight; - float fX = rtText.left; - float fY; - float fCharWidth; - float fCharHeight; - int32_t iHorScale = pTxtRun->iHorizontalScale; - int32_t iVerScale = pTxtRun->iVerticalScale; - bool bSkipSpace = pTxtRun->bSkipSpace; - FX_FORMCHAR formChars[3]; - float fYBase; - - if (bRTLPiece) - fX = rtText.right(); - - fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f; - fY = fYBase + fAscent; - - int32_t iCount = 0; - int32_t iNext = 0; - wchar_t wPrev = 0xFEFF; - wchar_t wNext = 0xFEFF; - wchar_t wForm = 0xFEFF; - wchar_t wLast = 0xFEFF; - bool bShadda = false; - bool bLam = false; - for (int32_t i = 0; i <= iLength; i++) { - int32_t iWidth; - wchar_t wch; - if (pAccess) { - wch = pAccess->GetChar(pIdentity, i); - iWidth = pAccess->GetWidth(pIdentity, i); - } else { - wch = *pStr++; - iWidth = *pWidths++; - } - - uint32_t dwProps = FX_GetUnicodeProperties(wch); - FX_CHARTYPE chartype = GetCharTypeFromProp(dwProps); - if (chartype == FX_CHARTYPE_ArabicAlef && iWidth == 0) { - wPrev = 0xFEFF; - wLast = wch; - continue; - } - - if (chartype >= FX_CHARTYPE_ArabicAlef) { - if (i < iLength) { - if (pAccess) { - 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 = pdfium::arabic::GetFormChar(wch, wPrev, wNext); - bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647); - } else if (chartype == FX_CHARTYPE_Combination) { - wForm = wch; - if (wch >= 0x064C && wch <= 0x0651) { - if (bShadda) { - wForm = 0xFEFF; - bShadda = false; - } else { - wNext = 0xFEFF; - if (pAccess) { - 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 (chartype == FX_CHARTYPE_Numeric) { - wForm = wch; - } else if (wch == L'.') { - wForm = wch; - } else if (wch == L',') { - wForm = wch; - } else if (bRTLPiece) { - wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, false); - } else { - wForm = wch; - } - if (chartype != FX_CHARTYPE_Combination) - bShadda = false; - if (chartype < FX_CHARTYPE_ArabicAlef) - bLam = false; - - dwProps = FX_GetUnicodeProperties(wForm); - bool bEmptyChar = - (chartype >= FX_CHARTYPE_Tab && chartype <= FX_CHARTYPE_Control); - if (wForm == 0xFEFF) - bEmptyChar = true; - - int32_t iForms = bLam ? 3 : 1; - iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms; - if (!pCharPos) { - if (iWidth > 0) - wPrev = wch; - wLast = wch; - continue; - } - - int32_t 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 = (wchar_t)formChars[j].wForm; - iCharWidth = formChars[j].iWidth; - if (j > 0) { - chartype = FX_CHARTYPE_Combination; - wch = wForm; - wLast = (wchar_t)formChars[j - 1].wForm; - } - if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) { - pCharPos->m_GlyphIndex = - bCharCode ? wch : pFont->GetGlyphIndex(wForm, false); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - pCharPos->m_ExtGID = pCharPos->m_GlyphIndex; -#endif - pCharPos->m_FontCharWidth = iCharWidth; - if (pWSForms) - *pWSForms += wForm; - } - - int32_t iCharHeight = 1000; - - fCharWidth = fFontSize * iCharWidth / 1000.0f; - fCharHeight = fFontSize * iCharHeight / 1000.0f; - if (bRTLPiece && chartype != FX_CHARTYPE_Combination) - fX -= fCharWidth; - - if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) { - pCharPos->m_Origin = CFX_PointF(fX, fY); - if ((dwStyles & FX_LAYOUTSTYLE_CombText) != 0) { - int32_t iFormWidth = iCharWidth; - pFont->GetCharWidth(wForm, iFormWidth, false); - float fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f; - pCharPos->m_Origin.x += fOffset; - } - - if (chartype == FX_CHARTYPE_Combination) { - CFX_Rect rtBBox; - if (pFont->GetCharBBox(wForm, &rtBBox, false)) { - pCharPos->m_Origin.y = - fYBase + fFontSize - - fFontSize * (float)rtBBox.height / (float)iMaxHeight; - } - if (wForm == wch && wLast != 0xFEFF) { - uint32_t dwLastProps = FX_GetUnicodeProperties(wLast); - if ((dwLastProps & FX_CHARTYPEBITSMASK) == - FX_CHARTYPE_Combination) { - CFX_Rect rtBox; - if (pFont->GetCharBBox(wLast, &rtBox, false)) - pCharPos->m_Origin.y -= fFontSize * rtBox.height / iMaxHeight; - } - } - } - CFX_PointF ptOffset; - pCharPos->m_Origin.x += ptOffset.x; - pCharPos->m_Origin.y -= ptOffset.y; - } - if (!bRTLPiece && chartype != FX_CHARTYPE_Combination) - fX += fCharWidth; - - if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) { - pCharPos->m_bGlyphAdjust = true; - pCharPos->m_AdjustMatrix[0] = -1; - pCharPos->m_AdjustMatrix[1] = 0; - pCharPos->m_AdjustMatrix[2] = 0; - pCharPos->m_AdjustMatrix[3] = 1; - - 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 = static_cast(formChars[0].wch); - wLast = wch; - } - return iCount; -} - -std::vector CFX_TxtBreak::GetCharRects(const FX_TXTRUN* pTxtRun, - bool bCharBBox) const { - if (!pTxtRun || pTxtRun->iLength < 1) - return std::vector(); - - CFDE_TxtEdtPage* pAccess = pTxtRun->pAccess; - const FDE_TEXTEDITPIECE* pIdentity = pTxtRun->pIdentity; - const wchar_t* pStr = pTxtRun->wsStr.c_str(); - int32_t* pWidths = pTxtRun->pWidths; - int32_t iLength = pTxtRun->iLength; - CFX_RectF rect(*pTxtRun->pRect); - float fFontSize = pTxtRun->fFontSize; - int32_t iFontSize = FXSYS_round(fFontSize * 20.0f); - float fScale = fFontSize / 1000.0f; - CFX_RetainPtr pFont = pTxtRun->pFont; - if (!pFont) - bCharBBox = false; - - CFX_Rect bbox; - if (bCharBBox) - bCharBBox = pFont->GetBBox(&bbox); - - float fLeft = std::max(0.0f, bbox.left * fScale); - float fHeight = fabs(bbox.height * fScale); - bool bRTLPiece = !!(pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel); - bool bSingleLine = !!(pTxtRun->dwStyles & FX_LAYOUTSTYLE_SingleLine); - bool bCombText = !!(pTxtRun->dwStyles & FX_LAYOUTSTYLE_CombText); - wchar_t wch; - wchar_t wLineBreakChar = pTxtRun->wLineBreakChar; - int32_t iCharSize; - float fCharSize; - float fStart = bRTLPiece ? rect.right() : rect.left; - - std::vector rtArray(iLength); - for (int32_t i = 0; i < iLength; i++) { - if (pAccess) { - wch = pAccess->GetChar(pIdentity, i); - iCharSize = pAccess->GetWidth(pIdentity, i); - } else { - wch = *pStr++; - iCharSize = *pWidths++; - } - fCharSize = static_cast(iCharSize) / 20000.0f; - bool bRet = (!bSingleLine && 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; - } - 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, false); - float fRTLeft = 0, fCharWidth = 0; - if (iCharWidth > 0) { - fCharWidth = iCharWidth * fScale; - fRTLeft = fLeft; - if (bCombText) - fRTLeft = (rect.width - fCharWidth) / 2.0f; - } - CFX_RectF rtBBoxF; - 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[i] = rtBBoxF; - continue; - } - rtArray[i] = rect; - } - return rtArray; -} - -FX_TXTRUN::FX_TXTRUN() - : pAccess(nullptr), - pIdentity(nullptr), - pWidths(nullptr), - iLength(0), - pFont(nullptr), - fFontSize(12), - dwStyles(0), - iHorizontalScale(100), - iVerticalScale(100), - dwCharStyles(0), - pRect(nullptr), - wLineBreakChar(L'\n'), - bSkipSpace(true) {} - -FX_TXTRUN::~FX_TXTRUN() {} - -FX_TXTRUN::FX_TXTRUN(const FX_TXTRUN& other) = default; diff --git a/xfa/fgas/layout/fgas_textbreak.h b/xfa/fgas/layout/fgas_textbreak.h deleted file mode 100644 index 81aaf58219..0000000000 --- a/xfa/fgas/layout/fgas_textbreak.h +++ /dev/null @@ -1,102 +0,0 @@ -// 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_FGAS_LAYOUT_FGAS_TEXTBREAK_H_ -#define XFA_FGAS_LAYOUT_FGAS_TEXTBREAK_H_ - -#include -#include -#include - -#include "core/fxcrt/cfx_char.h" -#include "core/fxge/cfx_renderdevice.h" -#include "third_party/base/stl_util.h" -#include "xfa/fde/cfde_txtedtpage.h" -#include "xfa/fgas/layout/cfx_break.h" - -class CFGAS_GEFont; -struct FDE_TEXTEDITPIECE; - -#define FX_TXTCHARSTYLE_ArabicShadda 0x0020 -#define FX_TXTCHARSTYLE_OddBidiLevel 0x0040 - -enum CFX_TxtLineAlignment { - CFX_TxtLineAlignment_Left = 0, - CFX_TxtLineAlignment_Center = 1 << 0, - CFX_TxtLineAlignment_Right = 1 << 1, - CFX_TxtLineAlignment_Justified = 1 << 2 -}; - -inline bool CFX_BreakTypeNoneOrPiece(CFX_BreakType type) { - return type == CFX_BreakType::None || type == CFX_BreakType::Piece; -} - -struct FX_TXTRUN { - FX_TXTRUN(); - FX_TXTRUN(const FX_TXTRUN& other); - ~FX_TXTRUN(); - - CFDE_TxtEdtPage* pAccess; - const FDE_TEXTEDITPIECE* pIdentity; - CFX_WideString wsStr; - int32_t* pWidths; - int32_t iLength; - CFX_RetainPtr pFont; - float fFontSize; - uint32_t dwStyles; - int32_t iHorizontalScale; - int32_t iVerticalScale; - uint32_t dwCharStyles; - const CFX_RectF* pRect; - wchar_t wLineBreakChar; - bool bSkipSpace; -}; - -class CFX_TxtBreak : public CFX_Break { - public: - CFX_TxtBreak(); - ~CFX_TxtBreak() override; - - void SetLineWidth(float fLineWidth); - void SetAlignment(int32_t iAlignment); - void SetCombWidth(float fCombWidth); - CFX_BreakType EndBreak(CFX_BreakType dwStatus); - - int32_t GetDisplayPos(const FX_TXTRUN* pTxtRun, - FXTEXT_CHARPOS* pCharPos, - bool bCharCode = false, - CFX_WideString* pWSForms = nullptr) const; - std::vector GetCharRects(const FX_TXTRUN* pTxtRun, - bool bCharBBox = false) const; - CFX_BreakType AppendChar(wchar_t wch); - - private: - void AppendChar_Combination(CFX_Char* pCurChar); - void AppendChar_Tab(CFX_Char* pCurChar); - void AppendChar_PageLoad(CFX_Char* pCurChar, uint32_t dwProps); - CFX_BreakType AppendChar_Control(CFX_Char* pCurChar); - CFX_BreakType AppendChar_Arabic(CFX_Char* pCurChar); - CFX_BreakType AppendChar_Others(CFX_Char* pCurChar); - - void ResetContextCharStyles(); - bool EndBreak_SplitLine(CFX_BreakLine* pNextLine, bool bAllChars); - void EndBreak_BidiLine(std::deque* tpos, CFX_BreakType dwStatus); - void EndBreak_Alignment(const std::deque& tpos, - bool bAllChars, - CFX_BreakType dwStatus); - int32_t GetBreakPos(std::vector& ca, - int32_t& iEndPos, - bool bAllChars = false, - bool bOnlyBrk = false); - void SplitTextLine(CFX_BreakLine* pCurLine, - CFX_BreakLine* pNextLine, - bool bAllChars = false); - - int32_t m_iAlignment; - int32_t m_iCombWidth; -}; - -#endif // XFA_FGAS_LAYOUT_FGAS_TEXTBREAK_H_ diff --git a/xfa/fxfa/app/cxfa_textlayout.h b/xfa/fxfa/app/cxfa_textlayout.h index 9bfc977247..5bce1c9ab2 100644 --- a/xfa/fxfa/app/cxfa_textlayout.h +++ b/xfa/fxfa/app/cxfa_textlayout.h @@ -14,7 +14,7 @@ #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" #include "xfa/fde/css/fde_css.h" -#include "xfa/fgas/layout/fgas_rtfbreak.h" +#include "xfa/fgas/layout/cfx_rtfbreak.h" #include "xfa/fxfa/app/cxfa_textparser.h" class CFDE_Brush; -- cgit v1.2.3