Move xfa/src up to xfa/.

This CL moves the xfa/src files up to the xfa/ directory and fixes the includes,
include guards, and build files.

R=tsepez@chromium.org

Review URL: https://codereview.chromium.org/1803723002 .
diff --git a/xfa/fxfa/app/xfa_checksum.cpp b/xfa/fxfa/app/xfa_checksum.cpp
new file mode 100644
index 0000000..1639c0d
--- /dev/null
+++ b/xfa/fxfa/app/xfa_checksum.cpp
@@ -0,0 +1,190 @@
+// 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/fxfa/app/xfa_checksum.h"
+
+#include "core/include/fdrm/fx_crypt.h"
+#include "xfa/fgas/crt/fgas_algorithm.h"
+
+CXFA_SAXReaderHandler::CXFA_SAXReaderHandler(CXFA_ChecksumContext* pContext)
+    : m_pContext(pContext) {
+  FXSYS_assert(m_pContext);
+}
+CXFA_SAXReaderHandler::~CXFA_SAXReaderHandler() {}
+void* CXFA_SAXReaderHandler::OnTagEnter(const CFX_ByteStringC& bsTagName,
+                                        FX_SAXNODE eType,
+                                        FX_DWORD dwStartPos) {
+  UpdateChecksum(TRUE);
+  if (eType != FX_SAXNODE_Tag && eType != FX_SAXNODE_Instruction) {
+    return NULL;
+  }
+  m_SAXContext.m_eNode = eType;
+  CFX_ByteTextBuf& textBuf = m_SAXContext.m_TextBuf;
+  textBuf << "<";
+  if (eType == FX_SAXNODE_Instruction) {
+    textBuf << "?";
+  }
+  textBuf << bsTagName;
+  m_SAXContext.m_bsTagName = bsTagName;
+  return &m_SAXContext;
+}
+void CXFA_SAXReaderHandler::OnTagAttribute(void* pTag,
+                                           const CFX_ByteStringC& bsAttri,
+                                           const CFX_ByteStringC& bsValue) {
+  if (pTag == NULL) {
+    return;
+  }
+  CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
+  textBuf << " " << bsAttri << "=\"" << bsValue << "\"";
+}
+void CXFA_SAXReaderHandler::OnTagBreak(void* pTag) {
+  if (pTag == NULL) {
+    return;
+  }
+  CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
+  textBuf << ">";
+  UpdateChecksum(FALSE);
+}
+void CXFA_SAXReaderHandler::OnTagData(void* pTag,
+                                      FX_SAXNODE eType,
+                                      const CFX_ByteStringC& bsData,
+                                      FX_DWORD dwStartPos) {
+  if (pTag == NULL) {
+    return;
+  }
+  CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
+  if (eType == FX_SAXNODE_CharData) {
+    textBuf << "<![CDATA[";
+  }
+  textBuf << bsData;
+  if (eType == FX_SAXNODE_CharData) {
+    textBuf << "]]>";
+  }
+}
+void CXFA_SAXReaderHandler::OnTagClose(void* pTag, FX_DWORD dwEndPos) {
+  if (pTag == NULL) {
+    return;
+  }
+  CXFA_SAXContext* pSAXContext = (CXFA_SAXContext*)pTag;
+  CFX_ByteTextBuf& textBuf = pSAXContext->m_TextBuf;
+  if (pSAXContext->m_eNode == FX_SAXNODE_Instruction) {
+    textBuf << "?>";
+  } else if (pSAXContext->m_eNode == FX_SAXNODE_Tag) {
+    textBuf << "></" << pSAXContext->m_bsTagName << ">";
+  }
+  UpdateChecksum(FALSE);
+}
+void CXFA_SAXReaderHandler::OnTagEnd(void* pTag,
+                                     const CFX_ByteStringC& bsTagName,
+                                     FX_DWORD dwEndPos) {
+  if (pTag == NULL) {
+    return;
+  }
+  CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
+  textBuf << "</" << bsTagName << ">";
+  UpdateChecksum(FALSE);
+}
+void CXFA_SAXReaderHandler::OnTargetData(void* pTag,
+                                         FX_SAXNODE eType,
+                                         const CFX_ByteStringC& bsData,
+                                         FX_DWORD dwStartPos) {
+  if (pTag == NULL && eType != FX_SAXNODE_Comment) {
+    return;
+  }
+  if (eType == FX_SAXNODE_Comment) {
+    CFX_ByteTextBuf& textBuf = m_SAXContext.m_TextBuf;
+    textBuf << "<!--" << bsData << "-->";
+    UpdateChecksum(FALSE);
+  } else {
+    CFX_ByteTextBuf& textBuf = ((CXFA_SAXContext*)pTag)->m_TextBuf;
+    textBuf << " " << bsData;
+  }
+}
+void CXFA_SAXReaderHandler::UpdateChecksum(FX_BOOL bCheckSpace) {
+  int32_t iLength = m_SAXContext.m_TextBuf.GetLength();
+  if (iLength < 1) {
+    return;
+  }
+  uint8_t* pBuffer = m_SAXContext.m_TextBuf.GetBuffer();
+  FX_BOOL bUpdata = TRUE;
+  if (bCheckSpace) {
+    bUpdata = FALSE;
+    for (int32_t i = 0; i < iLength; i++) {
+      bUpdata = (pBuffer[i] > 0x20);
+      if (bUpdata) {
+        break;
+      }
+    }
+  }
+  if (bUpdata) {
+    m_pContext->Update(CFX_ByteStringC(pBuffer, iLength));
+  }
+  m_SAXContext.m_TextBuf.Clear();
+}
+IXFA_ChecksumContext* XFA_Checksum_Create() {
+  return new CXFA_ChecksumContext;
+}
+CXFA_ChecksumContext::CXFA_ChecksumContext()
+    : m_pSAXReader(NULL), m_pByteContext(NULL) {}
+CXFA_ChecksumContext::~CXFA_ChecksumContext() {
+  FinishChecksum();
+}
+FX_BOOL CXFA_ChecksumContext::StartChecksum() {
+  FinishChecksum();
+  m_pByteContext = FX_Alloc(uint8_t, 128);
+  CRYPT_SHA1Start(m_pByteContext);
+  m_bsChecksum.Empty();
+  m_pSAXReader = FX_SAXReader_Create();
+  return m_pSAXReader != NULL;
+}
+FX_BOOL CXFA_ChecksumContext::UpdateChecksum(IFX_FileRead* pSrcFile,
+                                             FX_FILESIZE offset,
+                                             size_t size) {
+  if (m_pSAXReader == NULL) {
+    return FALSE;
+  }
+  if (pSrcFile == NULL) {
+    return FALSE;
+  }
+  if (size < 1) {
+    size = pSrcFile->GetSize();
+  }
+  CXFA_SAXReaderHandler handler(this);
+  m_pSAXReader->SetHandler(&handler);
+  if (m_pSAXReader->StartParse(
+          pSrcFile, (FX_DWORD)offset, (FX_DWORD)size,
+          FX_SAXPARSEMODE_NotSkipSpace | FX_SAXPARSEMODE_NotConvert_amp |
+              FX_SAXPARSEMODE_NotConvert_lt | FX_SAXPARSEMODE_NotConvert_gt |
+              FX_SAXPARSEMODE_NotConvert_sharp) < 0) {
+    return FALSE;
+  }
+  return m_pSAXReader->ContinueParse(NULL) > 99;
+}
+void CXFA_ChecksumContext::FinishChecksum() {
+  if (m_pSAXReader) {
+    m_pSAXReader->Release();
+    m_pSAXReader = NULL;
+  }
+  if (m_pByteContext) {
+    uint8_t digest[20];
+    FXSYS_memset(digest, 0, 20);
+    CRYPT_SHA1Finish(m_pByteContext, digest);
+    int32_t nLen = FX_Base64EncodeA(digest, 20, NULL);
+    FX_CHAR* pBuffer = m_bsChecksum.GetBuffer(nLen);
+    FX_Base64EncodeA(digest, 20, pBuffer);
+    m_bsChecksum.ReleaseBuffer(nLen);
+    FX_Free(m_pByteContext);
+    m_pByteContext = NULL;
+  }
+}
+void CXFA_ChecksumContext::GetChecksum(CFX_ByteString& bsChecksum) {
+  bsChecksum = m_bsChecksum;
+}
+void CXFA_ChecksumContext::Update(const CFX_ByteStringC& bsText) {
+  if (m_pByteContext) {
+    CRYPT_SHA1Update(m_pByteContext, bsText.GetPtr(), bsText.GetLength());
+  }
+}
diff --git a/xfa/fxfa/app/xfa_checksum.h b/xfa/fxfa/app/xfa_checksum.h
new file mode 100644
index 0000000..5331800
--- /dev/null
+++ b/xfa/fxfa/app/xfa_checksum.h
@@ -0,0 +1,73 @@
+// 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_FXFA_APP_XFA_CHECKSUM_H_
+#define XFA_FXFA_APP_XFA_CHECKSUM_H_
+
+#include "xfa/fgas/xml/fgas_sax.h"
+#include "xfa/include/fxfa/fxfa.h"
+
+class CXFA_SAXReaderHandler;
+class CXFA_ChecksumContext;
+
+class CXFA_SAXContext {
+ public:
+  CXFA_SAXContext() : m_eNode(FX_SAXNODE_Unknown) {}
+  CFX_ByteTextBuf m_TextBuf;
+  CFX_ByteString m_bsTagName;
+  FX_SAXNODE m_eNode;
+};
+class CXFA_SAXReaderHandler : public IFX_SAXReaderHandler {
+ public:
+  CXFA_SAXReaderHandler(CXFA_ChecksumContext* pContext);
+  virtual ~CXFA_SAXReaderHandler();
+  virtual void* OnTagEnter(const CFX_ByteStringC& bsTagName,
+                           FX_SAXNODE eType,
+                           FX_DWORD dwStartPos);
+  virtual void OnTagAttribute(void* pTag,
+                              const CFX_ByteStringC& bsAttri,
+                              const CFX_ByteStringC& bsValue);
+  virtual void OnTagBreak(void* pTag);
+  virtual void OnTagData(void* pTag,
+                         FX_SAXNODE eType,
+                         const CFX_ByteStringC& bsData,
+                         FX_DWORD dwStartPos);
+  virtual void OnTagClose(void* pTag, FX_DWORD dwEndPos);
+  virtual void OnTagEnd(void* pTag,
+                        const CFX_ByteStringC& bsTagName,
+                        FX_DWORD dwEndPos);
+
+  virtual void OnTargetData(void* pTag,
+                            FX_SAXNODE eType,
+                            const CFX_ByteStringC& bsData,
+                            FX_DWORD dwStartPos);
+
+ protected:
+  void UpdateChecksum(FX_BOOL bCheckSpace);
+  CXFA_ChecksumContext* m_pContext;
+  CXFA_SAXContext m_SAXContext;
+};
+
+class CXFA_ChecksumContext : public IXFA_ChecksumContext {
+ public:
+  CXFA_ChecksumContext();
+  virtual ~CXFA_ChecksumContext();
+  virtual void Release() { delete this; }
+  virtual FX_BOOL StartChecksum();
+  virtual FX_BOOL UpdateChecksum(IFX_FileRead* pSrcFile,
+                                 FX_FILESIZE offset = 0,
+                                 size_t size = 0);
+  virtual void FinishChecksum();
+  virtual void GetChecksum(CFX_ByteString& bsChecksum);
+  void Update(const CFX_ByteStringC& bsText);
+
+ protected:
+  IFX_SAXReader* m_pSAXReader;
+  uint8_t* m_pByteContext;
+  CFX_ByteString m_bsChecksum;
+};
+
+#endif  // XFA_FXFA_APP_XFA_CHECKSUM_H_
diff --git a/xfa/fxfa/app/xfa_ffapp.cpp b/xfa/fxfa/app/xfa_ffapp.cpp
new file mode 100644
index 0000000..8327d1b
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffapp.cpp
@@ -0,0 +1,190 @@
+// 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/fxfa/app/xfa_ffapp.h"
+
+#include <algorithm>
+
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdochandler.h"
+#include "xfa/fxfa/app/xfa_ffwidgethandler.h"
+#include "xfa/fxfa/app/xfa_fontmgr.h"
+#include "xfa/fxfa/app/xfa_fwladapter.h"
+#include "xfa/fxfa/app/xfa_fwltheme.h"
+#include "xfa/include/fwl/core/fwl_widgetmgr.h"
+
+CXFA_FileRead::CXFA_FileRead(const CFX_ArrayTemplate<CPDF_Stream*>& streams) {
+  int32_t iCount = streams.GetSize();
+  for (int32_t i = 0; i < iCount; i++) {
+    CPDF_StreamAcc& acc = m_Data.Add();
+    acc.LoadAllData(streams[i]);
+  }
+}
+FX_FILESIZE CXFA_FileRead::GetSize() {
+  FX_DWORD dwSize = 0;
+  int32_t iCount = m_Data.GetSize();
+  for (int32_t i = 0; i < iCount; i++) {
+    CPDF_StreamAcc& acc = m_Data[i];
+    dwSize += acc.GetSize();
+  }
+  return dwSize;
+}
+FX_BOOL CXFA_FileRead::ReadBlock(void* buffer,
+                                 FX_FILESIZE offset,
+                                 size_t size) {
+  int32_t iCount = m_Data.GetSize();
+  int32_t index = 0;
+  while (index < iCount) {
+    CPDF_StreamAcc& acc = m_Data[index];
+    FX_FILESIZE dwSize = acc.GetSize();
+    if (offset < dwSize) {
+      break;
+    }
+    offset -= dwSize;
+    index++;
+  }
+  while (index < iCount) {
+    CPDF_StreamAcc& acc = m_Data[index];
+    FX_DWORD dwSize = acc.GetSize();
+    size_t dwRead = std::min(size, static_cast<size_t>(dwSize - offset));
+    FXSYS_memcpy(buffer, acc.GetData() + offset, dwRead);
+    size -= dwRead;
+    if (size == 0) {
+      return TRUE;
+    }
+    buffer = (uint8_t*)buffer + dwRead;
+    offset = 0;
+    index++;
+  }
+  return FALSE;
+}
+// static
+IXFA_App* IXFA_App::Create(IXFA_AppProvider* pProvider) {
+  return new CXFA_FFApp(pProvider);
+}
+// virtual
+IXFA_App::~IXFA_App() {}
+CXFA_FFApp::CXFA_FFApp(IXFA_AppProvider* pProvider)
+    : m_pDocHandler(nullptr),
+      m_pFWLTheme(nullptr),
+      m_pProvider(pProvider),
+      m_pFontMgr(nullptr),
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+      m_pFontSource(nullptr),
+#endif
+      m_pAdapterWidgetMgr(nullptr),
+      m_pWidgetMgrDelegate(nullptr),
+      m_pFDEFontMgr(nullptr),
+      m_pMenuHandler(nullptr),
+      m_pAdapterThreadMgr(nullptr) {
+  m_pFWLApp = IFWL_App::Create(this);
+  FWL_SetApp(m_pFWLApp);
+  m_pFWLApp->Initialize();
+  IXFA_TimeZoneProvider::Create();
+}
+CXFA_FFApp::~CXFA_FFApp() {
+  delete m_pDocHandler;
+  if (m_pFWLApp) {
+    m_pFWLApp->Finalize();
+    m_pFWLApp->Release();
+    delete m_pFWLApp;
+  }
+  if (m_pFWLTheme)
+    m_pFWLTheme->Release();
+  delete m_pAdapterWidgetMgr;
+  delete m_pAdapterThreadMgr;
+  delete m_pMenuHandler;
+  IXFA_TimeZoneProvider::Destroy();
+  delete m_pFontMgr;
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+  if (m_pFontSource)
+    m_pFontSource->Release();
+#endif
+  if (m_pFDEFontMgr)
+    m_pFDEFontMgr->Release();
+}
+IXFA_MenuHandler* CXFA_FFApp::GetMenuHandler() {
+  if (!m_pMenuHandler) {
+    m_pMenuHandler = new CXFA_FFMenuHandler;
+  }
+  return m_pMenuHandler;
+}
+IXFA_DocHandler* CXFA_FFApp::GetDocHandler() {
+  if (!m_pDocHandler) {
+    m_pDocHandler = new CXFA_FFDocHandler;
+  }
+  return m_pDocHandler;
+}
+IXFA_Doc* CXFA_FFApp::CreateDoc(IXFA_DocProvider* pProvider,
+                                IFX_FileRead* pStream,
+                                FX_BOOL bTakeOverFile) {
+  CXFA_FFDoc* pDoc = new CXFA_FFDoc(this, pProvider);
+  FX_BOOL bSuccess = pDoc->OpenDoc(pStream, bTakeOverFile);
+  if (!bSuccess) {
+    delete pDoc;
+    pDoc = NULL;
+  }
+  return pDoc;
+}
+IXFA_Doc* CXFA_FFApp::CreateDoc(IXFA_DocProvider* pProvider,
+                                CPDF_Document* pPDFDoc) {
+  if (pPDFDoc == NULL) {
+    return NULL;
+  }
+  CXFA_FFDoc* pDoc = new CXFA_FFDoc(this, pProvider);
+  FX_BOOL bSuccess = pDoc->OpenDoc(pPDFDoc);
+  if (!bSuccess) {
+    delete pDoc;
+    pDoc = NULL;
+  }
+  return pDoc;
+}
+
+void CXFA_FFApp::SetDefaultFontMgr(IXFA_FontMgr* pFontMgr) {
+  if (!m_pFontMgr) {
+    m_pFontMgr = new CXFA_FontMgr();
+  }
+  m_pFontMgr->SetDefFontMgr(pFontMgr);
+}
+CXFA_FontMgr* CXFA_FFApp::GetXFAFontMgr() {
+  return m_pFontMgr;
+}
+IFX_FontMgr* CXFA_FFApp::GetFDEFontMgr() {
+  if (!m_pFDEFontMgr) {
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+    m_pFDEFontMgr = IFX_FontMgr::Create(FX_GetDefFontEnumerator());
+#else
+    m_pFontSource = FX_CreateDefaultFontSourceEnum();
+    m_pFDEFontMgr = IFX_FontMgr::Create(m_pFontSource);
+#endif
+  }
+  return m_pFDEFontMgr;
+}
+CXFA_FWLTheme* CXFA_FFApp::GetFWLTheme() {
+  if (!m_pFWLTheme) {
+    m_pFWLTheme = new CXFA_FWLTheme(this);
+  }
+  return m_pFWLTheme;
+}
+IFWL_AdapterWidgetMgr* CXFA_FFApp::GetWidgetMgr(
+    IFWL_WidgetMgrDelegate* pDelegate) {
+  if (!m_pAdapterWidgetMgr) {
+    m_pAdapterWidgetMgr = new CXFA_FWLAdapterWidgetMgr;
+    pDelegate->OnSetCapability(FWL_WGTMGR_DisableThread |
+                               FWL_WGTMGR_DisableForm);
+    m_pWidgetMgrDelegate = pDelegate;
+  }
+  return m_pAdapterWidgetMgr;
+}
+IFWL_AdapterThreadMgr* CXFA_FFApp::GetThreadMgr() {
+  if (!m_pAdapterThreadMgr) {
+    m_pAdapterThreadMgr = new CFWL_SDAdapterThreadMgr;
+  }
+  return m_pAdapterThreadMgr;
+}
+IFWL_AdapterTimerMgr* CXFA_FFApp::GetTimerMgr() {
+  return m_pProvider->GetTimerMgr();
+}
diff --git a/xfa/fxfa/app/xfa_ffapp.h b/xfa/fxfa/app/xfa_ffapp.h
new file mode 100644
index 0000000..0374d4a
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffapp.h
@@ -0,0 +1,81 @@
+// 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_FXFA_APP_XFA_FFAPP_H_
+#define XFA_FXFA_APP_XFA_FFAPP_H_
+
+#include "core/include/fpdfapi/cpdf_stream.h"
+#include "xfa/fgas/font/fgas_font.h"
+#include "xfa/include/fwl/adapter/fwl_adapternative.h"
+#include "xfa/include/fwl/adapter/fwl_sdadapterimp.h"
+#include "xfa/include/fwl/core/fwl_app.h"
+#include "xfa/include/fxfa/fxfa.h"
+
+class CXFA_FWLAdapterWidgetMgr;
+class CXFA_FWLTheme;
+class CXFA_FFDocHandler;
+class CXFA_FFMenuHandler;
+class CXFA_FontMgr;
+
+class CXFA_FileRead : public IFX_FileRead {
+ public:
+  explicit CXFA_FileRead(const CFX_ArrayTemplate<CPDF_Stream*>& streams);
+
+  virtual FX_FILESIZE GetSize();
+  virtual FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size);
+
+  virtual void Release() { delete this; }
+
+ protected:
+  CFX_ObjectArray<CPDF_StreamAcc> m_Data;
+};
+
+class CXFA_FFApp : public IXFA_App, public IFWL_AdapterNative {
+ public:
+  CXFA_FFApp(IXFA_AppProvider* pProvider);
+  ~CXFA_FFApp() override;
+
+  // IFXFA_App:
+  IXFA_DocHandler* GetDocHandler() override;
+  IXFA_Doc* CreateDoc(IXFA_DocProvider* pProvider,
+                      IFX_FileRead* pStream,
+                      FX_BOOL bTakeOverFile) override;
+  IXFA_Doc* CreateDoc(IXFA_DocProvider* pProvider,
+                      CPDF_Document* pPDFDoc) override;
+  IXFA_AppProvider* GetAppProvider() override { return m_pProvider; }
+  void SetDefaultFontMgr(IXFA_FontMgr* pFontMgr) override;
+  IXFA_MenuHandler* GetMenuHandler() override;
+
+  // IFWL_AdapterNative:
+  IFWL_AdapterWidgetMgr* GetWidgetMgr(
+      IFWL_WidgetMgrDelegate* pDelegate) override;
+  IFWL_AdapterThreadMgr* GetThreadMgr() override;
+  IFWL_AdapterTimerMgr* GetTimerMgr() override;
+
+  CXFA_FontMgr* GetXFAFontMgr();
+  IFX_FontMgr* GetFDEFontMgr();
+  CXFA_FWLTheme* GetFWLTheme();
+  IFWL_WidgetMgrDelegate* GetWidgetMgrDelegate() {
+    return m_pWidgetMgrDelegate;
+  }
+
+ protected:
+  CXFA_FFDocHandler* m_pDocHandler;
+  IFWL_App* m_pFWLApp;
+  CXFA_FWLTheme* m_pFWLTheme;
+  IXFA_AppProvider* m_pProvider;
+  CXFA_FontMgr* m_pFontMgr;
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+  IFX_FontSourceEnum* m_pFontSource;
+#endif
+  CXFA_FWLAdapterWidgetMgr* m_pAdapterWidgetMgr;
+  IFWL_WidgetMgrDelegate* m_pWidgetMgrDelegate;
+  IFX_FontMgr* m_pFDEFontMgr;
+  CXFA_FFMenuHandler* m_pMenuHandler;
+  CFWL_SDAdapterThreadMgr* m_pAdapterThreadMgr;
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFAPP_H_
diff --git a/xfa/fxfa/app/xfa_ffbarcode.cpp b/xfa/fxfa/app/xfa_ffbarcode.cpp
new file mode 100644
index 0000000..2062ca1
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffbarcode.cpp
@@ -0,0 +1,235 @@
+// 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/fxfa/app/xfa_ffbarcode.h"
+
+#include "core/include/fxcrt/fx_ext.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_fftextedit.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_fwladapter.h"
+#include "xfa/include/fwl/core/fwl_app.h"
+#include "xfa/include/fwl/lightwidget/barcode.h"
+
+static XFA_LPCBARCODETYPEENUMINFO XFA_GetBarcodeTypeByName(
+    const CFX_WideStringC& wsName);
+CXFA_FFBarcode::CXFA_FFBarcode(CXFA_FFPageView* pPageView,
+                               CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFTextEdit(pPageView, pDataAcc) {}
+CXFA_FFBarcode::~CXFA_FFBarcode() {}
+FX_BOOL CXFA_FFBarcode::LoadWidget() {
+  CFWL_Barcode* pFWLBarcode = CFWL_Barcode::Create();
+  if (pFWLBarcode) {
+    pFWLBarcode->Initialize();
+  }
+  m_pNormalWidget = pFWLBarcode;
+  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
+  m_pNormalWidget->SetPrivateData(pWidget, this, NULL);
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  m_pOldDelegate = m_pNormalWidget->SetDelegate(this);
+  m_pNormalWidget->LockUpdate();
+  CFX_WideString wsText;
+  m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Display);
+  pFWLBarcode->SetText(wsText);
+  UpdateWidgetProperty();
+  m_pNormalWidget->UnlockUpdate();
+  return CXFA_FFField::LoadWidget();
+}
+void CXFA_FFBarcode::RenderWidget(CFX_Graphics* pGS,
+                                  CFX_Matrix* pMatrix,
+                                  FX_DWORD dwStatus,
+                                  int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
+  CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
+  DrawBorder(pGS, borderUI, m_rtUI, &mtRotate);
+  RenderCaption(pGS, &mtRotate);
+  CFX_RectF rtWidget;
+  m_pNormalWidget->GetWidgetRect(rtWidget);
+  CFX_Matrix mt;
+  mt.Set(1, 0, 0, 1, rtWidget.left, rtWidget.top);
+  mt.Concat(mtRotate);
+  m_pNormalWidget->DrawWidget(pGS, &mt);
+}
+void CXFA_FFBarcode::UpdateWidgetProperty() {
+  CXFA_FFTextEdit::UpdateWidgetProperty();
+  CFWL_Barcode* pBarCodeWidget = (CFWL_Barcode*)m_pNormalWidget;
+  CFX_WideString wsType = GetDataAcc()->GetBarcodeType();
+  XFA_LPCBARCODETYPEENUMINFO pBarcodeTypeInfo =
+      XFA_GetBarcodeTypeByName(wsType);
+  pBarCodeWidget->SetType(pBarcodeTypeInfo->eBCType);
+  CXFA_WidgetAcc* pAcc = GetDataAcc();
+  int32_t intVal;
+  FX_CHAR charVal;
+  FX_BOOL boolVal;
+  FX_FLOAT floatVal;
+  if (pAcc->GetBarcodeAttribute_CharEncoding(intVal)) {
+    pBarCodeWidget->SetCharEncoding((BC_CHAR_ENCODING)intVal);
+  }
+  if (pAcc->GetBarcodeAttribute_Checksum(intVal)) {
+    pBarCodeWidget->SetCalChecksum(intVal);
+  }
+  if (pAcc->GetBarcodeAttribute_DataLength(intVal)) {
+    pBarCodeWidget->SetDataLength(intVal);
+  }
+  if (pAcc->GetBarcodeAttribute_StartChar(charVal)) {
+    pBarCodeWidget->SetStartChar(charVal);
+  }
+  if (pAcc->GetBarcodeAttribute_EndChar(charVal)) {
+    pBarCodeWidget->SetEndChar(charVal);
+  }
+  if (pAcc->GetBarcodeAttribute_ECLevel(intVal)) {
+    pBarCodeWidget->SetErrorCorrectionLevel(intVal);
+  }
+  if (pAcc->GetBarcodeAttribute_ModuleWidth(intVal)) {
+    pBarCodeWidget->SetModuleWidth(intVal);
+  }
+  if (pAcc->GetBarcodeAttribute_ModuleHeight(intVal)) {
+    pBarCodeWidget->SetModuleHeight(intVal);
+  }
+  if (pAcc->GetBarcodeAttribute_PrintChecksum(boolVal)) {
+    pBarCodeWidget->SetPrintChecksum(boolVal);
+  }
+  if (pAcc->GetBarcodeAttribute_TextLocation(intVal)) {
+    pBarCodeWidget->SetTextLocation((BC_TEXT_LOC)intVal);
+  }
+  if (pAcc->GetBarcodeAttribute_Truncate(boolVal)) {
+    pBarCodeWidget->SetTruncated(boolVal);
+  }
+  if (pAcc->GetBarcodeAttribute_WideNarrowRatio(floatVal)) {
+    pBarCodeWidget->SetWideNarrowRatio((int32_t)floatVal);
+  }
+  if (pBarcodeTypeInfo->eName == XFA_BARCODETYPE_code3Of9 ||
+      pBarcodeTypeInfo->eName == XFA_BARCODETYPE_ean8 ||
+      pBarcodeTypeInfo->eName == XFA_BARCODETYPE_ean13 ||
+      pBarcodeTypeInfo->eName == XFA_BARCODETYPE_upcA) {
+    pBarCodeWidget->SetPrintChecksum(TRUE);
+  }
+}
+FX_BOOL CXFA_FFBarcode::OnLButtonDown(FX_DWORD dwFlags,
+                                      FX_FLOAT fx,
+                                      FX_FLOAT fy) {
+  CFWL_Barcode* pBarCodeWidget = (CFWL_Barcode*)m_pNormalWidget;
+  if (!pBarCodeWidget || pBarCodeWidget->IsProtectedType()) {
+    return FALSE;
+  }
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) {
+    return FALSE;
+  }
+  return CXFA_FFTextEdit::OnLButtonDown(dwFlags, fx, fy);
+}
+FX_BOOL CXFA_FFBarcode::OnRButtonDown(FX_DWORD dwFlags,
+                                      FX_FLOAT fx,
+                                      FX_FLOAT fy) {
+  CFWL_Barcode* pBarCodeWidget = (CFWL_Barcode*)m_pNormalWidget;
+  if (!pBarCodeWidget || pBarCodeWidget->IsProtectedType()) {
+    return FALSE;
+  }
+  return CXFA_FFTextEdit::OnRButtonDown(dwFlags, fx, fy);
+}
+extern const XFA_BARCODETYPEENUMINFO g_XFABarCodeTypeEnumData[] = {
+    {0x7fb4a18, L"ean13", XFA_BARCODETYPE_ean13, BC_EAN13},
+    {0x8d13a3d, L"code11", XFA_BARCODETYPE_code11, BC_UNKNOWN},
+    {0x8d149a8, L"code49", XFA_BARCODETYPE_code49, BC_UNKNOWN},
+    {0x8d16347, L"code93", XFA_BARCODETYPE_code93, BC_UNKNOWN},
+    {0x91a92e2, L"upsMaxicode", XFA_BARCODETYPE_upsMaxicode, BC_UNKNOWN},
+    {0xa7d48dc, L"fim", XFA_BARCODETYPE_fim, BC_UNKNOWN},
+    {0xb359fe9, L"msi", XFA_BARCODETYPE_msi, BC_UNKNOWN},
+    {0x121f738c, L"code2Of5Matrix", XFA_BARCODETYPE_code2Of5Matrix, BC_UNKNOWN},
+    {0x15358616, L"ucc128", XFA_BARCODETYPE_ucc128, BC_UNKNOWN},
+    {0x1f4bfa05, L"rfid", XFA_BARCODETYPE_rfid, BC_UNKNOWN},
+    {0x1fda71bc, L"rss14Stacked", XFA_BARCODETYPE_rss14Stacked, BC_UNKNOWN},
+    {0x22065087, L"ean8add2", XFA_BARCODETYPE_ean8add2, BC_UNKNOWN},
+    {0x2206508a, L"ean8add5", XFA_BARCODETYPE_ean8add5, BC_UNKNOWN},
+    {0x2278366c, L"codabar", XFA_BARCODETYPE_codabar, BC_CODABAR},
+    {0x2a039a8d, L"telepen", XFA_BARCODETYPE_telepen, BC_UNKNOWN},
+    {0x323ed337, L"upcApwcd", XFA_BARCODETYPE_upcApwcd, BC_UNKNOWN},
+    {0x347a1846, L"postUSIMB", XFA_BARCODETYPE_postUSIMB, BC_UNKNOWN},
+    {0x391bb836, L"code128", XFA_BARCODETYPE_code128, BC_CODE128},
+    {0x398eddaf, L"dataMatrix", XFA_BARCODETYPE_dataMatrix, BC_DATAMATRIX},
+    {0x3cff60a8, L"upcEadd2", XFA_BARCODETYPE_upcEadd2, BC_UNKNOWN},
+    {0x3cff60ab, L"upcEadd5", XFA_BARCODETYPE_upcEadd5, BC_UNKNOWN},
+    {0x402cb188, L"code2Of5Standard", XFA_BARCODETYPE_code2Of5Standard,
+     BC_UNKNOWN},
+    {0x411764f7, L"aztec", XFA_BARCODETYPE_aztec, BC_UNKNOWN},
+    {0x44d4e84c, L"ean8", XFA_BARCODETYPE_ean8, BC_EAN8},
+    {0x48468902, L"ucc128sscc", XFA_BARCODETYPE_ucc128sscc, BC_UNKNOWN},
+    {0x4880aea4, L"upcAadd2", XFA_BARCODETYPE_upcAadd2, BC_UNKNOWN},
+    {0x4880aea7, L"upcAadd5", XFA_BARCODETYPE_upcAadd5, BC_UNKNOWN},
+    {0x54f18256, L"code2Of5Industrial", XFA_BARCODETYPE_code2Of5Industrial,
+     BC_UNKNOWN},
+    {0x58e15f25, L"rss14Limited", XFA_BARCODETYPE_rss14Limited, BC_UNKNOWN},
+    {0x5c08d1b9, L"postAUSReplyPaid", XFA_BARCODETYPE_postAUSReplyPaid,
+     BC_UNKNOWN},
+    {0x5fa700bd, L"rss14", XFA_BARCODETYPE_rss14, BC_UNKNOWN},
+    {0x631a7e35, L"logmars", XFA_BARCODETYPE_logmars, BC_UNKNOWN},
+    {0x6a236236, L"pdf417", XFA_BARCODETYPE_pdf417, BC_PDF417},
+    {0x6d098ece, L"upcean2", XFA_BARCODETYPE_upcean2, BC_UNKNOWN},
+    {0x6d098ed1, L"upcean5", XFA_BARCODETYPE_upcean5, BC_UNKNOWN},
+    {0x76b04eed, L"code3Of9extended", XFA_BARCODETYPE_code3Of9extended,
+     BC_UNKNOWN},
+    {0x7c7db84a, L"maxicode", XFA_BARCODETYPE_maxicode, BC_UNKNOWN},
+    {0x8266f7f7, L"ucc128random", XFA_BARCODETYPE_ucc128random, BC_UNKNOWN},
+    {0x83eca147, L"postUSDPBC", XFA_BARCODETYPE_postUSDPBC, BC_UNKNOWN},
+    {0x8dd71de0, L"postAUSStandard", XFA_BARCODETYPE_postAUSStandard,
+     BC_UNKNOWN},
+    {0x98adad85, L"plessey", XFA_BARCODETYPE_plessey, BC_UNKNOWN},
+    {0x9f84cce6, L"ean13pwcd", XFA_BARCODETYPE_ean13pwcd, BC_UNKNOWN},
+    {0xb514fbe9, L"upcA", XFA_BARCODETYPE_upcA, BC_UPCA},
+    {0xb514fbed, L"upcE", XFA_BARCODETYPE_upcE, BC_UNKNOWN},
+    {0xb5c6a853, L"ean13add2", XFA_BARCODETYPE_ean13add2, BC_UNKNOWN},
+    {0xb5c6a856, L"ean13add5", XFA_BARCODETYPE_ean13add5, BC_UNKNOWN},
+    {0xb81fc512, L"postUKRM4SCC", XFA_BARCODETYPE_postUKRM4SCC, BC_UNKNOWN},
+    {0xbad34b22, L"code128SSCC", XFA_BARCODETYPE_code128SSCC, BC_UNKNOWN},
+    {0xbfbe0cf6, L"postUS5Zip", XFA_BARCODETYPE_postUS5Zip, BC_UNKNOWN},
+    {0xc56618e8, L"pdf417macro", XFA_BARCODETYPE_pdf417macro, BC_UNKNOWN},
+    {0xca730f8a, L"code2Of5Interleaved", XFA_BARCODETYPE_code2Of5Interleaved,
+     BC_UNKNOWN},
+    {0xd0097ac6, L"rss14Expanded", XFA_BARCODETYPE_rss14Expanded, BC_UNKNOWN},
+    {0xd25a0240, L"postAUSCust2", XFA_BARCODETYPE_postAUSCust2, BC_UNKNOWN},
+    {0xd25a0241, L"postAUSCust3", XFA_BARCODETYPE_postAUSCust3, BC_UNKNOWN},
+    {0xd53ed3e7, L"rss14Truncated", XFA_BARCODETYPE_rss14Truncated, BC_UNKNOWN},
+    {0xe72bcd57, L"code128A", XFA_BARCODETYPE_code128A, BC_UNKNOWN},
+    {0xe72bcd58, L"code128B", XFA_BARCODETYPE_code128B, BC_CODE128_B},
+    {0xe72bcd59, L"code128C", XFA_BARCODETYPE_code128C, BC_CODE128_C},
+    {0xee83c50f, L"rss14StackedOmni", XFA_BARCODETYPE_rss14StackedOmni,
+     BC_UNKNOWN},
+    {0xf2a18f7e, L"QRCode", XFA_BARCODETYPE_QRCode, BC_QR_CODE},
+    {0xfaeaf37f, L"postUSStandard", XFA_BARCODETYPE_postUSStandard, BC_UNKNOWN},
+    {0xfb48155c, L"code3Of9", XFA_BARCODETYPE_code3Of9, BC_CODE39},
+};
+extern const int32_t g_iXFABarcodeTypeCount =
+    sizeof(g_XFABarCodeTypeEnumData) / sizeof(XFA_BARCODETYPEENUMINFO);
+static XFA_LPCBARCODETYPEENUMINFO XFA_GetBarcodeTypeByName(
+    const CFX_WideStringC& wsName) {
+  int32_t iLength = wsName.GetLength();
+  if (iLength == 0) {
+    return NULL;
+  }
+  uint32_t uHash = FX_HashCode_String_GetW(wsName.GetPtr(), iLength, TRUE);
+  int32_t iStart = 0, iEnd = g_iXFABarcodeTypeCount - 1;
+  do {
+    int32_t iMid = (iStart + iEnd) / 2;
+    XFA_LPCBARCODETYPEENUMINFO pInfo = g_XFABarCodeTypeEnumData + iMid;
+    if (uHash == pInfo->uHash) {
+      return pInfo;
+    } else if (uHash < pInfo->uHash) {
+      iEnd = iMid - 1;
+    } else {
+      iStart = iMid + 1;
+    }
+  } while (iStart <= iEnd);
+  return NULL;
+}
diff --git a/xfa/fxfa/app/xfa_ffbarcode.h b/xfa/fxfa/app/xfa_ffbarcode.h
new file mode 100644
index 0000000..114a492
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffbarcode.h
@@ -0,0 +1,101 @@
+// 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_FXFA_APP_XFA_FFBARCODE_H_
+#define XFA_FXFA_APP_XFA_FFBARCODE_H_
+
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_fftextedit.h"
+#include "xfa/include/fxbarcode/BC_BarCode.h"
+
+class CXFA_FFBarcode : public CXFA_FFTextEdit {
+ public:
+  CXFA_FFBarcode(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFBarcode();
+  virtual FX_BOOL LoadWidget();
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+  virtual void UpdateWidgetProperty();
+  virtual FX_BOOL OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+};
+
+enum XFA_BARCODETYPEENUM {
+  XFA_BARCODETYPE_aztec,
+  XFA_BARCODETYPE_codabar,
+  XFA_BARCODETYPE_code11,
+  XFA_BARCODETYPE_code128,
+  XFA_BARCODETYPE_code128A,
+  XFA_BARCODETYPE_code128B,
+  XFA_BARCODETYPE_code128C,
+  XFA_BARCODETYPE_code128SSCC,
+  XFA_BARCODETYPE_code2Of5Industrial,
+  XFA_BARCODETYPE_code2Of5Interleaved,
+  XFA_BARCODETYPE_code2Of5Matrix,
+  XFA_BARCODETYPE_code2Of5Standard,
+  XFA_BARCODETYPE_code3Of9,
+  XFA_BARCODETYPE_code3Of9extended,
+  XFA_BARCODETYPE_code49,
+  XFA_BARCODETYPE_code93,
+  XFA_BARCODETYPE_dataMatrix,
+  XFA_BARCODETYPE_ean13,
+  XFA_BARCODETYPE_ean13add2,
+  XFA_BARCODETYPE_ean13add5,
+  XFA_BARCODETYPE_ean13pwcd,
+  XFA_BARCODETYPE_ean8,
+  XFA_BARCODETYPE_ean8add2,
+  XFA_BARCODETYPE_ean8add5,
+  XFA_BARCODETYPE_fim,
+  XFA_BARCODETYPE_logmars,
+  XFA_BARCODETYPE_maxicode,
+  XFA_BARCODETYPE_msi,
+  XFA_BARCODETYPE_pdf417,
+  XFA_BARCODETYPE_pdf417macro,
+  XFA_BARCODETYPE_plessey,
+  XFA_BARCODETYPE_postAUSCust2,
+  XFA_BARCODETYPE_postAUSCust3,
+  XFA_BARCODETYPE_postAUSReplyPaid,
+  XFA_BARCODETYPE_postAUSStandard,
+  XFA_BARCODETYPE_postUKRM4SCC,
+  XFA_BARCODETYPE_postUS5Zip,
+  XFA_BARCODETYPE_postUSDPBC,
+  XFA_BARCODETYPE_postUSIMB,
+  XFA_BARCODETYPE_postUSStandard,
+  XFA_BARCODETYPE_QRCode,
+  XFA_BARCODETYPE_rfid,
+  XFA_BARCODETYPE_rss14,
+  XFA_BARCODETYPE_rss14Expanded,
+  XFA_BARCODETYPE_rss14Limited,
+  XFA_BARCODETYPE_rss14Stacked,
+  XFA_BARCODETYPE_rss14StackedOmni,
+  XFA_BARCODETYPE_rss14Truncated,
+  XFA_BARCODETYPE_telepen,
+  XFA_BARCODETYPE_ucc128,
+  XFA_BARCODETYPE_ucc128random,
+  XFA_BARCODETYPE_ucc128sscc,
+  XFA_BARCODETYPE_upcA,
+  XFA_BARCODETYPE_upcAadd2,
+  XFA_BARCODETYPE_upcAadd5,
+  XFA_BARCODETYPE_upcApwcd,
+  XFA_BARCODETYPE_upcE,
+  XFA_BARCODETYPE_upcEadd2,
+  XFA_BARCODETYPE_upcEadd5,
+  XFA_BARCODETYPE_upcean2,
+  XFA_BARCODETYPE_upcean5,
+  XFA_BARCODETYPE_upsMaxicode
+};
+struct XFA_BARCODETYPEENUMINFO {
+  uint32_t uHash;
+  const FX_WCHAR* pName;
+  XFA_BARCODETYPEENUM eName;
+  BC_TYPE eBCType;
+};
+typedef XFA_BARCODETYPEENUMINFO const* XFA_LPCBARCODETYPEENUMINFO;
+extern const XFA_BARCODETYPEENUMINFO g_XFABarCodeTypeEnumData[];
+
+#endif  // XFA_FXFA_APP_XFA_FFBARCODE_H_
diff --git a/xfa/fxfa/app/xfa_ffcheckbutton.cpp b/xfa/fxfa/app/xfa_ffcheckbutton.cpp
new file mode 100644
index 0000000..862a2cd
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffcheckbutton.cpp
@@ -0,0 +1,335 @@
+// 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/fxfa/app/xfa_ffcheckbutton.h"
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_ffexclgroup.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/include/fwl/core/fwl_widgetmgr.h"
+#include "xfa/include/fwl/lightwidget/checkbox.h"
+
+CXFA_FFCheckButton::CXFA_FFCheckButton(CXFA_FFPageView* pPageView,
+                                       CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFField(pPageView, pDataAcc), m_pOldDelegate(NULL) {
+  m_rtCheckBox.Set(0, 0, 0, 0);
+}
+CXFA_FFCheckButton::~CXFA_FFCheckButton() {}
+FX_BOOL CXFA_FFCheckButton::LoadWidget() {
+  CFWL_CheckBox* pCheckBox = CFWL_CheckBox::Create();
+  pCheckBox->Initialize();
+  m_pNormalWidget = pCheckBox;
+  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
+  m_pNormalWidget->SetPrivateData(pWidget, this, NULL);
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  m_pOldDelegate = m_pNormalWidget->SetDelegate(this);
+  if (m_pDataAcc->IsRadioButton()) {
+    pCheckBox->ModifyStylesEx(FWL_STYLEEXT_CKB_RadioButton, 0xFFFFFFFF);
+  }
+  m_pNormalWidget = (CFWL_Widget*)pCheckBox;
+  m_pNormalWidget->SetPrivateData(m_pNormalWidget->GetWidget(), this, NULL);
+  m_pNormalWidget->LockUpdate();
+  UpdateWidgetProperty();
+  XFA_CHECKSTATE eState = m_pDataAcc->GetCheckState();
+  SetFWLCheckState(eState);
+  m_pNormalWidget->UnlockUpdate();
+  return CXFA_FFField::LoadWidget();
+}
+void CXFA_FFCheckButton::UpdateWidgetProperty() {
+  CFWL_CheckBox* pCheckBox = (CFWL_CheckBox*)m_pNormalWidget;
+  if (!m_pNormalWidget) {
+    return;
+  }
+  FX_FLOAT fSize = m_pDataAcc->GetCheckButtonSize();
+  pCheckBox->SetBoxSize(fSize);
+  FX_DWORD dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCross;
+  int32_t iCheckMark = m_pDataAcc->GetCheckButtonMark();
+  switch (iCheckMark) {
+    case XFA_ATTRIBUTEENUM_Check:
+      dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCheck;
+      break;
+    case XFA_ATTRIBUTEENUM_Circle:
+      dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle;
+      break;
+    case XFA_ATTRIBUTEENUM_Cross:
+      break;
+    case XFA_ATTRIBUTEENUM_Diamond:
+      dwStyleEx = FWL_STYLEEXT_CKB_SignShapeDiamond;
+      break;
+    case XFA_ATTRIBUTEENUM_Square:
+      dwStyleEx = FWL_STYLEEXT_CKB_SignShapeSquare;
+      break;
+    case XFA_ATTRIBUTEENUM_Star:
+      dwStyleEx = FWL_STYLEEXT_CKB_SignShapeStar;
+      break;
+    default: {
+      int32_t iShape = m_pDataAcc->GetCheckButtonShape();
+      if (iShape == XFA_ATTRIBUTEENUM_Round) {
+        dwStyleEx = FWL_STYLEEXT_CKB_SignShapeCircle;
+      }
+    } break;
+  }
+  if (m_pDataAcc->IsAllowNeutral()) {
+    dwStyleEx |= FWL_STYLEEXT_CKB_3State;
+  }
+  pCheckBox->ModifyStylesEx(
+      dwStyleEx, FWL_STYLEEXT_CKB_SignShapeMask | FWL_STYLEEXT_CKB_3State);
+}
+FX_BOOL CXFA_FFCheckButton::PerformLayout() {
+  CXFA_FFWidget::PerformLayout();
+  FX_FLOAT fCheckSize = m_pDataAcc->GetCheckButtonSize();
+  CXFA_Margin mgWidget = m_pDataAcc->GetMargin();
+  CFX_RectF rtWidget;
+  GetRectWithoutRotate(rtWidget);
+  if (mgWidget) {
+    XFA_RectWidthoutMargin(rtWidget, mgWidget);
+  }
+  int32_t iCapPlacement = -1;
+  FX_FLOAT fCapReserve = 0;
+  CXFA_Caption caption = m_pDataAcc->GetCaption();
+  if (caption && caption.GetPresence()) {
+    m_rtCaption.Set(rtWidget.left, rtWidget.top, rtWidget.width,
+                    rtWidget.height);
+    iCapPlacement = caption.GetPlacementType();
+    fCapReserve = caption.GetReserve();
+    if (fCapReserve <= 0) {
+      if (iCapPlacement == XFA_ATTRIBUTEENUM_Top ||
+          iCapPlacement == XFA_ATTRIBUTEENUM_Bottom) {
+        fCapReserve = rtWidget.height - fCheckSize;
+      } else {
+        fCapReserve = rtWidget.width - fCheckSize;
+      }
+    }
+  }
+  int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left;
+  int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top;
+  if (CXFA_Para para = m_pDataAcc->GetPara()) {
+    iHorzAlign = para.GetHorizontalAlign();
+    iVertAlign = para.GetVerticalAlign();
+  }
+  m_rtUI = rtWidget;
+  CXFA_Margin mgCap = caption.GetMargin();
+  switch (iCapPlacement) {
+    case XFA_ATTRIBUTEENUM_Left: {
+      m_rtCaption.width = fCapReserve;
+      CapLeftRightPlacement(mgCap);
+      m_rtUI.width -= fCapReserve;
+      m_rtUI.left += fCapReserve;
+    } break;
+    case XFA_ATTRIBUTEENUM_Top: {
+      m_rtCaption.height = fCapReserve;
+      XFA_RectWidthoutMargin(m_rtCaption, mgCap);
+      m_rtUI.height -= fCapReserve;
+      m_rtUI.top += fCapReserve;
+    } break;
+    case XFA_ATTRIBUTEENUM_Right: {
+      m_rtCaption.left = m_rtCaption.right() - fCapReserve;
+      m_rtCaption.width = fCapReserve;
+      CapLeftRightPlacement(mgCap);
+      m_rtUI.width -= fCapReserve;
+    } break;
+    case XFA_ATTRIBUTEENUM_Bottom: {
+      m_rtCaption.top = m_rtCaption.bottom() - fCapReserve;
+      m_rtCaption.height = fCapReserve;
+      XFA_RectWidthoutMargin(m_rtCaption, mgCap);
+      m_rtUI.height -= fCapReserve;
+    } break;
+    case XFA_ATTRIBUTEENUM_Inline:
+      break;
+    default:
+      iHorzAlign = XFA_ATTRIBUTEENUM_Right;
+      break;
+  }
+  if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) {
+    m_rtUI.left += (m_rtUI.width - fCheckSize) / 2;
+  } else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) {
+    m_rtUI.left = m_rtUI.right() - fCheckSize;
+  }
+  if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) {
+    m_rtUI.top += (m_rtUI.height - fCheckSize) / 2;
+  } else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) {
+    m_rtUI.top = m_rtUI.bottom() - fCheckSize;
+  }
+  m_rtUI.width = fCheckSize;
+  m_rtUI.height = fCheckSize;
+  AddUIMargin(iCapPlacement);
+  m_rtCheckBox = m_rtUI;
+  CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
+  if (borderUI) {
+    CXFA_Margin margin = borderUI.GetMargin();
+    if (margin) {
+      XFA_RectWidthoutMargin(m_rtUI, margin);
+    }
+  }
+  m_rtUI.Normalize();
+  LayoutCaption();
+  SetFWLRect();
+  if (m_pNormalWidget) {
+    m_pNormalWidget->Update();
+  }
+  return TRUE;
+}
+void CXFA_FFCheckButton::CapLeftRightPlacement(CXFA_Margin mgCap) {
+  XFA_RectWidthoutMargin(m_rtCaption, mgCap);
+  if (m_rtCaption.height < 0) {
+    m_rtCaption.top += m_rtCaption.height;
+  }
+  if (m_rtCaption.width < 0) {
+    m_rtCaption.left += m_rtCaption.width;
+    m_rtCaption.width = -m_rtCaption.width;
+  }
+}
+void CXFA_FFCheckButton::AddUIMargin(int32_t iCapPlacement) {
+  CFX_RectF rtUIMargin;
+  m_pDataAcc->GetUIMargin(rtUIMargin);
+  m_rtUI.top -= rtUIMargin.top / 2 - rtUIMargin.height / 2;
+  FX_FLOAT fLeftAddRight = rtUIMargin.left + rtUIMargin.width;
+  FX_FLOAT fTopAddBottom = rtUIMargin.top + rtUIMargin.height;
+  if (m_rtUI.width < fLeftAddRight) {
+    if (iCapPlacement == XFA_ATTRIBUTEENUM_Right ||
+        iCapPlacement == XFA_ATTRIBUTEENUM_Left) {
+      m_rtUI.left -= fLeftAddRight - m_rtUI.width;
+    } else {
+      m_rtUI.left -= 2 * (fLeftAddRight - m_rtUI.width);
+    }
+    m_rtUI.width += 2 * (fLeftAddRight - m_rtUI.width);
+  }
+  if (m_rtUI.height < fTopAddBottom) {
+    if (iCapPlacement == XFA_ATTRIBUTEENUM_Right) {
+      m_rtUI.left -= fTopAddBottom - m_rtUI.height;
+    }
+    m_rtUI.top -= fTopAddBottom - m_rtUI.height;
+    m_rtUI.height += 2 * (fTopAddBottom - m_rtUI.height);
+  }
+}
+void CXFA_FFCheckButton::RenderWidget(CFX_Graphics* pGS,
+                                      CFX_Matrix* pMatrix,
+                                      FX_DWORD dwStatus,
+                                      int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
+  CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
+  DrawBorder(pGS, borderUI, m_rtUI, &mtRotate,
+             m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round
+                 ? XFA_DRAWBOX_ForceRound
+                 : 0);
+  RenderCaption(pGS, &mtRotate);
+  DrawHighlight(pGS, &mtRotate, dwStatus,
+                m_pDataAcc->GetCheckButtonShape() == XFA_ATTRIBUTEENUM_Round);
+  CFX_Matrix mt;
+  mt.Set(1, 0, 0, 1, m_rtCheckBox.left, m_rtCheckBox.top);
+  mt.Concat(mtRotate);
+  GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget->GetWidget(),
+                                                 pGS, &mt);
+}
+FX_BOOL CXFA_FFCheckButton::OnLButtonUp(FX_DWORD dwFlags,
+                                        FX_FLOAT fx,
+                                        FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  if (!IsButtonDown()) {
+    return FALSE;
+  }
+  SetButtonDown(FALSE);
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_LButtonUp;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+XFA_CHECKSTATE CXFA_FFCheckButton::FWLState2XFAState() {
+  XFA_CHECKSTATE eCheckState = XFA_CHECKSTATE_Off;
+  FX_DWORD dwState = m_pNormalWidget->GetStates();
+  if (dwState & FWL_STATE_CKB_Checked) {
+    eCheckState = XFA_CHECKSTATE_On;
+  } else if (dwState & FWL_STATE_CKB_Neutral) {
+    eCheckState = XFA_CHECKSTATE_Neutral;
+  }
+  return eCheckState;
+}
+FX_BOOL CXFA_FFCheckButton::CommitData() {
+  XFA_CHECKSTATE eCheckState = FWLState2XFAState();
+  m_pDataAcc->SetCheckState(eCheckState, TRUE);
+  return TRUE;
+}
+FX_BOOL CXFA_FFCheckButton::IsDataChanged() {
+  XFA_CHECKSTATE eCheckState = FWLState2XFAState();
+  return m_pDataAcc->GetCheckState() != eCheckState;
+}
+void CXFA_FFCheckButton::SetFWLCheckState(XFA_CHECKSTATE eCheckState) {
+  if (eCheckState == XFA_CHECKSTATE_Neutral) {
+    m_pNormalWidget->SetStates(FWL_STATE_CKB_Neutral, TRUE);
+  } else {
+    m_pNormalWidget->SetStates(FWL_STATE_CKB_Checked,
+                               eCheckState == XFA_CHECKSTATE_On);
+  }
+}
+FX_BOOL CXFA_FFCheckButton::UpdateFWLData() {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  XFA_CHECKSTATE eState = m_pDataAcc->GetCheckState();
+  SetFWLCheckState(eState);
+  m_pNormalWidget->Update();
+  return TRUE;
+}
+int32_t CXFA_FFCheckButton::OnProcessMessage(CFWL_Message* pMessage) {
+  return m_pOldDelegate->OnProcessMessage(pMessage);
+}
+FWL_ERR CXFA_FFCheckButton::OnProcessEvent(CFWL_Event* pEvent) {
+  CXFA_FFField::OnProcessEvent(pEvent);
+  FX_DWORD dwEventID = pEvent->GetClassID();
+  switch (dwEventID) {
+    case FWL_EVTHASH_CKB_CheckStateChanged: {
+      CXFA_EventParam eParam;
+      eParam.m_eType = XFA_EVENT_Change;
+      m_pDataAcc->GetValue(eParam.m_wsNewText, XFA_VALUEPICTURE_Raw);
+      CXFA_WidgetAcc* pFFExclGroup = m_pDataAcc->GetExclGroup();
+      if (ProcessCommittedData()) {
+        eParam.m_pTarget = pFFExclGroup;
+        if (pFFExclGroup) {
+          m_pDocView->AddValidateWidget(pFFExclGroup);
+          m_pDocView->AddCalculateWidgetAcc(pFFExclGroup);
+          pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
+        }
+        eParam.m_pTarget = m_pDataAcc;
+        m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
+      } else {
+        SetFWLCheckState(m_pDataAcc->GetCheckState());
+      }
+      if (pFFExclGroup) {
+        eParam.m_pTarget = pFFExclGroup;
+        pFFExclGroup->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam);
+      }
+      eParam.m_pTarget = m_pDataAcc;
+      m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam);
+      break;
+    }
+    default: {}
+  }
+  return m_pOldDelegate->OnProcessEvent(pEvent);
+}
+FWL_ERR CXFA_FFCheckButton::OnDrawWidget(CFX_Graphics* pGraphics,
+                                         const CFX_Matrix* pMatrix) {
+  return m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
+}
diff --git a/xfa/fxfa/app/xfa_ffcheckbutton.h b/xfa/fxfa/app/xfa_ffcheckbutton.h
new file mode 100644
index 0000000..8527365
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffcheckbutton.h
@@ -0,0 +1,43 @@
+// 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_FXFA_APP_XFA_FFCHECKBUTTON_H_
+#define XFA_FXFA_APP_XFA_FFCHECKBUTTON_H_
+
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+
+class CXFA_FFCheckButton : public CXFA_FFField {
+ public:
+  CXFA_FFCheckButton(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFCheckButton();
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+
+  virtual FX_BOOL LoadWidget();
+  virtual FX_BOOL PerformLayout();
+  virtual FX_BOOL UpdateFWLData();
+  virtual void UpdateWidgetProperty();
+  virtual FX_BOOL OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  void SetFWLCheckState(XFA_CHECKSTATE eCheckState);
+  virtual int32_t OnProcessMessage(CFWL_Message* pMessage);
+  virtual FWL_ERR OnProcessEvent(CFWL_Event* pEvent);
+  virtual FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics,
+                               const CFX_Matrix* pMatrix = NULL);
+
+ protected:
+  virtual FX_BOOL CommitData();
+  virtual FX_BOOL IsDataChanged();
+  void CapLeftRightPlacement(CXFA_Margin mgCap);
+  void AddUIMargin(int32_t iCapPlacement);
+  XFA_CHECKSTATE FWLState2XFAState();
+  IFWL_WidgetDelegate* m_pOldDelegate;
+  CFX_RectF m_rtCheckBox;
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFCHECKBUTTON_H_
diff --git a/xfa/fxfa/app/xfa_ffchoicelist.cpp b/xfa/fxfa/app/xfa_ffchoicelist.cpp
new file mode 100644
index 0000000..2789e07
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffchoicelist.cpp
@@ -0,0 +1,530 @@
+// 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/fxfa/app/xfa_ffchoicelist.h"
+
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_fwladapter.h"
+#include "xfa/include/fwl/basewidget/fwl_edit.h"
+#include "xfa/include/fwl/core/fwl_app.h"
+#include "xfa/include/fwl/lightwidget/combobox.h"
+#include "xfa/include/fwl/lightwidget/listbox.h"
+
+CXFA_FFListBox::CXFA_FFListBox(CXFA_FFPageView* pPageView,
+                               CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFField(pPageView, pDataAcc), m_pOldDelegate(NULL) {}
+CXFA_FFListBox::~CXFA_FFListBox() {
+  if (m_pNormalWidget) {
+    IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
+    IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+    pNoteDriver->UnregisterEventTarget(pWidget);
+  }
+}
+FX_BOOL CXFA_FFListBox::LoadWidget() {
+  CFWL_ListBox* pListBox = CFWL_ListBox::Create();
+  pListBox->Initialize();
+  pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll | FWL_WGTSTYLE_NoBackground,
+                         0xFFFFFFFF);
+  m_pNormalWidget = (CFWL_Widget*)pListBox;
+  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
+  m_pNormalWidget->SetPrivateData(pWidget, this, NULL);
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  m_pOldDelegate = m_pNormalWidget->SetDelegate(this);
+  m_pNormalWidget->LockUpdate();
+  CFX_WideStringArray wsLabelArray;
+  m_pDataAcc->GetChoiceListItems(wsLabelArray, FALSE);
+  int32_t iItems = wsLabelArray.GetSize();
+  for (int32_t i = 0; i < iItems; i++) {
+    pListBox->AddString(wsLabelArray[i]);
+  }
+  FX_DWORD dwExtendedStyle = FWL_STYLEEXT_LTB_ShowScrollBarFocus;
+  if (m_pDataAcc->GetChoiceListOpen() == XFA_ATTRIBUTEENUM_MultiSelect) {
+    dwExtendedStyle |= FWL_STYLEEXT_LTB_MultiSelection;
+  }
+  dwExtendedStyle |= GetAlignment();
+  m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
+  CFX_Int32Array iSelArray;
+  m_pDataAcc->GetSelectedItems(iSelArray);
+  int32_t iSelCount = iSelArray.GetSize();
+  for (int32_t j = 0; j < iSelCount; j++) {
+    FWL_HLISTITEM item = pListBox->GetItem(iSelArray[j]);
+    pListBox->SetSelItem(item, TRUE);
+  }
+  m_pNormalWidget->UnlockUpdate();
+  return CXFA_FFField::LoadWidget();
+}
+FX_BOOL CXFA_FFListBox::OnKillFocus(CXFA_FFWidget* pNewFocus) {
+  FX_BOOL flag = ProcessCommittedData();
+  if (!flag) {
+    UpdateFWLData();
+  }
+  CXFA_FFField::OnKillFocus(pNewFocus);
+  return TRUE;
+}
+FX_BOOL CXFA_FFListBox::CommitData() {
+  CFWL_ListBox* pListBox = static_cast<CFWL_ListBox*>(m_pNormalWidget);
+  int32_t iSels = pListBox->CountSelItems();
+  CFX_Int32Array iSelArray;
+  for (int32_t i = 0; i < iSels; i++) {
+    iSelArray.Add(pListBox->GetSelIndex(i));
+  }
+  m_pDataAcc->SetSelectdItems(iSelArray, TRUE);
+  return TRUE;
+}
+FX_BOOL CXFA_FFListBox::IsDataChanged() {
+  CFX_Int32Array iSelArray;
+  m_pDataAcc->GetSelectedItems(iSelArray);
+  int32_t iOldSels = iSelArray.GetSize();
+  CFWL_ListBox* pListBox = (CFWL_ListBox*)m_pNormalWidget;
+  int32_t iSels = pListBox->CountSelItems();
+  if (iOldSels == iSels) {
+    int32_t iIndex = 0;
+    for (; iIndex < iSels; iIndex++) {
+      FWL_HLISTITEM hlistItem = pListBox->GetItem(iSelArray[iIndex]);
+      if (!(pListBox->GetItemStates(hlistItem) && FWL_ITEMSTATE_LTB_Selected)) {
+        break;
+      }
+    }
+    if (iIndex == iSels) {
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
+FX_DWORD CXFA_FFListBox::GetAlignment() {
+  FX_DWORD dwExtendedStyle = 0;
+  if (CXFA_Para para = m_pDataAcc->GetPara()) {
+    int32_t iHorz = para.GetHorizontalAlign();
+    switch (iHorz) {
+      case XFA_ATTRIBUTEENUM_Center:
+        dwExtendedStyle |= FWL_STYLEEXT_LTB_CenterAlign;
+        break;
+      case XFA_ATTRIBUTEENUM_Justify:
+        break;
+      case XFA_ATTRIBUTEENUM_JustifyAll:
+        break;
+      case XFA_ATTRIBUTEENUM_Radix:
+        break;
+      case XFA_ATTRIBUTEENUM_Right:
+        dwExtendedStyle |= FWL_STYLEEXT_LTB_RightAlign;
+        break;
+      default:
+        dwExtendedStyle |= FWL_STYLEEXT_LTB_LeftAlign;
+        break;
+    }
+  }
+  return dwExtendedStyle;
+}
+FX_BOOL CXFA_FFListBox::UpdateFWLData() {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFWL_ListBox* pListBox = ((CFWL_ListBox*)m_pNormalWidget);
+  CFX_ArrayTemplate<FWL_HLISTITEM> selItemArray;
+  CFX_Int32Array iSelArray;
+  m_pDataAcc->GetSelectedItems(iSelArray);
+  int32_t iSelCount = iSelArray.GetSize();
+  for (int32_t j = 0; j < iSelCount; j++) {
+    FWL_HLISTITEM lpItemSel = pListBox->GetSelItem(iSelArray[j]);
+    selItemArray.Add(lpItemSel);
+  }
+  pListBox->SetSelItem(pListBox->GetSelItem(-1), FALSE);
+  for (int32_t i = 0; i < iSelCount; i++) {
+    ((CFWL_ListBox*)m_pNormalWidget)->SetSelItem(selItemArray[i], TRUE);
+  }
+  m_pNormalWidget->Update();
+  return TRUE;
+}
+void CXFA_FFListBox::OnSelectChanged(IFWL_Widget* pWidget,
+                                     const CFX_Int32Array& arrSels) {
+  CXFA_EventParam eParam;
+  eParam.m_eType = XFA_EVENT_Change;
+  eParam.m_pTarget = m_pDataAcc;
+  m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw);
+  CFWL_ListBox* pListBox = (CFWL_ListBox*)m_pNormalWidget;
+  int32_t iSels = pListBox->CountSelItems();
+  if (iSels > 0) {
+    pListBox->GetItemText(pListBox->GetSelItem(0), eParam.m_wsNewText);
+  }
+  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
+}
+void CXFA_FFListBox::SetItemState(int32_t nIndex, FX_BOOL bSelected) {
+  FWL_HLISTITEM item = ((CFWL_ListBox*)m_pNormalWidget)->GetSelItem(nIndex);
+  ((CFWL_ListBox*)m_pNormalWidget)->SetSelItem(item, bSelected);
+  m_pNormalWidget->Update();
+  AddInvalidateRect();
+}
+void CXFA_FFListBox::InsertItem(const CFX_WideStringC& wsLabel,
+                                int32_t nIndex) {
+  CFX_WideString wsTemp(wsLabel);
+  ((CFWL_ListBox*)m_pNormalWidget)->AddString(wsTemp);
+  m_pNormalWidget->Update();
+  AddInvalidateRect();
+}
+void CXFA_FFListBox::DeleteItem(int32_t nIndex) {
+  if (nIndex < 0) {
+    ((CFWL_ListBox*)m_pNormalWidget)->DeleteAll();
+  } else {
+    ((CFWL_ListBox*)m_pNormalWidget)
+        ->DeleteString(((CFWL_ListBox*)m_pNormalWidget)->GetItem(nIndex));
+  }
+  m_pNormalWidget->Update();
+  AddInvalidateRect();
+}
+int32_t CXFA_FFListBox::OnProcessMessage(CFWL_Message* pMessage) {
+  return m_pOldDelegate->OnProcessMessage(pMessage);
+}
+FWL_ERR CXFA_FFListBox::OnProcessEvent(CFWL_Event* pEvent) {
+  CXFA_FFField::OnProcessEvent(pEvent);
+  FX_DWORD dwEventID = pEvent->GetClassID();
+  switch (dwEventID) {
+    case FWL_EVTHASH_LTB_SelChanged: {
+      CFX_Int32Array arrSels;
+      OnSelectChanged(m_pNormalWidget->GetWidget(), arrSels);
+      break;
+    }
+    default: {}
+  }
+  return m_pOldDelegate->OnProcessEvent(pEvent);
+}
+FWL_ERR CXFA_FFListBox::OnDrawWidget(CFX_Graphics* pGraphics,
+                                     const CFX_Matrix* pMatrix) {
+  return m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
+}
+
+CXFA_FFComboBox::CXFA_FFComboBox(CXFA_FFPageView* pPageView,
+                                 CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFField(pPageView, pDataAcc), m_pOldDelegate(NULL) {}
+
+CXFA_FFComboBox::~CXFA_FFComboBox() {}
+
+FX_BOOL CXFA_FFComboBox::GetBBox(CFX_RectF& rtBox,
+                                 FX_DWORD dwStatus,
+                                 FX_BOOL bDrawFocus) {
+  if (bDrawFocus)
+    return FALSE;
+  return CXFA_FFWidget::GetBBox(rtBox, dwStatus);
+}
+
+FX_BOOL CXFA_FFComboBox::PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFX_RectF rtWidget;
+  ((CFWL_ComboBox*)m_pNormalWidget)->GetBBox(rtWidget);
+  if (rtWidget.Contains(fx, fy)) {
+    return TRUE;
+  }
+  return FALSE;
+}
+FX_BOOL CXFA_FFComboBox::LoadWidget() {
+  CFWL_ComboBox* pComboBox = CFWL_ComboBox::Create();
+  pComboBox->Initialize();
+  m_pNormalWidget = (CFWL_Widget*)pComboBox;
+  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
+  m_pNormalWidget->SetPrivateData(pWidget, this, NULL);
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  m_pOldDelegate = m_pNormalWidget->SetDelegate(this);
+  m_pNormalWidget->LockUpdate();
+  CFX_WideStringArray wsLabelArray;
+  m_pDataAcc->GetChoiceListItems(wsLabelArray, FALSE);
+  int32_t iItems = wsLabelArray.GetSize();
+  for (int32_t i = 0; i < iItems; i++) {
+    pComboBox->AddString(wsLabelArray[i]);
+  }
+  CFX_Int32Array iSelArray;
+  m_pDataAcc->GetSelectedItems(iSelArray);
+  int32_t iSelCount = iSelArray.GetSize();
+  if (iSelCount > 0) {
+    pComboBox->SetCurSel(iSelArray[0]);
+  } else {
+    CFX_WideString wsText;
+    m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Raw);
+    pComboBox->SetEditText(wsText);
+  }
+  UpdateWidgetProperty();
+  m_pNormalWidget->UnlockUpdate();
+  return CXFA_FFField::LoadWidget();
+}
+void CXFA_FFComboBox::UpdateWidgetProperty() {
+  CFWL_ComboBox* pComboBox = (CFWL_ComboBox*)m_pNormalWidget;
+  if (!pComboBox) {
+    return;
+  }
+  FX_DWORD dwExtendedStyle = 0;
+  FX_DWORD dwEditStyles =
+      FWL_STYLEEXT_EDT_ReadOnly | FWL_STYLEEXT_EDT_LastLineHeight;
+  dwExtendedStyle |= UpdateUIProperty();
+  if (m_pDataAcc->IsChoiceListAllowTextEntry()) {
+    dwEditStyles &= ~FWL_STYLEEXT_EDT_ReadOnly;
+    dwExtendedStyle |= FWL_STYLEEXT_CMB_DropDown;
+  }
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open ||
+      !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    dwEditStyles |= FWL_STYLEEXT_EDT_ReadOnly;
+    dwExtendedStyle |= FWL_STYLEEXT_CMB_ReadOnly;
+  }
+  dwExtendedStyle |= GetAlignment();
+  m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
+  if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) {
+    dwEditStyles |= FWL_STYLEEXT_EDT_AutoHScroll;
+  }
+  pComboBox->EditModifyStylesEx(dwEditStyles, 0xFFFFFFFF);
+}
+FX_BOOL CXFA_FFComboBox::OnRButtonUp(FX_DWORD dwFlags,
+                                     FX_FLOAT fx,
+                                     FX_FLOAT fy) {
+  if (!CXFA_FFField::OnRButtonUp(dwFlags, fx, fy))
+    return FALSE;
+
+  GetDoc()->GetDocProvider()->PopupMenu(this, CFX_PointF(fx, fy), nullptr);
+  return TRUE;
+}
+FX_BOOL CXFA_FFComboBox::OnKillFocus(CXFA_FFWidget* pNewWidget) {
+  FX_BOOL flag = ProcessCommittedData();
+  if (!flag) {
+    UpdateFWLData();
+  }
+  CXFA_FFField::OnKillFocus(pNewWidget);
+  return TRUE;
+}
+void CXFA_FFComboBox::OpenDropDownList() {
+  ((CFWL_ComboBox*)m_pNormalWidget)->OpenDropDownList(TRUE);
+}
+FX_BOOL CXFA_FFComboBox::CommitData() {
+  return m_pDataAcc->SetValue(m_wsNewValue, XFA_VALUEPICTURE_Raw);
+}
+FX_BOOL CXFA_FFComboBox::IsDataChanged() {
+  CFWL_ComboBox* pFWLcombobox = ((CFWL_ComboBox*)m_pNormalWidget);
+  CFX_WideString wsText;
+  pFWLcombobox->GetEditText(wsText);
+  int32_t iCursel = pFWLcombobox->GetCurSel();
+  if (iCursel >= 0) {
+    CFX_WideString wsSel;
+    pFWLcombobox->GetTextByIndex(iCursel, wsSel);
+    if (wsSel == wsText) {
+      m_pDataAcc->GetChoiceListItem(wsText, iCursel, TRUE);
+    }
+  }
+  CFX_WideString wsOldValue;
+  m_pDataAcc->GetValue(wsOldValue, XFA_VALUEPICTURE_Raw);
+  if (wsOldValue != wsText) {
+    m_wsNewValue = wsText;
+    return TRUE;
+  }
+  return FALSE;
+}
+void CXFA_FFComboBox::FWLEventSelChange(CXFA_EventParam* pParam) {
+  pParam->m_eType = XFA_EVENT_Change;
+  pParam->m_pTarget = m_pDataAcc;
+  CFWL_ComboBox* pFWLcombobox = ((CFWL_ComboBox*)m_pNormalWidget);
+  pFWLcombobox->GetEditText(pParam->m_wsNewText);
+  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, pParam);
+}
+FX_DWORD CXFA_FFComboBox::GetAlignment() {
+  FX_DWORD dwExtendedStyle = 0;
+  if (CXFA_Para para = m_pDataAcc->GetPara()) {
+    int32_t iHorz = para.GetHorizontalAlign();
+    switch (iHorz) {
+      case XFA_ATTRIBUTEENUM_Center:
+        dwExtendedStyle |=
+            FWL_STYLEEXT_CMB_EditHCenter | FWL_STYLEEXT_CMB_ListItemCenterAlign;
+        break;
+      case XFA_ATTRIBUTEENUM_Justify:
+        dwExtendedStyle |= FWL_STYLEEXT_CMB_EditJustified;
+        break;
+      case XFA_ATTRIBUTEENUM_JustifyAll:
+        break;
+      case XFA_ATTRIBUTEENUM_Radix:
+        break;
+      case XFA_ATTRIBUTEENUM_Right:
+        break;
+      default:
+        dwExtendedStyle |=
+            FWL_STYLEEXT_CMB_EditHNear | FWL_STYLEEXT_CMB_ListItemLeftAlign;
+        break;
+    }
+    int32_t iVert = para.GetVerticalAlign();
+    switch (iVert) {
+      case XFA_ATTRIBUTEENUM_Middle:
+        dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVCenter;
+        break;
+      case XFA_ATTRIBUTEENUM_Bottom:
+        dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVFar;
+        break;
+      default:
+        dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVNear;
+        break;
+    }
+  }
+  return dwExtendedStyle;
+}
+FX_BOOL CXFA_FFComboBox::UpdateFWLData() {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFX_Int32Array iSelArray;
+  m_pDataAcc->GetSelectedItems(iSelArray);
+  int32_t iSelCount = iSelArray.GetSize();
+  if (iSelCount > 0) {
+    ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(iSelArray[0]);
+  } else {
+    CFX_WideString wsText;
+    ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(-1);
+    m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Raw);
+    ((CFWL_ComboBox*)m_pNormalWidget)->SetEditText(wsText);
+  }
+  m_pNormalWidget->Update();
+  return TRUE;
+}
+FX_BOOL CXFA_FFComboBox::CanUndo() {
+  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
+         ((CFWL_ComboBox*)m_pNormalWidget)->EditCanUndo();
+}
+FX_BOOL CXFA_FFComboBox::CanRedo() {
+  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
+         ((CFWL_ComboBox*)m_pNormalWidget)->EditCanRedo();
+}
+FX_BOOL CXFA_FFComboBox::Undo() {
+  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
+         ((CFWL_ComboBox*)m_pNormalWidget)->EditUndo();
+}
+FX_BOOL CXFA_FFComboBox::Redo() {
+  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
+         ((CFWL_ComboBox*)m_pNormalWidget)->EditRedo();
+}
+FX_BOOL CXFA_FFComboBox::CanCopy() {
+  return ((CFWL_ComboBox*)m_pNormalWidget)->EditCanCopy();
+}
+FX_BOOL CXFA_FFComboBox::CanCut() {
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) {
+    return FALSE;
+  }
+  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
+         ((CFWL_ComboBox*)m_pNormalWidget)->EditCanCut();
+}
+FX_BOOL CXFA_FFComboBox::CanPaste() {
+  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
+         (m_pDataAcc->GetAccess() == XFA_ATTRIBUTEENUM_Open);
+}
+FX_BOOL CXFA_FFComboBox::CanSelectAll() {
+  return ((CFWL_ComboBox*)m_pNormalWidget)->EditCanSelectAll();
+}
+FX_BOOL CXFA_FFComboBox::Copy(CFX_WideString& wsCopy) {
+  return ((CFWL_ComboBox*)m_pNormalWidget)->EditCopy(wsCopy);
+}
+FX_BOOL CXFA_FFComboBox::Cut(CFX_WideString& wsCut) {
+  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
+         ((CFWL_ComboBox*)m_pNormalWidget)->EditCut(wsCut);
+}
+FX_BOOL CXFA_FFComboBox::Paste(const CFX_WideString& wsPaste) {
+  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
+         ((CFWL_ComboBox*)m_pNormalWidget)->EditPaste(wsPaste);
+}
+FX_BOOL CXFA_FFComboBox::SelectAll() {
+  return ((CFWL_ComboBox*)m_pNormalWidget)->EditSelectAll();
+}
+FX_BOOL CXFA_FFComboBox::Delete() {
+  return ((CFWL_ComboBox*)m_pNormalWidget)->EditDelete();
+}
+FX_BOOL CXFA_FFComboBox::DeSelect() {
+  return ((CFWL_ComboBox*)m_pNormalWidget)->EditDeSelect();
+}
+void CXFA_FFComboBox::SetItemState(int32_t nIndex, FX_BOOL bSelected) {
+  if (bSelected) {
+    ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(nIndex);
+  } else {
+    ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(-1);
+  }
+  m_pNormalWidget->Update();
+  AddInvalidateRect();
+}
+void CXFA_FFComboBox::InsertItem(const CFX_WideStringC& wsLabel,
+                                 int32_t nIndex) {
+  ((CFWL_ComboBox*)m_pNormalWidget)->AddString(wsLabel);
+  m_pNormalWidget->Update();
+  AddInvalidateRect();
+}
+void CXFA_FFComboBox::DeleteItem(int32_t nIndex) {
+  if (nIndex < 0) {
+    ((CFWL_ComboBox*)m_pNormalWidget)->RemoveAll();
+  } else {
+    ((CFWL_ComboBox*)m_pNormalWidget)->RemoveAt(nIndex);
+  }
+  m_pNormalWidget->Update();
+  AddInvalidateRect();
+}
+void CXFA_FFComboBox::OnTextChanged(IFWL_Widget* pWidget,
+                                    const CFX_WideString& wsChanged) {
+  CXFA_EventParam eParam;
+  m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw);
+  eParam.m_wsChange = wsChanged;
+  FWLEventSelChange(&eParam);
+}
+void CXFA_FFComboBox::OnSelectChanged(IFWL_Widget* pWidget,
+                                      const CFX_Int32Array& arrSels,
+                                      FX_BOOL bLButtonUp) {
+  CXFA_EventParam eParam;
+  m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw);
+  FWLEventSelChange(&eParam);
+  if (m_pDataAcc->GetChoiceListCommitOn() == XFA_ATTRIBUTEENUM_Select &&
+      bLButtonUp) {
+    m_pDocView->SetFocusWidgetAcc(NULL);
+  }
+}
+void CXFA_FFComboBox::OnPreOpen(IFWL_Widget* pWidget) {
+  CXFA_EventParam eParam;
+  eParam.m_eType = XFA_EVENT_PreOpen;
+  eParam.m_pTarget = m_pDataAcc;
+  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_PreOpen, &eParam);
+}
+void CXFA_FFComboBox::OnPostOpen(IFWL_Widget* pWidget) {
+  CXFA_EventParam eParam;
+  eParam.m_eType = XFA_EVENT_PostOpen;
+  eParam.m_pTarget = m_pDataAcc;
+  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_PostOpen, &eParam);
+}
+
+int32_t CXFA_FFComboBox::OnProcessMessage(CFWL_Message* pMessage) {
+  return m_pOldDelegate->OnProcessMessage(pMessage);
+}
+FWL_ERR CXFA_FFComboBox::OnProcessEvent(CFWL_Event* pEvent) {
+  CXFA_FFField::OnProcessEvent(pEvent);
+  FX_DWORD dwEventID = pEvent->GetClassID();
+  switch (dwEventID) {
+    case FWL_EVTHASH_CMB_SelChanged: {
+      CFWL_EvtCmbSelChanged* postEvent = (CFWL_EvtCmbSelChanged*)pEvent;
+      OnSelectChanged(m_pNormalWidget->GetWidget(), postEvent->iArraySels,
+                      postEvent->bLButtonUp);
+      break;
+    }
+    case FWL_EVTHASH_CMB_EditChanged: {
+      CFX_WideString wsChanged;
+      OnTextChanged(m_pNormalWidget->GetWidget(), wsChanged);
+      break;
+    }
+    case FWL_EVTHASH_CMB_PreDropDown: {
+      OnPreOpen(m_pNormalWidget->GetWidget());
+      break;
+    }
+    case FWL_EVTHASH_CMB_PostDropDown: {
+      OnPostOpen(m_pNormalWidget->GetWidget());
+      break;
+    }
+    default: {}
+  }
+  return m_pOldDelegate->OnProcessEvent(pEvent);
+}
+FWL_ERR CXFA_FFComboBox::OnDrawWidget(CFX_Graphics* pGraphics,
+                                      const CFX_Matrix* pMatrix) {
+  return m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
+}
diff --git a/xfa/fxfa/app/xfa_ffchoicelist.h b/xfa/fxfa/app/xfa_ffchoicelist.h
new file mode 100644
index 0000000..1699b18
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffchoicelist.h
@@ -0,0 +1,96 @@
+// 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_FXFA_APP_XFA_FFCHOICELIST_H_
+#define XFA_FXFA_APP_XFA_FFCHOICELIST_H_
+
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+
+class CXFA_FFListBox : public CXFA_FFField {
+ public:
+  CXFA_FFListBox(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFListBox();
+  virtual FX_BOOL LoadWidget();
+  virtual FX_BOOL OnKillFocus(CXFA_FFWidget* pNewWidget);
+
+ protected:
+  virtual FX_BOOL CommitData();
+  virtual FX_BOOL UpdateFWLData();
+  virtual FX_BOOL IsDataChanged();
+  FX_DWORD GetAlignment();
+
+ public:
+  void OnSelectChanged(IFWL_Widget* pWidget, const CFX_Int32Array& arrSels);
+  void SetItemState(int32_t nIndex, FX_BOOL bSelected);
+  void InsertItem(const CFX_WideStringC& wsLabel, int32_t nIndex = -1);
+  void DeleteItem(int32_t nIndex);
+  virtual int32_t OnProcessMessage(CFWL_Message* pMessage);
+  virtual FWL_ERR OnProcessEvent(CFWL_Event* pEvent);
+  virtual FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics,
+                               const CFX_Matrix* pMatrix = NULL);
+
+ protected:
+  IFWL_WidgetDelegate* m_pOldDelegate;
+};
+class CXFA_FFComboBox : public CXFA_FFField {
+ public:
+  CXFA_FFComboBox(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFComboBox();
+  virtual FX_BOOL GetBBox(CFX_RectF& rtBox,
+                          FX_DWORD dwStatus,
+                          FX_BOOL bDrawFocus = FALSE);
+  virtual FX_BOOL LoadWidget();
+  virtual void UpdateWidgetProperty();
+  virtual FX_BOOL OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnKillFocus(CXFA_FFWidget* pNewWidget);
+  virtual FX_BOOL CanUndo();
+  virtual FX_BOOL CanRedo();
+  virtual FX_BOOL Undo();
+  virtual FX_BOOL Redo();
+
+  virtual FX_BOOL CanCopy();
+  virtual FX_BOOL CanCut();
+  virtual FX_BOOL CanPaste();
+  virtual FX_BOOL CanSelectAll();
+  virtual FX_BOOL Copy(CFX_WideString& wsCopy);
+  virtual FX_BOOL Cut(CFX_WideString& wsCut);
+  virtual FX_BOOL Paste(const CFX_WideString& wsPaste);
+  virtual FX_BOOL SelectAll();
+  virtual FX_BOOL Delete();
+  virtual FX_BOOL DeSelect();
+  void OpenDropDownList();
+
+ protected:
+  virtual FX_BOOL PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL CommitData();
+  virtual FX_BOOL UpdateFWLData();
+  virtual FX_BOOL IsDataChanged();
+  FX_DWORD GetAlignment();
+  void FWLEventSelChange(CXFA_EventParam* pParam);
+
+  CFX_WideString m_wsNewValue;
+
+ public:
+  void OnTextChanged(IFWL_Widget* pWidget, const CFX_WideString& wsChanged);
+  void OnSelectChanged(IFWL_Widget* pWidget,
+                       const CFX_Int32Array& arrSels,
+                       FX_BOOL bLButtonUp);
+  void OnPreOpen(IFWL_Widget* pWidget);
+  void OnPostOpen(IFWL_Widget* pWidget);
+  void SetItemState(int32_t nIndex, FX_BOOL bSelected);
+  void InsertItem(const CFX_WideStringC& wsLabel, int32_t nIndex = -1);
+  void DeleteItem(int32_t nIndex);
+  virtual int32_t OnProcessMessage(CFWL_Message* pMessage);
+  virtual FWL_ERR OnProcessEvent(CFWL_Event* pEvent);
+  virtual FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics,
+                               const CFX_Matrix* pMatrix = NULL);
+
+ protected:
+  IFWL_WidgetDelegate* m_pOldDelegate;
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFCHOICELIST_H_
diff --git a/xfa/fxfa/app/xfa_ffdoc.cpp b/xfa/fxfa/app/xfa_ffdoc.cpp
new file mode 100644
index 0000000..e33dd4f
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffdoc.cpp
@@ -0,0 +1,431 @@
+// 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/fxfa/app/xfa_ffdoc.h"
+
+#include "core/include/fpdfapi/cpdf_array.h"
+#include "core/include/fpdfapi/cpdf_document.h"
+#include "core/include/fpdfdoc/fpdf_doc.h"
+#include "core/include/fxcrt/fx_ext.h"
+#include "xfa/fgas/crt/fgas_algorithm.h"
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_ffnotify.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_fontmgr.h"
+#include "xfa/fxfa/parser/xfa_docdata.h"
+#include "xfa/fxfa/parser/xfa_parser.h"
+#include "xfa/include/fwl/core/fwl_note.h"
+
+CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocProvider* pDocProvider)
+    : m_pDocProvider(pDocProvider),
+      m_pDocument(nullptr),
+      m_pStream(nullptr),
+      m_pApp(pApp),
+      m_pNotify(nullptr),
+      m_pPDFDoc(nullptr),
+      m_dwDocType(XFA_DOCTYPE_Static),
+      m_bOwnStream(TRUE) {}
+CXFA_FFDoc::~CXFA_FFDoc() {
+  CloseDoc();
+}
+FX_DWORD CXFA_FFDoc::GetDocType() {
+  return m_dwDocType;
+}
+int32_t CXFA_FFDoc::StartLoad() {
+  m_pNotify = new CXFA_FFNotify(this);
+  IXFA_DocParser* pDocParser = IXFA_DocParser::Create(m_pNotify);
+  int32_t iStatus = pDocParser->StartParse(m_pStream);
+  m_pDocument = pDocParser->GetDocument();
+  return iStatus;
+}
+FX_BOOL XFA_GetPDFContentsFromPDFXML(IFDE_XMLNode* pPDFElement,
+                                     uint8_t*& pByteBuffer,
+                                     int32_t& iBufferSize) {
+  IFDE_XMLElement* pDocumentElement = NULL;
+  for (IFDE_XMLNode* pXMLNode =
+           pPDFElement->GetNodeItem(IFDE_XMLNode::FirstChild);
+       pXMLNode; pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+    if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+      CFX_WideString wsTagName;
+      IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLNode;
+      pXMLElement->GetTagName(wsTagName);
+      if (wsTagName.Equal(FX_WSTRC(L"document"))) {
+        pDocumentElement = pXMLElement;
+        break;
+      }
+    }
+  }
+  if (!pDocumentElement) {
+    return FALSE;
+  }
+  IFDE_XMLElement* pChunkElement = NULL;
+  for (IFDE_XMLNode* pXMLNode =
+           pDocumentElement->GetNodeItem(IFDE_XMLNode::FirstChild);
+       pXMLNode; pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+    if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+      CFX_WideString wsTagName;
+      IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLNode;
+      pXMLElement->GetTagName(wsTagName);
+      if (wsTagName.Equal(FX_WSTRC(L"chunk"))) {
+        pChunkElement = pXMLElement;
+        break;
+      }
+    }
+  }
+  if (!pChunkElement) {
+    return FALSE;
+  }
+  CFX_WideString wsPDFContent;
+  pChunkElement->GetTextData(wsPDFContent);
+  iBufferSize = FX_Base64DecodeW(wsPDFContent, wsPDFContent.GetLength(), NULL);
+  pByteBuffer = FX_Alloc(uint8_t, iBufferSize + 1);
+  pByteBuffer[iBufferSize] = '0';  // FIXME: I bet this is wrong.
+  FX_Base64DecodeW(wsPDFContent, wsPDFContent.GetLength(), pByteBuffer);
+  return TRUE;
+}
+void XFA_XPDPacket_MergeRootNode(CXFA_Node* pOriginRoot, CXFA_Node* pNewRoot) {
+  CXFA_Node* pChildNode = pNewRoot->GetNodeItem(XFA_NODEITEM_FirstChild);
+  while (pChildNode) {
+    CXFA_Node* pOriginChild =
+        pOriginRoot->GetFirstChildByName(pChildNode->GetNameHash());
+    if (pOriginChild) {
+      pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
+    } else {
+      CXFA_Node* pNextSibling =
+          pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
+      pNewRoot->RemoveChild(pChildNode);
+      pOriginRoot->InsertChild(pChildNode);
+      pChildNode = pNextSibling;
+      pNextSibling = NULL;
+    }
+  }
+}
+int32_t CXFA_FFDoc::DoLoad(IFX_Pause* pPause) {
+  int32_t iStatus = m_pDocument->GetParser()->DoParse(pPause);
+  if (iStatus == XFA_PARSESTATUS_Done && !m_pPDFDoc) {
+    CXFA_Node* pPDFNode = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Pdf));
+    if (!pPDFNode) {
+      return XFA_PARSESTATUS_SyntaxErr;
+    }
+    IFDE_XMLNode* pPDFXML = pPDFNode->GetXMLMappingNode();
+    if (pPDFXML->GetType() != FDE_XMLNODE_Element) {
+      return XFA_PARSESTATUS_SyntaxErr;
+    }
+    int32_t iBufferSize = 0;
+    uint8_t* pByteBuffer = NULL;
+    IFX_FileRead* pXFAReader = NULL;
+    if (XFA_GetPDFContentsFromPDFXML(pPDFXML, pByteBuffer, iBufferSize)) {
+      pXFAReader = FX_CreateMemoryStream(pByteBuffer, iBufferSize, TRUE);
+    } else {
+      CFX_WideString wsHref;
+      ((IFDE_XMLElement*)pPDFXML)->GetString(L"href", wsHref);
+      if (!wsHref.IsEmpty()) {
+        pXFAReader = GetDocProvider()->OpenLinkedFile(this, wsHref);
+      }
+    }
+    if (!pXFAReader) {
+      return XFA_PARSESTATUS_SyntaxErr;
+    }
+    CPDF_Document* pPDFDocument =
+        GetDocProvider()->OpenPDF(this, pXFAReader, TRUE);
+    FXSYS_assert(!m_pPDFDoc);
+    if (!OpenDoc(pPDFDocument)) {
+      return XFA_PARSESTATUS_SyntaxErr;
+    }
+    IXFA_Parser* pParser = IXFA_Parser::Create(m_pDocument, TRUE);
+    if (!pParser) {
+      return XFA_PARSESTATUS_SyntaxErr;
+    }
+    CXFA_Node* pRootNode = NULL;
+    if (pParser->StartParse(m_pStream) == XFA_PARSESTATUS_Ready &&
+        pParser->DoParse(NULL) == XFA_PARSESTATUS_Done) {
+      pRootNode = pParser->GetRootNode();
+    }
+    if (pRootNode && m_pDocument->GetRoot()) {
+      XFA_XPDPacket_MergeRootNode(m_pDocument->GetRoot(), pRootNode);
+      iStatus = XFA_PARSESTATUS_Done;
+    } else {
+      iStatus = XFA_PARSESTATUS_StatusErr;
+    }
+    pParser->Release();
+    pParser = NULL;
+  }
+  return iStatus;
+}
+void CXFA_FFDoc::StopLoad() {
+  m_pApp->GetXFAFontMgr()->LoadDocFonts(this);
+  m_dwDocType = XFA_DOCTYPE_Static;
+  CXFA_Node* pConfig = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config));
+  if (!pConfig) {
+    return;
+  }
+  CXFA_Node* pAcrobat = pConfig->GetFirstChildByClass(XFA_ELEMENT_Acrobat);
+  if (!pAcrobat) {
+    return;
+  }
+  CXFA_Node* pAcrobat7 = pAcrobat->GetFirstChildByClass(XFA_ELEMENT_Acrobat7);
+  if (!pAcrobat7) {
+    return;
+  }
+  CXFA_Node* pDynamicRender =
+      pAcrobat7->GetFirstChildByClass(XFA_ELEMENT_DynamicRender);
+  if (!pDynamicRender) {
+    return;
+  }
+  CFX_WideString wsType;
+  if (pDynamicRender->TryContent(wsType) && wsType == FX_WSTRC(L"required")) {
+    m_dwDocType = XFA_DOCTYPE_Dynamic;
+  }
+}
+IXFA_DocView* CXFA_FFDoc::CreateDocView(FX_DWORD dwView) {
+  CXFA_FFDocView* pDocView =
+      (CXFA_FFDocView*)m_mapTypeToDocView.GetValueAt((void*)(uintptr_t)dwView);
+  if (!pDocView) {
+    pDocView = new CXFA_FFDocView(this);
+    m_mapTypeToDocView.SetAt((void*)(uintptr_t)dwView, pDocView);
+  }
+  return pDocView;
+}
+CXFA_FFDocView* CXFA_FFDoc::GetDocView(IXFA_DocLayout* pLayout) {
+  FX_POSITION ps = m_mapTypeToDocView.GetStartPosition();
+  while (ps) {
+    void* pType;
+    CXFA_FFDocView* pDocView;
+    m_mapTypeToDocView.GetNextAssoc(ps, pType, (void*&)pDocView);
+    if (pDocView->GetXFALayout() == pLayout) {
+      return pDocView;
+    }
+  }
+  return NULL;
+}
+CXFA_FFDocView* CXFA_FFDoc::GetDocView() {
+  FX_POSITION ps = m_mapTypeToDocView.GetStartPosition();
+  if (ps) {
+    void* pType;
+    CXFA_FFDocView* pDocView;
+    m_mapTypeToDocView.GetNextAssoc(ps, pType, (void*&)pDocView);
+    return pDocView;
+  }
+  return NULL;
+}
+FX_BOOL CXFA_FFDoc::OpenDoc(IFX_FileRead* pStream, FX_BOOL bTakeOverFile) {
+  m_bOwnStream = bTakeOverFile;
+  m_pStream = pStream;
+  return TRUE;
+}
+FX_BOOL CXFA_FFDoc::OpenDoc(CPDF_Document* pPDFDoc) {
+  if (pPDFDoc == NULL) {
+    return FALSE;
+  }
+  CPDF_Dictionary* pRoot = pPDFDoc->GetRoot();
+  if (pRoot == NULL) {
+    return FALSE;
+  }
+  CPDF_Dictionary* pAcroForm = pRoot->GetDictBy("AcroForm");
+  if (pAcroForm == NULL) {
+    return FALSE;
+  }
+  CPDF_Object* pElementXFA = pAcroForm->GetElementValue("XFA");
+  if (pElementXFA == NULL) {
+    return FALSE;
+  }
+  CFX_ArrayTemplate<CPDF_Stream*> xfaStreams;
+  if (pElementXFA->IsArray()) {
+    CPDF_Array* pXFAArray = (CPDF_Array*)pElementXFA;
+    FX_DWORD count = pXFAArray->GetCount() / 2;
+    for (FX_DWORD i = 0; i < count; i++) {
+      if (CPDF_Stream* pStream = pXFAArray->GetStreamAt(i * 2 + 1))
+        xfaStreams.Add(pStream);
+    }
+  } else if (pElementXFA->IsStream()) {
+    xfaStreams.Add((CPDF_Stream*)pElementXFA);
+  }
+  if (xfaStreams.GetSize() < 1) {
+    return FALSE;
+  }
+  IFX_FileRead* pFileRead = new CXFA_FileRead(xfaStreams);
+  m_pPDFDoc = pPDFDoc;
+  if (m_pStream) {
+    m_pStream->Release();
+    m_pStream = NULL;
+  }
+  m_pStream = pFileRead;
+  m_bOwnStream = TRUE;
+  return TRUE;
+}
+FX_BOOL CXFA_FFDoc::CloseDoc() {
+  FX_POSITION psClose = m_mapTypeToDocView.GetStartPosition();
+  while (psClose) {
+    void* pType;
+    CXFA_FFDocView* pDocView;
+    m_mapTypeToDocView.GetNextAssoc(psClose, pType, (void*&)pDocView);
+    pDocView->RunDocClose();
+  }
+  if (m_pDocument) {
+    m_pDocument->ClearLayoutData();
+  }
+  FX_POSITION ps = m_mapTypeToDocView.GetStartPosition();
+  while (ps) {
+    void* pType;
+    CXFA_FFDocView* pDocView;
+    m_mapTypeToDocView.GetNextAssoc(ps, pType, (void*&)pDocView);
+    delete pDocView;
+  }
+  m_mapTypeToDocView.RemoveAll();
+  if (m_pDocument) {
+    IXFA_Parser* pParser = m_pDocument->GetParser();
+    pParser->Release();
+    m_pDocument = NULL;
+  }
+  if (m_pNotify) {
+    delete m_pNotify;
+    m_pNotify = NULL;
+  }
+  m_pApp->GetXFAFontMgr()->ReleaseDocFonts(this);
+  if (m_dwDocType != XFA_DOCTYPE_XDP && m_pStream && m_bOwnStream) {
+    m_pStream->Release();
+    m_pStream = NULL;
+  }
+  ps = m_mapNamedImages.GetStartPosition();
+  while (ps) {
+    void* pName;
+    FX_IMAGEDIB_AND_DPI* pImage = NULL;
+    m_mapNamedImages.GetNextAssoc(ps, pName, (void*&)pImage);
+    if (pImage) {
+      delete pImage->pDibSource;
+      pImage->pDibSource = NULL;
+      FX_Free(pImage);
+      pImage = NULL;
+    }
+  }
+  m_mapNamedImages.RemoveAll();
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->ClearEventTargets(FALSE);
+  return TRUE;
+}
+void CXFA_FFDoc::SetDocType(FX_DWORD dwType) {
+  m_dwDocType = dwType;
+}
+CPDF_Document* CXFA_FFDoc::GetPDFDoc() {
+  return m_pPDFDoc;
+}
+
+CFX_DIBitmap* CXFA_FFDoc::GetPDFNamedImage(const CFX_WideStringC& wsName,
+                                           int32_t& iImageXDpi,
+                                           int32_t& iImageYDpi) {
+  if (!m_pPDFDoc)
+    return nullptr;
+
+  FX_DWORD dwHash =
+      FX_HashCode_String_GetW(wsName.GetPtr(), wsName.GetLength(), FALSE);
+  FX_IMAGEDIB_AND_DPI* imageDIBDpi = nullptr;
+  if (m_mapNamedImages.Lookup((void*)(uintptr_t)dwHash, (void*&)imageDIBDpi)) {
+    iImageXDpi = imageDIBDpi->iImageXDpi;
+    iImageYDpi = imageDIBDpi->iImageYDpi;
+    return static_cast<CFX_DIBitmap*>(imageDIBDpi->pDibSource);
+  }
+
+  CPDF_Dictionary* pRoot = m_pPDFDoc->GetRoot();
+  if (!pRoot)
+    return nullptr;
+
+  CPDF_Dictionary* pNames = pRoot->GetDictBy("Names");
+  if (!pNames)
+    return nullptr;
+
+  CPDF_Dictionary* pXFAImages = pNames->GetDictBy("XFAImages");
+  if (!pXFAImages)
+    return nullptr;
+
+  CPDF_NameTree nametree(pXFAImages);
+  CFX_ByteString bsName = PDF_EncodeText(wsName.GetPtr(), wsName.GetLength());
+  CPDF_Object* pObject = nametree.LookupValue(bsName);
+  if (!pObject) {
+    int32_t iCount = nametree.GetCount();
+    for (int32_t i = 0; i < iCount; i++) {
+      CFX_ByteString bsTemp;
+      CPDF_Object* pTempObject = nametree.LookupValue(i, bsTemp);
+      if (bsTemp == bsName) {
+        pObject = pTempObject;
+        break;
+      }
+    }
+  }
+
+  if (!pObject || !pObject->IsStream())
+    return nullptr;
+
+  if (!imageDIBDpi) {
+    imageDIBDpi = FX_Alloc(FX_IMAGEDIB_AND_DPI, 1);
+    imageDIBDpi->pDibSource = nullptr;
+    imageDIBDpi->iImageXDpi = 0;
+    imageDIBDpi->iImageYDpi = 0;
+    CPDF_StreamAcc streamAcc;
+    streamAcc.LoadAllData((CPDF_Stream*)pObject);
+    IFX_FileRead* pImageFileRead = FX_CreateMemoryStream(
+        (uint8_t*)streamAcc.GetData(), streamAcc.GetSize());
+    imageDIBDpi->pDibSource = XFA_LoadImageFromBuffer(
+        pImageFileRead, FXCODEC_IMAGE_UNKNOWN, iImageXDpi, iImageYDpi);
+    imageDIBDpi->iImageXDpi = iImageXDpi;
+    imageDIBDpi->iImageYDpi = iImageYDpi;
+    pImageFileRead->Release();
+  }
+  m_mapNamedImages.SetAt((void*)(uintptr_t)dwHash, imageDIBDpi);
+  return (CFX_DIBitmap*)imageDIBDpi->pDibSource;
+}
+
+IFDE_XMLElement* CXFA_FFDoc::GetPackageData(const CFX_WideStringC& wsPackage) {
+  FX_DWORD packetHash =
+      FX_HashCode_String_GetW(wsPackage.GetPtr(), wsPackage.GetLength());
+  CXFA_Node* pNode = ToNode(m_pDocument->GetXFAObject(packetHash));
+  if (!pNode) {
+    return NULL;
+  }
+  IFDE_XMLNode* pXMLNode = pNode->GetXMLMappingNode();
+  return (pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element)
+             ? (IFDE_XMLElement*)pXMLNode
+             : NULL;
+}
+FX_BOOL CXFA_FFDoc::SavePackage(const CFX_WideStringC& wsPackage,
+                                IFX_FileWrite* pFile,
+                                IXFA_ChecksumContext* pCSContext) {
+  IXFA_PacketExport* pExport = IXFA_PacketExport::Create(m_pDocument);
+  if (!pExport) {
+    return FALSE;
+  }
+  FX_DWORD packetHash =
+      FX_HashCode_String_GetW(wsPackage.GetPtr(), wsPackage.GetLength());
+  CXFA_Node* pNode = NULL;
+  if (packetHash == XFA_HASHCODE_Xfa) {
+    pNode = m_pDocument->GetRoot();
+  } else {
+    pNode = ToNode(m_pDocument->GetXFAObject(packetHash));
+  }
+  FX_BOOL bFlags = FALSE;
+  if (pNode) {
+    CFX_ByteString bsChecksum;
+    if (pCSContext) {
+      pCSContext->GetChecksum(bsChecksum);
+    }
+    bFlags = pExport->Export(pFile, pNode, 0, bsChecksum.GetLength()
+                                                  ? (const FX_CHAR*)bsChecksum
+                                                  : NULL);
+  } else {
+    bFlags = pExport->Export(pFile);
+  }
+  pExport->Release();
+  return bFlags;
+}
+FX_BOOL CXFA_FFDoc::ImportData(IFX_FileRead* pStream, FX_BOOL bXDP) {
+  FX_BOOL bRet = FALSE;
+  IXFA_PacketImport* pImport = IXFA_PacketImport::Create(m_pDocument);
+  if (pImport) {
+    bRet = pImport->ImportData(pStream);
+    pImport->Release();
+  }
+  return bRet;
+}
diff --git a/xfa/fxfa/app/xfa_ffdoc.h b/xfa/fxfa/app/xfa_ffdoc.h
new file mode 100644
index 0000000..d656d30
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffdoc.h
@@ -0,0 +1,64 @@
+// 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_FXFA_APP_XFA_FFDOC_H_
+#define XFA_FXFA_APP_XFA_FFDOC_H_
+
+#include "xfa/fxfa/parser/xfa_document.h"
+#include "xfa/include/fxfa/fxfa.h"
+
+class CXFA_FFApp;
+class CXFA_FFNotify;
+class CXFA_FFDocView;
+
+struct FX_IMAGEDIB_AND_DPI {
+  CFX_DIBSource* pDibSource;
+  int32_t iImageXDpi;
+  int32_t iImageYDpi;
+};
+
+class CXFA_FFDoc : public IXFA_Doc {
+ public:
+  CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocProvider* pDocProvider);
+  ~CXFA_FFDoc();
+  IXFA_DocProvider* GetDocProvider() { return m_pDocProvider; }
+  FX_DWORD GetDocType();
+  int32_t StartLoad();
+  int32_t DoLoad(IFX_Pause* pPause = NULL);
+  void StopLoad();
+  IXFA_DocView* CreateDocView(FX_DWORD dwView = 0);
+  FX_BOOL OpenDoc(IFX_FileRead* pStream, FX_BOOL bTakeOverFile);
+  FX_BOOL OpenDoc(CPDF_Document* pPDFDoc);
+  FX_BOOL CloseDoc();
+  void SetDocType(FX_DWORD dwType);
+  CXFA_Document* GetXFADoc() { return m_pDocument; }
+  CXFA_FFApp* GetApp() { return m_pApp; }
+  CXFA_FFDocView* GetDocView(IXFA_DocLayout* pLayout);
+  CXFA_FFDocView* GetDocView();
+  CPDF_Document* GetPDFDoc();
+  CFX_DIBitmap* GetPDFNamedImage(const CFX_WideStringC& wsName,
+                                 int32_t& iImageXDpi,
+                                 int32_t& iImageYDpi);
+  IFDE_XMLElement* GetPackageData(const CFX_WideStringC& wsPackage);
+  FX_BOOL SavePackage(const CFX_WideStringC& wsPackage,
+                      IFX_FileWrite* pFile,
+                      IXFA_ChecksumContext* pCSContext = NULL);
+  FX_BOOL ImportData(IFX_FileRead* pStream, FX_BOOL bXDP = TRUE);
+
+ protected:
+  IXFA_DocProvider* m_pDocProvider;
+  CXFA_Document* m_pDocument;
+  IFX_FileRead* m_pStream;
+  CXFA_FFApp* m_pApp;
+  CXFA_FFNotify* m_pNotify;
+  CPDF_Document* m_pPDFDoc;
+  CFX_MapPtrToPtr m_mapNamedImages;
+  CFX_MapPtrToPtr m_mapTypeToDocView;
+  FX_DWORD m_dwDocType;
+  FX_BOOL m_bOwnStream;
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFDOC_H_
diff --git a/xfa/fxfa/app/xfa_ffdochandler.cpp b/xfa/fxfa/app/xfa_ffdochandler.cpp
new file mode 100644
index 0000000..5ea7884
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffdochandler.cpp
@@ -0,0 +1,110 @@
+// 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/fxfa/app/xfa_ffdochandler.h"
+
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/parser/xfa_script.h"
+
+CXFA_FFDocHandler::CXFA_FFDocHandler() {}
+CXFA_FFDocHandler::~CXFA_FFDocHandler() {}
+void CXFA_FFDocHandler::ReleaseDoc(IXFA_Doc* hDoc) {
+  delete hDoc;  // virtual dtor.
+}
+IXFA_DocProvider* CXFA_FFDocHandler::GetDocProvider(IXFA_Doc* hDoc) {
+  return static_cast<CXFA_FFDoc*>(hDoc)->GetDocProvider();
+}
+FX_DWORD CXFA_FFDocHandler::GetDocType(IXFA_Doc* hDoc) {
+  return static_cast<CXFA_FFDoc*>(hDoc)->GetDocType();
+}
+int32_t CXFA_FFDocHandler::StartLoad(IXFA_Doc* hDoc) {
+  return static_cast<CXFA_FFDoc*>(hDoc)->StartLoad();
+}
+int32_t CXFA_FFDocHandler::DoLoad(IXFA_Doc* hDoc, IFX_Pause* pPause) {
+  return static_cast<CXFA_FFDoc*>(hDoc)->DoLoad(pPause);
+}
+void CXFA_FFDocHandler::StopLoad(IXFA_Doc* hDoc) {
+  static_cast<CXFA_FFDoc*>(hDoc)->StopLoad();
+}
+
+IXFA_DocView* CXFA_FFDocHandler::CreateDocView(IXFA_Doc* hDoc,
+                                               FX_DWORD dwView) {
+  return static_cast<CXFA_FFDoc*>(hDoc)->CreateDocView(dwView);
+}
+int32_t CXFA_FFDocHandler::CountPackages(IXFA_Doc* hDoc) {
+  return 0;
+}
+void CXFA_FFDocHandler::GetPackageName(IXFA_Doc* hDoc,
+                                       int32_t iPackage,
+                                       CFX_WideStringC& wsPackage) {}
+IFDE_XMLElement* CXFA_FFDocHandler::GetPackageData(
+    IXFA_Doc* hDoc,
+    const CFX_WideStringC& wsPackage) {
+  return static_cast<CXFA_FFDoc*>(hDoc)->GetPackageData(wsPackage);
+}
+FX_BOOL CXFA_FFDocHandler::SavePackage(IXFA_Doc* hDoc,
+                                       const CFX_WideStringC& wsPackage,
+                                       IFX_FileWrite* pFile,
+                                       IXFA_ChecksumContext* pCSContext) {
+  return static_cast<CXFA_FFDoc*>(hDoc)
+      ->SavePackage(wsPackage, pFile, pCSContext);
+}
+FX_BOOL CXFA_FFDocHandler::CloseDoc(IXFA_Doc* hDoc) {
+  return static_cast<CXFA_FFDoc*>(hDoc)->CloseDoc();
+}
+
+FX_BOOL CXFA_FFDocHandler::ImportData(IXFA_Doc* hDoc,
+                                      IFX_FileRead* pStream,
+                                      FX_BOOL bXDP) {
+  return static_cast<CXFA_FFDoc*>(hDoc)->ImportData(pStream, bXDP);
+}
+void CXFA_FFDocHandler::SetJSERuntime(IXFA_Doc* hDoc, FXJSE_HRUNTIME hRuntime) {
+  static_cast<CXFA_FFDoc*>(hDoc)->GetXFADoc()->InitScriptContext(hRuntime);
+}
+FXJSE_HVALUE CXFA_FFDocHandler::GetXFAScriptObject(IXFA_Doc* hDoc) {
+  CXFA_Document* pXFADoc = static_cast<CXFA_FFDoc*>(hDoc)->GetXFADoc();
+  if (!pXFADoc) {
+    return NULL;
+  }
+  IXFA_ScriptContext* pScriptContext = pXFADoc->GetScriptContext();
+  if (!pScriptContext) {
+    return NULL;
+  }
+  return pScriptContext->GetJSValueFromMap(pXFADoc->GetRoot());
+}
+XFA_ATTRIBUTEENUM CXFA_FFDocHandler::GetRestoreState(IXFA_Doc* hDoc) {
+  CXFA_Document* pXFADoc = static_cast<CXFA_FFDoc*>(hDoc)->GetXFADoc();
+  if (!pXFADoc) {
+    return XFA_ATTRIBUTEENUM_Unknown;
+  }
+  CXFA_Node* pForm = ToNode(pXFADoc->GetXFAObject(XFA_HASHCODE_Form));
+  if (!pForm) {
+    return XFA_ATTRIBUTEENUM_Unknown;
+  }
+  CXFA_Node* pSubForm = pForm->GetFirstChildByClass(XFA_ELEMENT_Subform);
+  if (!pSubForm) {
+    return XFA_ATTRIBUTEENUM_Unknown;
+  }
+  return pSubForm->GetEnum(XFA_ATTRIBUTE_RestoreState);
+}
+FX_BOOL CXFA_FFDocHandler::RunDocScript(IXFA_Doc* hDoc,
+                                        XFA_SCRIPTTYPE eScriptType,
+                                        const CFX_WideStringC& wsScript,
+                                        FXJSE_HVALUE hRetValue,
+                                        FXJSE_HVALUE hThisObject) {
+  CXFA_Document* pXFADoc = static_cast<CXFA_FFDoc*>(hDoc)->GetXFADoc();
+  if (!pXFADoc) {
+    return FALSE;
+  }
+  IXFA_ScriptContext* pScriptContext = pXFADoc->GetScriptContext();
+  if (!pScriptContext) {
+    return FALSE;
+  }
+  return pScriptContext->RunScript(
+      (XFA_SCRIPTLANGTYPE)eScriptType, wsScript, hRetValue,
+      hThisObject ? (CXFA_Object*)FXJSE_Value_ToObject(hThisObject, NULL)
+                  : NULL);
+}
diff --git a/xfa/fxfa/app/xfa_ffdochandler.h b/xfa/fxfa/app/xfa_ffdochandler.h
new file mode 100644
index 0000000..47dd85f
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffdochandler.h
@@ -0,0 +1,50 @@
+// 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_FXFA_APP_XFA_FFDOCHANDLER_H_
+#define XFA_FXFA_APP_XFA_FFDOCHANDLER_H_
+
+#include "xfa/include/fxfa/fxfa.h"
+
+class CXFA_FFDocHandler : public IXFA_DocHandler {
+ public:
+  CXFA_FFDocHandler();
+  ~CXFA_FFDocHandler();
+  virtual void ReleaseDoc(IXFA_Doc* hDoc);
+  virtual IXFA_DocProvider* GetDocProvider(IXFA_Doc* hDoc);
+  virtual FX_DWORD GetDocType(IXFA_Doc* hDoc);
+  virtual int32_t StartLoad(IXFA_Doc* hDoc);
+  virtual int32_t DoLoad(IXFA_Doc* hDoc, IFX_Pause* pPause = NULL);
+  virtual void StopLoad(IXFA_Doc* hDoc);
+
+  virtual IXFA_DocView* CreateDocView(IXFA_Doc* hDoc, FX_DWORD dwView = 0);
+  virtual int32_t CountPackages(IXFA_Doc* hDoc);
+  virtual void GetPackageName(IXFA_Doc* hDoc,
+                              int32_t iPackage,
+                              CFX_WideStringC& wsPackage);
+  virtual IFDE_XMLElement* GetPackageData(IXFA_Doc* hDoc,
+                                          const CFX_WideStringC& wsPackage);
+  virtual FX_BOOL SavePackage(IXFA_Doc* hDoc,
+                              const CFX_WideStringC& wsPackage,
+                              IFX_FileWrite* pFile,
+                              IXFA_ChecksumContext* pCSContext = NULL);
+  virtual FX_BOOL CloseDoc(IXFA_Doc* hDoc);
+  virtual FX_BOOL ImportData(IXFA_Doc* hDoc,
+                             IFX_FileRead* pStream,
+                             FX_BOOL bXDP = TRUE);
+  virtual void SetJSERuntime(IXFA_Doc* hDoc, FXJSE_HRUNTIME hRuntime);
+  virtual FXJSE_HVALUE GetXFAScriptObject(IXFA_Doc* hDoc);
+  virtual XFA_ATTRIBUTEENUM GetRestoreState(IXFA_Doc* hDoc);
+  virtual FX_BOOL RunDocScript(IXFA_Doc* hDoc,
+                               XFA_SCRIPTTYPE eScriptType,
+                               const CFX_WideStringC& wsScript,
+                               FXJSE_HVALUE hRetValue,
+                               FXJSE_HVALUE hThisObject);
+
+ protected:
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFDOCHANDLER_H_
diff --git a/xfa/fxfa/app/xfa_ffdocview.cpp b/xfa/fxfa/app/xfa_ffdocview.cpp
new file mode 100644
index 0000000..082ca2b
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffdocview.cpp
@@ -0,0 +1,932 @@
+// 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/fxfa/app/xfa_ffdocview.h"
+
+#include "core/include/fxcrt/fx_ext.h"
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffbarcode.h"
+#include "xfa/fxfa/app/xfa_ffcheckbutton.h"
+#include "xfa/fxfa/app/xfa_ffchoicelist.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdraw.h"
+#include "xfa/fxfa/app/xfa_ffexclgroup.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffimage.h"
+#include "xfa/fxfa/app/xfa_ffimageedit.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffpath.h"
+#include "xfa/fxfa/app/xfa_ffpushbutton.h"
+#include "xfa/fxfa/app/xfa_ffsignature.h"
+#include "xfa/fxfa/app/xfa_ffsubform.h"
+#include "xfa/fxfa/app/xfa_fftext.h"
+#include "xfa/fxfa/app/xfa_fftextedit.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_ffwidgetacc.h"
+#include "xfa/fxfa/app/xfa_ffwidgethandler.h"
+#include "xfa/fxfa/app/xfa_fwladapter.h"
+#include "xfa/fxfa/app/xfa_textlayout.h"
+#include "xfa/fxfa/parser/xfa_script.h"
+
+extern const XFA_ATTRIBUTEENUM gs_EventActivity[] = {
+    XFA_ATTRIBUTEENUM_Click,      XFA_ATTRIBUTEENUM_Change,
+    XFA_ATTRIBUTEENUM_DocClose,   XFA_ATTRIBUTEENUM_DocReady,
+    XFA_ATTRIBUTEENUM_Enter,      XFA_ATTRIBUTEENUM_Exit,
+    XFA_ATTRIBUTEENUM_Full,       XFA_ATTRIBUTEENUM_IndexChange,
+    XFA_ATTRIBUTEENUM_Initialize, XFA_ATTRIBUTEENUM_MouseDown,
+    XFA_ATTRIBUTEENUM_MouseEnter, XFA_ATTRIBUTEENUM_MouseExit,
+    XFA_ATTRIBUTEENUM_MouseUp,    XFA_ATTRIBUTEENUM_PostExecute,
+    XFA_ATTRIBUTEENUM_PostOpen,   XFA_ATTRIBUTEENUM_PostPrint,
+    XFA_ATTRIBUTEENUM_PostSave,   XFA_ATTRIBUTEENUM_PostSign,
+    XFA_ATTRIBUTEENUM_PostSubmit, XFA_ATTRIBUTEENUM_PreExecute,
+    XFA_ATTRIBUTEENUM_PreOpen,    XFA_ATTRIBUTEENUM_PrePrint,
+    XFA_ATTRIBUTEENUM_PreSave,    XFA_ATTRIBUTEENUM_PreSign,
+    XFA_ATTRIBUTEENUM_PreSubmit,  XFA_ATTRIBUTEENUM_Ready,
+    XFA_ATTRIBUTEENUM_Unknown,
+};
+CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc)
+    : m_bLayoutEvent(FALSE),
+      m_pListFocusWidget(nullptr),
+      m_bInLayoutStatus(FALSE),
+      m_pDoc(pDoc),
+      m_pWidgetHandler(nullptr),
+      m_pXFADocLayout(nullptr),
+      m_pFocusAcc(nullptr),
+      m_pFocusWidget(nullptr),
+      m_pOldFocusWidget(nullptr),
+      m_iStatus(XFA_DOCVIEW_LAYOUTSTATUS_None),
+      m_iLock(0) {}
+CXFA_FFDocView::~CXFA_FFDocView() {
+  DestroyDocView();
+  if (m_pWidgetHandler) {
+    delete m_pWidgetHandler;
+  }
+  m_pWidgetHandler = NULL;
+}
+void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) {
+  RunBindItems();
+  ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize);
+  ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange);
+}
+int32_t CXFA_FFDocView::StartLayout(int32_t iStartPage) {
+  m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start;
+  m_pDoc->GetXFADoc()->DoProtoMerge();
+  m_pDoc->GetXFADoc()->DoDataMerge();
+  m_pXFADocLayout = GetXFALayout();
+  int32_t iStatus = m_pXFADocLayout->StartLayout();
+  if (iStatus < 0) {
+    return iStatus;
+  }
+  CXFA_Node* pRootItem =
+      ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
+  if (!pRootItem) {
+    return iStatus;
+  }
+  InitLayout(pRootItem);
+  InitCalculate(pRootItem);
+  InitValidate(pRootItem);
+  ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, TRUE);
+  m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start;
+  return iStatus;
+}
+int32_t CXFA_FFDocView::DoLayout(IFX_Pause* pPause) {
+  int32_t iStatus = 100;
+  iStatus = m_pXFADocLayout->DoLayout(pPause);
+  if (iStatus != 100) {
+    return iStatus;
+  }
+  m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Doing;
+  return iStatus;
+}
+void CXFA_FFDocView::StopLayout() {
+  CXFA_Node* pRootItem =
+      ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
+  if (!pRootItem) {
+    return;
+  }
+  CXFA_Node* pSubformNode = pRootItem->GetChild(0, XFA_ELEMENT_Subform);
+  if (!pSubformNode) {
+    return;
+  }
+  CXFA_Node* pPageSetNode =
+      pSubformNode->GetFirstChildByClass(XFA_ELEMENT_PageSet);
+  if (!pPageSetNode) {
+    return;
+  }
+  RunCalculateWidgets();
+  RunValidate();
+  InitLayout(pPageSetNode);
+  InitCalculate(pPageSetNode);
+  InitValidate(pPageSetNode);
+  ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, TRUE);
+  ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready);
+  ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady);
+  RunCalculateWidgets();
+  RunValidate();
+  if (RunLayout()) {
+    ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready);
+  }
+  m_CalculateAccs.RemoveAll();
+  if (m_pFocusAcc && !m_pFocusWidget) {
+    SetFocusWidgetAcc(m_pFocusAcc);
+  }
+  m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_End;
+}
+int32_t CXFA_FFDocView::GetLayoutStatus() {
+  return m_iStatus;
+}
+void CXFA_FFDocView::ShowNullTestMsg() {
+  int32_t iCount = m_arrNullTestMsg.GetSize();
+  CXFA_FFApp* pApp = m_pDoc->GetApp();
+  IXFA_AppProvider* pAppProvider = pApp->GetAppProvider();
+  if (pAppProvider && iCount) {
+    int32_t iRemain = iCount > 7 ? iCount - 7 : 0;
+    iCount -= iRemain;
+    CFX_WideString wsMsg;
+    for (int32_t i = 0; i < iCount; i++) {
+      wsMsg += m_arrNullTestMsg[i] + FX_WSTRC(L"\n");
+    }
+    if (iRemain > 0) {
+      CFX_WideString wsLimit;
+      pAppProvider->LoadString(XFA_IDS_ValidateLimit, wsLimit);
+      if (!wsLimit.IsEmpty()) {
+        CFX_WideString wsTemp;
+        wsTemp.Format((const FX_WCHAR*)wsLimit, iRemain);
+        wsMsg += FX_WSTRC(L"\n") + wsTemp;
+      }
+    }
+    CFX_WideString wsTitle;
+    pAppProvider->LoadString(XFA_IDS_AppName, wsTitle);
+    pAppProvider->MsgBox(wsMsg, wsTitle, XFA_MBICON_Status, XFA_MB_OK);
+  }
+  m_arrNullTestMsg.RemoveAll();
+}
+void CXFA_FFDocView::UpdateDocView() {
+  if (IsUpdateLocked()) {
+    return;
+  }
+  LockUpdate();
+  int32_t iNewAdds = m_NewAddedNodes.GetSize();
+  for (int32_t i = 0; i < iNewAdds; i++) {
+    CXFA_Node* pNode = reinterpret_cast<CXFA_Node*>(m_NewAddedNodes[i]);
+    InitCalculate(pNode);
+    InitValidate(pNode);
+    ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, TRUE);
+  }
+  m_NewAddedNodes.RemoveAll();
+  RunSubformIndexChange();
+  RunCalculateWidgets();
+  RunValidate();
+  ShowNullTestMsg();
+  if (RunLayout() && m_bLayoutEvent) {
+    RunEventLayoutReady();
+  }
+  m_bLayoutEvent = FALSE;
+  m_CalculateAccs.RemoveAll();
+  RunInvalidate();
+  UnlockUpdate();
+}
+int32_t CXFA_FFDocView::CountPageViews() {
+  if (!m_pXFADocLayout) {
+    return 0;
+  }
+  return m_pXFADocLayout->CountPages();
+}
+IXFA_PageView* CXFA_FFDocView::GetPageView(int32_t nIndex) {
+  if (!m_pXFADocLayout) {
+    return NULL;
+  }
+  return static_cast<CXFA_FFPageView*>(m_pXFADocLayout->GetPage(nIndex));
+}
+IXFA_Widget* CXFA_FFDocView::GetWidgetByName(const CFX_WideStringC& wsName) {
+  return GetWidgetByName(wsName, NULL);
+}
+CXFA_WidgetAcc* CXFA_FFDocView::GetWidgetAccByName(
+    const CFX_WideStringC& wsName) {
+  return GetWidgetAccByName(wsName, NULL);
+}
+IXFA_DocLayout* CXFA_FFDocView::GetXFALayout() const {
+  return m_pDoc->GetXFADoc()->GetDocLayout();
+}
+FX_BOOL CXFA_FFDocView::ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc) {
+  CXFA_Node* pNode = pWidgetAcc->GetNode();
+  XFA_ELEMENT eType = pNode->GetClassID();
+  if (eType != XFA_ELEMENT_Field && eType != XFA_ELEMENT_ExclGroup) {
+    return FALSE;
+  }
+  FX_BOOL bNotify = IsStaticNotify();
+  pWidgetAcc->ResetData();
+  pWidgetAcc->UpdateUIDisplay();
+  if (bNotify) {
+    pWidgetAcc->NotifyEvent(XFA_WIDGETEVENT_PostContentChanged, NULL, NULL,
+                            NULL);
+  }
+  if (CXFA_Validate validate = pWidgetAcc->GetValidate()) {
+    AddValidateWidget(pWidgetAcc);
+    validate.GetNode()->SetFlag(XFA_NODEFLAG_NeedsInitApp, TRUE, FALSE);
+  }
+  return TRUE;
+}
+void CXFA_FFDocView::ResetWidgetData(CXFA_WidgetAcc* pWidgetAcc) {
+  m_bLayoutEvent = TRUE;
+  FX_BOOL bChanged = FALSE;
+  CXFA_Node* pFormNode = NULL;
+  if (pWidgetAcc) {
+    bChanged = ResetSingleWidgetAccData(pWidgetAcc);
+    pFormNode = pWidgetAcc->GetNode();
+  } else {
+    pFormNode = GetRootSubform();
+  }
+  if (!pFormNode) {
+    return;
+  }
+  if (pFormNode->GetClassID() != XFA_ELEMENT_Field &&
+      pFormNode->GetClassID() != XFA_ELEMENT_ExclGroup) {
+    CXFA_WidgetAccIterator Iterator(this, pFormNode);
+    while (CXFA_WidgetAcc* pAcc = Iterator.MoveToNext()) {
+      bChanged |= ResetSingleWidgetAccData(pAcc);
+      if (pAcc->GetNode()->GetClassID() == XFA_ELEMENT_ExclGroup) {
+        Iterator.SkipTree();
+      }
+    }
+  }
+  if (bChanged) {
+    m_pDoc->GetDocProvider()->SetChangeMark(m_pDoc);
+  }
+}
+int32_t CXFA_FFDocView::ProcessWidgetEvent(CXFA_EventParam* pParam,
+                                           CXFA_WidgetAcc* pWidgetAcc) {
+  if (pParam == NULL) {
+    return XFA_EVENTERROR_Error;
+  }
+  if (pParam->m_eType == XFA_EVENT_Validate) {
+    CFX_WideString wsValidateStr = FX_WSTRC(L"preSubmit");
+    CXFA_Node* pConfigItem =
+        ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Config));
+    if (pConfigItem) {
+      CXFA_Node* pValidateNode = NULL;
+      CXFA_Node* pAcrobatNode = pConfigItem->GetChild(0, XFA_ELEMENT_Acrobat);
+      pValidateNode =
+          pAcrobatNode ? pAcrobatNode->GetChild(0, XFA_ELEMENT_Validate) : NULL;
+      if (!pValidateNode) {
+        CXFA_Node* pPresentNode = pConfigItem->GetChild(0, XFA_ELEMENT_Present);
+        pValidateNode = pPresentNode
+                            ? pPresentNode->GetChild(0, XFA_ELEMENT_Validate)
+                            : NULL;
+      }
+      if (pValidateNode) {
+        wsValidateStr = pValidateNode->GetContent();
+      }
+    }
+    FX_BOOL bValidate = FALSE;
+    switch (pParam->m_iValidateActivities) {
+      case XFA_VALIDATE_preSubmit:
+        bValidate = wsValidateStr.Find(L"preSubmit") != -1;
+        break;
+      case XFA_VALIDATE_prePrint:
+        bValidate = wsValidateStr.Find(L"prePrint") != -1;
+        break;
+      case XFA_VALIDATE_preExecute:
+        bValidate = wsValidateStr.Find(L"preExecute") != -1;
+        break;
+      case XFA_VALIDATE_preSave:
+        bValidate = wsValidateStr.Find(L"preSave") != -1;
+        break;
+    }
+    if (!bValidate) {
+      return XFA_EVENTERROR_Sucess;
+    }
+  }
+  CXFA_Node* pNode = pWidgetAcc ? pWidgetAcc->GetNode() : NULL;
+  if (!pNode) {
+    CXFA_Node* pRootItem =
+        ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
+    if (!pRootItem) {
+      return XFA_EVENTERROR_Error;
+    }
+    pNode = pRootItem->GetChild(0, XFA_ELEMENT_Subform);
+  }
+  ExecEventActivityByDeepFirst(pNode, pParam->m_eType, pParam->m_bIsFormReady);
+  return XFA_EVENTERROR_Sucess;
+}
+IXFA_WidgetHandler* CXFA_FFDocView::GetWidgetHandler() {
+  if (!m_pWidgetHandler) {
+    m_pWidgetHandler = new CXFA_FFWidgetHandler(this);
+  }
+  return m_pWidgetHandler;
+}
+IXFA_WidgetIterator* CXFA_FFDocView::CreateWidgetIterator() {
+  CXFA_Node* pFormRoot = GetRootSubform();
+  if (!pFormRoot) {
+    return NULL;
+  }
+  return new CXFA_FFDocWidgetIterator(this, pFormRoot);
+}
+IXFA_WidgetAccIterator* CXFA_FFDocView::CreateWidgetAccIterator(
+    XFA_WIDGETORDER eOrder) {
+  CXFA_Node* pFormRoot = GetRootSubform();
+  if (!pFormRoot) {
+    return NULL;
+  }
+  return new CXFA_WidgetAccIterator(this, pFormRoot);
+}
+IXFA_Widget* CXFA_FFDocView::GetFocusWidget() {
+  return m_pFocusWidget;
+}
+void CXFA_FFDocView::KillFocus() {
+  if (m_pFocusWidget &&
+      (m_pFocusWidget->GetStatus() & XFA_WIDGETSTATUS_Focused)) {
+    (m_pFocusWidget)->OnKillFocus(NULL);
+  }
+  m_pFocusAcc = NULL;
+  m_pFocusWidget = NULL;
+  m_pOldFocusWidget = NULL;
+}
+FX_BOOL CXFA_FFDocView::SetFocus(IXFA_Widget* hWidget) {
+  CXFA_FFWidget* pNewFocus = (CXFA_FFWidget*)hWidget;
+  if (m_pOldFocusWidget == pNewFocus) {
+    return FALSE;
+  }
+  CXFA_FFWidget* pOldFocus = m_pOldFocusWidget;
+  m_pOldFocusWidget = pNewFocus;
+  if (pOldFocus) {
+    if (m_pFocusWidget != m_pOldFocusWidget &&
+        (pOldFocus->GetStatus() & XFA_WIDGETSTATUS_Focused)) {
+      m_pFocusWidget = pOldFocus;
+      pOldFocus->OnKillFocus(pNewFocus);
+    } else if ((pOldFocus->GetStatus() & XFA_WIDGETSTATUS_Visible)) {
+      if (!pOldFocus->IsLoaded()) {
+        pOldFocus->LoadWidget();
+      }
+      pOldFocus->OnSetFocus(m_pFocusWidget);
+      m_pFocusWidget = pOldFocus;
+      pOldFocus->OnKillFocus(pNewFocus);
+    }
+  }
+  if (m_pFocusWidget == m_pOldFocusWidget) {
+    return FALSE;
+  }
+  pNewFocus = m_pOldFocusWidget;
+  if (m_pListFocusWidget && pNewFocus == m_pListFocusWidget) {
+    m_pFocusAcc = NULL;
+    m_pFocusWidget = NULL;
+    m_pListFocusWidget = NULL;
+    m_pOldFocusWidget = NULL;
+    return FALSE;
+  }
+  if (pNewFocus && (pNewFocus->GetStatus() & XFA_WIDGETSTATUS_Visible)) {
+    if (!pNewFocus->IsLoaded()) {
+      pNewFocus->LoadWidget();
+    }
+    pNewFocus->OnSetFocus(m_pFocusWidget);
+  }
+  m_pFocusAcc = pNewFocus ? pNewFocus->GetDataAcc() : NULL;
+  m_pFocusWidget = pNewFocus;
+  m_pOldFocusWidget = m_pFocusWidget;
+  return TRUE;
+}
+CXFA_WidgetAcc* CXFA_FFDocView::GetFocusWidgetAcc() {
+  return m_pFocusAcc;
+}
+void CXFA_FFDocView::SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
+  CXFA_FFWidget* pNewFocus =
+      pWidgetAcc ? pWidgetAcc->GetNextWidget(NULL) : NULL;
+  if (SetFocus(pNewFocus)) {
+    m_pFocusAcc = pWidgetAcc;
+    if (m_iStatus == XFA_DOCVIEW_LAYOUTSTATUS_End) {
+      m_pDoc->GetDocProvider()->SetFocusWidget(m_pDoc, m_pFocusWidget);
+    }
+  }
+}
+void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) {
+  if (m_pFocusAcc == pWidget->GetDataAcc()) {
+    m_pFocusAcc = NULL;
+    m_pFocusWidget = NULL;
+    m_pOldFocusWidget = NULL;
+  }
+}
+static int32_t XFA_ProcessEvent(CXFA_FFDocView* pDocView,
+                                CXFA_WidgetAcc* pWidgetAcc,
+                                CXFA_EventParam* pParam) {
+  if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  if (!pWidgetAcc || pWidgetAcc->GetClassID() == XFA_ELEMENT_Draw) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  switch (pParam->m_eType) {
+    case XFA_EVENT_Calculate:
+      return pWidgetAcc->ProcessCalculate();
+    case XFA_EVENT_Validate:
+      if (((CXFA_FFDoc*)pDocView->GetDoc())
+              ->GetDocProvider()
+              ->IsValidationsEnabled(pDocView->GetDoc())) {
+        return pWidgetAcc->ProcessValidate(0x01);
+      }
+      return XFA_EVENTERROR_Disabled;
+    case XFA_EVENT_InitCalculate: {
+      CXFA_Calculate calc = pWidgetAcc->GetCalculate();
+      if (!calc) {
+        return XFA_EVENTERROR_NotExist;
+      }
+      if (pWidgetAcc->GetNode()->HasFlag(XFA_NODEFLAG_UserInteractive)) {
+        return XFA_EVENTERROR_Disabled;
+      }
+      CXFA_Script script = calc.GetScript();
+      return pWidgetAcc->ExecuteScript(script, pParam);
+    }
+    default:
+      break;
+  }
+  int32_t iRet =
+      pWidgetAcc->ProcessEvent(gs_EventActivity[pParam->m_eType], pParam);
+  return iRet;
+}
+int32_t CXFA_FFDocView::ExecEventActivityByDeepFirst(CXFA_Node* pFormNode,
+                                                     XFA_EVENTTYPE eEventType,
+                                                     FX_BOOL bIsFormReady,
+                                                     FX_BOOL bRecursive,
+                                                     CXFA_Node* pExclude) {
+  int32_t iRet = XFA_EVENTERROR_NotExist;
+  if (pFormNode == pExclude) {
+    return iRet;
+  }
+  XFA_ELEMENT elementType = pFormNode->GetClassID();
+  if (elementType == XFA_ELEMENT_Field) {
+    if (eEventType == XFA_EVENT_IndexChange) {
+      return iRet;
+    }
+    CXFA_WidgetAcc* pWidgetAcc = (CXFA_WidgetAcc*)pFormNode->GetWidgetData();
+    if (pWidgetAcc == NULL) {
+      return iRet;
+    }
+    CXFA_EventParam eParam;
+    eParam.m_eType = eEventType;
+    eParam.m_pTarget = pWidgetAcc;
+    eParam.m_bIsFormReady = bIsFormReady;
+    return XFA_ProcessEvent(this, pWidgetAcc, &eParam);
+  }
+  if (bRecursive) {
+    for (CXFA_Node* pNode = pFormNode->GetNodeItem(
+             XFA_NODEITEM_FirstChild, XFA_OBJECTTYPE_ContainerNode);
+         pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling,
+                                           XFA_OBJECTTYPE_ContainerNode)) {
+      elementType = pNode->GetClassID();
+      if (elementType != XFA_ELEMENT_Variables &&
+          elementType != XFA_ELEMENT_Draw) {
+        iRet |= ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady,
+                                             bRecursive, pExclude);
+      }
+    }
+  }
+  CXFA_WidgetAcc* pWidgetAcc = (CXFA_WidgetAcc*)pFormNode->GetWidgetData();
+  if (pWidgetAcc == NULL) {
+    return iRet;
+  }
+  CXFA_EventParam eParam;
+  eParam.m_eType = eEventType;
+  eParam.m_pTarget = pWidgetAcc;
+  eParam.m_bIsFormReady = bIsFormReady;
+  iRet |= XFA_ProcessEvent(this, pWidgetAcc, &eParam);
+  return iRet;
+}
+CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const CFX_WideStringC& wsName,
+                                               CXFA_FFWidget* pRefWidget) {
+  CXFA_WidgetAcc* pRefAcc = pRefWidget ? pRefWidget->GetDataAcc() : NULL;
+  if (CXFA_WidgetAcc* pAcc = GetWidgetAccByName(wsName, pRefAcc)) {
+    return pAcc->GetNextWidget(NULL);
+  }
+  return NULL;
+}
+CXFA_WidgetAcc* CXFA_FFDocView::GetWidgetAccByName(
+    const CFX_WideStringC& wsName,
+    CXFA_WidgetAcc* pRefWidgetAcc) {
+  CFX_WideString wsExpression;
+  FX_DWORD dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
+                     XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
+  IXFA_ScriptContext* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext();
+  if (!pScriptContext) {
+    return NULL;
+  }
+  CXFA_Node* refNode = NULL;
+  if (pRefWidgetAcc) {
+    refNode = pRefWidgetAcc->GetNode();
+    wsExpression = wsName;
+  } else {
+    wsExpression = L"$form." + wsName;
+  }
+  XFA_RESOLVENODE_RS resoveNodeRS;
+  int32_t iRet = pScriptContext->ResolveObjects(refNode, wsExpression,
+                                                resoveNodeRS, dwStyle);
+  if (iRet < 1) {
+    return NULL;
+  }
+  if (resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
+    CXFA_Node* pNode = resoveNodeRS.nodes[0]->AsNode();
+    if (pNode) {
+      return (CXFA_WidgetAcc*)pNode->GetWidgetData();
+    }
+  }
+  return NULL;
+}
+void CXFA_FFDocView::OnPageEvent(IXFA_LayoutPage* pSender,
+                                 XFA_PAGEEVENT eEvent,
+                                 int32_t iPageIndex) {
+  CXFA_FFPageView* pFFPageView = static_cast<CXFA_FFPageView*>(pSender);
+  if (eEvent == XFA_PAGEEVENT_PageRemoved) {
+    m_pDoc->GetDocProvider()->PageViewEvent(pFFPageView,
+                                            XFA_PAGEVIEWEVENT_PostRemoved);
+    return;
+  }
+  m_pDoc->GetDocProvider()->PageViewEvent(pFFPageView,
+                                          XFA_PAGEVIEWEVENT_PostAdded);
+  pFFPageView->LoadPageView();
+}
+void CXFA_FFDocView::LockUpdate() {
+  m_iLock++;
+}
+void CXFA_FFDocView::UnlockUpdate() {
+  m_iLock--;
+}
+FX_BOOL CXFA_FFDocView::IsUpdateLocked() {
+  return m_iLock;
+}
+void CXFA_FFDocView::ClearInvalidateList() {
+  FX_POSITION ps = m_mapPageInvalidate.GetStartPosition();
+  while (ps) {
+    void* pPageView = NULL;
+    CFX_RectF* pRect = NULL;
+    m_mapPageInvalidate.GetNextAssoc(ps, pPageView, (void*&)pRect);
+    delete pRect;
+  }
+  m_mapPageInvalidate.RemoveAll();
+}
+void CXFA_FFDocView::AddInvalidateRect(CXFA_FFWidget* pWidget,
+                                       const CFX_RectF& rtInvalidate) {
+  AddInvalidateRect(pWidget->GetPageView(), rtInvalidate);
+}
+void CXFA_FFDocView::AddInvalidateRect(IXFA_PageView* pPageView,
+                                       const CFX_RectF& rtInvalidate) {
+  CFX_RectF* pRect = (CFX_RectF*)m_mapPageInvalidate.GetValueAt(pPageView);
+  if (!pRect) {
+    pRect = new CFX_RectF;
+    pRect->Set(rtInvalidate.left, rtInvalidate.top, rtInvalidate.width,
+               rtInvalidate.height);
+    m_mapPageInvalidate.SetAt(pPageView, pRect);
+  } else {
+    pRect->Union(rtInvalidate);
+  }
+}
+void CXFA_FFDocView::RunInvalidate() {
+  FX_POSITION ps = m_mapPageInvalidate.GetStartPosition();
+  while (ps) {
+    IXFA_PageView* pPageView = NULL;
+    CFX_RectF* pRect = NULL;
+    m_mapPageInvalidate.GetNextAssoc(ps, (void*&)pPageView, (void*&)pRect);
+    m_pDoc->GetDocProvider()->InvalidateRect(pPageView, *pRect);
+    delete pRect;
+  }
+  m_mapPageInvalidate.RemoveAll();
+}
+FX_BOOL CXFA_FFDocView::RunLayout() {
+  LockUpdate();
+  m_bInLayoutStatus = TRUE;
+  if (!m_pXFADocLayout->IncrementLayout() &&
+      m_pXFADocLayout->StartLayout() < 100) {
+    m_pXFADocLayout->DoLayout();
+    UnlockUpdate();
+    m_bInLayoutStatus = FALSE;
+    return TRUE;
+  }
+  m_bInLayoutStatus = FALSE;
+  UnlockUpdate();
+  return FALSE;
+}
+void CXFA_FFDocView::RunSubformIndexChange() {
+  int32_t iSubforms = m_IndexChangedSubforms.GetSize();
+  for (int32_t i = 0; i < iSubforms; i++) {
+    CXFA_Node* pSubformNode =
+        reinterpret_cast<CXFA_Node*>(m_IndexChangedSubforms[i]);
+    CXFA_WidgetAcc* pWidgetAcc = (CXFA_WidgetAcc*)pSubformNode->GetWidgetData();
+    if (!pWidgetAcc) {
+      continue;
+    }
+    CXFA_EventParam eParam;
+    eParam.m_eType = XFA_EVENT_IndexChange;
+    eParam.m_pTarget = pWidgetAcc;
+    pWidgetAcc->ProcessEvent(XFA_ATTRIBUTEENUM_IndexChange, &eParam);
+  }
+  m_IndexChangedSubforms.RemoveAll();
+}
+void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) {
+  m_NewAddedNodes.Add(pNode);
+  InitLayout(pNode);
+}
+void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) {
+  FXSYS_assert(pNode->GetClassID() == XFA_ELEMENT_Subform);
+  m_IndexChangedSubforms.Add(pNode);
+}
+void CXFA_FFDocView::RunDocClose() {
+  CXFA_Node* pRootItem =
+      ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
+  if (!pRootItem) {
+    return;
+  }
+  ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocClose);
+}
+void CXFA_FFDocView::DestroyDocView() {
+  ClearInvalidateList();
+  m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_None;
+  m_iLock = 0;
+  m_ValidateAccs.RemoveAll();
+  m_bindItems.RemoveAll();
+  m_CalculateAccs.RemoveAll();
+}
+FX_BOOL CXFA_FFDocView::IsStaticNotify() {
+  return m_pDoc->GetDocType() == XFA_DOCTYPE_Static;
+}
+void CXFA_FFDocView::AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
+  int32_t iAccs = m_CalculateAccs.GetSize();
+  CXFA_WidgetAcc* pCurrentAcc =
+      (iAccs < 1) ? (CXFA_WidgetAcc*)NULL
+                  : (CXFA_WidgetAcc*)m_CalculateAccs[iAccs - 1];
+  if (pCurrentAcc != pWidgetAcc) {
+    m_CalculateAccs.Add(pWidgetAcc);
+  }
+}
+void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) {
+  CXFA_CalcData* pGlobalData =
+      (CXFA_CalcData*)pNodeChange->GetUserData(XFA_CalcData);
+  int32_t iCount = pGlobalData ? pGlobalData->m_Globals.GetSize() : 0;
+  for (int32_t i = 0; i < iCount; i++) {
+    CXFA_WidgetAcc* pResultAcc = (CXFA_WidgetAcc*)pGlobalData->m_Globals[i];
+    if (pResultAcc->GetNode()->HasFlag(XFA_NODEFLAG_HasRemoved)) {
+      continue;
+    }
+    int32_t iAccs = m_CalculateAccs.GetSize();
+    CXFA_WidgetAcc* pCurrentAcc =
+        (iAccs < 1) ? (CXFA_WidgetAcc*)NULL
+                    : (CXFA_WidgetAcc*)m_CalculateAccs[iAccs - 1];
+    if (pCurrentAcc != pResultAcc) {
+      m_CalculateAccs.Add(pResultAcc);
+    }
+  }
+}
+void CXFA_FFDocView::RunCalculateRecursive(int32_t& iIndex) {
+  while (iIndex < m_CalculateAccs.GetSize()) {
+    CXFA_WidgetAcc* pCurAcc = (CXFA_WidgetAcc*)m_CalculateAccs[iIndex];
+    AddCalculateNodeNotify(pCurAcc->GetNode());
+    int32_t iRefCount =
+        (int32_t)(uintptr_t)pCurAcc->GetNode()->GetUserData(XFA_CalcRefCount);
+    iRefCount++;
+    pCurAcc->GetNode()->SetUserData(XFA_CalcRefCount,
+                                    (void*)(uintptr_t)iRefCount);
+    if (iRefCount > 11) {
+      break;
+    }
+    if ((pCurAcc->ProcessCalculate()) == XFA_EVENTERROR_Sucess) {
+      AddValidateWidget(pCurAcc);
+    }
+    iIndex++;
+    RunCalculateRecursive(iIndex);
+  }
+}
+int32_t CXFA_FFDocView::RunCalculateWidgets() {
+  if (!m_pDoc->GetDocProvider()->IsCalculationsEnabled(m_pDoc)) {
+    return XFA_EVENTERROR_Disabled;
+  }
+  int32_t iCounts = m_CalculateAccs.GetSize();
+  int32_t iIndex = 0;
+  if (iCounts > 0) {
+    RunCalculateRecursive(iIndex);
+  }
+  for (int32_t i = 0; i < m_CalculateAccs.GetSize(); i++) {
+    CXFA_WidgetAcc* pCurAcc = (CXFA_WidgetAcc*)m_CalculateAccs[i];
+    pCurAcc->GetNode()->SetUserData(XFA_CalcRefCount, (void*)(uintptr_t)0);
+  }
+  m_CalculateAccs.RemoveAll();
+  return XFA_EVENTERROR_Sucess;
+}
+void CXFA_FFDocView::AddValidateWidget(CXFA_WidgetAcc* pWidget) {
+  if (m_ValidateAccs.Find(pWidget) < 0) {
+    m_ValidateAccs.Add(pWidget);
+  }
+}
+FX_BOOL CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) {
+  ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate);
+  return TRUE;
+}
+FX_BOOL CXFA_FFDocView::InitValidate(CXFA_Node* pNode) {
+  if (!m_pDoc->GetDocProvider()->IsValidationsEnabled(m_pDoc)) {
+    return FALSE;
+  }
+  ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate);
+  m_ValidateAccs.RemoveAll();
+  return TRUE;
+}
+FX_BOOL CXFA_FFDocView::RunValidate() {
+  if (!m_pDoc->GetDocProvider()->IsValidationsEnabled(m_pDoc)) {
+    return FALSE;
+  }
+  int32_t iCounts = m_ValidateAccs.GetSize();
+  for (int32_t i = 0; i < iCounts; i++) {
+    CXFA_WidgetAcc* pAcc = (CXFA_WidgetAcc*)m_ValidateAccs[i];
+    if (pAcc->GetNode()->HasFlag(XFA_NODEFLAG_HasRemoved)) {
+      continue;
+    }
+    pAcc->ProcessValidate();
+  }
+  m_ValidateAccs.RemoveAll();
+  return TRUE;
+}
+FX_BOOL CXFA_FFDocView::RunEventLayoutReady() {
+  CXFA_Node* pRootItem =
+      ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
+  if (!pRootItem) {
+    return FALSE;
+  }
+  ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready);
+  RunLayout();
+  return TRUE;
+}
+void CXFA_FFDocView::RunBindItems() {
+  int32_t iCount = m_bindItems.GetSize();
+  for (int32_t i = 0; i < iCount; i++) {
+    if (reinterpret_cast<CXFA_Node*>(m_bindItems[i])
+            ->HasFlag(XFA_NODEFLAG_HasRemoved)) {
+      continue;
+    }
+    CXFA_Node* pWidgetNode = reinterpret_cast<CXFA_Node*>(m_bindItems[i])
+                                 ->GetNodeItem(XFA_NODEITEM_Parent);
+    CXFA_WidgetAcc* pAcc = (CXFA_WidgetAcc*)pWidgetNode->GetWidgetData();
+    if (!pAcc) {
+      continue;
+    }
+    CXFA_BindItems binditems(reinterpret_cast<CXFA_Node*>(m_bindItems[i]));
+    IXFA_ScriptContext* pScriptContext =
+        pWidgetNode->GetDocument()->GetScriptContext();
+    CFX_WideStringC wsRef;
+    binditems.GetRef(wsRef);
+    FX_DWORD dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
+                       XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent |
+                       XFA_RESOLVENODE_ALL;
+    XFA_RESOLVENODE_RS rs;
+    pScriptContext->ResolveObjects(pWidgetNode, wsRef, rs, dwStyle);
+    int32_t iCount = rs.nodes.GetSize();
+    pAcc->DeleteItem(-1);
+    if (rs.dwFlags != XFA_RESOVENODE_RSTYPE_Nodes || iCount < 1) {
+      continue;
+    }
+    CFX_WideStringC wsValueRef, wsLabelRef;
+    binditems.GetValueRef(wsValueRef);
+    binditems.GetLabelRef(wsLabelRef);
+    const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef;
+    const bool bLabelUseContent =
+        wsLabelRef.IsEmpty() || wsLabelRef == FX_WSTRC(L"$");
+    const bool bValueUseContent =
+        wsValueRef.IsEmpty() || wsValueRef == FX_WSTRC(L"$");
+    CFX_WideString wsValue, wsLabel;
+    FX_DWORD uValueHash = FX_HashCode_String_GetW(CFX_WideString(wsValueRef),
+                                                  wsValueRef.GetLength());
+    for (int32_t i = 0; i < iCount; i++) {
+      CXFA_Object* refObj = rs.nodes[i];
+      if (!refObj->IsNode()) {
+        continue;
+      }
+      CXFA_Node* refNode = refObj->AsNode();
+      if (bValueUseContent) {
+        wsValue = refNode->GetContent();
+      } else {
+        CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash);
+        if (nodeValue == NULL) {
+          wsValue = refNode->GetContent();
+        } else {
+          wsValue = nodeValue->GetContent();
+        }
+      }
+      if (!bUseValue) {
+        if (bLabelUseContent) {
+          wsLabel = refNode->GetContent();
+        } else {
+          CXFA_Node* nodeLabel = refNode->GetFirstChildByName(wsLabelRef);
+          if (nodeLabel)
+            wsLabel = nodeLabel->GetContent();
+        }
+      } else {
+        wsLabel = wsValue;
+      }
+      pAcc->InsertItem(wsLabel, wsValue);
+    }
+  }
+  m_bindItems.RemoveAll();
+}
+void CXFA_FFDocView::SetChangeMark() {
+  if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End) {
+    return;
+  }
+  m_pDoc->GetDocProvider()->SetChangeMark(m_pDoc);
+}
+CXFA_Node* CXFA_FFDocView::GetRootSubform() {
+  CXFA_Node* pFormPacketNode =
+      ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
+  if (!pFormPacketNode) {
+    return NULL;
+  }
+  return pFormPacketNode->GetFirstChildByClass(XFA_ELEMENT_Subform);
+}
+CXFA_FFDocWidgetIterator::CXFA_FFDocWidgetIterator(CXFA_FFDocView* pDocView,
+                                                   CXFA_Node* pTravelRoot)
+    : m_ContentIterator(pTravelRoot) {
+  m_pDocView = pDocView;
+  m_pCurWidget = NULL;
+}
+CXFA_FFDocWidgetIterator::~CXFA_FFDocWidgetIterator() {}
+void CXFA_FFDocWidgetIterator::Reset() {
+  m_ContentIterator.Reset();
+  m_pCurWidget = NULL;
+}
+IXFA_Widget* CXFA_FFDocWidgetIterator::MoveToFirst() {
+  return NULL;
+}
+IXFA_Widget* CXFA_FFDocWidgetIterator::MoveToLast() {
+  return NULL;
+}
+IXFA_Widget* CXFA_FFDocWidgetIterator::MoveToNext() {
+  CXFA_Node* pItem = m_pCurWidget ? m_ContentIterator.MoveToNext()
+                                  : m_ContentIterator.GetCurrent();
+  while (pItem) {
+    if (CXFA_WidgetAcc* pAcc = (CXFA_WidgetAcc*)pItem->GetWidgetData()) {
+      while ((m_pCurWidget = pAcc->GetNextWidget(NULL))) {
+        if (!m_pCurWidget->IsLoaded() &&
+            (m_pCurWidget->GetStatus() & XFA_WIDGETSTATUS_Visible)) {
+          m_pCurWidget->LoadWidget();
+        }
+        return m_pCurWidget;
+      }
+    }
+    pItem = m_ContentIterator.MoveToNext();
+  }
+  return NULL;
+}
+IXFA_Widget* CXFA_FFDocWidgetIterator::MoveToPrevious() {
+  return NULL;
+}
+IXFA_Widget* CXFA_FFDocWidgetIterator::GetCurrentWidget() {
+  return NULL;
+}
+FX_BOOL CXFA_FFDocWidgetIterator::SetCurrentWidget(IXFA_Widget* hWidget) {
+  return FALSE;
+}
+IXFA_WidgetAccIterator* XFA_WidgetAccIterator_Create(
+    CXFA_WidgetAcc* pTravelRoot,
+    XFA_WIDGETORDER eOrder) {
+  if (!pTravelRoot) {
+    return NULL;
+  }
+  return new CXFA_WidgetAccIterator(pTravelRoot->GetDocView(),
+                                    pTravelRoot->GetNode());
+}
+CXFA_WidgetAccIterator::CXFA_WidgetAccIterator(CXFA_FFDocView* pDocView,
+                                               CXFA_Node* pTravelRoot)
+    : m_ContentIterator(pTravelRoot) {
+  m_pDocView = pDocView;
+  m_pCurWidgetAcc = NULL;
+}
+CXFA_WidgetAccIterator::~CXFA_WidgetAccIterator() {}
+void CXFA_WidgetAccIterator::Reset() {
+  m_pCurWidgetAcc = NULL;
+  m_ContentIterator.Reset();
+}
+CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToFirst() {
+  return NULL;
+}
+CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToLast() {
+  return NULL;
+}
+CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToNext() {
+  CXFA_Node* pItem = m_pCurWidgetAcc ? m_ContentIterator.MoveToNext()
+                                     : m_ContentIterator.GetCurrent();
+  while (pItem) {
+    if ((m_pCurWidgetAcc = (CXFA_WidgetAcc*)pItem->GetWidgetData())) {
+      return m_pCurWidgetAcc;
+    }
+    pItem = m_ContentIterator.MoveToNext();
+  }
+  return NULL;
+}
+CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToPrevious() {
+  return NULL;
+}
+CXFA_WidgetAcc* CXFA_WidgetAccIterator::GetCurrentWidgetAcc() {
+  return NULL;
+}
+FX_BOOL CXFA_WidgetAccIterator::SetCurrentWidgetAcc(CXFA_WidgetAcc* hWidget) {
+  return FALSE;
+}
+void CXFA_WidgetAccIterator::SkipTree() {
+  m_ContentIterator.SkipChildrenAndMoveToNext();
+  m_pCurWidgetAcc = NULL;
+}
diff --git a/xfa/fxfa/app/xfa_ffdocview.h b/xfa/fxfa/app/xfa_ffdocview.h
new file mode 100644
index 0000000..284a32f
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffdocview.h
@@ -0,0 +1,170 @@
+// 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_FXFA_APP_XFA_FFDOCVIEW_H_
+#define XFA_FXFA_APP_XFA_FFDOCVIEW_H_
+
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+
+class CXFA_FFWidgetHandler;
+class CXFA_FFDoc;
+class CXFA_FFWidget;
+extern const XFA_ATTRIBUTEENUM gs_EventActivity[];
+enum XFA_DOCVIEW_LAYOUTSTATUS {
+  XFA_DOCVIEW_LAYOUTSTATUS_None,
+  XFA_DOCVIEW_LAYOUTSTATUS_Start,
+  XFA_DOCVIEW_LAYOUTSTATUS_FormInitialize,
+  XFA_DOCVIEW_LAYOUTSTATUS_FormInitCalculate,
+  XFA_DOCVIEW_LAYOUTSTATUS_FormInitValidate,
+  XFA_DOCVIEW_LAYOUTSTATUS_FormFormReady,
+  XFA_DOCVIEW_LAYOUTSTATUS_Doing,
+  XFA_DOCVIEW_LAYOUTSTATUS_PagesetInitialize,
+  XFA_DOCVIEW_LAYOUTSTATUS_PagesetInitCalculate,
+  XFA_DOCVIEW_LAYOUTSTATUS_PagesetInitValidate,
+  XFA_DOCVIEW_LAYOUTSTATUS_PagesetFormReady,
+  XFA_DOCVIEW_LAYOUTSTATUS_LayoutReady,
+  XFA_DOCVIEW_LAYOUTSTATUS_DocReady,
+  XFA_DOCVIEW_LAYOUTSTATUS_End
+};
+class CXFA_FFDocView : public IXFA_DocView {
+ public:
+  CXFA_FFDocView(CXFA_FFDoc* pDoc);
+  ~CXFA_FFDocView();
+
+  virtual IXFA_Doc* GetDoc() { return m_pDoc; }
+  virtual int32_t StartLayout(int32_t iStartPage = 0);
+  virtual int32_t DoLayout(IFX_Pause* pPause = NULL);
+  virtual void StopLayout();
+  virtual int32_t GetLayoutStatus();
+  virtual void UpdateDocView();
+  virtual int32_t CountPageViews();
+  virtual IXFA_PageView* GetPageView(int32_t nIndex);
+  virtual IXFA_Widget* GetWidgetByName(const CFX_WideStringC& wsName);
+  virtual CXFA_WidgetAcc* GetWidgetAccByName(const CFX_WideStringC& wsName);
+  virtual void ResetWidgetData(CXFA_WidgetAcc* pWidgetAcc = NULL);
+  virtual int32_t ProcessWidgetEvent(CXFA_EventParam* pParam,
+                                     CXFA_WidgetAcc* pWidgetAcc = NULL);
+  virtual IXFA_WidgetHandler* GetWidgetHandler();
+  virtual IXFA_WidgetIterator* CreateWidgetIterator();
+  virtual IXFA_WidgetAccIterator* CreateWidgetAccIterator(
+      XFA_WIDGETORDER eOrder = XFA_WIDGETORDER_PreOrder);
+  virtual IXFA_Widget* GetFocusWidget();
+  virtual void KillFocus();
+  virtual FX_BOOL SetFocus(IXFA_Widget* hWidget);
+  CXFA_FFWidget* GetWidgetByName(const CFX_WideStringC& wsName,
+                                 CXFA_FFWidget* pRefWidget = NULL);
+  CXFA_WidgetAcc* GetWidgetAccByName(const CFX_WideStringC& wsName,
+                                     CXFA_WidgetAcc* pRefWidgetAcc = NULL);
+  IXFA_DocLayout* GetXFALayout() const;
+  void OnPageEvent(IXFA_LayoutPage* pSender,
+                   XFA_PAGEEVENT eEvent,
+                   int32_t iPageIndex);
+  void LockUpdate();
+  void UnlockUpdate();
+  FX_BOOL IsUpdateLocked();
+  void ClearInvalidateList();
+  void AddInvalidateRect(CXFA_FFWidget* pWidget, const CFX_RectF& rtInvalidate);
+  void AddInvalidateRect(IXFA_PageView* pPageView,
+                         const CFX_RectF& rtInvalidate);
+  void RunInvalidate();
+  void RunDocClose();
+  void DestroyDocView();
+
+  FX_BOOL InitValidate(CXFA_Node* pNode);
+  FX_BOOL RunValidate();
+
+  void SetChangeMark();
+
+  void AddValidateWidget(CXFA_WidgetAcc* pWidget);
+  void AddCalculateNodeNotify(CXFA_Node* pNodeChange);
+  void AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc);
+  int32_t RunCalculateWidgets();
+  FX_BOOL IsStaticNotify();
+  FX_BOOL RunLayout();
+  void RunSubformIndexChange();
+  void AddNewFormNode(CXFA_Node* pNode);
+  void AddIndexChangedSubform(CXFA_Node* pNode);
+  CXFA_WidgetAcc* GetFocusWidgetAcc();
+  void SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc);
+  void DeleteLayoutItem(CXFA_FFWidget* pWidget);
+  int32_t ExecEventActivityByDeepFirst(CXFA_Node* pFormNode,
+                                       XFA_EVENTTYPE eEventType,
+                                       FX_BOOL bIsFormReady = FALSE,
+                                       FX_BOOL bRecursive = TRUE,
+                                       CXFA_Node* pExclude = NULL);
+  FX_BOOL m_bLayoutEvent;
+  CFX_WideStringArray m_arrNullTestMsg;
+  CXFA_FFWidget* m_pListFocusWidget;
+  FX_BOOL m_bInLayoutStatus;
+
+ protected:
+  FX_BOOL RunEventLayoutReady();
+  void RunBindItems();
+  FX_BOOL InitCalculate(CXFA_Node* pNode);
+  void InitLayout(CXFA_Node* pNode);
+  void RunCalculateRecursive(int32_t& iIndex);
+  void ShowNullTestMsg();
+  FX_BOOL ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc);
+  CXFA_Node* GetRootSubform();
+
+  CXFA_FFDoc* m_pDoc;
+  CXFA_FFWidgetHandler* m_pWidgetHandler;
+  IXFA_DocLayout* m_pXFADocLayout;
+  CXFA_WidgetAcc* m_pFocusAcc;
+  CXFA_FFWidget* m_pFocusWidget;
+  CXFA_FFWidget* m_pOldFocusWidget;
+  CFX_MapPtrToPtr m_mapPageInvalidate;
+  CFX_PtrArray m_ValidateAccs;
+  CFX_PtrArray m_bindItems;
+  CFX_PtrArray m_CalculateAccs;
+
+  CFX_PtrArray m_NewAddedNodes;
+  CFX_PtrArray m_IndexChangedSubforms;
+  XFA_DOCVIEW_LAYOUTSTATUS m_iStatus;
+  int32_t m_iLock;
+  friend class CXFA_FFNotify;
+};
+class CXFA_FFDocWidgetIterator : public IXFA_WidgetIterator {
+ public:
+  CXFA_FFDocWidgetIterator(CXFA_FFDocView* pDocView, CXFA_Node* pTravelRoot);
+  virtual ~CXFA_FFDocWidgetIterator();
+
+  virtual void Release() { delete this; }
+
+  virtual void Reset();
+  virtual IXFA_Widget* MoveToFirst();
+  virtual IXFA_Widget* MoveToLast();
+  virtual IXFA_Widget* MoveToNext();
+  virtual IXFA_Widget* MoveToPrevious();
+  virtual IXFA_Widget* GetCurrentWidget();
+  virtual FX_BOOL SetCurrentWidget(IXFA_Widget* hWidget);
+
+ protected:
+  CXFA_ContainerIterator m_ContentIterator;
+  CXFA_FFDocView* m_pDocView;
+  CXFA_FFWidget* m_pCurWidget;
+};
+class CXFA_WidgetAccIterator : public IXFA_WidgetAccIterator {
+ public:
+  CXFA_WidgetAccIterator(CXFA_FFDocView* pDocView, CXFA_Node* pTravelRoot);
+  virtual ~CXFA_WidgetAccIterator();
+  virtual void Release() { delete this; }
+  virtual void Reset();
+  virtual CXFA_WidgetAcc* MoveToFirst();
+  virtual CXFA_WidgetAcc* MoveToLast();
+  virtual CXFA_WidgetAcc* MoveToNext();
+  virtual CXFA_WidgetAcc* MoveToPrevious();
+  virtual CXFA_WidgetAcc* GetCurrentWidgetAcc();
+  virtual FX_BOOL SetCurrentWidgetAcc(CXFA_WidgetAcc* hWidget);
+  virtual void SkipTree();
+
+ protected:
+  CXFA_ContainerIterator m_ContentIterator;
+  CXFA_FFDocView* m_pDocView;
+  CXFA_WidgetAcc* m_pCurWidgetAcc;
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFDOCVIEW_H_
diff --git a/xfa/fxfa/app/xfa_ffdraw.cpp b/xfa/fxfa/app/xfa_ffdraw.cpp
new file mode 100644
index 0000000..06cfdfe
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffdraw.cpp
@@ -0,0 +1,16 @@
+// 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/fxfa/app/xfa_ffdraw.h"
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+
+CXFA_FFDraw::CXFA_FFDraw(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFWidget(pPageView, pDataAcc) {}
+CXFA_FFDraw::~CXFA_FFDraw() {}
diff --git a/xfa/fxfa/app/xfa_ffdraw.h b/xfa/fxfa/app/xfa_ffdraw.h
new file mode 100644
index 0000000..a5db598
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffdraw.h
@@ -0,0 +1,19 @@
+// 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_FXFA_APP_XFA_FFDRAW_H_
+#define XFA_FXFA_APP_XFA_FFDRAW_H_
+
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+
+class CXFA_FFDraw : public CXFA_FFWidget {
+ public:
+  CXFA_FFDraw(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFDraw();
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFDRAW_H_
diff --git a/xfa/fxfa/app/xfa_ffexclgroup.cpp b/xfa/fxfa/app/xfa_ffexclgroup.cpp
new file mode 100644
index 0000000..4e24218
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffexclgroup.cpp
@@ -0,0 +1,31 @@
+// 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/fxfa/app/xfa_ffexclgroup.h"
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+
+CXFA_FFExclGroup::CXFA_FFExclGroup(CXFA_FFPageView* pPageView,
+                                   CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFWidget(pPageView, pDataAcc) {}
+CXFA_FFExclGroup::~CXFA_FFExclGroup() {}
+void CXFA_FFExclGroup::RenderWidget(CFX_Graphics* pGS,
+                                    CFX_Matrix* pMatrix,
+                                    FX_DWORD dwStatus,
+                                    int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
+}
diff --git a/xfa/fxfa/app/xfa_ffexclgroup.h b/xfa/fxfa/app/xfa_ffexclgroup.h
new file mode 100644
index 0000000..fd3f4d8
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffexclgroup.h
@@ -0,0 +1,24 @@
+// 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_FXFA_APP_XFA_FFEXCLGROUP_H_
+#define XFA_FXFA_APP_XFA_FFEXCLGROUP_H_
+
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+
+class CXFA_FFExclGroup : public CXFA_FFWidget {
+ public:
+  CXFA_FFExclGroup(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFExclGroup();
+
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFEXCLGROUP_H_
diff --git a/xfa/fxfa/app/xfa_fffield.cpp b/xfa/fxfa/app/xfa_fffield.cpp
new file mode 100644
index 0000000..39e7ee5
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fffield.cpp
@@ -0,0 +1,835 @@
+// 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/fxfa/app/xfa_fffield.h"
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_fwltheme.h"
+#include "xfa/fxfa/app/xfa_textlayout.h"
+#include "xfa/include/fwl/basewidget/fwl_edit.h"
+#include "xfa/include/fwl/core/fwl_widgetmgr.h"
+#include "xfa/include/fwl/lightwidget/edit.h"
+#include "xfa/include/fwl/lightwidget/picturebox.h"
+
+CXFA_FFField::CXFA_FFField(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFWidget(pPageView, pDataAcc), m_pNormalWidget(NULL) {
+  m_rtUI.Set(0, 0, 0, 0);
+  m_rtCaption.Set(0, 0, 0, 0);
+}
+CXFA_FFField::~CXFA_FFField() {
+  CXFA_FFField::UnloadWidget();
+}
+
+FX_BOOL CXFA_FFField::GetBBox(CFX_RectF& rtBox,
+                              FX_DWORD dwStatus,
+                              FX_BOOL bDrawFocus) {
+  if (!bDrawFocus)
+    return CXFA_FFWidget::GetBBox(rtBox, dwStatus);
+
+  XFA_ELEMENT type = (XFA_ELEMENT)m_pDataAcc->GetUIType();
+  if (type == XFA_ELEMENT_Button || type == XFA_ELEMENT_CheckButton ||
+      type == XFA_ELEMENT_ImageEdit || type == XFA_ELEMENT_Signature ||
+      type == XFA_ELEMENT_ChoiceList) {
+    rtBox = m_rtUI;
+    CFX_Matrix mt;
+    GetRotateMatrix(mt);
+    mt.TransformRect(rtBox);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+void CXFA_FFField::RenderWidget(CFX_Graphics* pGS,
+                                CFX_Matrix* pMatrix,
+                                FX_DWORD dwStatus,
+                                int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
+  CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
+  DrawBorder(pGS, borderUI, m_rtUI, &mtRotate);
+  RenderCaption(pGS, &mtRotate);
+  DrawHighlight(pGS, &mtRotate, dwStatus, FALSE);
+  CFX_RectF rtWidget;
+  m_pNormalWidget->GetWidgetRect(rtWidget);
+  CFX_Matrix mt;
+  mt.Set(1, 0, 0, 1, rtWidget.left, rtWidget.top);
+  mt.Concat(mtRotate);
+  GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget->GetWidget(),
+                                                 pGS, &mt);
+}
+void CXFA_FFField::DrawHighlight(CFX_Graphics* pGS,
+                                 CFX_Matrix* pMatrix,
+                                 FX_DWORD dwStatus,
+                                 FX_BOOL bEllipse) {
+  if (m_rtUI.IsEmpty() || !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    return;
+  }
+  if ((dwStatus & XFA_WIDGETSTATUS_Highlight) &&
+      m_pDataAcc->GetAccess() == XFA_ATTRIBUTEENUM_Open) {
+    CXFA_FFDoc* pDoc = GetDoc();
+    CFX_Color crHighlight(pDoc->GetDocProvider()->GetHighlightColor(pDoc));
+    pGS->SetFillColor(&crHighlight);
+    CFX_Path path;
+    path.Create();
+    if (bEllipse) {
+      path.AddEllipse(m_rtUI);
+    } else {
+      path.AddRectangle(m_rtUI.left, m_rtUI.top, m_rtUI.width, m_rtUI.height);
+    }
+    pGS->FillPath(&path, FXFILL_WINDING, pMatrix);
+  }
+}
+void CXFA_FFField::DrawFocus(CFX_Graphics* pGS, CFX_Matrix* pMatrix) {
+  if (m_dwStatus & XFA_WIDGETSTATUS_Focused) {
+    CFX_Color cr(0xFF000000);
+    pGS->SetStrokeColor(&cr);
+    FX_FLOAT DashPattern[2] = {1, 1};
+    pGS->SetLineDash(0.0f, DashPattern, 2);
+    pGS->SetLineWidth(0, FALSE);
+    CFX_Path path;
+    path.Create();
+    path.AddRectangle(m_rtUI.left, m_rtUI.top, m_rtUI.width, m_rtUI.height);
+    pGS->StrokePath(&path, pMatrix);
+  }
+}
+void CXFA_FFField::SetFWLThemeProvider() {
+  if (m_pNormalWidget) {
+    m_pNormalWidget->m_pIface->SetThemeProvider(GetApp()->GetFWLTheme());
+  }
+}
+FX_BOOL CXFA_FFField::IsLoaded() {
+  return m_pNormalWidget && CXFA_FFWidget::IsLoaded();
+}
+FX_BOOL CXFA_FFField::LoadWidget() {
+  SetFWLThemeProvider();
+  m_pDataAcc->LoadCaption();
+  PerformLayout();
+  return TRUE;
+}
+void CXFA_FFField::UnloadWidget() {
+  delete m_pNormalWidget;
+  m_pNormalWidget = nullptr;
+}
+void CXFA_FFField::SetEditScrollOffset() {
+  XFA_ELEMENT eType = m_pDataAcc->GetUIType();
+  if (eType == XFA_ELEMENT_TextEdit || eType == XFA_ELEMENT_NumericEdit ||
+      eType == XFA_ELEMENT_PasswordEdit) {
+    FX_FLOAT fScrollOffset = 0;
+    CXFA_FFField* pPrev = static_cast<CXFA_FFField*>(GetPrev());
+    if (pPrev) {
+      CFX_RectF rtMargin;
+      m_pDataAcc->GetUIMargin(rtMargin);
+      fScrollOffset = -rtMargin.top;
+    }
+    while (pPrev) {
+      fScrollOffset += pPrev->m_rtUI.height;
+      pPrev = static_cast<CXFA_FFField*>(pPrev->GetPrev());
+    }
+    ((CFWL_Edit*)m_pNormalWidget)->SetScrollOffset(fScrollOffset);
+  }
+}
+FX_BOOL CXFA_FFField::PerformLayout() {
+  CXFA_FFWidget::PerformLayout();
+  CapPlacement();
+  LayoutCaption();
+  SetFWLRect();
+  SetEditScrollOffset();
+  if (m_pNormalWidget) {
+    m_pNormalWidget->Update();
+  }
+  return TRUE;
+}
+void CXFA_FFField::CapPlacement() {
+  CFX_RectF rtWidget;
+  GetRectWithoutRotate(rtWidget);
+  CXFA_Margin mgWidget = m_pDataAcc->GetMargin();
+  if (mgWidget) {
+    CXFA_LayoutItem* pItem = this;
+    FX_FLOAT fLeftInset = 0, fRightInset = 0, fTopInset = 0, fBottomInset = 0;
+    mgWidget.GetLeftInset(fLeftInset);
+    mgWidget.GetRightInset(fRightInset);
+    mgWidget.GetTopInset(fTopInset);
+    mgWidget.GetBottomInset(fBottomInset);
+    if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) {
+      rtWidget.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
+    } else {
+      if (pItem->GetPrev() == NULL) {
+        rtWidget.Deflate(fLeftInset, fTopInset, fRightInset, 0);
+      } else if (pItem->GetNext() == NULL) {
+        rtWidget.Deflate(fLeftInset, 0, fRightInset, fBottomInset);
+      } else {
+        rtWidget.Deflate(fLeftInset, 0, fRightInset, 0);
+      }
+    }
+  }
+  XFA_ATTRIBUTEENUM iCapPlacement = XFA_ATTRIBUTEENUM_Unknown;
+  FX_FLOAT fCapReserve = 0;
+  CXFA_Caption caption = m_pDataAcc->GetCaption();
+  if (caption && caption.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) {
+    iCapPlacement = (XFA_ATTRIBUTEENUM)caption.GetPlacementType();
+    if (iCapPlacement == XFA_ATTRIBUTEENUM_Top && GetPrev()) {
+      m_rtCaption.Set(0, 0, 0, 0);
+    } else if (iCapPlacement == XFA_ATTRIBUTEENUM_Bottom && GetNext()) {
+      m_rtCaption.Set(0, 0, 0, 0);
+    } else {
+      fCapReserve = caption.GetReserve();
+      CXFA_LayoutItem* pItem = this;
+      if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) {
+        m_rtCaption.Set(rtWidget.left, rtWidget.top, rtWidget.width,
+                        rtWidget.height);
+      } else {
+        pItem = pItem->GetFirst();
+        pItem->GetRect(m_rtCaption);
+        pItem = pItem->GetNext();
+        while (pItem) {
+          CFX_RectF rtRect;
+          pItem->GetRect(rtRect);
+          m_rtCaption.height += rtRect.Height();
+          pItem = pItem->GetNext();
+        }
+        XFA_RectWidthoutMargin(m_rtCaption, mgWidget);
+      }
+      CXFA_TextLayout* pCapTextLayout = m_pDataAcc->GetCaptionTextLayout();
+      if (fCapReserve <= 0 && pCapTextLayout) {
+        CFX_SizeF size;
+        CFX_SizeF minSize;
+        CFX_SizeF maxSize;
+        pCapTextLayout->CalcSize(minSize, maxSize, size);
+        if (iCapPlacement == XFA_ATTRIBUTEENUM_Top ||
+            iCapPlacement == XFA_ATTRIBUTEENUM_Bottom) {
+          fCapReserve = size.y;
+        } else {
+          fCapReserve = size.x;
+        }
+      }
+    }
+  }
+  m_rtUI = rtWidget;
+  switch (iCapPlacement) {
+    case XFA_ATTRIBUTEENUM_Left: {
+      m_rtCaption.width = fCapReserve;
+      CapLeftRightPlacement(caption, rtWidget, iCapPlacement);
+      m_rtUI.width -= fCapReserve;
+      m_rtUI.left += fCapReserve;
+    } break;
+    case XFA_ATTRIBUTEENUM_Top: {
+      m_rtCaption.height = fCapReserve;
+      CapTopBottomPlacement(caption, rtWidget, iCapPlacement);
+      m_rtUI.top += fCapReserve;
+      m_rtUI.height -= fCapReserve;
+    } break;
+    case XFA_ATTRIBUTEENUM_Right: {
+      m_rtCaption.left = m_rtCaption.right() - fCapReserve;
+      m_rtCaption.width = fCapReserve;
+      CapLeftRightPlacement(caption, rtWidget, iCapPlacement);
+      m_rtUI.width -= fCapReserve;
+    } break;
+    case XFA_ATTRIBUTEENUM_Bottom: {
+      m_rtCaption.top = m_rtCaption.bottom() - fCapReserve;
+      m_rtCaption.height = fCapReserve;
+      CapTopBottomPlacement(caption, rtWidget, iCapPlacement);
+      m_rtUI.height -= fCapReserve;
+    } break;
+    case XFA_ATTRIBUTEENUM_Inline:
+      break;
+    default:
+      break;
+  }
+  CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
+  if (borderUI) {
+    CXFA_Margin margin = borderUI.GetMargin();
+    if (margin) {
+      XFA_RectWidthoutMargin(m_rtUI, margin);
+    }
+  }
+  m_rtUI.Normalize();
+}
+void CXFA_FFField::CapTopBottomPlacement(CXFA_Caption caption,
+                                         const CFX_RectF& rtWidget,
+                                         int32_t iCapPlacement) {
+  CFX_RectF rtUIMargin;
+  m_pDataAcc->GetUIMargin(rtUIMargin);
+  m_rtCaption.left += rtUIMargin.left;
+  if (CXFA_Margin mgCap = caption.GetMargin()) {
+    XFA_RectWidthoutMargin(m_rtCaption, mgCap);
+    if (m_rtCaption.height < 0) {
+      m_rtCaption.top += m_rtCaption.height;
+    }
+  }
+  FX_FLOAT fWidth = rtUIMargin.left + rtUIMargin.width;
+  FX_FLOAT fHeight = m_rtCaption.height + rtUIMargin.top + rtUIMargin.height;
+  if (fWidth > rtWidget.width) {
+    m_rtUI.width += fWidth - rtWidget.width;
+  }
+  if (fHeight == XFA_DEFAULTUI_HEIGHT && m_rtUI.height < XFA_MINUI_HEIGHT) {
+    m_rtUI.height = XFA_MINUI_HEIGHT;
+    m_rtCaption.top += rtUIMargin.top + rtUIMargin.height;
+  } else if (fHeight > rtWidget.height) {
+    m_rtUI.height += fHeight - rtWidget.height;
+    if (iCapPlacement == XFA_ATTRIBUTEENUM_Bottom) {
+      m_rtCaption.top += fHeight - rtWidget.height;
+    }
+  }
+}
+void CXFA_FFField::CapLeftRightPlacement(CXFA_Caption caption,
+                                         const CFX_RectF& rtWidget,
+                                         int32_t iCapPlacement) {
+  CFX_RectF rtUIMargin;
+  m_pDataAcc->GetUIMargin(rtUIMargin);
+  m_rtCaption.top += rtUIMargin.top;
+  m_rtCaption.height -= rtUIMargin.top;
+  if (CXFA_Margin mgCap = caption.GetMargin()) {
+    XFA_RectWidthoutMargin(m_rtCaption, mgCap);
+    if (m_rtCaption.height < 0) {
+      m_rtCaption.top += m_rtCaption.height;
+    }
+  }
+  FX_FLOAT fWidth = m_rtCaption.width + rtUIMargin.left + rtUIMargin.width;
+  FX_FLOAT fHeight = rtUIMargin.top + rtUIMargin.height;
+  if (fWidth > rtWidget.width) {
+    m_rtUI.width += fWidth - rtWidget.width;
+    if (iCapPlacement == XFA_ATTRIBUTEENUM_Right) {
+      m_rtCaption.left += fWidth - rtWidget.width;
+    }
+  }
+  if (fHeight == XFA_DEFAULTUI_HEIGHT && m_rtUI.height < XFA_MINUI_HEIGHT) {
+    m_rtUI.height = XFA_MINUI_HEIGHT;
+    m_rtCaption.top += rtUIMargin.top + rtUIMargin.height;
+  } else if (fHeight > rtWidget.height) {
+    m_rtUI.height += fHeight - rtWidget.height;
+  }
+}
+void CXFA_FFField::UpdateFWL() {
+  if (m_pNormalWidget) {
+    m_pNormalWidget->Update();
+  }
+}
+FX_DWORD CXFA_FFField::UpdateUIProperty() {
+  CXFA_Node* pUiNode = m_pDataAcc->GetUIChild();
+  FX_DWORD dwStyle = 0;
+  if (pUiNode && pUiNode->GetClassID() == XFA_ELEMENT_DefaultUi) {
+    dwStyle = FWL_STYLEEXT_EDT_ReadOnly;
+  }
+  return dwStyle;
+}
+void CXFA_FFField::SetFWLRect() {
+  if (!m_pNormalWidget) {
+    return;
+  }
+  CFX_RectF rtUi = m_rtUI;
+  if (rtUi.width < 1.0) {
+    FXSYS_assert(rtUi.width < 1.0);
+    rtUi.width = 1.0;
+  }
+  if (!m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    FX_FLOAT fFontSize = m_pDataAcc->GetFontSize();
+    if (rtUi.height < fFontSize) {
+      rtUi.height = fFontSize;
+    }
+  }
+  m_pNormalWidget->SetWidgetRect(rtUi);
+}
+FX_BOOL CXFA_FFField::OnMouseEnter() {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_MouseEnter;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  ms.m_pSrcTarget = NULL;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnMouseExit() {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_MouseLeave;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+void CXFA_FFField::FWLToClient(FX_FLOAT& fx, FX_FLOAT& fy) {
+  if (!m_pNormalWidget) {
+    return;
+  }
+  CFX_RectF rtWidget;
+  m_pNormalWidget->GetWidgetRect(rtWidget);
+  fx -= rtWidget.left;
+  fy -= rtWidget.top;
+}
+FX_BOOL CXFA_FFField::OnLButtonDown(FX_DWORD dwFlags,
+                                    FX_FLOAT fx,
+                                    FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open ||
+      !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    return FALSE;
+  }
+  if (!PtInActiveRect(fx, fy)) {
+    return FALSE;
+  }
+  SetButtonDown(TRUE);
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_LButtonDown;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  if (!IsButtonDown()) {
+    return FALSE;
+  }
+  SetButtonDown(FALSE);
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_LButtonUp;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnLButtonDblClk(FX_DWORD dwFlags,
+                                      FX_FLOAT fx,
+                                      FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_LButtonDblClk;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_MouseMove;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnMouseWheel(FX_DWORD dwFlags,
+                                   int16_t zDelta,
+                                   FX_FLOAT fx,
+                                   FX_FLOAT fy) {
+  return FALSE;
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFWL_MsgMouseWheel ms;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  ms.m_fDeltaX = zDelta;
+  ms.m_fDeltaY = 0;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnRButtonDown(FX_DWORD dwFlags,
+                                    FX_FLOAT fx,
+                                    FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open ||
+      !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    return FALSE;
+  }
+  if (!PtInActiveRect(fx, fy)) {
+    return FALSE;
+  }
+  SetButtonDown(TRUE);
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_RButtonDown;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  if (!IsButtonDown()) {
+    return FALSE;
+  }
+  SetButtonDown(FALSE);
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_RButtonUp;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnRButtonDblClk(FX_DWORD dwFlags,
+                                      FX_FLOAT fx,
+                                      FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_RButtonDblClk;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+
+FX_BOOL CXFA_FFField::OnSetFocus(CXFA_FFWidget* pOldWidget) {
+  CXFA_FFWidget::OnSetFocus(pOldWidget);
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFWL_MsgSetFocus ms;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  ms.m_pSrcTarget = NULL;
+  TranslateFWLMessage(&ms);
+  m_dwStatus |= XFA_WIDGETSTATUS_Focused;
+  AddInvalidateRect();
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnKillFocus(CXFA_FFWidget* pNewWidget) {
+  if (!m_pNormalWidget) {
+    return CXFA_FFWidget::OnKillFocus(pNewWidget);
+  }
+  CFWL_MsgKillFocus ms;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  ms.m_pSrcTarget = NULL;
+  TranslateFWLMessage(&ms);
+  m_dwStatus &= ~XFA_WIDGETSTATUS_Focused;
+  AddInvalidateRect();
+  CXFA_FFWidget::OnKillFocus(pNewWidget);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnKeyDown(FX_DWORD dwKeyCode, FX_DWORD dwFlags) {
+  if (!m_pNormalWidget || !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    return FALSE;
+  }
+  CFWL_MsgKey ms;
+  ms.m_dwCmd = FWL_MSGKEYCMD_KeyDown;
+  ms.m_dwFlags = dwFlags;
+  ms.m_dwKeyCode = dwKeyCode;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  ms.m_pSrcTarget = NULL;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnKeyUp(FX_DWORD dwKeyCode, FX_DWORD dwFlags) {
+  if (!m_pNormalWidget || !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    return FALSE;
+  }
+  CFWL_MsgKey ms;
+  ms.m_dwCmd = FWL_MSGKEYCMD_KeyUp;
+  ms.m_dwFlags = dwFlags;
+  ms.m_dwKeyCode = dwKeyCode;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  ms.m_pSrcTarget = NULL;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::OnChar(FX_DWORD dwChar, FX_DWORD dwFlags) {
+  if (!m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    return FALSE;
+  }
+  if (dwChar == FWL_VKEY_Tab) {
+    return TRUE;
+  }
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) {
+    return FALSE;
+  }
+  CFWL_MsgKey ms;
+  ms.m_dwCmd = FWL_MSGKEYCMD_Char;
+  ms.m_dwFlags = dwFlags;
+  ms.m_dwKeyCode = dwChar;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  ms.m_pSrcTarget = NULL;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_DWORD CXFA_FFField::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) {
+  if (m_pNormalWidget) {
+    FX_FLOAT ffx = fx, ffy = fy;
+    FWLToClient(ffx, ffy);
+    FX_DWORD dwWidgetHit = m_pNormalWidget->HitTest(ffx, ffy);
+    if (dwWidgetHit != FWL_WGTHITTEST_Unknown) {
+      return FWL_WGTHITTEST_Client;
+    }
+  }
+  CFX_RectF rtBox;
+  GetRectWithoutRotate(rtBox);
+  if (!rtBox.Contains(fx, fy)) {
+    return FWL_WGTHITTEST_Unknown;
+  }
+  if (m_rtCaption.Contains(fx, fy)) {
+    return FWL_WGTHITTEST_Titlebar;
+  }
+  return FWL_WGTHITTEST_Border;
+}
+FX_BOOL CXFA_FFField::OnSetCursor(FX_FLOAT fx, FX_FLOAT fy) {
+  return TRUE;
+}
+FX_BOOL CXFA_FFField::PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFX_RectF rtWidget;
+  m_pNormalWidget->GetWidgetRect(rtWidget);
+  if (rtWidget.Contains(fx, fy)) {
+    return TRUE;
+  }
+  return FALSE;
+}
+void CXFA_FFField::LayoutCaption() {
+  CXFA_TextLayout* pCapTextLayout = m_pDataAcc->GetCaptionTextLayout();
+  if (!pCapTextLayout)
+    return;
+
+  FX_FLOAT fHeight = 0;
+  pCapTextLayout->Layout(CFX_SizeF(m_rtCaption.width, m_rtCaption.height),
+                         &fHeight);
+  if (m_rtCaption.height < fHeight)
+    m_rtCaption.height = fHeight;
+}
+void CXFA_FFField::RenderCaption(CFX_Graphics* pGS, CFX_Matrix* pMatrix) {
+  CXFA_TextLayout* pCapTextLayout = m_pDataAcc->GetCaptionTextLayout();
+  if (!pCapTextLayout) {
+    return;
+  }
+  CXFA_Caption caption = m_pDataAcc->GetCaption();
+  if (caption && caption.GetPresence() == XFA_ATTRIBUTEENUM_Visible) {
+    if (!pCapTextLayout->IsLoaded()) {
+      pCapTextLayout->Layout(CFX_SizeF(m_rtCaption.width, m_rtCaption.height));
+    }
+    CFX_RectF rtWidget;
+    GetRectWithoutRotate(rtWidget);
+    CFX_RectF rtClip = m_rtCaption;
+    rtClip.Intersect(rtWidget);
+    CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
+    CFX_Matrix mt;
+    mt.Set(1, 0, 0, 1, m_rtCaption.left, m_rtCaption.top);
+    if (pMatrix) {
+      pMatrix->TransformRect(rtClip);
+      mt.Concat(*pMatrix);
+    }
+    pCapTextLayout->DrawString(pRenderDevice, mt, rtClip);
+  }
+}
+FX_BOOL CXFA_FFField::ProcessCommittedData() {
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) {
+    return FALSE;
+  }
+  if (!IsDataChanged()) {
+    return FALSE;
+  }
+  if (CalculateOverride() != 1) {
+    return FALSE;
+  }
+  if (!CommitData()) {
+    return FALSE;
+  }
+  m_pDocView->SetChangeMark();
+  m_pDocView->AddValidateWidget(m_pDataAcc);
+  return TRUE;
+}
+int32_t CXFA_FFField::CalculateOverride() {
+  CXFA_WidgetAcc* pAcc = m_pDataAcc->GetExclGroup();
+  if (!pAcc) {
+    return CalculateWidgetAcc(m_pDataAcc);
+  }
+  if (CalculateWidgetAcc(pAcc) == 0) {
+    return 0;
+  }
+  CXFA_Node* pNode = pAcc->GetExclGroupFirstMember();
+  if (!pNode) {
+    return 1;
+  }
+  CXFA_WidgetAcc* pWidgetAcc = NULL;
+  while (pNode) {
+    pWidgetAcc = (CXFA_WidgetAcc*)pNode->GetWidgetData();
+    if (!pWidgetAcc) {
+      return 1;
+    }
+    if (CalculateWidgetAcc(pWidgetAcc) == 0) {
+      return 0;
+    }
+    pNode = pWidgetAcc->GetExclGroupNextMember(pNode);
+  }
+  return 1;
+}
+int32_t CXFA_FFField::CalculateWidgetAcc(CXFA_WidgetAcc* pAcc) {
+  CXFA_Calculate calc = pAcc->GetCalculate();
+  if (!calc) {
+    return 1;
+  }
+  XFA_VERSION version = pAcc->GetDoc()->GetXFADoc()->GetCurVersionMode();
+  if (calc) {
+    int32_t iOverride = calc.GetOverride();
+    switch (iOverride) {
+      case XFA_ATTRIBUTEENUM_Error: {
+        if (version <= XFA_VERSION_204) {
+          return 1;
+        }
+        IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider();
+        if (pAppProvider) {
+          CFX_WideString wsMessage;
+          CFX_WideString wsWarning;
+          pAppProvider->LoadString(XFA_IDS_NotModifyField, wsWarning);
+          wsMessage += wsWarning;
+          CFX_WideString wsTitle;
+          pAppProvider->LoadString(XFA_IDS_CalcOverride, wsTitle);
+          pAppProvider->MsgBox(wsMessage, wsTitle, XFA_MBICON_Warning,
+                               XFA_MB_OK);
+        }
+      }
+        return 0;
+      case XFA_ATTRIBUTEENUM_Warning: {
+        if (version <= XFA_VERSION_204) {
+          CXFA_Script script = calc.GetScript();
+          if (!script) {
+            return 1;
+          }
+          CFX_WideString wsExpression;
+          script.GetExpression(wsExpression);
+          if (wsExpression.IsEmpty()) {
+            return 1;
+          }
+        }
+        if (pAcc->GetNode()->HasFlag(XFA_NODEFLAG_UserInteractive)) {
+          return 1;
+        }
+        IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider();
+        if (pAppProvider) {
+          CFX_WideString wsMessage;
+          calc.GetMessageText(wsMessage);
+          if (!wsMessage.IsEmpty()) {
+            wsMessage += L"\r\n";
+          }
+          CFX_WideString wsWarning;
+          pAppProvider->LoadString(XFA_IDS_ModifyField, wsWarning);
+          wsMessage += wsWarning;
+          CFX_WideString wsTitle;
+          pAppProvider->LoadString(XFA_IDS_CalcOverride, wsTitle);
+          if (pAppProvider->MsgBox(wsMessage, wsTitle, XFA_MBICON_Warning,
+                                   XFA_MB_YesNo) == XFA_IDYes) {
+            pAcc->GetNode()->SetFlag(XFA_NODEFLAG_UserInteractive, TRUE, FALSE);
+            return 1;
+          }
+        }
+        return 0;
+      }
+      case XFA_ATTRIBUTEENUM_Ignore:
+        return 0;
+      case XFA_ATTRIBUTEENUM_Disabled:
+        pAcc->GetNode()->SetFlag(XFA_NODEFLAG_UserInteractive, TRUE, FALSE);
+      default:
+        return 1;
+    }
+  }
+  return 1;
+}
+FX_BOOL CXFA_FFField::CommitData() {
+  return FALSE;
+}
+FX_BOOL CXFA_FFField::IsDataChanged() {
+  return FALSE;
+}
+void CXFA_FFField::TranslateFWLMessage(CFWL_Message* pMessage) {
+  GetApp()->GetWidgetMgrDelegate()->OnProcessMessageToForm(pMessage);
+}
+int32_t CXFA_FFField::OnProcessMessage(CFWL_Message* pMessage) {
+  return FWL_ERR_Succeeded;
+}
+FWL_ERR CXFA_FFField::OnProcessEvent(CFWL_Event* pEvent) {
+  FX_DWORD dwEventID = pEvent->GetClassID();
+  switch (dwEventID) {
+    case FWL_EVTHASH_Mouse: {
+      CFWL_EvtMouse* event = (CFWL_EvtMouse*)pEvent;
+      if (event->m_dwCmd == FWL_MSGMOUSECMD_MouseEnter) {
+        CXFA_EventParam eParam;
+        eParam.m_eType = XFA_EVENT_MouseEnter;
+        eParam.m_pTarget = m_pDataAcc;
+        m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_MouseEnter, &eParam);
+      } else if (event->m_dwCmd == FWL_MSGMOUSECMD_MouseLeave) {
+        CXFA_EventParam eParam;
+        eParam.m_eType = XFA_EVENT_MouseExit;
+        eParam.m_pTarget = m_pDataAcc;
+        m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_MouseExit, &eParam);
+      } else if (event->m_dwCmd == FWL_MSGMOUSECMD_LButtonDown) {
+        CXFA_EventParam eParam;
+        eParam.m_eType = XFA_EVENT_MouseDown;
+        eParam.m_pTarget = m_pDataAcc;
+        m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_MouseDown, &eParam);
+      } else if (event->m_dwCmd == FWL_MSGMOUSECMD_LButtonUp) {
+        CXFA_EventParam eParam;
+        eParam.m_eType = XFA_EVENT_MouseUp;
+        eParam.m_pTarget = m_pDataAcc;
+        m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_MouseUp, &eParam);
+      }
+      break;
+    }
+    case FWL_EVTHASH_Click: {
+      CXFA_EventParam eParam;
+      eParam.m_eType = XFA_EVENT_Click;
+      eParam.m_pTarget = m_pDataAcc;
+      m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Click, &eParam);
+      break;
+    }
+    default: {}
+  }
+  return FWL_ERR_Succeeded;
+}
+FWL_ERR CXFA_FFField::OnDrawWidget(CFX_Graphics* pGraphics,
+                                   const CFX_Matrix* pMatrix) {
+  return FWL_ERR_Succeeded;
+}
diff --git a/xfa/fxfa/app/xfa_fffield.h b/xfa/fxfa/app/xfa_fffield.h
new file mode 100644
index 0000000..4f816ce
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fffield.h
@@ -0,0 +1,100 @@
+// 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_FXFA_APP_XFA_FFFIELD_H_
+#define XFA_FXFA_APP_XFA_FFFIELD_H_
+
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/include/fwl/adapter/fwl_sdadapterimp.h"
+#include "xfa/include/fwl/core/fwl_widget.h"
+#include "xfa/include/fwl/lightwidget/widget.h"
+
+#define XFA_MINUI_HEIGHT 4.32f
+#define XFA_DEFAULTUI_HEIGHT 2.0f
+
+class CXFA_FFField : public CXFA_FFWidget, public IFWL_WidgetDelegate {
+ public:
+  CXFA_FFField(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFField();
+
+  virtual FX_BOOL GetBBox(CFX_RectF& rtBox,
+                          FX_DWORD dwStatus,
+                          FX_BOOL bDrawFocus = FALSE);
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+  virtual FX_BOOL IsLoaded();
+  virtual FX_BOOL LoadWidget();
+  virtual void UnloadWidget();
+  virtual FX_BOOL PerformLayout();
+  virtual void UpdateFWL();
+  FX_DWORD UpdateUIProperty();
+  virtual FX_BOOL OnMouseEnter();
+  virtual FX_BOOL OnMouseExit();
+  virtual FX_BOOL OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnLButtonDblClk(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnMouseWheel(FX_DWORD dwFlags,
+                               int16_t zDelta,
+                               FX_FLOAT fx,
+                               FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonDblClk(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+
+  virtual FX_BOOL OnSetFocus(CXFA_FFWidget* pOldWidget);
+  virtual FX_BOOL OnKillFocus(CXFA_FFWidget* pNewWidget);
+  virtual FX_BOOL OnKeyDown(FX_DWORD dwKeyCode, FX_DWORD dwFlags);
+  virtual FX_BOOL OnKeyUp(FX_DWORD dwKeyCode, FX_DWORD dwFlags);
+  virtual FX_BOOL OnChar(FX_DWORD dwChar, FX_DWORD dwFlags);
+  virtual FX_DWORD OnHitTest(FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnSetCursor(FX_FLOAT fx, FX_FLOAT fy);
+
+ protected:
+  virtual FX_BOOL PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy);
+  virtual void SetFWLRect();
+  void SetFWLThemeProvider();
+  CFWL_Widget* GetNormalWidget() { return m_pNormalWidget; }
+  void FWLToClient(FX_FLOAT& fx, FX_FLOAT& fy);
+  void LayoutCaption();
+  void RenderCaption(CFX_Graphics* pGS, CFX_Matrix* pMatrix = NULL);
+
+  int32_t CalculateOverride();
+  int32_t CalculateWidgetAcc(CXFA_WidgetAcc* pAcc);
+  FX_BOOL ProcessCommittedData();
+  virtual FX_BOOL CommitData();
+  virtual FX_BOOL IsDataChanged();
+  void DrawHighlight(CFX_Graphics* pGS,
+                     CFX_Matrix* pMatrix,
+                     FX_DWORD dwStatus,
+                     FX_BOOL bEllipse = FALSE);
+  void DrawFocus(CFX_Graphics* pGS, CFX_Matrix* pMatrix);
+  void TranslateFWLMessage(CFWL_Message* pMessage);
+  void CapPlacement();
+  void CapTopBottomPlacement(CXFA_Caption caption,
+                             const CFX_RectF& rtWidget,
+                             int32_t iCapPlacement);
+  void CapLeftRightPlacement(CXFA_Caption caption,
+                             const CFX_RectF& rtWidget,
+                             int32_t iCapPlacement);
+  void SetEditScrollOffset();
+
+ public:
+  virtual int32_t OnProcessMessage(CFWL_Message* pMessage);
+  virtual FWL_ERR OnProcessEvent(CFWL_Event* pEvent);
+  virtual FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics,
+                               const CFX_Matrix* pMatrix = NULL);
+
+ protected:
+  CFWL_Widget* m_pNormalWidget;
+  CFX_RectF m_rtUI;
+  CFX_RectF m_rtCaption;
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFFIELD_H_
diff --git a/xfa/fxfa/app/xfa_ffimage.cpp b/xfa/fxfa/app/xfa_ffimage.cpp
new file mode 100644
index 0000000..c17273d
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffimage.cpp
@@ -0,0 +1,67 @@
+// 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/fxfa/app/xfa_ffimage.h"
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdraw.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+
+CXFA_FFImage::CXFA_FFImage(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFDraw(pPageView, pDataAcc) {}
+CXFA_FFImage::~CXFA_FFImage() {
+  CXFA_FFImage::UnloadWidget();
+}
+FX_BOOL CXFA_FFImage::IsLoaded() {
+  return GetDataAcc()->GetImageImage() != NULL;
+}
+FX_BOOL CXFA_FFImage::LoadWidget() {
+  if (GetDataAcc()->GetImageImage()) {
+    return TRUE;
+  }
+  GetDataAcc()->LoadImageImage();
+  return CXFA_FFDraw::LoadWidget();
+}
+void CXFA_FFImage::UnloadWidget() {
+  GetDataAcc()->SetImageImage(NULL);
+}
+void CXFA_FFImage::RenderWidget(CFX_Graphics* pGS,
+                                CFX_Matrix* pMatrix,
+                                FX_DWORD dwStatus,
+                                int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
+  if (CFX_DIBitmap* pDIBitmap = GetDataAcc()->GetImageImage()) {
+    CFX_RectF rtImage;
+    GetRectWithoutRotate(rtImage);
+    if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
+      XFA_RectWidthoutMargin(rtImage, mgWidget);
+    }
+    int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left;
+    int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top;
+    if (CXFA_Para para = m_pDataAcc->GetPara()) {
+      iHorzAlign = para.GetHorizontalAlign();
+      iVertAlign = para.GetVerticalAlign();
+    }
+    CXFA_Value value = m_pDataAcc->GetFormValue();
+    CXFA_Image imageObj = value.GetImage();
+    int32_t iAspect = imageObj.GetAspect();
+    int32_t iImageXDpi = 0;
+    int32_t iImageYDpi = 0;
+    m_pDataAcc->GetImageDpi(iImageXDpi, iImageYDpi);
+    XFA_DrawImage(pGS, rtImage, &mtRotate, pDIBitmap, iAspect, iImageXDpi,
+                  iImageYDpi, iHorzAlign, iVertAlign);
+  }
+}
diff --git a/xfa/fxfa/app/xfa_ffimage.h b/xfa/fxfa/app/xfa_ffimage.h
new file mode 100644
index 0000000..71bb495
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffimage.h
@@ -0,0 +1,25 @@
+// 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_FXFA_APP_XFA_FFIMAGE_H_
+#define XFA_FXFA_APP_XFA_FFIMAGE_H_
+
+#include "xfa/fxfa/app/xfa_ffdraw.h"
+
+class CXFA_FFImage : public CXFA_FFDraw {
+ public:
+  CXFA_FFImage(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFImage();
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+  virtual FX_BOOL IsLoaded();
+  virtual FX_BOOL LoadWidget();
+  virtual void UnloadWidget();
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFIMAGE_H_
diff --git a/xfa/fxfa/app/xfa_ffimageedit.cpp b/xfa/fxfa/app/xfa_ffimageedit.cpp
new file mode 100644
index 0000000..4f9f6c6
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffimageedit.cpp
@@ -0,0 +1,183 @@
+// 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/fxfa/app/xfa_ffimageedit.h"
+
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/include/fwl/core/fwl_app.h"
+#include "xfa/include/fwl/lightwidget/picturebox.h"
+
+CXFA_FFImageEdit::CXFA_FFImageEdit(CXFA_FFPageView* pPageView,
+                                   CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFField(pPageView, pDataAcc), m_pOldDelegate(NULL) {}
+CXFA_FFImageEdit::~CXFA_FFImageEdit() {
+  CXFA_FFImageEdit::UnloadWidget();
+}
+FX_BOOL CXFA_FFImageEdit::LoadWidget() {
+  CFWL_PictureBox* pPictureBox = new CFWL_PictureBox;
+  if (pPictureBox) {
+    pPictureBox->Initialize();
+  }
+  m_pNormalWidget = (CFWL_Widget*)pPictureBox;
+  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
+  m_pNormalWidget->SetPrivateData(pWidget, this, NULL);
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  m_pOldDelegate = pPictureBox->SetDelegate(this);
+  CXFA_FFField::LoadWidget();
+  if (m_pDataAcc->GetImageEditImage()) {
+    return TRUE;
+  }
+  UpdateFWLData();
+  return TRUE;
+}
+void CXFA_FFImageEdit::UnloadWidget() {
+  m_pDataAcc->SetImageEditImage(NULL);
+  CXFA_FFField::UnloadWidget();
+}
+void CXFA_FFImageEdit::RenderWidget(CFX_Graphics* pGS,
+                                    CFX_Matrix* pMatrix,
+                                    FX_DWORD dwStatus,
+                                    int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
+  CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
+  DrawBorder(pGS, borderUI, m_rtUI, &mtRotate);
+  RenderCaption(pGS, &mtRotate);
+  if (CFX_DIBitmap* pDIBitmap = m_pDataAcc->GetImageEditImage()) {
+    CFX_RectF rtImage;
+    m_pNormalWidget->GetWidgetRect(rtImage);
+    int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left;
+    int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top;
+    if (CXFA_Para para = m_pDataAcc->GetPara()) {
+      iHorzAlign = para.GetHorizontalAlign();
+      iVertAlign = para.GetVerticalAlign();
+    }
+    int32_t iAspect = XFA_ATTRIBUTEENUM_Fit;
+    if (CXFA_Value value = m_pDataAcc->GetFormValue()) {
+      if (CXFA_Image imageObj = value.GetImage()) {
+        iAspect = imageObj.GetAspect();
+      }
+    }
+    int32_t iImageXDpi = 0;
+    int32_t iImageYDpi = 0;
+    m_pDataAcc->GetImageEditDpi(iImageXDpi, iImageYDpi);
+    XFA_DrawImage(pGS, rtImage, &mtRotate, pDIBitmap, iAspect, iImageXDpi,
+                  iImageYDpi, iHorzAlign, iVertAlign);
+  }
+}
+FX_BOOL CXFA_FFImageEdit::OnLButtonDown(FX_DWORD dwFlags,
+                                        FX_FLOAT fx,
+                                        FX_FLOAT fy) {
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) {
+    return FALSE;
+  }
+  if (!PtInActiveRect(fx, fy)) {
+    return FALSE;
+  }
+  SetButtonDown(TRUE);
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_LButtonDown;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  TranslateFWLMessage(&ms);
+  IXFA_AppProvider* pAppProvider = GetAppProvider();
+  if (!pAppProvider) {
+    return TRUE;
+  }
+  CFX_WideString wsTitle;
+  CFX_WideString wsFilter;
+  pAppProvider->LoadString(XFA_IDS_ImageFilter, wsFilter);
+  CFX_WideStringArray wsPathArray;
+  pAppProvider->ShowFileDialog(wsTitle, wsFilter, wsPathArray);
+  int32_t iSize = wsPathArray.GetSize();
+  if (iSize < 1) {
+    return TRUE;
+  }
+  CFX_WideString wsFilePath = wsPathArray[0];
+  FX_STRSIZE nLen = wsFilePath.GetLength();
+  FX_STRSIZE nIndex = nLen - 1;
+  while (nIndex > 0 && wsFilePath[nIndex] != '.') {
+    nIndex--;
+  }
+  if (nIndex <= 0) {
+    return TRUE;
+  }
+  CFX_WideString wsContentType(L"image/");
+  wsContentType += wsFilePath.Right(nLen - nIndex - 1);
+  wsContentType.MakeLower();
+  FXCODEC_IMAGE_TYPE eImageType = XFA_GetImageType(wsContentType);
+  if (eImageType == FXCODEC_IMAGE_UNKNOWN) {
+    return TRUE;
+  }
+  CFX_WideString wsImage;
+  IFX_FileRead* pFileRead = FX_CreateFileRead(wsFilePath);
+  if (pFileRead) {
+    int32_t nDataSize = pFileRead->GetSize();
+    if (nDataSize > 0) {
+      CFX_ByteString bsBuf;
+      FX_CHAR* pImageBuffer = bsBuf.GetBuffer(nDataSize);
+      pFileRead->ReadBlock(pImageBuffer, 0, nDataSize);
+      bsBuf.ReleaseBuffer();
+      if (!bsBuf.IsEmpty()) {
+        FX_CHAR* pData = XFA_Base64Encode(bsBuf, nDataSize);
+        wsImage = CFX_WideString::FromLocal(pData);
+        FX_Free(pData);
+      }
+    }
+    m_pDataAcc->SetImageEditImage(NULL);
+    pFileRead->Release();
+  }
+  m_pDataAcc->SetImageEdit(wsContentType, CFX_WideStringC(), wsImage);
+  m_pDataAcc->LoadImageEditImage();
+  AddInvalidateRect();
+  m_pDocView->SetChangeMark();
+  return TRUE;
+}
+void CXFA_FFImageEdit::SetFWLRect() {
+  if (!m_pNormalWidget) {
+    return;
+  }
+  CFX_RectF rtUIMargin;
+  m_pDataAcc->GetUIMargin(rtUIMargin);
+  CFX_RectF rtImage(m_rtUI);
+  rtImage.Deflate(rtUIMargin.left, rtUIMargin.top, rtUIMargin.width,
+                  rtUIMargin.height);
+  m_pNormalWidget->SetWidgetRect(rtImage);
+}
+FX_BOOL CXFA_FFImageEdit::CommitData() {
+  return TRUE;
+}
+FX_BOOL CXFA_FFImageEdit::UpdateFWLData() {
+  m_pDataAcc->SetImageEditImage(NULL);
+  m_pDataAcc->LoadImageEditImage();
+  return TRUE;
+}
+int32_t CXFA_FFImageEdit::OnProcessMessage(CFWL_Message* pMessage) {
+  return m_pOldDelegate->OnProcessMessage(pMessage);
+}
+FWL_ERR CXFA_FFImageEdit::OnProcessEvent(CFWL_Event* pEvent) {
+  CXFA_FFField::OnProcessEvent(pEvent);
+  return m_pOldDelegate->OnProcessEvent(pEvent);
+}
+FWL_ERR CXFA_FFImageEdit::OnDrawWidget(CFX_Graphics* pGraphics,
+                                       const CFX_Matrix* pMatrix) {
+  return m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
+}
diff --git a/xfa/fxfa/app/xfa_ffimageedit.h b/xfa/fxfa/app/xfa_ffimageedit.h
new file mode 100644
index 0000000..7ecd18a
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffimageedit.h
@@ -0,0 +1,36 @@
+// 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_FXFA_APP_XFA_FFIMAGEEDIT_H_
+#define XFA_FXFA_APP_XFA_FFIMAGEEDIT_H_
+
+#include "xfa/fxfa/app/xfa_fffield.h"
+
+class CXFA_FFImageEdit : public CXFA_FFField {
+ public:
+  CXFA_FFImageEdit(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFImageEdit();
+
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+  virtual FX_BOOL LoadWidget();
+  virtual void UnloadWidget();
+  virtual FX_BOOL OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual int32_t OnProcessMessage(CFWL_Message* pMessage);
+  virtual FWL_ERR OnProcessEvent(CFWL_Event* pEvent);
+  virtual FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics,
+                               const CFX_Matrix* pMatrix = NULL);
+
+ protected:
+  virtual void SetFWLRect();
+  virtual FX_BOOL UpdateFWLData();
+  virtual FX_BOOL CommitData();
+  IFWL_WidgetDelegate* m_pOldDelegate;
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFIMAGEEDIT_H_
diff --git a/xfa/fxfa/app/xfa_ffnotify.cpp b/xfa/fxfa/app/xfa_ffnotify.cpp
new file mode 100644
index 0000000..845f7b8
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffnotify.cpp
@@ -0,0 +1,648 @@
+// 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/fxfa/app/xfa_ffnotify.h"
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffbarcode.h"
+#include "xfa/fxfa/app/xfa_ffcheckbutton.h"
+#include "xfa/fxfa/app/xfa_ffchoicelist.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_ffdraw.h"
+#include "xfa/fxfa/app/xfa_ffexclgroup.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffimage.h"
+#include "xfa/fxfa/app/xfa_ffimageedit.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffpath.h"
+#include "xfa/fxfa/app/xfa_ffpushbutton.h"
+#include "xfa/fxfa/app/xfa_ffsignature.h"
+#include "xfa/fxfa/app/xfa_ffsubform.h"
+#include "xfa/fxfa/app/xfa_fftext.h"
+#include "xfa/fxfa/app/xfa_fftextedit.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_ffwidgetacc.h"
+#include "xfa/fxfa/app/xfa_ffwidgethandler.h"
+#include "xfa/fxfa/app/xfa_fwladapter.h"
+#include "xfa/fxfa/app/xfa_textlayout.h"
+
+static void XFA_FFDeleteWidgetAcc(void* pData) {
+  delete static_cast<CXFA_WidgetAcc*>(pData);
+}
+static XFA_MAPDATABLOCKCALLBACKINFO gs_XFADeleteWidgetAcc = {
+    XFA_FFDeleteWidgetAcc, NULL};
+CXFA_FFNotify::CXFA_FFNotify(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {}
+CXFA_FFNotify::~CXFA_FFNotify() {}
+void CXFA_FFNotify::OnPageEvent(IXFA_LayoutPage* pSender,
+                                XFA_PAGEEVENT eEvent,
+                                void* pParam) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pSender->GetLayout());
+  if (!pDocView) {
+    return;
+  }
+  pDocView->OnPageEvent(pSender, eEvent, (int32_t)(uintptr_t)pParam);
+}
+void CXFA_FFNotify::OnNodeEvent(CXFA_Node* pSender,
+                                XFA_NODEEVENT eEvent,
+                                void* pParam,
+                                void* pParam2,
+                                void* pParam3,
+                                void* pParam4) {
+  switch (eEvent) {
+    case XFA_NODEEVENT_Ready:
+      OnNodeReady(pSender);
+      break;
+    case XFA_NODEEVENT_ValueChanging:
+      OnValueChanging(pSender, pParam, pParam2);
+      break;
+    case XFA_NODEEVENT_ValueChanged:
+      OnValueChanged(pSender, pParam, pParam2, pParam3, pParam4);
+      break;
+    case XFA_NODEEVENT_ChildAdded:
+      OnChildAdded(pSender, pParam, pParam2);
+      break;
+    case XFA_NODEEVENT_ChildRemoved:
+      OnChildRemoved(pSender, pParam, pParam2);
+      break;
+  }
+}
+void CXFA_FFNotify::OnWidgetDataEvent(CXFA_WidgetData* pSender,
+                                      FX_DWORD dwEvent,
+                                      void* pParam,
+                                      void* pAdditional,
+                                      void* pAdditional2) {
+  CXFA_WidgetAcc* pWidgetAcc = static_cast<CXFA_WidgetAcc*>(pSender);
+  switch (dwEvent) {
+    case XFA_WIDGETEVENT_ListItemAdded: {
+      if (pWidgetAcc->GetUIType() != XFA_ELEMENT_ChoiceList) {
+        return;
+      }
+      FX_BOOL bStaticNotify = pWidgetAcc->GetDocView()->IsStaticNotify();
+      CXFA_FFWidget* pWidget = pWidgetAcc->GetNextWidget(NULL);
+      if (!pWidget) {
+        if (bStaticNotify) {
+          pWidgetAcc->GetDoc()->GetDocProvider()->WidgetEvent(
+              pWidget, pWidgetAcc, XFA_WIDGETEVENT_ListItemAdded, pParam,
+              pAdditional);
+        }
+        return;
+      }
+      while (pWidget) {
+        if (pWidget->IsLoaded()) {
+          if (pWidgetAcc->IsListBox()) {
+            static_cast<CXFA_FFListBox*>(pWidget)
+                ->InsertItem((const CFX_WideStringC&)(const FX_WCHAR*)pParam,
+                             (int32_t)(uintptr_t)pAdditional2);
+          } else {
+            static_cast<CXFA_FFComboBox*>(pWidget)
+                ->InsertItem((const CFX_WideStringC&)(const FX_WCHAR*)pParam,
+                             (int32_t)(uintptr_t)pAdditional2);
+          }
+        }
+        if (bStaticNotify) {
+          pWidgetAcc->GetDoc()->GetDocProvider()->WidgetEvent(
+              pWidget, pWidgetAcc, XFA_WIDGETEVENT_ListItemAdded, pParam,
+              pAdditional);
+        }
+        pWidget = pWidgetAcc->GetNextWidget(pWidget);
+      }
+    } break;
+    case XFA_WIDGETEVENT_ListItemRemoved: {
+      if (pWidgetAcc->GetUIType() != XFA_ELEMENT_ChoiceList) {
+        return;
+      }
+      FX_BOOL bStaticNotify = pWidgetAcc->GetDocView()->IsStaticNotify();
+      CXFA_FFWidget* pWidget = pWidgetAcc->GetNextWidget(NULL);
+      if (!pWidget) {
+        if (bStaticNotify) {
+          pWidgetAcc->GetDoc()->GetDocProvider()->WidgetEvent(
+              pWidget, pWidgetAcc, XFA_WIDGETEVENT_ListItemRemoved, pParam,
+              pAdditional);
+        }
+        return;
+      }
+      while (pWidget) {
+        if (pWidget->IsLoaded()) {
+          if (pWidgetAcc->IsListBox()) {
+            static_cast<CXFA_FFListBox*>(pWidget)
+                ->DeleteItem((int32_t)(uintptr_t)pParam);
+          } else {
+            static_cast<CXFA_FFComboBox*>(pWidget)
+                ->DeleteItem((int32_t)(uintptr_t)pParam);
+          }
+        }
+        if (bStaticNotify) {
+          pWidgetAcc->GetDoc()->GetDocProvider()->WidgetEvent(
+              pWidget, pWidgetAcc, XFA_WIDGETEVENT_ListItemRemoved, pParam,
+              pAdditional);
+        }
+        pWidget = pWidgetAcc->GetNextWidget(pWidget);
+      }
+    } break;
+  }
+}
+CXFA_LayoutItem* CXFA_FFNotify::OnCreateLayoutItem(CXFA_Node* pNode) {
+  IXFA_DocLayout* pLayout = m_pDoc->GetXFADoc()->GetDocLayout();
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout);
+  XFA_ELEMENT eType = pNode->GetClassID();
+  if (eType == XFA_ELEMENT_PageArea) {
+    return new CXFA_FFPageView(pDocView, pNode);
+  }
+  if (eType == XFA_ELEMENT_ContentArea) {
+    return new CXFA_ContainerLayoutItem(pNode);
+  }
+  CXFA_WidgetAcc* pAcc = static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData());
+  if (!pAcc) {
+    return new CXFA_ContentLayoutItem(pNode);
+  }
+  CXFA_FFPageView* pPageView = NULL;
+  CXFA_FFWidget* pWidget = NULL;
+  switch (pAcc->GetUIType()) {
+    case XFA_ELEMENT_Barcode:
+      pWidget = new CXFA_FFBarcode(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_Button:
+      pWidget = new CXFA_FFPushButton(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_CheckButton:
+      pWidget = new CXFA_FFCheckButton(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_ChoiceList: {
+      if (pAcc->IsListBox()) {
+        pWidget = new CXFA_FFListBox(pPageView, pAcc);
+      } else {
+        pWidget = new CXFA_FFComboBox(pPageView, pAcc);
+      }
+    } break;
+    case XFA_ELEMENT_DateTimeEdit:
+      pWidget = new CXFA_FFDateTimeEdit(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_ImageEdit:
+      pWidget = new CXFA_FFImageEdit(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_NumericEdit:
+      pWidget = new CXFA_FFNumericEdit(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_PasswordEdit:
+      pWidget = new CXFA_FFPasswordEdit(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_Signature:
+      pWidget = new CXFA_FFSignature(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_TextEdit:
+      pWidget = new CXFA_FFTextEdit(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_Arc:
+      pWidget = new CXFA_FFArc(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_Line:
+      pWidget = new CXFA_FFLine(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_Rectangle:
+      pWidget = new CXFA_FFRectangle(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_Text:
+      pWidget = new CXFA_FFText(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_Image:
+      pWidget = new CXFA_FFImage(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_Draw:
+      pWidget = new CXFA_FFDraw(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_Subform:
+      pWidget = new CXFA_FFSubForm(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_ExclGroup:
+      pWidget = new CXFA_FFExclGroup(pPageView, pAcc);
+      break;
+    case XFA_ELEMENT_DefaultUi:
+    default:
+      pWidget = NULL;
+      break;
+  }
+  if (!pWidget) {
+    return NULL;
+  }
+  pWidget->SetDocView(pDocView);
+  return pWidget;
+}
+void CXFA_FFNotify::OnLayoutEvent(IXFA_DocLayout* pLayout,
+                                  CXFA_LayoutItem* pSender,
+                                  XFA_LAYOUTEVENT eEvent,
+                                  void* pParam,
+                                  void* pParam2) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView(pLayout);
+  if (!pDocView || !XFA_GetWidgetFromLayoutItem(pSender)) {
+    return;
+  }
+  switch (eEvent) {
+    case XFA_LAYOUTEVENT_ItemAdded:
+      OnLayoutItemAdd(pDocView, pLayout, pSender, pParam, pParam2);
+      break;
+    case XFA_LAYOUTEVENT_ItemRemoving:
+      OnLayoutItemRemoving(pDocView, pLayout, pSender, pParam, pParam2);
+      break;
+    case XFA_LAYOUTEVENT_RectChanged:
+      OnLayoutItemRectChanged(pDocView, pLayout, pSender, pParam, pParam2);
+      break;
+    case XFA_LAYOUTEVENT_StatusChanged:
+      OnLayoutItemStatustChanged(pDocView, pLayout, pSender, pParam, pParam2);
+      break;
+  }
+}
+void CXFA_FFNotify::StartFieldDrawLayout(CXFA_Node* pItem,
+                                         FX_FLOAT& fCalcWidth,
+                                         FX_FLOAT& fCalcHeight) {
+  CXFA_WidgetAcc* pAcc = static_cast<CXFA_WidgetAcc*>(pItem->GetWidgetData());
+  if (!pAcc) {
+    return;
+  }
+  pAcc->StartWidgetLayout(fCalcWidth, fCalcHeight);
+}
+FX_BOOL CXFA_FFNotify::FindSplitPos(CXFA_Node* pItem,
+                                    int32_t iBlockIndex,
+                                    FX_FLOAT& fCalcHeightPos) {
+  CXFA_WidgetAcc* pAcc = static_cast<CXFA_WidgetAcc*>(pItem->GetWidgetData());
+  if (!pAcc) {
+    return FALSE;
+  }
+  return (XFA_LAYOUTRESULT)pAcc->FindSplitPos(iBlockIndex, fCalcHeightPos);
+}
+FX_BOOL CXFA_FFNotify::RunScript(CXFA_Node* pScript, CXFA_Node* pFormItem) {
+  FX_BOOL bRet = FALSE;
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return bRet;
+  }
+  CXFA_WidgetAcc* pWidgetAcc =
+      static_cast<CXFA_WidgetAcc*>(pFormItem->GetWidgetData());
+  if (!pWidgetAcc) {
+    return bRet;
+  }
+  CXFA_EventParam EventParam;
+  EventParam.m_eType = XFA_EVENT_Unknown;
+  FXJSE_HVALUE pRetValue = NULL;
+  int32_t iRet =
+      pWidgetAcc->ExecuteScript(CXFA_Script(pScript), &EventParam, &pRetValue);
+  if (iRet == XFA_EVENTERROR_Sucess && pRetValue) {
+    bRet = FXJSE_Value_ToBoolean(pRetValue);
+    FXJSE_Value_Release(pRetValue);
+  }
+  return bRet;
+}
+int32_t CXFA_FFNotify::ExecEventByDeepFirst(CXFA_Node* pFormNode,
+                                            XFA_EVENTTYPE eEventType,
+                                            FX_BOOL bIsFormReady,
+                                            FX_BOOL bRecursive,
+                                            CXFA_WidgetAcc* pExclude) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  return pDocView->ExecEventActivityByDeepFirst(
+      pFormNode, eEventType, bIsFormReady, bRecursive,
+      pExclude ? pExclude->GetNode() : NULL);
+}
+void CXFA_FFNotify::AddCalcValidate(CXFA_Node* pNode) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return;
+  }
+  CXFA_WidgetAcc* pWidgetAcc =
+      static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData());
+  if (!pWidgetAcc) {
+    return;
+  }
+  pDocView->AddCalculateWidgetAcc(pWidgetAcc);
+  pDocView->AddValidateWidget(pWidgetAcc);
+}
+IXFA_Doc* CXFA_FFNotify::GetHDOC() {
+  return m_pDoc;
+}
+IXFA_DocProvider* CXFA_FFNotify::GetDocProvider() {
+  return m_pDoc->GetDocProvider();
+}
+IXFA_AppProvider* CXFA_FFNotify::GetAppProvider() {
+  return m_pDoc->GetApp()->GetAppProvider();
+}
+IXFA_WidgetHandler* CXFA_FFNotify::GetWidgetHandler() {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  return pDocView ? pDocView->GetWidgetHandler() : NULL;
+}
+IXFA_Widget* CXFA_FFNotify::GetHWidget(CXFA_LayoutItem* pLayoutItem) {
+  return XFA_GetWidgetFromLayoutItem(pLayoutItem);
+}
+void CXFA_FFNotify::OpenDropDownList(IXFA_Widget* hWidget) {
+  CXFA_FFWidget* pWidget = static_cast<CXFA_FFWidget*>(hWidget);
+  if (pWidget->GetDataAcc()->GetUIType() != XFA_ELEMENT_ChoiceList) {
+    return;
+  }
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  pDocView->LockUpdate();
+  static_cast<CXFA_FFComboBox*>(pWidget)->OpenDropDownList();
+  pDocView->UnlockUpdate();
+  pDocView->UpdateDocView();
+}
+CFX_WideString CXFA_FFNotify::GetCurrentDateTime() {
+  CFX_Unitime dataTime;
+  dataTime.Now();
+  CFX_WideString wsDateTime;
+  wsDateTime.Format(L"%d%02d%02dT%02d%02d%02d", dataTime.GetYear(),
+                    dataTime.GetMonth(), dataTime.GetDay(), dataTime.GetHour(),
+                    dataTime.GetMinute(), dataTime.GetSecond());
+  return wsDateTime;
+}
+void CXFA_FFNotify::ResetData(CXFA_WidgetData* pWidgetData) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return;
+  }
+  pDocView->ResetWidgetData(static_cast<CXFA_WidgetAcc*>(pWidgetData));
+}
+int32_t CXFA_FFNotify::GetLayoutStatus() {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  return pDocView ? pDocView->GetLayoutStatus() : 0;
+}
+void CXFA_FFNotify::RunNodeInitialize(CXFA_Node* pNode) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return;
+  }
+  pDocView->AddNewFormNode(pNode);
+}
+void CXFA_FFNotify::RunSubformIndexChange(CXFA_Node* pSubformNode) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return;
+  }
+  pDocView->AddIndexChangedSubform(pSubformNode);
+}
+CXFA_Node* CXFA_FFNotify::GetFocusWidgetNode() {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return NULL;
+  }
+  CXFA_WidgetAcc* pAcc = pDocView->GetFocusWidgetAcc();
+  return pAcc ? pAcc->GetNode() : NULL;
+}
+void CXFA_FFNotify::SetFocusWidgetNode(CXFA_Node* pNode) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return;
+  }
+  CXFA_WidgetAcc* pAcc =
+      pNode ? static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData()) : nullptr;
+  pDocView->SetFocusWidgetAcc(pAcc);
+}
+void CXFA_FFNotify::OnNodeReady(CXFA_Node* pNode) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return;
+  }
+  XFA_ELEMENT iType = pNode->GetClassID();
+  if (XFA_IsCreateWidget(iType)) {
+    CXFA_WidgetAcc* pAcc =
+        new CXFA_WidgetAcc(pDocView, static_cast<CXFA_Node*>(pNode));
+    pNode->SetObject(XFA_ATTRIBUTE_WidgetData, pAcc, &gs_XFADeleteWidgetAcc);
+    return;
+  }
+  switch (iType) {
+    case XFA_ELEMENT_BindItems:
+      pDocView->m_bindItems.Add(pNode);
+      break;
+    case XFA_ELEMENT_Validate: {
+      pNode->SetFlag(XFA_NODEFLAG_NeedsInitApp, TRUE, FALSE);
+    } break;
+    default:
+      break;
+  }
+}
+void CXFA_FFNotify::OnValueChanging(CXFA_Node* pSender,
+                                    void* pParam,
+                                    void* pParam2) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return;
+  }
+  if (pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End) {
+    return;
+  }
+  FX_DWORD dwPacket = pSender->GetPacketID();
+  if (dwPacket & XFA_XDPPACKET_Datasets) {
+  } else if (pSender->IsFormContainer()) {
+    XFA_ATTRIBUTE eAttr = (XFA_ATTRIBUTE)(uintptr_t)pParam;
+    if (eAttr == XFA_ATTRIBUTE_Presence) {
+      CXFA_WidgetAcc* pWidgetAcc =
+          static_cast<CXFA_WidgetAcc*>(pSender->GetWidgetData());
+      if (!pWidgetAcc) {
+        return;
+      }
+      CXFA_FFWidget* pWidget = NULL;
+      while ((pWidget = pWidgetAcc->GetNextWidget(pWidget))) {
+        if (pWidget->IsLoaded()) {
+          pWidget->AddInvalidateRect();
+        }
+      }
+    }
+  }
+}
+void CXFA_FFNotify::OnValueChanged(CXFA_Node* pSender,
+                                   void* pParam,
+                                   void* pParam2,
+                                   void* pParam3,
+                                   void* pParam4) {
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return;
+  }
+  FX_DWORD dwPacket = pSender->GetPacketID();
+  XFA_ATTRIBUTE eAttr = (XFA_ATTRIBUTE)(uintptr_t)pParam;
+  if (dwPacket & XFA_XDPPACKET_Form) {
+    CXFA_Node* pParentNode = static_cast<CXFA_Node*>(pParam3);
+    CXFA_Node* pWidgetNode = static_cast<CXFA_Node*>(pParam4);
+    XFA_ELEMENT ePType = pParentNode->GetClassID();
+    FX_BOOL bIsContainerNode = pParentNode->IsContainerNode();
+    CXFA_WidgetAcc* pWidgetAcc =
+        static_cast<CXFA_WidgetAcc*>(pWidgetNode->GetWidgetData());
+    if (!pWidgetAcc) {
+      return;
+    }
+    FX_BOOL bUpdateProperty = FALSE;
+    pDocView->SetChangeMark();
+    switch (ePType) {
+      case XFA_ELEMENT_Caption: {
+        CXFA_TextLayout* pCapOut = pWidgetAcc->GetCaptionTextLayout();
+        if (!pCapOut) {
+          return;
+        }
+        pCapOut->Unload();
+      } break;
+      case XFA_ELEMENT_Ui:
+      case XFA_ELEMENT_Para:
+        bUpdateProperty = TRUE;
+        break;
+      case XFA_ELEMENT_Font:
+      case XFA_ELEMENT_Margin:
+      case XFA_ELEMENT_Value:
+      case XFA_ELEMENT_Items:
+        break;
+      default:
+        break;
+    }
+    if (bIsContainerNode && eAttr == XFA_ATTRIBUTE_Access) {
+      bUpdateProperty = TRUE;
+      FX_BOOL bNotify = pDocView->IsStaticNotify();
+      if (bNotify) {
+        pWidgetAcc->NotifyEvent(XFA_WIDGETEVENT_AccessChanged, NULL, pParam2,
+                                NULL);
+      }
+    }
+    if (eAttr == XFA_ATTRIBUTE_Value) {
+      pDocView->AddCalculateNodeNotify(pSender);
+      if (ePType == XFA_ELEMENT_Value || bIsContainerNode) {
+        FX_BOOL bNotify = pDocView->IsStaticNotify();
+        if (bIsContainerNode) {
+          pWidgetAcc->UpdateUIDisplay();
+          pDocView->AddCalculateWidgetAcc(pWidgetAcc);
+          pDocView->AddValidateWidget(pWidgetAcc);
+        } else if (pWidgetNode->GetNodeItem(XFA_NODEITEM_Parent)
+                       ->GetClassID() == XFA_ELEMENT_ExclGroup) {
+          pWidgetAcc->UpdateUIDisplay();
+        }
+        if (bNotify) {
+          pWidgetAcc->NotifyEvent(XFA_WIDGETEVENT_PostContentChanged, NULL,
+                                  NULL, NULL);
+        }
+        return;
+      }
+    }
+    CXFA_FFWidget* pWidget = NULL;
+    while ((pWidget = pWidgetAcc->GetNextWidget(pWidget))) {
+      if (!pWidget->IsLoaded()) {
+        continue;
+      }
+      if (bUpdateProperty) {
+        pWidget->UpdateWidgetProperty();
+      }
+      pWidget->PerformLayout();
+      pWidget->AddInvalidateRect();
+    }
+  } else {
+    if (eAttr == XFA_ATTRIBUTE_Value) {
+      pDocView->AddCalculateNodeNotify(pSender);
+    }
+  }
+}
+void CXFA_FFNotify::OnChildAdded(CXFA_Node* pSender,
+                                 void* pParam,
+                                 void* pParam2) {
+  if (!pSender->IsFormContainer()) {
+    return;
+  }
+  CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
+  if (!pDocView) {
+    return;
+  }
+  FX_BOOL bLayoutReady =
+      !(pDocView->m_bInLayoutStatus) &&
+      (pDocView->GetLayoutStatus() == XFA_DOCVIEW_LAYOUTSTATUS_End);
+  if (bLayoutReady) {
+    m_pDoc->GetDocProvider()->SetChangeMark(m_pDoc);
+  }
+}
+void CXFA_FFNotify::OnChildRemoved(CXFA_Node* pSender,
+                                   void* pParam,
+                                   void* pParam2) {
+  if (CXFA_FFDocView* pDocView = m_pDoc->GetDocView()) {
+    FX_BOOL bLayoutReady =
+        !(pDocView->m_bInLayoutStatus) &&
+        (pDocView->GetLayoutStatus() == XFA_DOCVIEW_LAYOUTSTATUS_End);
+    if (bLayoutReady) {
+      m_pDoc->GetDocProvider()->SetChangeMark(m_pDoc);
+    }
+  }
+}
+void CXFA_FFNotify::OnLayoutItemAdd(CXFA_FFDocView* pDocView,
+                                    IXFA_DocLayout* pLayout,
+                                    CXFA_LayoutItem* pSender,
+                                    void* pParam,
+                                    void* pParam2) {
+  CXFA_FFWidget* pWidget = static_cast<CXFA_FFWidget*>(pSender);
+  int32_t iPageIdx = (int32_t)(uintptr_t)pParam;
+  IXFA_PageView* pNewPageView = pDocView->GetPageView(iPageIdx);
+  FX_DWORD dwStatus = (FX_DWORD)(uintptr_t)pParam2;
+  FX_DWORD dwFilter = XFA_WIDGETSTATUS_Visible | XFA_WIDGETSTATUS_Viewable |
+                      XFA_WIDGETSTATUS_Printable;
+  pWidget->ModifyStatus(dwStatus, dwFilter);
+  IXFA_PageView* pPrePageView = pWidget->GetPageView();
+  if (pPrePageView != pNewPageView ||
+      (dwStatus & (XFA_WIDGETSTATUS_Visible | XFA_WIDGETSTATUS_Viewable)) ==
+          (XFA_WIDGETSTATUS_Visible | XFA_WIDGETSTATUS_Viewable)) {
+    pWidget->SetPageView(pNewPageView);
+    m_pDoc->GetDocProvider()->WidgetEvent(pWidget, pWidget->GetDataAcc(),
+                                          XFA_WIDGETEVENT_PostAdded,
+                                          pNewPageView, pPrePageView);
+  }
+  if (pDocView->GetLayoutStatus() != XFA_DOCVIEW_LAYOUTSTATUS_End ||
+      !(dwStatus & XFA_WIDGETSTATUS_Visible)) {
+    return;
+  }
+  if (pWidget->IsLoaded()) {
+    CFX_RectF rtOld;
+    pWidget->GetWidgetRect(rtOld);
+    if (rtOld != pWidget->ReCacheWidgetRect())
+      pWidget->PerformLayout();
+  } else {
+    pWidget->LoadWidget();
+  }
+  pWidget->AddInvalidateRect(nullptr);
+}
+void CXFA_FFNotify::OnLayoutItemRemoving(CXFA_FFDocView* pDocView,
+                                         IXFA_DocLayout* pLayout,
+                                         CXFA_LayoutItem* pSender,
+                                         void* pParam,
+                                         void* pParam2) {
+  CXFA_FFWidget* pWidget = static_cast<CXFA_FFWidget*>(pSender);
+  pDocView->DeleteLayoutItem(pWidget);
+  m_pDoc->GetDocProvider()->WidgetEvent(pWidget, pWidget->GetDataAcc(),
+                                        XFA_WIDGETEVENT_PreRemoved, nullptr,
+                                        pWidget->GetPageView());
+  pWidget->AddInvalidateRect(nullptr);
+}
+void CXFA_FFNotify::OnLayoutItemRectChanged(CXFA_FFDocView* pDocView,
+                                            IXFA_DocLayout* pLayout,
+                                            CXFA_LayoutItem* pSender,
+                                            void* pParam,
+                                            void* pParam2) {}
+void CXFA_FFNotify::OnLayoutItemStatustChanged(CXFA_FFDocView* pDocView,
+                                               IXFA_DocLayout* pLayout,
+                                               CXFA_LayoutItem* pSender,
+                                               void* pParam,
+                                               void* pParam2) {
+  CXFA_FFWidget* pWidget = static_cast<CXFA_FFWidget*>(pSender);
+  if (!pWidget) {
+    return;
+  }
+  FX_DWORD dwStatus = (FX_DWORD)(uintptr_t)pParam;
+  if (dwStatus == 0) {
+    CXFA_LayoutItem* pPreItem = pSender->GetPrev();
+    if (pPreItem) {
+      CXFA_FFWidget* pPreWidget = static_cast<CXFA_FFWidget*>(pPreItem);
+      if (pPreWidget) {
+        dwStatus = pPreWidget->GetStatus();
+      }
+    }
+  }
+  FX_DWORD dwOldStatus = pWidget->GetStatus();
+  FX_DWORD dwFilter = XFA_WIDGETSTATUS_Visible | XFA_WIDGETSTATUS_Viewable |
+                      XFA_WIDGETSTATUS_Printable;
+  if ((dwOldStatus & dwFilter) == dwStatus) {
+    return;
+  }
+  pWidget->ModifyStatus(dwStatus, dwFilter);
+}
diff --git a/xfa/fxfa/app/xfa_ffnotify.h b/xfa/fxfa/app/xfa_ffnotify.h
new file mode 100644
index 0000000..e61c079
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffnotify.h
@@ -0,0 +1,99 @@
+// 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_FXFA_APP_XFA_FFNOTIFY_H_
+#define XFA_FXFA_APP_XFA_FFNOTIFY_H_
+
+#include "xfa/fxfa/parser/xfa_document.h"
+
+class CXFA_FFNotify : public IXFA_Notify {
+ public:
+  CXFA_FFNotify(CXFA_FFDoc* pDoc);
+  ~CXFA_FFNotify();
+
+  virtual void OnPageEvent(IXFA_LayoutPage* pSender,
+                           XFA_PAGEEVENT eEvent,
+                           void* pParam = NULL);
+
+  virtual void OnNodeEvent(CXFA_Node* pSender,
+                           XFA_NODEEVENT eEvent,
+                           void* pParam = NULL,
+                           void* pParam2 = NULL,
+                           void* pParam3 = NULL,
+                           void* pParam4 = NULL);
+  virtual void OnWidgetDataEvent(CXFA_WidgetData* pSender,
+                                 FX_DWORD dwEvent,
+                                 void* pParam = NULL,
+                                 void* pAdditional = NULL,
+                                 void* pAdditional2 = NULL);
+  virtual CXFA_LayoutItem* OnCreateLayoutItem(CXFA_Node* pNode);
+  virtual void OnLayoutEvent(IXFA_DocLayout* pLayout,
+                             CXFA_LayoutItem* pSender,
+                             XFA_LAYOUTEVENT eEvent,
+                             void* pParam = NULL,
+                             void* pParam2 = NULL);
+
+  virtual void StartFieldDrawLayout(CXFA_Node* pItem,
+                                    FX_FLOAT& fCalcWidth,
+                                    FX_FLOAT& fCalcHeight);
+  virtual FX_BOOL FindSplitPos(CXFA_Node* pItem,
+                               int32_t iBlockIndex,
+                               FX_FLOAT& fCalcHeightPos);
+  virtual FX_BOOL RunScript(CXFA_Node* pScript, CXFA_Node* pFormItem);
+  virtual int32_t ExecEventByDeepFirst(CXFA_Node* pFormNode,
+                                       XFA_EVENTTYPE eEventType,
+                                       FX_BOOL bIsFormReady = FALSE,
+                                       FX_BOOL bRecursive = TRUE,
+                                       CXFA_WidgetAcc* pExclude = NULL);
+  virtual void AddCalcValidate(CXFA_Node* pNode);
+  virtual IXFA_Doc* GetHDOC();
+  virtual IXFA_DocProvider* GetDocProvider();
+  virtual IXFA_AppProvider* GetAppProvider();
+  virtual IXFA_WidgetHandler* GetWidgetHandler();
+  virtual IXFA_Widget* GetHWidget(CXFA_LayoutItem* pLayoutItem);
+  virtual void OpenDropDownList(IXFA_Widget* hWidget);
+  virtual CFX_WideString GetCurrentDateTime();
+  virtual void ResetData(CXFA_WidgetData* pWidgetData = NULL);
+  virtual int32_t GetLayoutStatus();
+  virtual void RunNodeInitialize(CXFA_Node* pNode);
+  virtual void RunSubformIndexChange(CXFA_Node* pSubformNode);
+  virtual CXFA_Node* GetFocusWidgetNode();
+  virtual void SetFocusWidgetNode(CXFA_Node* pNode);
+
+ protected:
+  void OnNodeReady(CXFA_Node* pNode);
+  void OnValueChanging(CXFA_Node* pSender, void* pParam, void* pParam2);
+  void OnValueChanged(CXFA_Node* pSender,
+                      void* pParam,
+                      void* pParam2,
+                      void* pParam3,
+                      void* pParam4);
+  void OnChildAdded(CXFA_Node* pSender, void* pParam, void* pParam2);
+  void OnChildRemoved(CXFA_Node* pSender, void* pParam, void* pParam2);
+  void OnLayoutItemAdd(CXFA_FFDocView* pDocView,
+                       IXFA_DocLayout* pLayout,
+                       CXFA_LayoutItem* pSender,
+                       void* pParam,
+                       void* pParam2);
+  void OnLayoutItemRemoving(CXFA_FFDocView* pDocView,
+                            IXFA_DocLayout* pLayout,
+                            CXFA_LayoutItem* pSender,
+                            void* pParam,
+                            void* pParam2);
+  void OnLayoutItemRectChanged(CXFA_FFDocView* pDocView,
+                               IXFA_DocLayout* pLayout,
+                               CXFA_LayoutItem* pSender,
+                               void* pParam,
+                               void* pParam2);
+  void OnLayoutItemStatustChanged(CXFA_FFDocView* pDocView,
+                                  IXFA_DocLayout* pLayout,
+                                  CXFA_LayoutItem* pSender,
+                                  void* pParam,
+                                  void* pParam2);
+  CXFA_FFDoc* m_pDoc;
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFNOTIFY_H_
diff --git a/xfa/fxfa/app/xfa_ffpageview.cpp b/xfa/fxfa/app/xfa_ffpageview.cpp
new file mode 100644
index 0000000..1bc1681
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffpageview.cpp
@@ -0,0 +1,424 @@
+// 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/fxfa/app/xfa_ffpageview.h"
+
+#include "xfa/fde/fde_render.h"
+#include "xfa/fxfa/app/xfa_ffcheckbutton.h"
+#include "xfa/fxfa/app/xfa_ffchoicelist.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffimageedit.h"
+#include "xfa/fxfa/app/xfa_ffpushbutton.h"
+#include "xfa/fxfa/app/xfa_fftextedit.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_fwladapter.h"
+
+CXFA_FFPageView::CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea)
+    : CXFA_ContainerLayoutItem(pPageArea),
+      m_pDocView(pDocView),
+      m_bLoaded(FALSE) {}
+CXFA_FFPageView::~CXFA_FFPageView() {}
+IXFA_DocView* CXFA_FFPageView::GetDocView() {
+  return m_pDocView;
+}
+int32_t CXFA_FFPageView::GetPageViewIndex() {
+  return GetPageIndex();
+}
+void CXFA_FFPageView::GetPageViewRect(CFX_RectF& rtPage) {
+  CFX_SizeF sz;
+  GetPageSize(sz);
+  rtPage.Set(0, 0, sz);
+}
+void CXFA_FFPageView::GetDisplayMatrix(CFX_Matrix& mt,
+                                       const CFX_Rect& rtDisp,
+                                       int32_t iRotate) {
+  CFX_SizeF sz;
+  GetPageSize(sz);
+  CFX_RectF fdePage;
+  fdePage.Set(0, 0, sz.x, sz.y);
+  FDE_GetPageMatrix(mt, fdePage, rtDisp, iRotate, 0);
+}
+int32_t CXFA_FFPageView::LoadPageView(IFX_Pause* pPause) {
+  if (m_bLoaded) {
+    return 100;
+  }
+  m_bLoaded = TRUE;
+  return 100;
+}
+void CXFA_FFPageView::UnloadPageView() {
+  if (!m_bLoaded) {
+    return;
+  }
+}
+FX_BOOL CXFA_FFPageView::IsPageViewLoaded() {
+  return m_bLoaded;
+}
+IXFA_Widget* CXFA_FFPageView::GetWidgetByPos(FX_FLOAT fx, FX_FLOAT fy) {
+  if (!m_bLoaded) {
+    return nullptr;
+  }
+  IXFA_WidgetIterator* pIterator = CreateWidgetIterator();
+  CXFA_FFWidget* pWidget = nullptr;
+  while ((pWidget = static_cast<CXFA_FFWidget*>(pIterator->MoveToNext()))) {
+    if (!(pWidget->GetStatus() & XFA_WIDGETSTATUS_Visible)) {
+      continue;
+    }
+    CXFA_WidgetAcc* pAcc = pWidget->GetDataAcc();
+    int32_t type = pAcc->GetClassID();
+    if (type != XFA_ELEMENT_Field && type != XFA_ELEMENT_Draw) {
+      continue;
+    }
+    FX_FLOAT fWidgetx = fx;
+    FX_FLOAT fWidgety = fy;
+    pWidget->Rotate2Normal(fWidgetx, fWidgety);
+    FX_DWORD dwFlag = pWidget->OnHitTest(fWidgetx, fWidgety);
+    if ((FWL_WGTHITTEST_Client == dwFlag ||
+         FWL_WGTHITTEST_HyperLink == dwFlag)) {
+      break;
+    }
+  }
+  pIterator->Release();
+  return pWidget;
+}
+IXFA_WidgetIterator* CXFA_FFPageView::CreateWidgetIterator(
+    FX_DWORD dwTraverseWay,
+    FX_DWORD dwWidgetFilter) {
+  switch (dwTraverseWay) {
+    case XFA_TRAVERSEWAY_Tranvalse:
+      return new CXFA_FFTabOrderPageWidgetIterator(this, dwWidgetFilter);
+    case XFA_TRAVERSEWAY_Form:
+      return new CXFA_FFPageWidgetIterator(this, dwWidgetFilter);
+  }
+  return NULL;
+}
+static FX_BOOL XFA_PageWidgetFilter(CXFA_FFWidget* pWidget,
+                                    FX_DWORD dwFilter,
+                                    FX_BOOL bTraversal,
+                                    FX_BOOL bIgnorerelevant) {
+  CXFA_WidgetAcc* pWidgetAcc = pWidget->GetDataAcc();
+  FX_DWORD dwType = dwFilter & XFA_WIDGETFILTER_AllType;
+  if ((dwType == XFA_WIDGETFILTER_Field) &&
+      (pWidgetAcc->GetClassID() != XFA_ELEMENT_Field)) {
+    return FALSE;
+  }
+  FX_DWORD dwStatus = pWidget->GetStatus();
+  if (bTraversal && (dwStatus & XFA_WIDGETSTATUS_Disabled)) {
+    return FALSE;
+  }
+  if (bIgnorerelevant) {
+    return (dwStatus & XFA_WIDGETFILTER_Visible) != 0;
+  }
+  dwFilter &= (XFA_WIDGETFILTER_Visible | XFA_WIDGETFILTER_Viewable |
+               XFA_WIDGETFILTER_Printable);
+  return (dwFilter & dwStatus) == dwFilter;
+}
+CXFA_FFPageWidgetIterator::CXFA_FFPageWidgetIterator(CXFA_FFPageView* pPageView,
+                                                     FX_DWORD dwFilter) {
+  m_pPageView = pPageView;
+  m_dwFilter = dwFilter;
+  m_sIterator.Init(pPageView);
+  m_bIgnorerelevant = ((CXFA_FFDoc*)m_pPageView->GetDocView()->GetDoc())
+                          ->GetXFADoc()
+                          ->GetCurVersionMode() < XFA_VERSION_205;
+}
+CXFA_FFPageWidgetIterator::~CXFA_FFPageWidgetIterator() {}
+void CXFA_FFPageWidgetIterator::Reset() {
+  m_sIterator.Reset();
+}
+IXFA_Widget* CXFA_FFPageWidgetIterator::MoveToFirst() {
+  m_sIterator.Reset();
+  for (CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); pLayoutItem;
+       pLayoutItem = m_sIterator.MoveToNext()) {
+    if (IXFA_Widget* hWidget = GetWidget(pLayoutItem)) {
+      return hWidget;
+    }
+  }
+  return NULL;
+}
+IXFA_Widget* CXFA_FFPageWidgetIterator::MoveToLast() {
+  m_sIterator.SetCurrent(NULL);
+  return MoveToPrevious();
+}
+IXFA_Widget* CXFA_FFPageWidgetIterator::MoveToNext() {
+  for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToNext(); pLayoutItem;
+       pLayoutItem = m_sIterator.MoveToNext()) {
+    if (IXFA_Widget* hWidget = GetWidget(pLayoutItem)) {
+      return hWidget;
+    }
+  }
+  return NULL;
+}
+IXFA_Widget* CXFA_FFPageWidgetIterator::MoveToPrevious() {
+  for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToPrev(); pLayoutItem;
+       pLayoutItem = m_sIterator.MoveToPrev()) {
+    if (IXFA_Widget* hWidget = GetWidget(pLayoutItem)) {
+      return hWidget;
+    }
+  }
+  return NULL;
+}
+IXFA_Widget* CXFA_FFPageWidgetIterator::GetCurrentWidget() {
+  CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent();
+  return pLayoutItem ? XFA_GetWidgetFromLayoutItem(pLayoutItem) : NULL;
+}
+FX_BOOL CXFA_FFPageWidgetIterator::SetCurrentWidget(IXFA_Widget* hWidget) {
+  CXFA_FFWidget* pWidget = static_cast<CXFA_FFWidget*>(hWidget);
+  return pWidget && m_sIterator.SetCurrent(pWidget);
+}
+IXFA_Widget* CXFA_FFPageWidgetIterator::GetWidget(
+    CXFA_LayoutItem* pLayoutItem) {
+  if (CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pLayoutItem)) {
+    if (!XFA_PageWidgetFilter(pWidget, m_dwFilter, FALSE, m_bIgnorerelevant)) {
+      return NULL;
+    }
+    if (!pWidget->IsLoaded() &&
+        (pWidget->GetStatus() & XFA_WIDGETSTATUS_Visible) != 0) {
+      pWidget->LoadWidget();
+    }
+    return pWidget;
+  }
+  return NULL;
+}
+CXFA_FFTabOrderPageWidgetIterator::CXFA_FFTabOrderPageWidgetIterator(
+    CXFA_FFPageView* pPageView,
+    FX_DWORD dwFilter)
+    : m_pPageView(pPageView), m_dwFilter(dwFilter), m_iCurWidget(-1) {
+  m_bIgnorerelevant = ((CXFA_FFDoc*)m_pPageView->GetDocView()->GetDoc())
+                          ->GetXFADoc()
+                          ->GetCurVersionMode() < XFA_VERSION_205;
+  Reset();
+}
+CXFA_FFTabOrderPageWidgetIterator::~CXFA_FFTabOrderPageWidgetIterator() {}
+void CXFA_FFTabOrderPageWidgetIterator::Release() {
+  delete this;
+}
+void CXFA_FFTabOrderPageWidgetIterator::Reset() {
+  CreateTabOrderWidgetArray();
+  m_iCurWidget = -1;
+}
+IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::MoveToFirst() {
+  if (m_TabOrderWidgetArray.GetSize() > 0) {
+    for (int32_t i = 0; i < m_TabOrderWidgetArray.GetSize(); i++) {
+      if (XFA_PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE,
+                               m_bIgnorerelevant)) {
+        m_iCurWidget = i;
+        return m_TabOrderWidgetArray[m_iCurWidget];
+      }
+    }
+  }
+  return NULL;
+}
+IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::MoveToLast() {
+  if (m_TabOrderWidgetArray.GetSize() > 0) {
+    for (int32_t i = m_TabOrderWidgetArray.GetSize() - 1; i >= 0; i--) {
+      if (XFA_PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE,
+                               m_bIgnorerelevant)) {
+        m_iCurWidget = i;
+        return m_TabOrderWidgetArray[m_iCurWidget];
+      }
+    }
+  }
+  return NULL;
+}
+IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::MoveToNext() {
+  for (int32_t i = m_iCurWidget + 1; i < m_TabOrderWidgetArray.GetSize(); i++) {
+    if (XFA_PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE,
+                             m_bIgnorerelevant)) {
+      m_iCurWidget = i;
+      return m_TabOrderWidgetArray[m_iCurWidget];
+    }
+  }
+  m_iCurWidget = -1;
+  return NULL;
+}
+IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::MoveToPrevious() {
+  for (int32_t i = m_iCurWidget - 1; i >= 0; i--) {
+    if (XFA_PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE,
+                             m_bIgnorerelevant)) {
+      m_iCurWidget = i;
+      return m_TabOrderWidgetArray[m_iCurWidget];
+    }
+  }
+  m_iCurWidget = -1;
+  return NULL;
+}
+IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::GetCurrentWidget() {
+  if (m_iCurWidget >= 0) {
+    return m_TabOrderWidgetArray[m_iCurWidget];
+  }
+  return NULL;
+}
+FX_BOOL CXFA_FFTabOrderPageWidgetIterator::SetCurrentWidget(
+    IXFA_Widget* hWidget) {
+  int32_t iWidgetIndex =
+      m_TabOrderWidgetArray.Find(static_cast<CXFA_FFWidget*>(hWidget));
+  if (iWidgetIndex >= 0) {
+    m_iCurWidget = iWidgetIndex;
+    return TRUE;
+  }
+  return FALSE;
+}
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetTraverseWidget(
+    CXFA_FFWidget* pWidget) {
+  CXFA_WidgetAcc* pAcc = pWidget->GetDataAcc();
+  CXFA_Node* pTraversal = pAcc->GetNode()->GetChild(0, XFA_ELEMENT_Traversal);
+  if (pTraversal) {
+    CXFA_Node* pTraverse = pTraversal->GetChild(0, XFA_ELEMENT_Traverse);
+    if (pTraverse) {
+      CFX_WideString wsTraverseWidgetName;
+      if (pTraverse->GetAttribute(XFA_ATTRIBUTE_Ref, wsTraverseWidgetName)) {
+        return FindWidgetByName(wsTraverseWidgetName, pWidget);
+      }
+    }
+  }
+  return NULL;
+}
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::FindWidgetByName(
+    const CFX_WideStringC& wsWidgetName,
+    CXFA_FFWidget* pRefWidget) {
+  return pRefWidget->GetDocView()->GetWidgetByName(wsWidgetName, pRefWidget);
+}
+void CXFA_FFTabOrderPageWidgetIterator::CreateTabOrderWidgetArray() {
+  m_TabOrderWidgetArray.RemoveAll();
+  CXFA_WidgetArray SpaceOrderWidgetArray;
+  CreateSpaceOrderWidgetArray(SpaceOrderWidgetArray);
+  int32_t nWidgetCount = SpaceOrderWidgetArray.GetSize();
+  if (nWidgetCount < 1) {
+    return;
+  }
+  CXFA_FFWidget* hWidget = SpaceOrderWidgetArray[0];
+  for (; m_TabOrderWidgetArray.GetSize() < nWidgetCount;) {
+    if (m_TabOrderWidgetArray.Find(hWidget) < 0) {
+      m_TabOrderWidgetArray.Add(hWidget);
+      CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc();
+      if (pWidgetAcc->GetUIType() == XFA_ELEMENT_ExclGroup) {
+        int32_t iWidgetIndex = SpaceOrderWidgetArray.Find(hWidget) + 1;
+        while (TRUE) {
+          CXFA_FFWidget* pRadio =
+              SpaceOrderWidgetArray[(iWidgetIndex) % nWidgetCount];
+          if (pRadio->GetDataAcc()->GetExclGroup() != pWidgetAcc) {
+            break;
+          }
+          if (m_TabOrderWidgetArray.Find(hWidget) < 0) {
+            m_TabOrderWidgetArray.Add(pRadio);
+          }
+          iWidgetIndex++;
+        }
+      }
+      if (CXFA_FFWidget* hTraverseWidget = GetTraverseWidget(hWidget)) {
+        hWidget = hTraverseWidget;
+        continue;
+      }
+    }
+    int32_t iWidgetIndex = SpaceOrderWidgetArray.Find(hWidget);
+    hWidget = SpaceOrderWidgetArray[(iWidgetIndex + 1) % nWidgetCount];
+  }
+}
+static int32_t XFA_TabOrderWidgetComparator(const void* phWidget1,
+                                            const void* phWidget2) {
+  CXFA_FFWidget* pWidget1 = (*(CXFA_TabParam**)phWidget1)->m_pWidget;
+  CXFA_FFWidget* pWidget2 = (*(CXFA_TabParam**)phWidget2)->m_pWidget;
+  CFX_RectF rt1, rt2;
+  pWidget1->GetWidgetRect(rt1);
+  pWidget2->GetWidgetRect(rt2);
+  FX_FLOAT x1 = rt1.left, y1 = rt1.top, x2 = rt2.left, y2 = rt2.top;
+  if (y1 < y2 || (y1 - y2 < XFA_FLOAT_PERCISION && x1 < x2)) {
+    return -1;
+  }
+  return 1;
+}
+void CXFA_FFTabOrderPageWidgetIterator::OrderContainer(
+    CXFA_LayoutItemIterator* sIterator,
+    CXFA_LayoutItem* pContainerItem,
+    CXFA_TabParam* pContainer,
+    FX_BOOL& bCurrentItem,
+    FX_BOOL& bContentArea,
+    FX_BOOL bMarsterPage) {
+  CFX_PtrArray tabParams;
+  CXFA_LayoutItem* pSearchItem = sIterator->MoveToNext();
+  while (pSearchItem) {
+    if (!pSearchItem->IsContentLayoutItem()) {
+      bContentArea = TRUE;
+      pSearchItem = sIterator->MoveToNext();
+      continue;
+    }
+    if (bMarsterPage && bContentArea) {
+      break;
+    }
+    if (bMarsterPage || bContentArea) {
+      CXFA_FFWidget* hWidget = GetWidget(pSearchItem);
+      if (!hWidget) {
+        pSearchItem = sIterator->MoveToNext();
+        continue;
+      }
+      if (pContainerItem && (pSearchItem->GetParent() != pContainerItem)) {
+        bCurrentItem = TRUE;
+        break;
+      }
+      CXFA_TabParam* pParam = new CXFA_TabParam;
+      pParam->m_pWidget = hWidget;
+      tabParams.Add(pParam);
+      if (XFA_IsLayoutElement(pSearchItem->GetFormNode()->GetClassID(), TRUE)) {
+        OrderContainer(sIterator, pSearchItem, pParam, bCurrentItem,
+                       bContentArea, bMarsterPage);
+      }
+    }
+    if (bCurrentItem) {
+      pSearchItem = sIterator->GetCurrent();
+      bCurrentItem = FALSE;
+    } else {
+      pSearchItem = sIterator->MoveToNext();
+    }
+  }
+  int32_t iChildren = tabParams.GetSize();
+  if (iChildren > 1) {
+    FXSYS_qsort(tabParams.GetData(), iChildren, sizeof(void*),
+                XFA_TabOrderWidgetComparator);
+  }
+  for (int32_t iStart = 0; iStart < iChildren; iStart++) {
+    CXFA_TabParam* pParam = (CXFA_TabParam*)tabParams[iStart];
+    pContainer->m_Children.Add(pParam->m_pWidget);
+    if (pParam->m_Children.GetSize() > 0) {
+      pContainer->m_Children.Append(pParam->m_Children);
+    }
+    delete pParam;
+  }
+  tabParams.RemoveAll();
+}
+void CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderWidgetArray(
+    CXFA_WidgetArray& WidgetArray) {
+  CXFA_LayoutItemIterator sIterator;
+  sIterator.Init(m_pPageView);
+  CXFA_TabParam* pParam = new CXFA_TabParam;
+  FX_BOOL bCurrentItem = FALSE;
+  FX_BOOL bContentArea = FALSE;
+  OrderContainer(&sIterator, NULL, pParam, bCurrentItem, bContentArea);
+  if (pParam->m_Children.GetSize() > 0) {
+    WidgetArray.Append(pParam->m_Children);
+  }
+  sIterator.Reset();
+  bCurrentItem = FALSE;
+  bContentArea = FALSE;
+  pParam->m_Children.RemoveAll();
+  OrderContainer(&sIterator, NULL, pParam, bCurrentItem, bContentArea, TRUE);
+  if (pParam->m_Children.GetSize() > 0) {
+    WidgetArray.Append(pParam->m_Children);
+  }
+  delete pParam;
+}
+CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetWidget(
+    CXFA_LayoutItem* pLayoutItem) {
+  if (CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pLayoutItem)) {
+    if (!pWidget->IsLoaded() &&
+        (pWidget->GetStatus() & XFA_WIDGETSTATUS_Visible)) {
+      pWidget->LoadWidget();
+    }
+    return pWidget;
+  }
+  return NULL;
+}
diff --git a/xfa/fxfa/app/xfa_ffpageview.h b/xfa/fxfa/app/xfa_ffpageview.h
new file mode 100644
index 0000000..b68e828
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffpageview.h
@@ -0,0 +1,111 @@
+// 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_FXFA_APP_XFA_FFPAGEVIEW_H_
+#define XFA_FXFA_APP_XFA_FFPAGEVIEW_H_
+
+#include "xfa/fxfa/parser/xfa_doclayout.h"
+
+class CXFA_FFWidget;
+class CXFA_FFDocView;
+class CXFA_FFPageView : public CXFA_ContainerLayoutItem, public IXFA_PageView {
+ public:
+  CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea);
+  ~CXFA_FFPageView() override;
+
+  // IFXA_PageView:
+  IXFA_DocView* GetDocView() override;
+  int32_t GetPageViewIndex() override;
+  void GetPageViewRect(CFX_RectF& rtPage) override;
+  void GetDisplayMatrix(CFX_Matrix& mt,
+                        const CFX_Rect& rtDisp,
+                        int32_t iRotate) override;
+  int32_t LoadPageView(IFX_Pause* pPause = NULL) override;
+  void UnloadPageView() override;
+  IXFA_Widget* GetWidgetByPos(FX_FLOAT fx, FX_FLOAT fy) override;
+  IXFA_WidgetIterator* CreateWidgetIterator(
+      FX_DWORD dwTraverseWay = XFA_TRAVERSEWAY_Form,
+      FX_DWORD dwWidgetFilter = XFA_WIDGETFILTER_Visible |
+                                XFA_WIDGETFILTER_Viewable |
+                                XFA_WIDGETFILTER_AllType) override;
+
+  FX_BOOL IsPageViewLoaded();
+
+ protected:
+  CXFA_FFDocView* m_pDocView;
+  FX_BOOL m_bLoaded;
+};
+typedef CXFA_NodeIteratorTemplate<CXFA_LayoutItem,
+                                  CXFA_TraverseStrategy_LayoutItem>
+    CXFA_LayoutItemIterator;
+class CXFA_FFPageWidgetIterator : public IXFA_WidgetIterator {
+ public:
+  CXFA_FFPageWidgetIterator(CXFA_FFPageView* pPageView, FX_DWORD dwFilter);
+  virtual ~CXFA_FFPageWidgetIterator();
+  virtual void Release() { delete this; }
+
+  virtual void Reset();
+  virtual IXFA_Widget* MoveToFirst();
+  virtual IXFA_Widget* MoveToLast();
+  virtual IXFA_Widget* MoveToNext();
+  virtual IXFA_Widget* MoveToPrevious();
+  virtual IXFA_Widget* GetCurrentWidget();
+  virtual FX_BOOL SetCurrentWidget(IXFA_Widget* hWidget);
+
+ protected:
+  IXFA_Widget* GetWidget(CXFA_LayoutItem* pLayoutItem);
+  CXFA_FFPageView* m_pPageView;
+  IXFA_Widget* m_hCurWidget;
+  FX_DWORD m_dwFilter;
+  FX_BOOL m_bIgnorerelevant;
+  CXFA_LayoutItemIterator m_sIterator;
+};
+typedef CFX_ArrayTemplate<CXFA_FFWidget*> CXFA_WidgetArray;
+class CXFA_TabParam {
+ public:
+  CXFA_TabParam() : m_pWidget(NULL) {}
+  ~CXFA_TabParam() {}
+
+  CXFA_FFWidget* m_pWidget;
+  CXFA_WidgetArray m_Children;
+};
+class CXFA_FFTabOrderPageWidgetIterator : public IXFA_WidgetIterator {
+ public:
+  CXFA_FFTabOrderPageWidgetIterator(CXFA_FFPageView* pPageView,
+                                    FX_DWORD dwFilter);
+  virtual ~CXFA_FFTabOrderPageWidgetIterator();
+
+  virtual void Release();
+
+  virtual void Reset();
+  virtual IXFA_Widget* MoveToFirst();
+  virtual IXFA_Widget* MoveToLast();
+  virtual IXFA_Widget* MoveToNext();
+  virtual IXFA_Widget* MoveToPrevious();
+  virtual IXFA_Widget* GetCurrentWidget();
+  virtual FX_BOOL SetCurrentWidget(IXFA_Widget* hWidget);
+
+ protected:
+  CXFA_WidgetArray m_TabOrderWidgetArray;
+  CXFA_FFPageView* m_pPageView;
+  FX_DWORD m_dwFilter;
+  int32_t m_iCurWidget;
+  FX_BOOL m_bIgnorerelevant;
+  CXFA_FFWidget* GetTraverseWidget(CXFA_FFWidget* pWidget);
+  CXFA_FFWidget* FindWidgetByName(const CFX_WideStringC& wsWidgetName,
+                                  CXFA_FFWidget* pRefWidget);
+  void CreateTabOrderWidgetArray();
+  void CreateSpaceOrderWidgetArray(CXFA_WidgetArray& WidgetArray);
+  CXFA_FFWidget* GetWidget(CXFA_LayoutItem* pLayoutItem);
+  void OrderContainer(CXFA_LayoutItemIterator* sIterator,
+                      CXFA_LayoutItem* pContainerItem,
+                      CXFA_TabParam* pContainer,
+                      FX_BOOL& bCurrentItem,
+                      FX_BOOL& bContentArea,
+                      FX_BOOL bMarsterPage = FALSE);
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFPAGEVIEW_H_
diff --git a/xfa/fxfa/app/xfa_ffpath.cpp b/xfa/fxfa/app/xfa_ffpath.cpp
new file mode 100644
index 0000000..f082232
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffpath.cpp
@@ -0,0 +1,159 @@
+// 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/fxfa/app/xfa_ffpath.h"
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdraw.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/include/fxgraphics/fx_graphics.h"
+
+CXFA_FFLine::CXFA_FFLine(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFDraw(pPageView, pDataAcc) {}
+CXFA_FFLine::~CXFA_FFLine() {}
+void CXFA_FFLine::GetRectFromHand(CFX_RectF& rect,
+                                  int32_t iHand,
+                                  FX_FLOAT fLineWidth) {
+  FX_FLOAT fHalfWidth = fLineWidth / 2.0f;
+  if (rect.height < 1.0f) {
+    switch (iHand) {
+      case XFA_ATTRIBUTEENUM_Left:
+        rect.top -= fHalfWidth;
+        break;
+      case XFA_ATTRIBUTEENUM_Right:
+        rect.top += fHalfWidth;
+    }
+  } else if (rect.width < 1.0f) {
+    switch (iHand) {
+      case XFA_ATTRIBUTEENUM_Left:
+        rect.left += fHalfWidth;
+        break;
+      case XFA_ATTRIBUTEENUM_Right:
+        rect.left += fHalfWidth;
+        break;
+    }
+  } else {
+    switch (iHand) {
+      case XFA_ATTRIBUTEENUM_Left:
+        rect.Inflate(fHalfWidth, fHalfWidth);
+        break;
+      case XFA_ATTRIBUTEENUM_Right:
+        rect.Deflate(fHalfWidth, fHalfWidth);
+        break;
+    }
+  }
+}
+void CXFA_FFLine::RenderWidget(CFX_Graphics* pGS,
+                               CFX_Matrix* pMatrix,
+                               FX_DWORD dwStatus,
+                               int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CXFA_Value value = m_pDataAcc->GetFormValue();
+  if (!value) {
+    return;
+  }
+  CXFA_Line lineObj = value.GetLine();
+  FX_ARGB lineColor = 0xFF000000;
+  int32_t iStrokeType = 0;
+  FX_FLOAT fLineWidth = 1.0f;
+  FX_BOOL bSlope = lineObj.GetSlop();
+  int32_t iCap = 0;
+  CXFA_Edge edge = lineObj.GetEdge();
+  if (edge) {
+    if (edge.GetPresence() != XFA_ATTRIBUTEENUM_Visible) {
+      return;
+    }
+    lineColor = edge.GetColor();
+    iStrokeType = edge.GetStrokeType();
+    fLineWidth = edge.GetThickness();
+    iCap = edge.GetCapType();
+  }
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  CFX_RectF rtLine;
+  GetRectWithoutRotate(rtLine);
+  if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
+    XFA_RectWidthoutMargin(rtLine, mgWidget);
+  }
+  GetRectFromHand(rtLine, lineObj.GetHand(), fLineWidth);
+  CFX_Path linePath;
+  linePath.Create();
+  if (bSlope && rtLine.right() > 0.0f && rtLine.bottom() > 0.0f) {
+    linePath.AddLine(rtLine.right(), rtLine.top, rtLine.left, rtLine.bottom());
+  } else {
+    linePath.AddLine(rtLine.left, rtLine.top, rtLine.right(), rtLine.bottom());
+  }
+  CFX_Color color(lineColor);
+  pGS->SaveGraphState();
+  pGS->SetLineWidth(fLineWidth, TRUE);
+  XFA_StrokeTypeSetLineDash(pGS, iStrokeType, iCap);
+  pGS->SetStrokeColor(&color);
+  pGS->SetLineCap(XFA_LineCapToFXGE(iCap));
+  pGS->StrokePath(&linePath, &mtRotate);
+  pGS->RestoreGraphState();
+}
+CXFA_FFArc::CXFA_FFArc(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFDraw(pPageView, pDataAcc) {}
+CXFA_FFArc::~CXFA_FFArc() {}
+void CXFA_FFArc::RenderWidget(CFX_Graphics* pGS,
+                              CFX_Matrix* pMatrix,
+                              FX_DWORD dwStatus,
+                              int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CXFA_Value value = m_pDataAcc->GetFormValue();
+  if (!value) {
+    return;
+  }
+  CXFA_Arc arcObj = value.GetArc();
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  CFX_RectF rtArc;
+  GetRectWithoutRotate(rtArc);
+  if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
+    XFA_RectWidthoutMargin(rtArc, mgWidget);
+  }
+  DrawBorder(pGS, arcObj, rtArc, &mtRotate);
+}
+CXFA_FFRectangle::CXFA_FFRectangle(CXFA_FFPageView* pPageView,
+                                   CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFDraw(pPageView, pDataAcc) {}
+CXFA_FFRectangle::~CXFA_FFRectangle() {}
+void CXFA_FFRectangle::RenderWidget(CFX_Graphics* pGS,
+                                    CFX_Matrix* pMatrix,
+                                    FX_DWORD dwStatus,
+                                    int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CXFA_Value value = m_pDataAcc->GetFormValue();
+  if (!value) {
+    return;
+  }
+  CXFA_Rectangle rtObj = value.GetRectangle();
+  CFX_RectF rect;
+  GetRectWithoutRotate(rect);
+  if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
+    XFA_RectWidthoutMargin(rect, mgWidget);
+  }
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  DrawBorder(pGS, rtObj, rect, &mtRotate);
+}
diff --git a/xfa/fxfa/app/xfa_ffpath.h b/xfa/fxfa/app/xfa_ffpath.h
new file mode 100644
index 0000000..2b2c40d
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffpath.h
@@ -0,0 +1,43 @@
+// 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_FXFA_APP_XFA_FFPATH_H_
+#define XFA_FXFA_APP_XFA_FFPATH_H_
+
+#include "xfa/fxfa/app/xfa_ffdraw.h"
+
+class CXFA_FFLine : public CXFA_FFDraw {
+ public:
+  CXFA_FFLine(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFLine();
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+
+ private:
+  void GetRectFromHand(CFX_RectF& rect, int32_t iHand, FX_FLOAT fLineWidth);
+};
+class CXFA_FFArc : public CXFA_FFDraw {
+ public:
+  CXFA_FFArc(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFArc();
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+};
+class CXFA_FFRectangle : public CXFA_FFDraw {
+ public:
+  CXFA_FFRectangle(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFRectangle();
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFPATH_H_
diff --git a/xfa/fxfa/app/xfa_ffpushbutton.cpp b/xfa/fxfa/app/xfa_ffpushbutton.cpp
new file mode 100644
index 0000000..718853e
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffpushbutton.cpp
@@ -0,0 +1,249 @@
+// 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/fxfa/app/xfa_ffpushbutton.h"
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_ffwidgetacc.h"
+#include "xfa/fxfa/app/xfa_textlayout.h"
+#include "xfa/include/fwl/core/fwl_widgetmgr.h"
+#include "xfa/include/fwl/lightwidget/pushbutton.h"
+
+CXFA_FFPushButton::CXFA_FFPushButton(CXFA_FFPageView* pPageView,
+                                     CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFField(pPageView, pDataAcc),
+      m_pRolloverTextLayout(NULL),
+      m_pDownTextLayout(NULL),
+      m_pDownProvider(NULL),
+      m_pRollProvider(NULL),
+      m_pOldDelegate(NULL) {}
+CXFA_FFPushButton::~CXFA_FFPushButton() {
+  CXFA_FFPushButton::UnloadWidget();
+}
+void CXFA_FFPushButton::RenderWidget(CFX_Graphics* pGS,
+                                     CFX_Matrix* pMatrix,
+                                     FX_DWORD dwStatus,
+                                     int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
+  RenderHighlightCaption(pGS, &mtRotate);
+  CFX_RectF rtWidget;
+  GetRectWithoutRotate(rtWidget);
+  CFX_Matrix mt;
+  mt.Set(1, 0, 0, 1, rtWidget.left, rtWidget.top);
+  mt.Concat(mtRotate);
+  GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget->GetWidget(),
+                                                 pGS, &mt);
+}
+FX_BOOL CXFA_FFPushButton::LoadWidget() {
+  FXSYS_assert(m_pNormalWidget == NULL);
+  CFWL_PushButton* pPushButton = CFWL_PushButton::Create();
+  if (pPushButton) {
+    pPushButton->Initialize();
+  }
+  m_pOldDelegate = pPushButton->SetDelegate(this);
+  m_pNormalWidget = (CFWL_Widget*)pPushButton;
+  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
+  m_pNormalWidget->SetPrivateData(pWidget, this, NULL);
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  m_pNormalWidget->LockUpdate();
+  UpdateWidgetProperty();
+  LoadHighlightCaption();
+  m_pNormalWidget->UnlockUpdate();
+  return CXFA_FFField::LoadWidget();
+}
+void CXFA_FFPushButton::UpdateWidgetProperty() {
+  FX_DWORD dwStyleEx = 0;
+  switch (m_pDataAcc->GetButtonHighlight()) {
+    case XFA_ATTRIBUTEENUM_Inverted:
+      dwStyleEx = XFA_FWL_PSBSTYLEEXT_HiliteInverted;
+      break;
+    case XFA_ATTRIBUTEENUM_Outline:
+      dwStyleEx = XFA_FWL_PSBSTYLEEXT_HiliteOutLine;
+      break;
+    case XFA_ATTRIBUTEENUM_Push:
+      dwStyleEx = XFA_FWL_PSBSTYLEEXT_HilitePush;
+      break;
+    default:
+      break;
+  }
+  m_pNormalWidget->ModifyStylesEx(dwStyleEx, 0xFFFFFFFF);
+}
+void CXFA_FFPushButton::UnloadWidget() {
+  if (m_pRolloverTextLayout) {
+    delete m_pRolloverTextLayout;
+    m_pRolloverTextLayout = NULL;
+  }
+  if (m_pDownTextLayout) {
+    delete m_pDownTextLayout;
+    m_pDownTextLayout = NULL;
+  }
+  if (m_pDownProvider) {
+    delete m_pDownProvider;
+    m_pDownProvider = NULL;
+  }
+  if (m_pRollProvider) {
+    delete m_pRollProvider;
+    m_pRollProvider = NULL;
+  }
+  CXFA_FFField::UnloadWidget();
+}
+FX_BOOL CXFA_FFPushButton::PerformLayout() {
+  CXFA_FFWidget::PerformLayout();
+  CFX_RectF rtWidget;
+  GetRectWithoutRotate(rtWidget);
+  m_rtUI = rtWidget;
+  if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
+    XFA_RectWidthoutMargin(rtWidget, mgWidget);
+  }
+  CXFA_Caption caption = m_pDataAcc->GetCaption();
+  m_rtCaption.Set(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height);
+  if (CXFA_Margin mgCap = caption.GetMargin()) {
+    XFA_RectWidthoutMargin(m_rtCaption, mgCap);
+  }
+  LayoutHighlightCaption();
+  SetFWLRect();
+  if (m_pNormalWidget) {
+    m_pNormalWidget->Update();
+  }
+  return TRUE;
+}
+FX_FLOAT CXFA_FFPushButton::GetLineWidth() {
+  CXFA_Border border = m_pDataAcc->GetBorder();
+  if (border && border.GetPresence() == XFA_ATTRIBUTEENUM_Visible) {
+    CXFA_Edge edge = border.GetEdge(0);
+    return edge.GetThickness();
+  }
+  return 0;
+}
+FX_ARGB CXFA_FFPushButton::GetLineColor() {
+  return 0xFF000000;
+}
+FX_ARGB CXFA_FFPushButton::GetFillColor() {
+  return 0xFFFFFFFF;
+}
+void CXFA_FFPushButton::LoadHighlightCaption() {
+  CXFA_Caption caption = m_pDataAcc->GetCaption();
+  if (caption && caption.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) {
+    {
+      CFX_WideString wsRollover;
+      FX_BOOL bRichText;
+      if (m_pDataAcc->GetButtonRollover(wsRollover, bRichText)) {
+        if (m_pRollProvider == NULL) {
+          m_pRollProvider =
+              new CXFA_TextProvider(m_pDataAcc, XFA_TEXTPROVIDERTYPE_Rollover);
+        }
+        m_pRolloverTextLayout = new CXFA_TextLayout(m_pRollProvider);
+      }
+      CFX_WideString wsDown;
+      if (m_pDataAcc->GetButtonDown(wsDown, bRichText)) {
+        if (m_pDownProvider == NULL) {
+          m_pDownProvider =
+              new CXFA_TextProvider(m_pDataAcc, XFA_TEXTPROVIDERTYPE_Down);
+        }
+        m_pDownTextLayout = new CXFA_TextLayout(m_pDownProvider);
+      }
+    }
+  }
+}
+void CXFA_FFPushButton::LayoutHighlightCaption() {
+  CFX_SizeF sz(m_rtCaption.width, m_rtCaption.height);
+  LayoutCaption();
+  if (m_pRolloverTextLayout) {
+    m_pRolloverTextLayout->Layout(sz);
+  }
+  if (m_pDownTextLayout) {
+    m_pDownTextLayout->Layout(sz);
+  }
+}
+void CXFA_FFPushButton::RenderHighlightCaption(CFX_Graphics* pGS,
+                                               CFX_Matrix* pMatrix) {
+  CXFA_TextLayout* pCapTextLayout = m_pDataAcc->GetCaptionTextLayout();
+  CXFA_Caption caption = m_pDataAcc->GetCaption();
+  if (caption && caption.GetPresence() == XFA_ATTRIBUTEENUM_Visible) {
+    CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
+    CFX_RectF rtWidget;
+    GetRectWithoutRotate(rtWidget);
+    CFX_RectF rtClip = m_rtCaption;
+    rtClip.Intersect(rtWidget);
+    CFX_Matrix mt;
+    mt.Set(1, 0, 0, 1, m_rtCaption.left, m_rtCaption.top);
+    if (pMatrix) {
+      pMatrix->TransformRect(rtClip);
+      mt.Concat(*pMatrix);
+    }
+    {
+      FX_DWORD dwState = m_pNormalWidget->GetStates();
+      if (m_pDownTextLayout && (dwState & FWL_STATE_PSB_Pressed) &&
+          (dwState & FWL_STATE_PSB_Hovered)) {
+        if (m_pDownTextLayout->DrawString(pRenderDevice, mt, rtClip)) {
+          return;
+        }
+      } else if (m_pRolloverTextLayout && (dwState & FWL_STATE_PSB_Hovered)) {
+        if (m_pRolloverTextLayout->DrawString(pRenderDevice, mt, rtClip)) {
+          return;
+        }
+      }
+    }
+    if (pCapTextLayout) {
+      pCapTextLayout->DrawString(pRenderDevice, mt, rtClip);
+    }
+  }
+}
+int32_t CXFA_FFPushButton::OnProcessMessage(CFWL_Message* pMessage) {
+  return m_pOldDelegate->OnProcessMessage(pMessage);
+}
+FWL_ERR CXFA_FFPushButton::OnProcessEvent(CFWL_Event* pEvent) {
+  m_pOldDelegate->OnProcessEvent(pEvent);
+  return CXFA_FFField::OnProcessEvent(pEvent);
+}
+FWL_ERR CXFA_FFPushButton::OnDrawWidget(CFX_Graphics* pGraphics,
+                                        const CFX_Matrix* pMatrix) {
+  if (m_pNormalWidget->GetStylesEx() & XFA_FWL_PSBSTYLEEXT_HiliteInverted) {
+    if ((m_pNormalWidget->GetStates() & FWL_STATE_PSB_Pressed) &&
+        (m_pNormalWidget->GetStates() & FWL_STATE_PSB_Hovered)) {
+      CFX_RectF rtFill;
+      m_pNormalWidget->GetWidgetRect(rtFill);
+      rtFill.left = rtFill.top = 0;
+      FX_FLOAT fLineWith = GetLineWidth();
+      rtFill.Deflate(fLineWith, fLineWith);
+      CFX_Color cr(FXARGB_MAKE(128, 128, 255, 255));
+      pGraphics->SetFillColor(&cr);
+      CFX_Path path;
+      path.Create();
+      path.AddRectangle(rtFill.left, rtFill.top, rtFill.width, rtFill.height);
+      pGraphics->FillPath(&path, FXFILL_WINDING, (CFX_Matrix*)pMatrix);
+    }
+  } else if (m_pNormalWidget->GetStylesEx() &
+             XFA_FWL_PSBSTYLEEXT_HiliteOutLine) {
+    if ((m_pNormalWidget->GetStates() & FWL_STATE_PSB_Pressed) &&
+        (m_pNormalWidget->GetStates() & FWL_STATE_PSB_Hovered)) {
+      FX_FLOAT fLineWidth = GetLineWidth();
+      CFX_Color cr(FXARGB_MAKE(255, 128, 255, 255));
+      pGraphics->SetStrokeColor(&cr);
+      pGraphics->SetLineWidth(fLineWidth);
+      CFX_Path path;
+      path.Create();
+      CFX_RectF rect;
+      m_pNormalWidget->GetWidgetRect(rect);
+      path.AddRectangle(0, 0, rect.width, rect.height);
+      pGraphics->StrokePath(&path, (CFX_Matrix*)pMatrix);
+    }
+  } else if (m_pNormalWidget->GetStylesEx() & XFA_FWL_PSBSTYLEEXT_HilitePush) {
+  }
+  return FWL_ERR_Succeeded;
+}
diff --git a/xfa/fxfa/app/xfa_ffpushbutton.h b/xfa/fxfa/app/xfa_ffpushbutton.h
new file mode 100644
index 0000000..39f6bd4
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffpushbutton.h
@@ -0,0 +1,50 @@
+// 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_FXFA_APP_XFA_FFPUSHBUTTON_H_
+#define XFA_FXFA_APP_XFA_FFPUSHBUTTON_H_
+
+#include "xfa/fxfa/app/xfa_fffield.h"
+
+#define XFA_FWL_PSBSTYLEEXT_HiliteNone (0L << 0)
+#define XFA_FWL_PSBSTYLEEXT_HiliteInverted (1L << 0)
+#define XFA_FWL_PSBSTYLEEXT_HilitePush (2L << 0)
+#define XFA_FWL_PSBSTYLEEXT_HiliteOutLine (4L << 0)
+
+class CXFA_TextProvider;
+
+class CXFA_FFPushButton : public CXFA_FFField {
+ public:
+  CXFA_FFPushButton(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFPushButton();
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+  virtual FX_BOOL LoadWidget();
+  virtual void UnloadWidget();
+  virtual FX_BOOL PerformLayout();
+  virtual void UpdateWidgetProperty();
+  virtual int32_t OnProcessMessage(CFWL_Message* pMessage);
+  virtual FWL_ERR OnProcessEvent(CFWL_Event* pEvent);
+  virtual FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics,
+                               const CFX_Matrix* pMatrix = NULL);
+
+ protected:
+  void LoadHighlightCaption();
+  void LayoutHighlightCaption();
+  void RenderHighlightCaption(CFX_Graphics* pGS, CFX_Matrix* pMatrix = NULL);
+  FX_FLOAT GetLineWidth();
+  FX_ARGB GetLineColor();
+  FX_ARGB GetFillColor();
+  CXFA_TextLayout* m_pRolloverTextLayout;
+  CXFA_TextLayout* m_pDownTextLayout;
+  CXFA_TextProvider* m_pDownProvider;
+  CXFA_TextProvider* m_pRollProvider;
+  IFWL_WidgetDelegate* m_pOldDelegate;
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFPUSHBUTTON_H_
diff --git a/xfa/fxfa/app/xfa_ffsignature.cpp b/xfa/fxfa/app/xfa_ffsignature.cpp
new file mode 100644
index 0000000..96907c5
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffsignature.cpp
@@ -0,0 +1,120 @@
+// 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/fxfa/app/xfa_ffsignature.h"
+
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+
+CXFA_FFSignature::CXFA_FFSignature(CXFA_FFPageView* pPageView,
+                                   CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFField(pPageView, pDataAcc) {}
+CXFA_FFSignature::~CXFA_FFSignature() {}
+FX_BOOL CXFA_FFSignature::LoadWidget() {
+  return CXFA_FFField::LoadWidget();
+}
+void CXFA_FFSignature::RenderWidget(CFX_Graphics* pGS,
+                                    CFX_Matrix* pMatrix,
+                                    FX_DWORD dwStatus,
+                                    int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CFX_Matrix mtRotate;
+  GetRotateMatrix(mtRotate);
+  if (pMatrix) {
+    mtRotate.Concat(*pMatrix);
+  }
+  CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
+  CXFA_Border borderUI = m_pDataAcc->GetUIBorder();
+  DrawBorder(pGS, borderUI, m_rtUI, &mtRotate);
+  RenderCaption(pGS, &mtRotate);
+  DrawHighlight(pGS, &mtRotate, dwStatus, FALSE);
+  CFX_RectF rtWidget = m_rtUI;
+  IXFA_DocProvider* pDocProvider = m_pDataAcc->GetDoc()->GetDocProvider();
+  FXSYS_assert(pDocProvider);
+  pDocProvider->RenderCustomWidget(this, pGS, &mtRotate, rtWidget);
+}
+FX_BOOL CXFA_FFSignature::OnMouseEnter() {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnMouseExit() {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnLButtonDown(FX_DWORD dwFlags,
+                                        FX_FLOAT fx,
+                                        FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnLButtonUp(FX_DWORD dwFlags,
+                                      FX_FLOAT fx,
+                                      FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnLButtonDblClk(FX_DWORD dwFlags,
+                                          FX_FLOAT fx,
+                                          FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnMouseMove(FX_DWORD dwFlags,
+                                      FX_FLOAT fx,
+                                      FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnMouseWheel(FX_DWORD dwFlags,
+                                       int16_t zDelta,
+                                       FX_FLOAT fx,
+                                       FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnRButtonDown(FX_DWORD dwFlags,
+                                        FX_FLOAT fx,
+                                        FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnRButtonUp(FX_DWORD dwFlags,
+                                      FX_FLOAT fx,
+                                      FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnRButtonDblClk(FX_DWORD dwFlags,
+                                          FX_FLOAT fx,
+                                          FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnKeyDown(FX_DWORD dwKeyCode, FX_DWORD dwFlags) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnKeyUp(FX_DWORD dwKeyCode, FX_DWORD dwFlags) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFSignature::OnChar(FX_DWORD dwChar, FX_DWORD dwFlags) {
+  return FALSE;
+}
+FX_DWORD CXFA_FFSignature::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) {
+  if (m_pNormalWidget) {
+    FX_FLOAT ffx = fx, ffy = fy;
+    FWLToClient(ffx, ffy);
+    FX_DWORD dwWidgetHit = m_pNormalWidget->HitTest(ffx, ffy);
+    if (dwWidgetHit != FWL_WGTHITTEST_Unknown) {
+      return FWL_WGTHITTEST_Client;
+    }
+  }
+  CFX_RectF rtBox;
+  GetRectWithoutRotate(rtBox);
+  if (!rtBox.Contains(fx, fy)) {
+    return FWL_WGTHITTEST_Unknown;
+  }
+  if (m_rtCaption.Contains(fx, fy)) {
+    return FWL_WGTHITTEST_Titlebar;
+  }
+  return FWL_WGTHITTEST_Client;
+}
+FX_BOOL CXFA_FFSignature::OnSetCursor(FX_FLOAT fx, FX_FLOAT fy) {
+  return FALSE;
+}
diff --git a/xfa/fxfa/app/xfa_ffsignature.h b/xfa/fxfa/app/xfa_ffsignature.h
new file mode 100644
index 0000000..f976fed
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffsignature.h
@@ -0,0 +1,43 @@
+// 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_FXFA_APP_XFA_FFSIGNATURE_H_
+#define XFA_FXFA_APP_XFA_FFSIGNATURE_H_
+
+#include "xfa/fxfa/app/xfa_fffield.h"
+
+class CXFA_FFSignature final : public CXFA_FFField {
+ public:
+  CXFA_FFSignature(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFSignature();
+
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+  virtual FX_BOOL LoadWidget();
+  virtual FX_BOOL OnMouseEnter();
+  virtual FX_BOOL OnMouseExit();
+  virtual FX_BOOL OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnLButtonDblClk(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnMouseWheel(FX_DWORD dwFlags,
+                               int16_t zDelta,
+                               FX_FLOAT fx,
+                               FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonDblClk(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+
+  virtual FX_BOOL OnKeyDown(FX_DWORD dwKeyCode, FX_DWORD dwFlags);
+  virtual FX_BOOL OnKeyUp(FX_DWORD dwKeyCode, FX_DWORD dwFlags);
+  virtual FX_BOOL OnChar(FX_DWORD dwChar, FX_DWORD dwFlags);
+  virtual FX_DWORD OnHitTest(FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnSetCursor(FX_FLOAT fx, FX_FLOAT fy);
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFSIGNATURE_H_
diff --git a/xfa/fxfa/app/xfa_ffsubform.cpp b/xfa/fxfa/app/xfa_ffsubform.cpp
new file mode 100644
index 0000000..aebbb08
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffsubform.cpp
@@ -0,0 +1,17 @@
+// 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/fxfa/app/xfa_ffsubform.h"
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+
+CXFA_FFSubForm::CXFA_FFSubForm(CXFA_FFPageView* pPageView,
+                               CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFWidget(pPageView, pDataAcc) {}
+CXFA_FFSubForm::~CXFA_FFSubForm() {}
diff --git a/xfa/fxfa/app/xfa_ffsubform.h b/xfa/fxfa/app/xfa_ffsubform.h
new file mode 100644
index 0000000..e436911
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffsubform.h
@@ -0,0 +1,19 @@
+// 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_FXFA_APP_XFA_FFSUBFORM_H_
+#define XFA_FXFA_APP_XFA_FFSUBFORM_H_
+
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+
+class CXFA_FFSubForm : public CXFA_FFWidget {
+ public:
+  CXFA_FFSubForm(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFSubForm();
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFSUBFORM_H_
diff --git a/xfa/fxfa/app/xfa_fftext.cpp b/xfa/fxfa/app/xfa_fftext.cpp
new file mode 100644
index 0000000..aba8d16
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fftext.cpp
@@ -0,0 +1,179 @@
+// 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/fxfa/app/xfa_fftext.h"
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdraw.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_textlayout.h"
+#include "xfa/include/fwl/core/fwl_widgetdef.h"
+#include "xfa/include/fxgraphics/fx_graphics.h"
+
+CXFA_FFText::CXFA_FFText(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFDraw(pPageView, pDataAcc) {}
+CXFA_FFText::~CXFA_FFText() {}
+void CXFA_FFText::RenderWidget(CFX_Graphics* pGS,
+                               CFX_Matrix* pMatrix,
+                               FX_DWORD dwStatus,
+                               int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  {
+    CFX_Matrix mtRotate;
+    GetRotateMatrix(mtRotate);
+    if (pMatrix) {
+      mtRotate.Concat(*pMatrix);
+    }
+    CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
+    CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
+    if (pTextLayout) {
+      CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
+      CFX_RectF rtText;
+      GetRectWithoutRotate(rtText);
+      if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
+        CXFA_LayoutItem* pItem = this;
+        if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) {
+          XFA_RectWidthoutMargin(rtText, mgWidget);
+        } else {
+          FX_FLOAT fLeftInset, fRightInset, fTopInset = 0, fBottomInset = 0;
+          mgWidget.GetLeftInset(fLeftInset);
+          mgWidget.GetRightInset(fRightInset);
+          if (pItem->GetPrev() == NULL) {
+            mgWidget.GetTopInset(fTopInset);
+          } else if (pItem->GetNext() == NULL) {
+            mgWidget.GetBottomInset(fBottomInset);
+          }
+          rtText.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
+        }
+      }
+      CFX_Matrix mt;
+      mt.Set(1, 0, 0, 1, rtText.left, rtText.top);
+      CFX_RectF rtClip = rtText;
+      mtRotate.TransformRect(rtClip);
+      mt.Concat(mtRotate);
+      pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex());
+    }
+  }
+}
+FX_BOOL CXFA_FFText::IsLoaded() {
+  CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
+  return pTextLayout && !pTextLayout->m_bHasBlock;
+}
+FX_BOOL CXFA_FFText::PerformLayout() {
+  CXFA_FFDraw::PerformLayout();
+  CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
+  if (!pTextLayout) {
+    return FALSE;
+  }
+  if (!pTextLayout->m_bHasBlock) {
+    return TRUE;
+  }
+  pTextLayout->m_Blocks.RemoveAll();
+  CXFA_LayoutItem* pItem = this;
+  if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) {
+    return TRUE;
+  }
+  pItem = pItem->GetFirst();
+  while (pItem) {
+    CFX_RectF rtText;
+    pItem->GetRect(rtText);
+    if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) {
+      if (pItem->GetPrev() == NULL) {
+        FX_FLOAT fTopInset;
+        mgWidget.GetTopInset(fTopInset);
+        rtText.height -= fTopInset;
+      } else if (pItem->GetNext() == NULL) {
+        FX_FLOAT fBottomInset;
+        mgWidget.GetBottomInset(fBottomInset);
+        rtText.height -= fBottomInset;
+      }
+    }
+    pTextLayout->ItemBlocks(rtText, pItem->GetIndex());
+    pItem = pItem->GetNext();
+  }
+  pTextLayout->m_bHasBlock = FALSE;
+  return TRUE;
+}
+FX_BOOL CXFA_FFText::OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
+  CFX_RectF rtBox;
+  GetRectWithoutRotate(rtBox);
+  if (!rtBox.Contains(fx, fy)) {
+    return FALSE;
+  }
+  const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
+  if (NULL == wsURLContent) {
+    return FALSE;
+  }
+  SetButtonDown(TRUE);
+  return TRUE;
+}
+FX_BOOL CXFA_FFText::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
+  CFX_RectF rtBox;
+  GetRectWithoutRotate(rtBox);
+  if (!rtBox.Contains(fx, fy)) {
+    return FALSE;
+  }
+  const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
+  if (NULL == wsURLContent) {
+    return FALSE;
+  }
+  return TRUE;
+}
+FX_BOOL CXFA_FFText::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
+  if (!IsButtonDown()) {
+    return FALSE;
+  }
+  SetButtonDown(FALSE);
+  const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy);
+  if (NULL == wsURLContent) {
+    return FALSE;
+  }
+  CXFA_FFDoc* pDoc = GetDoc();
+  pDoc->GetDocProvider()->GotoURL(pDoc, CFX_WideStringC(wsURLContent), FALSE);
+  return TRUE;
+}
+FX_DWORD CXFA_FFText::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) {
+  CFX_RectF rtBox;
+  GetRectWithoutRotate(rtBox);
+  if (!rtBox.Contains(fx, fy)) {
+    return FWL_WGTHITTEST_Unknown;
+  }
+  if (!GetLinkURLAtPoint(fx, fy)) {
+    return FWL_WGTHITTEST_Unknown;
+  }
+  return FWL_WGTHITTEST_HyperLink;
+}
+const FX_WCHAR* CXFA_FFText::GetLinkURLAtPoint(FX_FLOAT fx, FX_FLOAT fy) {
+  CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout();
+  if (NULL == pTextLayout) {
+    return NULL;
+  }
+  FX_FLOAT x(fx), y(fy);
+  FWLToClient(x, y);
+  const CXFA_PieceLineArray* pPieceLines = pTextLayout->GetPieceLines();
+  int32_t iCount = pPieceLines->GetSize();
+  for (int32_t i = 0; i < iCount; i++) {
+    CXFA_PieceLine* pPieceLine = pPieceLines->GetAt(i);
+    int32_t iPieces = pPieceLine->m_textPieces.GetSize();
+    for (int32_t j = 0; j < iPieces; j++) {
+      XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(j);
+      if (pPiece->pLinkData && pPiece->rtPiece.Contains(x, y)) {
+        return pPiece->pLinkData->GetLinkURL();
+      }
+    }
+  }
+  return NULL;
+}
+void CXFA_FFText::FWLToClient(FX_FLOAT& fx, FX_FLOAT& fy) {
+  CFX_RectF rtWidget;
+  GetRectWithoutRotate(rtWidget);
+  fx -= rtWidget.left;
+  fy -= rtWidget.top;
+}
diff --git a/xfa/fxfa/app/xfa_fftext.h b/xfa/fxfa/app/xfa_fftext.h
new file mode 100644
index 0000000..edf12f5
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fftext.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_FXFA_APP_XFA_FFTEXT_H_
+#define XFA_FXFA_APP_XFA_FFTEXT_H_
+
+#include "xfa/fxfa/app/xfa_ffdraw.h"
+
+class CXFA_FFText : public CXFA_FFDraw {
+ public:
+  CXFA_FFText(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFText();
+  virtual FX_BOOL OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_DWORD OnHitTest(FX_FLOAT fx, FX_FLOAT fy);
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+  virtual FX_BOOL IsLoaded();
+  virtual FX_BOOL PerformLayout();
+
+ private:
+  virtual const FX_WCHAR* GetLinkURLAtPoint(FX_FLOAT fx, FX_FLOAT fy);
+  void FWLToClient(FX_FLOAT& fx, FX_FLOAT& fy);
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFTEXT_H_
diff --git a/xfa/fxfa/app/xfa_fftextedit.cpp b/xfa/fxfa/app/xfa_fftextedit.cpp
new file mode 100644
index 0000000..c35fe58
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fftextedit.cpp
@@ -0,0 +1,796 @@
+// 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/fxfa/app/xfa_fftextedit.h"
+
+#include <vector>
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_fwladapter.h"
+#include "xfa/fxfa/app/xfa_textlayout.h"
+#include "xfa/fxfa/parser/xfa_localevalue.h"
+#include "xfa/include/fwl/basewidget/fwl_datetimepicker.h"
+#include "xfa/include/fwl/basewidget/fwl_edit.h"
+#include "xfa/include/fwl/lightwidget/datetimepicker.h"
+#include "xfa/include/fwl/lightwidget/edit.h"
+
+CXFA_FFTextEdit::CXFA_FFTextEdit(CXFA_FFPageView* pPageView,
+                                 CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFField(pPageView, pDataAcc), m_pOldDelegate(NULL) {}
+CXFA_FFTextEdit::~CXFA_FFTextEdit() {
+  if (m_pNormalWidget) {
+    IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
+    IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+    pNoteDriver->UnregisterEventTarget(pWidget);
+  }
+}
+FX_BOOL CXFA_FFTextEdit::LoadWidget() {
+  CFWL_Edit* pFWLEdit = CFWL_Edit::Create();
+  pFWLEdit->Initialize();
+  m_pNormalWidget = pFWLEdit;
+  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
+  m_pNormalWidget->SetPrivateData(pWidget, this, NULL);
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  m_pOldDelegate = m_pNormalWidget->SetDelegate(this);
+  m_pNormalWidget->LockUpdate();
+  UpdateWidgetProperty();
+  CFX_WideString wsText;
+  m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Display);
+  pFWLEdit->SetText(wsText);
+  m_pNormalWidget->UnlockUpdate();
+  return CXFA_FFField::LoadWidget();
+}
+void CXFA_FFTextEdit::UpdateWidgetProperty() {
+  CFWL_Edit* pWidget = (CFWL_Edit*)m_pNormalWidget;
+  if (!pWidget) {
+    return;
+  }
+  FX_DWORD dwStyle = 0;
+  FX_DWORD dwExtendedStyle = FWL_STYLEEXT_EDT_ShowScrollbarFocus |
+                             FWL_STYLEEXT_EDT_OuterScrollbar |
+                             FWL_STYLEEXT_EDT_LastLineHeight;
+  dwExtendedStyle |= UpdateUIProperty();
+  if (m_pDataAcc->IsMultiLine()) {
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_MultiLine | FWL_STYLEEXT_EDT_WantReturn;
+    if (m_pDataAcc->GetVerticalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) {
+      dwStyle |= FWL_WGTSTYLE_VScroll;
+      dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoVScroll;
+    }
+  } else if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) {
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoHScroll;
+  }
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open ||
+      !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_ReadOnly;
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_MultiLine;
+  }
+  XFA_ELEMENT eType = XFA_ELEMENT_UNKNOWN;
+  int32_t iMaxChars = m_pDataAcc->GetMaxChars(eType);
+  if (eType == XFA_ELEMENT_ExData) {
+    iMaxChars = 0;
+  }
+  int32_t iNumCells = m_pDataAcc->GetNumberOfCells();
+  if (iNumCells == 0) {
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_CombText;
+    pWidget->SetLimit(iMaxChars > 0 ? iMaxChars : 1);
+  } else if (iNumCells > 0) {
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_CombText;
+    pWidget->SetLimit(iNumCells);
+  } else {
+    pWidget->SetLimit(iMaxChars);
+  }
+  dwExtendedStyle |= GetAlignment();
+  m_pNormalWidget->ModifyStyles(dwStyle, 0xFFFFFFFF);
+  m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
+}
+FX_BOOL CXFA_FFTextEdit::OnLButtonDown(FX_DWORD dwFlags,
+                                       FX_FLOAT fx,
+                                       FX_FLOAT fy) {
+  if (!PtInActiveRect(fx, fy)) {
+    return FALSE;
+  }
+  if (!IsFocused()) {
+    m_dwStatus |= XFA_WIDGETSTATUS_Focused;
+    UpdateFWLData();
+    AddInvalidateRect();
+  }
+  SetButtonDown(TRUE);
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_LButtonDown;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFTextEdit::OnRButtonDown(FX_DWORD dwFlags,
+                                       FX_FLOAT fx,
+                                       FX_FLOAT fy) {
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) {
+    return FALSE;
+  }
+  if (!PtInActiveRect(fx, fy)) {
+    return FALSE;
+  }
+  if (!IsFocused()) {
+    m_dwStatus |= XFA_WIDGETSTATUS_Focused;
+    UpdateFWLData();
+    AddInvalidateRect();
+  }
+  SetButtonDown(TRUE);
+  CFWL_MsgMouse ms;
+  ms.m_dwCmd = FWL_MSGMOUSECMD_RButtonDown;
+  ms.m_dwFlags = dwFlags;
+  ms.m_fx = fx;
+  ms.m_fy = fy;
+  FWLToClient(ms.m_fx, ms.m_fy);
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFTextEdit::OnRButtonUp(FX_DWORD dwFlags,
+                                     FX_FLOAT fx,
+                                     FX_FLOAT fy) {
+  if (!CXFA_FFField::OnRButtonUp(dwFlags, fx, fy))
+    return FALSE;
+
+  GetDoc()->GetDocProvider()->PopupMenu(this, CFX_PointF(fx, fy), nullptr);
+  return TRUE;
+}
+FX_BOOL CXFA_FFTextEdit::OnSetFocus(CXFA_FFWidget* pOldWidget) {
+  m_dwStatus &= ~XFA_WIDGETSTATUS_TextEditValueChanged;
+  if (!IsFocused()) {
+    m_dwStatus |= XFA_WIDGETSTATUS_Focused;
+    UpdateFWLData();
+    AddInvalidateRect();
+  }
+  CXFA_FFWidget::OnSetFocus(pOldWidget);
+  CFWL_MsgSetFocus ms;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  ms.m_pSrcTarget = NULL;
+  TranslateFWLMessage(&ms);
+  return TRUE;
+}
+FX_BOOL CXFA_FFTextEdit::OnKillFocus(CXFA_FFWidget* pNewWidget) {
+  CFWL_MsgKillFocus ms;
+  ms.m_pDstTarget = m_pNormalWidget->m_pIface;
+  ms.m_pSrcTarget = NULL;
+  TranslateFWLMessage(&ms);
+  m_dwStatus &= ~XFA_WIDGETSTATUS_Focused;
+  SetEditScrollOffset();
+  ProcessCommittedData();
+  UpdateFWLData();
+  AddInvalidateRect();
+  CXFA_FFWidget::OnKillFocus(pNewWidget);
+  m_dwStatus &= ~XFA_WIDGETSTATUS_TextEditValueChanged;
+  return TRUE;
+}
+FX_BOOL CXFA_FFTextEdit::CommitData() {
+  CFX_WideString wsText;
+  ((CFWL_Edit*)m_pNormalWidget)->GetText(wsText);
+  if (m_pDataAcc->SetValue(wsText, XFA_VALUEPICTURE_Edit)) {
+    m_pDataAcc->UpdateUIDisplay(this);
+    return TRUE;
+  }
+  ValidateNumberField(wsText);
+  return FALSE;
+}
+void CXFA_FFTextEdit::ValidateNumberField(const CFX_WideString& wsText) {
+  CXFA_WidgetAcc* pAcc = GetDataAcc();
+  if (pAcc && pAcc->GetUIType() == XFA_ELEMENT_NumericEdit) {
+    IXFA_AppProvider* pAppProvider = GetApp()->GetAppProvider();
+    if (pAppProvider) {
+      CFX_WideString wsTitle;
+      pAppProvider->LoadString(XFA_IDS_AppName, wsTitle);
+      CFX_WideString wsMessage;
+      CFX_WideString wsError;
+      pAppProvider->LoadString(XFA_IDS_ValidateNumberError, wsError);
+      CFX_WideString wsSomField;
+      pAcc->GetNode()->GetSOMExpression(wsSomField);
+      wsMessage.Format(wsError, (const FX_WCHAR*)wsText,
+                       (const FX_WCHAR*)wsSomField);
+      pAppProvider->MsgBox(wsMessage, wsTitle, XFA_MBICON_Error, XFA_MB_OK);
+    }
+  }
+}
+FX_BOOL CXFA_FFTextEdit::IsDataChanged() {
+  return (m_dwStatus & XFA_WIDGETSTATUS_TextEditValueChanged) != 0;
+}
+FX_DWORD CXFA_FFTextEdit::GetAlignment() {
+  FX_DWORD dwExtendedStyle = 0;
+  if (CXFA_Para para = m_pDataAcc->GetPara()) {
+    int32_t iHorz = para.GetHorizontalAlign();
+    switch (iHorz) {
+      case XFA_ATTRIBUTEENUM_Center:
+        dwExtendedStyle |= FWL_STYLEEXT_EDT_HCenter;
+        break;
+      case XFA_ATTRIBUTEENUM_Justify:
+        dwExtendedStyle |= FWL_STYLEEXT_EDT_Justified;
+        break;
+      case XFA_ATTRIBUTEENUM_JustifyAll:
+        break;
+      case XFA_ATTRIBUTEENUM_Radix:
+        break;
+      case XFA_ATTRIBUTEENUM_Right:
+        dwExtendedStyle |= FWL_STYLEEXT_EDT_HFar;
+        break;
+      default:
+        dwExtendedStyle |= FWL_STYLEEXT_EDT_HNear;
+        break;
+    }
+    int32_t iVert = para.GetVerticalAlign();
+    switch (iVert) {
+      case XFA_ATTRIBUTEENUM_Middle:
+        dwExtendedStyle |= FWL_STYLEEXT_EDT_VCenter;
+        break;
+      case XFA_ATTRIBUTEENUM_Bottom:
+        dwExtendedStyle |= FWL_STYLEEXT_EDT_VFar;
+        break;
+      default:
+        dwExtendedStyle |= FWL_STYLEEXT_EDT_VNear;
+        break;
+    }
+  }
+  return dwExtendedStyle;
+}
+FX_BOOL CXFA_FFTextEdit::UpdateFWLData() {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  XFA_VALUEPICTURE eType = XFA_VALUEPICTURE_Display;
+  if (IsFocused()) {
+    eType = XFA_VALUEPICTURE_Edit;
+  }
+  FX_BOOL bUpdate = FALSE;
+  if (m_pDataAcc->GetUIType() == XFA_ELEMENT_TextEdit &&
+      m_pDataAcc->GetNumberOfCells() < 0) {
+    XFA_ELEMENT elementType = XFA_ELEMENT_UNKNOWN;
+    int32_t iMaxChars = m_pDataAcc->GetMaxChars(elementType);
+    if (elementType == XFA_ELEMENT_ExData) {
+      iMaxChars = eType == XFA_VALUEPICTURE_Edit ? iMaxChars : 0;
+    }
+    if (((CFWL_Edit*)m_pNormalWidget)->GetLimit() != iMaxChars) {
+      ((CFWL_Edit*)m_pNormalWidget)->SetLimit(iMaxChars);
+      bUpdate = TRUE;
+    }
+  }
+  if (m_pDataAcc->GetUIType() == XFA_ELEMENT_Barcode) {
+    int32_t nDataLen = 0;
+    if (eType == XFA_VALUEPICTURE_Edit)
+      m_pDataAcc->GetBarcodeAttribute_DataLength(nDataLen);
+    static_cast<CFWL_Edit*>(m_pNormalWidget)->SetLimit(nDataLen);
+    bUpdate = TRUE;
+  }
+  CFX_WideString wsText;
+  m_pDataAcc->GetValue(wsText, eType);
+  CFX_WideString wsOldText;
+  ((CFWL_Edit*)m_pNormalWidget)->GetText(wsOldText);
+  if (wsText != wsOldText || (eType == XFA_VALUEPICTURE_Edit && bUpdate)) {
+    ((CFWL_Edit*)m_pNormalWidget)->SetText(wsText);
+    bUpdate = TRUE;
+  }
+  if (bUpdate) {
+    m_pNormalWidget->Update();
+  }
+  return TRUE;
+}
+FX_BOOL CXFA_FFTextEdit::CanUndo() {
+  return ((CFWL_Edit*)m_pNormalWidget)->CanUndo();
+}
+FX_BOOL CXFA_FFTextEdit::CanRedo() {
+  return ((CFWL_Edit*)m_pNormalWidget)->CanRedo();
+}
+FX_BOOL CXFA_FFTextEdit::Undo() {
+  return ((CFWL_Edit*)m_pNormalWidget)->Undo();
+}
+FX_BOOL CXFA_FFTextEdit::Redo() {
+  return ((CFWL_Edit*)m_pNormalWidget)->Redo();
+}
+FX_BOOL CXFA_FFTextEdit::CanCopy() {
+  int32_t nCount = ((CFWL_Edit*)m_pNormalWidget)->CountSelRanges();
+  return nCount > 0;
+}
+FX_BOOL CXFA_FFTextEdit::CanCut() {
+  if (m_pNormalWidget->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) {
+    return FALSE;
+  }
+  int32_t nCount = ((CFWL_Edit*)m_pNormalWidget)->CountSelRanges();
+  return nCount > 0;
+}
+FX_BOOL CXFA_FFTextEdit::CanPaste() {
+  return m_pDataAcc->GetAccess() == XFA_ATTRIBUTEENUM_Open;
+}
+FX_BOOL CXFA_FFTextEdit::CanSelectAll() {
+  return ((CFWL_Edit*)m_pNormalWidget)->GetTextLength() > 0;
+}
+FX_BOOL CXFA_FFTextEdit::Copy(CFX_WideString& wsCopy) {
+  return ((CFWL_Edit*)m_pNormalWidget)->Copy(wsCopy);
+}
+FX_BOOL CXFA_FFTextEdit::Cut(CFX_WideString& wsCut) {
+  return ((CFWL_Edit*)m_pNormalWidget)->Cut(wsCut);
+}
+FX_BOOL CXFA_FFTextEdit::Paste(const CFX_WideString& wsPaste) {
+  return ((CFWL_Edit*)m_pNormalWidget)->Paste(wsPaste);
+}
+FX_BOOL CXFA_FFTextEdit::SelectAll() {
+  int32_t nCount = ((CFWL_Edit*)m_pNormalWidget)->GetTextLength();
+  return ((CFWL_Edit*)m_pNormalWidget)->AddSelRange(0, nCount);
+}
+FX_BOOL CXFA_FFTextEdit::Delete() {
+  return ((CFWL_Edit*)m_pNormalWidget)->Delete();
+}
+FX_BOOL CXFA_FFTextEdit::DeSelect() {
+  return ((CFWL_Edit*)m_pNormalWidget)->ClearSelections();
+}
+FX_BOOL CXFA_FFTextEdit::GetSuggestWords(
+    CFX_PointF pointf,
+    std::vector<CFX_ByteString>& sSuggest) {
+  if (m_pDataAcc->GetUIType() != XFA_ELEMENT_TextEdit) {
+    return FALSE;
+  }
+  FWLToClient(pointf.x, pointf.y);
+  return ((CFWL_Edit*)m_pNormalWidget)->GetSuggestWords(pointf, sSuggest);
+}
+FX_BOOL CXFA_FFTextEdit::ReplaceSpellCheckWord(
+    CFX_PointF pointf,
+    const CFX_ByteStringC& bsReplace) {
+  if (m_pDataAcc->GetUIType() != XFA_ELEMENT_TextEdit) {
+    return FALSE;
+  }
+  FWLToClient(pointf.x, pointf.y);
+  return ((CFWL_Edit*)m_pNormalWidget)
+      ->ReplaceSpellCheckWord(pointf, bsReplace);
+}
+void CXFA_FFTextEdit::OnTextChanged(IFWL_Widget* pWidget,
+                                    const CFX_WideString& wsChanged,
+                                    const CFX_WideString& wsPrevText) {
+  m_dwStatus |= XFA_WIDGETSTATUS_TextEditValueChanged;
+  CXFA_EventParam eParam;
+  eParam.m_eType = XFA_EVENT_Change;
+  eParam.m_wsChange = wsChanged;
+  eParam.m_pTarget = m_pDataAcc;
+  eParam.m_wsPrevText = wsPrevText;
+  CFWL_Edit* pEdit = ((CFWL_Edit*)m_pNormalWidget);
+  if (m_pDataAcc->GetUIType() == XFA_ELEMENT_DateTimeEdit) {
+    CFWL_DateTimePicker* pDateTime = (CFWL_DateTimePicker*)pEdit;
+    pDateTime->GetEditText(eParam.m_wsNewText);
+    int32_t iSels = pDateTime->CountSelRanges();
+    if (iSels) {
+      eParam.m_iSelEnd = pDateTime->GetSelRange(0, eParam.m_iSelStart);
+    }
+  } else {
+    pEdit->GetText(eParam.m_wsNewText);
+    int32_t iSels = pEdit->CountSelRanges();
+    if (iSels) {
+      eParam.m_iSelEnd = pEdit->GetSelRange(0, eParam.m_iSelStart);
+    }
+  }
+  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
+}
+void CXFA_FFTextEdit::OnTextFull(IFWL_Widget* pWidget) {
+  CXFA_EventParam eParam;
+  eParam.m_eType = XFA_EVENT_Full;
+  eParam.m_pTarget = m_pDataAcc;
+  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Full, &eParam);
+}
+
+FX_BOOL CXFA_FFTextEdit::CheckWord(const CFX_ByteStringC& sWord) {
+  if (sWord.IsEmpty() || m_pDataAcc->GetUIType() != XFA_ELEMENT_TextEdit) {
+    return TRUE;
+  }
+  return GetDoc()->GetDocProvider()->CheckWord(GetDoc(), sWord);
+}
+FX_BOOL CXFA_FFTextEdit::GetSuggestWords(
+    const CFX_ByteStringC& sWord,
+    std::vector<CFX_ByteString>& sSuggest) {
+  if (m_pDataAcc->GetUIType() != XFA_ELEMENT_TextEdit) {
+    return FALSE;
+  }
+  return GetDoc()->GetDocProvider()->GetSuggestWords(GetDoc(), sWord, sSuggest);
+}
+int32_t CXFA_FFTextEdit::OnProcessMessage(CFWL_Message* pMessage) {
+  return m_pOldDelegate->OnProcessMessage(pMessage);
+}
+FWL_ERR CXFA_FFTextEdit::OnProcessEvent(CFWL_Event* pEvent) {
+  CXFA_FFField::OnProcessEvent(pEvent);
+  FX_DWORD dwEventID = pEvent->GetClassID();
+  switch (dwEventID) {
+    case FWL_EVTHASH_EDT_TextChanged: {
+      CFWL_EvtEdtTextChanged* event = (CFWL_EvtEdtTextChanged*)pEvent;
+      CFX_WideString wsChange;
+      OnTextChanged(m_pNormalWidget->GetWidget(), wsChange, event->wsPrevText);
+      break;
+    }
+    case FWL_EVTHASH_EDT_TextFull: {
+      OnTextFull(m_pNormalWidget->GetWidget());
+      break;
+    }
+    case FWL_EVTHASH_EDT_CheckWord: {
+      CFX_WideString wstr(L"FWL_EVENT_DTP_SelectChanged");
+      CFWL_EvtEdtCheckWord* event = (CFWL_EvtEdtCheckWord*)pEvent;
+      event->bCheckWord = CheckWord(event->bsWord);
+      break;
+    }
+    case FWL_EVTHASH_EDT_GetSuggestWords: {
+      CFWL_EvtEdtGetSuggestWords* event = (CFWL_EvtEdtGetSuggestWords*)pEvent;
+      event->bSuggestWords =
+          GetSuggestWords(event->bsWord, event->bsArraySuggestWords);
+      break;
+    }
+    default: {}
+  }
+  return m_pOldDelegate->OnProcessEvent(pEvent);
+}
+FWL_ERR CXFA_FFTextEdit::OnDrawWidget(CFX_Graphics* pGraphics,
+                                      const CFX_Matrix* pMatrix) {
+  return m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
+}
+CXFA_FFNumericEdit::CXFA_FFNumericEdit(CXFA_FFPageView* pPageView,
+                                       CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFTextEdit(pPageView, pDataAcc) {}
+CXFA_FFNumericEdit::~CXFA_FFNumericEdit() {}
+FX_BOOL CXFA_FFNumericEdit::LoadWidget() {
+  CFWL_Edit* pWidget = CFWL_Edit::Create();
+  pWidget->Initialize();
+  m_pNormalWidget = (CFWL_Widget*)pWidget;
+  IFWL_Widget* pIWidget = m_pNormalWidget->GetWidget();
+  m_pNormalWidget->SetPrivateData(pIWidget, this, NULL);
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(pIWidget, pIWidget);
+  m_pOldDelegate = m_pNormalWidget->SetDelegate(this);
+  m_pNormalWidget->LockUpdate();
+  CFX_WideString wsText;
+  m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Display);
+  pWidget->SetText(wsText);
+  UpdateWidgetProperty();
+  m_pNormalWidget->UnlockUpdate();
+  return CXFA_FFField::LoadWidget();
+}
+void CXFA_FFNumericEdit::UpdateWidgetProperty() {
+  CFWL_Edit* pWidget = (CFWL_Edit*)m_pNormalWidget;
+  if (!pWidget) {
+    return;
+  }
+  FX_DWORD dwExtendedStyle =
+      FWL_STYLEEXT_EDT_ShowScrollbarFocus | FWL_STYLEEXT_EDT_OuterScrollbar |
+      FWL_STYLEEXT_EDT_Validate | FWL_STYLEEXT_EDT_Number |
+      FWL_STYLEEXT_EDT_LastLineHeight;
+  dwExtendedStyle |= UpdateUIProperty();
+  if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) {
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoHScroll;
+  }
+  int32_t iNumCells = m_pDataAcc->GetNumberOfCells();
+  if (iNumCells > 0) {
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_CombText;
+    pWidget->SetLimit(iNumCells);
+  }
+  dwExtendedStyle |= GetAlignment();
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open ||
+      !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_ReadOnly;
+  }
+  m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
+}
+FWL_ERR CXFA_FFNumericEdit::OnProcessEvent(CFWL_Event* pEvent) {
+  FX_DWORD dwEventID = pEvent->GetClassID();
+  if (dwEventID == FWL_EVTHASH_EDT_Validate) {
+    CFWL_EvtEdtValidate* event = (CFWL_EvtEdtValidate*)pEvent;
+    CFX_WideString wsChange = event->wsInsert;
+    event->bValidate = OnValidate(m_pNormalWidget->GetWidget(), wsChange);
+    return event->bValidate;
+  } else {
+    return CXFA_FFTextEdit::OnProcessEvent(pEvent);
+  }
+}
+FX_BOOL CXFA_FFNumericEdit::OnValidate(IFWL_Widget* pWidget,
+                                       CFX_WideString& wsText) {
+  CFX_WideString wsPattern;
+  m_pDataAcc->GetPictureContent(wsPattern, XFA_VALUEPICTURE_Edit);
+  if (!wsPattern.IsEmpty()) {
+    return TRUE;
+  }
+  int32_t iLeads = 0;
+  m_pDataAcc->GetLeadDigits(iLeads);
+  int32_t iFracs = 0;
+  m_pDataAcc->GetFracDigits(iFracs);
+  CFX_WideString wsFormat;
+  CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(m_pDataAcc);
+  widgetValue.GetNumbericFormat(wsFormat, iLeads, iFracs);
+  return widgetValue.ValidateNumericTemp(wsText, wsFormat,
+                                         m_pDataAcc->GetLocal());
+}
+CXFA_FFPasswordEdit::CXFA_FFPasswordEdit(CXFA_FFPageView* pPageView,
+                                         CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFTextEdit(pPageView, pDataAcc) {}
+CXFA_FFPasswordEdit::~CXFA_FFPasswordEdit() {}
+FX_BOOL CXFA_FFPasswordEdit::LoadWidget() {
+  CFWL_Edit* pWidget = CFWL_Edit::Create();
+  pWidget->Initialize();
+  m_pNormalWidget = (CFWL_Widget*)pWidget;
+  IFWL_Widget* pIWidget = m_pNormalWidget->GetWidget();
+  m_pNormalWidget->SetPrivateData(pIWidget, this, NULL);
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(pIWidget, pIWidget);
+  m_pOldDelegate = m_pNormalWidget->SetDelegate(this);
+  m_pNormalWidget->LockUpdate();
+  CFX_WideString wsText;
+  m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Display);
+  pWidget->SetText(wsText);
+  UpdateWidgetProperty();
+  m_pNormalWidget->UnlockUpdate();
+  return CXFA_FFField::LoadWidget();
+}
+void CXFA_FFPasswordEdit::UpdateWidgetProperty() {
+  CFWL_Edit* pWidget = (CFWL_Edit*)m_pNormalWidget;
+  if (!pWidget) {
+    return;
+  }
+  FX_DWORD dwExtendedStyle =
+      FWL_STYLEEXT_EDT_ShowScrollbarFocus | FWL_STYLEEXT_EDT_OuterScrollbar |
+      FWL_STYLEEXT_EDT_Password | FWL_STYLEEXT_EDT_LastLineHeight;
+  dwExtendedStyle |= UpdateUIProperty();
+  CFX_WideString wsPassWord;
+  m_pDataAcc->GetPasswordChar(wsPassWord);
+  if (!wsPassWord.IsEmpty()) {
+    pWidget->SetAliasChar(wsPassWord.GetAt(0));
+  }
+  if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) {
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_AutoHScroll;
+  }
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open ||
+      !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    dwExtendedStyle |= FWL_STYLEEXT_EDT_ReadOnly;
+  }
+  dwExtendedStyle |= GetAlignment();
+  m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
+}
+CXFA_FFDateTimeEdit::CXFA_FFDateTimeEdit(CXFA_FFPageView* pPageView,
+                                         CXFA_WidgetAcc* pDataAcc)
+    : CXFA_FFTextEdit(pPageView, pDataAcc) {}
+
+CXFA_FFDateTimeEdit::~CXFA_FFDateTimeEdit() {}
+
+FX_BOOL CXFA_FFDateTimeEdit::GetBBox(CFX_RectF& rtBox,
+                                     FX_DWORD dwStatus,
+                                     FX_BOOL bDrawFocus) {
+  if (bDrawFocus)
+    return FALSE;
+  return CXFA_FFWidget::GetBBox(rtBox, dwStatus);
+}
+
+FX_BOOL CXFA_FFDateTimeEdit::PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy) {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  CFX_RectF rtWidget;
+  ((CFWL_DateTimePicker*)m_pNormalWidget)->GetBBox(rtWidget);
+  if (rtWidget.Contains(fx, fy)) {
+    return TRUE;
+  }
+  return FALSE;
+}
+FX_BOOL CXFA_FFDateTimeEdit::LoadWidget() {
+  CFWL_DateTimePicker* pWidget = CFWL_DateTimePicker::Create();
+  pWidget->Initialize();
+  m_pNormalWidget = (CFWL_Widget*)pWidget;
+  IFWL_Widget* pIWidget = m_pNormalWidget->GetWidget();
+  m_pNormalWidget->SetPrivateData(pIWidget, this, NULL);
+  IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(pIWidget, pIWidget);
+  m_pOldDelegate = m_pNormalWidget->SetDelegate(this);
+  m_pNormalWidget->LockUpdate();
+  CFX_WideString wsText;
+  m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Display);
+  pWidget->SetEditText(wsText);
+  if (CXFA_Value value = m_pDataAcc->GetFormValue()) {
+    switch (value.GetChildValueClassID()) {
+      case XFA_ELEMENT_Date: {
+        if (!wsText.IsEmpty()) {
+          CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pDataAcc);
+          CFX_Unitime date = lcValue.GetDate();
+          if ((FX_UNITIME)date != 0) {
+            pWidget->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay());
+          }
+        }
+      } break;
+      default:
+        break;
+    }
+  }
+  UpdateWidgetProperty();
+  m_pNormalWidget->UnlockUpdate();
+  return CXFA_FFField::LoadWidget();
+}
+void CXFA_FFDateTimeEdit::UpdateWidgetProperty() {
+  CFWL_DateTimePicker* pWidget = (CFWL_DateTimePicker*)m_pNormalWidget;
+  if (!pWidget) {
+    return;
+  }
+  FX_DWORD dwExtendedStyle = FWL_STYLEEXT_DTP_ShortDateFormat;
+  dwExtendedStyle |= UpdateUIProperty();
+  dwExtendedStyle |= GetAlignment();
+  m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
+  FX_DWORD dwEditStyles = FWL_STYLEEXT_EDT_LastLineHeight;
+  int32_t iNumCells = m_pDataAcc->GetNumberOfCells();
+  if (iNumCells > 0) {
+    dwEditStyles |= FWL_STYLEEXT_EDT_CombText;
+    pWidget->SetEditLimit(iNumCells);
+  }
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open ||
+      !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
+    dwEditStyles |= FWL_STYLEEXT_EDT_ReadOnly;
+  }
+  if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) {
+    dwEditStyles |= FWL_STYLEEXT_EDT_AutoHScroll;
+  }
+  pWidget->ModifyEditStylesEx(dwEditStyles, 0xFFFFFFFF);
+}
+FX_DWORD CXFA_FFDateTimeEdit::GetAlignment() {
+  FX_DWORD dwExtendedStyle = 0;
+  if (CXFA_Para para = m_pDataAcc->GetPara()) {
+    int32_t iHorz = para.GetHorizontalAlign();
+    switch (iHorz) {
+      case XFA_ATTRIBUTEENUM_Center:
+        dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHCenter;
+        break;
+      case XFA_ATTRIBUTEENUM_Justify:
+        dwExtendedStyle |= FWL_STYLEEXT_DTP_EditJustified;
+        break;
+      case XFA_ATTRIBUTEENUM_JustifyAll:
+        break;
+      case XFA_ATTRIBUTEENUM_Radix:
+        break;
+      case XFA_ATTRIBUTEENUM_Right:
+        dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHFar;
+        break;
+      default:
+        dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHNear;
+        break;
+    }
+    int32_t iVert = para.GetVerticalAlign();
+    switch (iVert) {
+      case XFA_ATTRIBUTEENUM_Middle:
+        dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVCenter;
+        break;
+      case XFA_ATTRIBUTEENUM_Bottom:
+        dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVFar;
+        break;
+      default:
+        dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVNear;
+        break;
+    }
+  }
+  return dwExtendedStyle;
+}
+FX_BOOL CXFA_FFDateTimeEdit::CommitData() {
+  CFX_WideString wsText;
+  ((CFWL_DateTimePicker*)m_pNormalWidget)->GetEditText(wsText);
+  if (m_pDataAcc->SetValue(wsText, XFA_VALUEPICTURE_Edit)) {
+    m_pDataAcc->UpdateUIDisplay(this);
+    return TRUE;
+  }
+  return FALSE;
+}
+FX_BOOL CXFA_FFDateTimeEdit::UpdateFWLData() {
+  if (!m_pNormalWidget) {
+    return FALSE;
+  }
+  XFA_VALUEPICTURE eType = XFA_VALUEPICTURE_Display;
+  if (IsFocused()) {
+    eType = XFA_VALUEPICTURE_Edit;
+  }
+  CFX_WideString wsText;
+  m_pDataAcc->GetValue(wsText, eType);
+  ((CFWL_DateTimePicker*)m_pNormalWidget)->SetEditText(wsText);
+  if (IsFocused() && !wsText.IsEmpty()) {
+    CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pDataAcc);
+    CFX_Unitime date = lcValue.GetDate();
+    if (lcValue.IsValid()) {
+      if ((FX_UNITIME)date != 0) {
+        ((CFWL_DateTimePicker*)m_pNormalWidget)
+            ->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay());
+      }
+    }
+  }
+  m_pNormalWidget->Update();
+  return TRUE;
+}
+FX_BOOL CXFA_FFDateTimeEdit::IsDataChanged() {
+  if (m_dwStatus & XFA_WIDGETSTATUS_TextEditValueChanged) {
+    return TRUE;
+  }
+  CFX_WideString wsText;
+  ((CFWL_DateTimePicker*)m_pNormalWidget)->GetEditText(wsText);
+  CFX_WideString wsOldValue;
+  m_pDataAcc->GetValue(wsOldValue, XFA_VALUEPICTURE_Edit);
+  return wsOldValue != wsText;
+}
+FX_BOOL CXFA_FFDateTimeEdit::CanUndo() {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->CanUndo();
+}
+FX_BOOL CXFA_FFDateTimeEdit::CanRedo() {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->CanRedo();
+}
+FX_BOOL CXFA_FFDateTimeEdit::Undo() {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->Undo();
+}
+FX_BOOL CXFA_FFDateTimeEdit::Redo() {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->Redo();
+}
+FX_BOOL CXFA_FFDateTimeEdit::CanCopy() {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->CanCopy();
+}
+FX_BOOL CXFA_FFDateTimeEdit::CanCut() {
+  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) {
+    return FALSE;
+  }
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->CanCut();
+}
+FX_BOOL CXFA_FFDateTimeEdit::CanPaste() {
+  return m_pDataAcc->GetAccess() == XFA_ATTRIBUTEENUM_Open;
+}
+FX_BOOL CXFA_FFDateTimeEdit::CanSelectAll() {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->CanSelectAll();
+}
+FX_BOOL CXFA_FFDateTimeEdit::Copy(CFX_WideString& wsCopy) {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->Copy(wsCopy);
+}
+FX_BOOL CXFA_FFDateTimeEdit::Cut(CFX_WideString& wsCut) {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->Cut(wsCut);
+}
+FX_BOOL CXFA_FFDateTimeEdit::Paste(const CFX_WideString& wsPaste) {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->Paste(wsPaste);
+}
+FX_BOOL CXFA_FFDateTimeEdit::SelectAll() {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->SelectAll();
+}
+FX_BOOL CXFA_FFDateTimeEdit::Delete() {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->Delete();
+}
+FX_BOOL CXFA_FFDateTimeEdit::DeSelect() {
+  return ((CFWL_DateTimePicker*)m_pNormalWidget)->DeSelect();
+}
+void CXFA_FFDateTimeEdit::OnSelectChanged(IFWL_Widget* pWidget,
+                                          int32_t iYear,
+                                          int32_t iMonth,
+                                          int32_t iDay) {
+  CFX_WideString wsPicture;
+  m_pDataAcc->GetPictureContent(wsPicture, XFA_VALUEPICTURE_Edit);
+  CXFA_LocaleValue date(XFA_VT_DATE, GetDoc()->GetXFADoc()->GetLocalMgr());
+  CFX_Unitime dt;
+  dt.Set(iYear, iMonth, iDay);
+  date.SetDate(dt);
+  CFX_WideString wsDate;
+  date.FormatPatterns(wsDate, wsPicture, m_pDataAcc->GetLocal(),
+                      XFA_VALUEPICTURE_Edit);
+  CFWL_DateTimePicker* pDateTime = (CFWL_DateTimePicker*)m_pNormalWidget;
+  pDateTime->SetEditText(wsDate);
+  pDateTime->Update();
+  GetDoc()->GetDocProvider()->SetFocusWidget(GetDoc(), NULL);
+  CXFA_EventParam eParam;
+  eParam.m_eType = XFA_EVENT_Change;
+  eParam.m_pTarget = m_pDataAcc;
+  m_pDataAcc->GetValue(eParam.m_wsNewText, XFA_VALUEPICTURE_Raw);
+  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
+}
+FWL_ERR CXFA_FFDateTimeEdit::OnProcessEvent(CFWL_Event* pEvent) {
+  FX_DWORD dwEventID = pEvent->GetClassID();
+  if (dwEventID == FWL_EVTHASH_DTP_SelectChanged) {
+    CFWL_Event_DtpSelectChanged* event = (CFWL_Event_DtpSelectChanged*)pEvent;
+    OnSelectChanged(m_pNormalWidget->GetWidget(), event->iYear, event->iMonth,
+                    event->iDay);
+    return TRUE;
+  } else {
+    return CXFA_FFTextEdit::OnProcessEvent(pEvent);
+  }
+}
diff --git a/xfa/fxfa/app/xfa_fftextedit.h b/xfa/fxfa/app/xfa_fftextedit.h
new file mode 100644
index 0000000..d379ab1
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fftextedit.h
@@ -0,0 +1,138 @@
+// 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_FXFA_APP_XFA_FFTEXTEDIT_H_
+#define XFA_FXFA_APP_XFA_FFTEXTEDIT_H_
+
+#include <vector>
+
+#include "xfa/fxfa/app/xfa_fffield.h"
+
+class CXFA_FFTextEdit : public CXFA_FFField {
+ public:
+  CXFA_FFTextEdit(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  ~CXFA_FFTextEdit() override;
+
+  // CXFA_FFField:
+  FX_BOOL LoadWidget() override;
+  void UpdateWidgetProperty() override;
+  FX_BOOL OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) override;
+  FX_BOOL OnRButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) override;
+  FX_BOOL OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) override;
+  FX_BOOL OnSetFocus(CXFA_FFWidget* pOldWidget) override;
+  FX_BOOL OnKillFocus(CXFA_FFWidget* pNewWidget) override;
+  FX_BOOL CanUndo() override;
+  FX_BOOL CanRedo() override;
+  FX_BOOL Undo() override;
+  FX_BOOL Redo() override;
+  FX_BOOL CanCopy() override;
+  FX_BOOL CanCut() override;
+  FX_BOOL CanPaste() override;
+  FX_BOOL CanSelectAll() override;
+  FX_BOOL Copy(CFX_WideString& wsCopy) override;
+  FX_BOOL Cut(CFX_WideString& wsCut) override;
+  FX_BOOL Paste(const CFX_WideString& wsPaste) override;
+  FX_BOOL SelectAll() override;
+  FX_BOOL Delete() override;
+  FX_BOOL DeSelect() override;
+  FX_BOOL GetSuggestWords(CFX_PointF pointf,
+                          std::vector<CFX_ByteString>& sSuggest) override;
+  FX_BOOL ReplaceSpellCheckWord(CFX_PointF pointf,
+                                const CFX_ByteStringC& bsReplace) override;
+
+  // IFWL_WidgetDelegate:
+  int32_t OnProcessMessage(CFWL_Message* pMessage) override;
+  FWL_ERR OnProcessEvent(CFWL_Event* pEvent) override;
+  FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics,
+                       const CFX_Matrix* pMatrix = NULL) override;
+
+  void OnTextChanged(IFWL_Widget* pWidget,
+                     const CFX_WideString& wsChanged,
+                     const CFX_WideString& wsPrevText);
+  void OnTextFull(IFWL_Widget* pWidget);
+  FX_BOOL CheckWord(const CFX_ByteStringC& sWord);
+  FX_BOOL GetSuggestWords(const CFX_ByteStringC& sWord,
+                          std::vector<CFX_ByteString>& sSuggest);
+
+ protected:
+  FX_DWORD GetAlignment();
+  FX_BOOL CommitData() override;
+  FX_BOOL UpdateFWLData() override;
+  FX_BOOL IsDataChanged() override;
+  void ValidateNumberField(const CFX_WideString& wsText);
+
+  IFWL_WidgetDelegate* m_pOldDelegate;
+};
+
+class CXFA_FFNumericEdit : public CXFA_FFTextEdit {
+ public:
+  CXFA_FFNumericEdit(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFNumericEdit();
+  virtual FX_BOOL LoadWidget();
+  virtual void UpdateWidgetProperty();
+  virtual FWL_ERR OnProcessEvent(CFWL_Event* pEvent);
+
+ public:
+  FX_BOOL OnValidate(IFWL_Widget* pWidget, CFX_WideString& wsText);
+};
+class CXFA_FFPasswordEdit : public CXFA_FFTextEdit {
+ public:
+  CXFA_FFPasswordEdit(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFPasswordEdit();
+  virtual FX_BOOL LoadWidget();
+  virtual void UpdateWidgetProperty();
+
+ protected:
+};
+enum XFA_DATETIMETYPE {
+  XFA_DATETIMETYPE_Date = 0,
+  XFA_DATETIMETYPE_Time,
+  XFA_DATETIMETYPE_DateAndTime
+};
+class CXFA_FFDateTimeEdit : public CXFA_FFTextEdit {
+ public:
+  CXFA_FFDateTimeEdit(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFDateTimeEdit();
+
+  virtual FX_BOOL GetBBox(CFX_RectF& rtBox,
+                          FX_DWORD dwStatus,
+                          FX_BOOL bDrawFocus = FALSE);
+  virtual FX_BOOL LoadWidget();
+  virtual void UpdateWidgetProperty();
+
+  virtual FX_BOOL CanUndo();
+  virtual FX_BOOL CanRedo();
+  virtual FX_BOOL Undo();
+  virtual FX_BOOL Redo();
+
+  virtual FX_BOOL CanCopy();
+  virtual FX_BOOL CanCut();
+  virtual FX_BOOL CanPaste();
+  virtual FX_BOOL CanSelectAll();
+  virtual FX_BOOL Copy(CFX_WideString& wsCopy);
+  virtual FX_BOOL Cut(CFX_WideString& wsCut);
+  virtual FX_BOOL Paste(const CFX_WideString& wsPaste);
+  virtual FX_BOOL SelectAll();
+  virtual FX_BOOL Delete();
+  virtual FX_BOOL DeSelect();
+
+ protected:
+  FX_DWORD GetAlignment();
+
+  virtual FX_BOOL PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL CommitData();
+  virtual FX_BOOL UpdateFWLData();
+  virtual FX_BOOL IsDataChanged();
+
+ public:
+  void OnSelectChanged(IFWL_Widget* pWidget,
+                       int32_t iYear,
+                       int32_t iMonth,
+                       int32_t iDay);
+  virtual FWL_ERR OnProcessEvent(CFWL_Event* pEvent);
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFTEXTEDIT_H_
diff --git a/xfa/fxfa/app/xfa_ffwidget.cpp b/xfa/fxfa/app/xfa_ffwidget.cpp
new file mode 100644
index 0000000..3153946
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffwidget.cpp
@@ -0,0 +1,1961 @@
+// 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/fxfa/app/xfa_ffwidget.h"
+
+#include <algorithm>
+
+#include "core/include/fpdfapi/fpdf_page.h"
+#include "core/include/fxcodec/fx_codec.h"
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_textlayout.h"
+#include "xfa/include/fxgraphics/fx_graphics.h"
+
+CXFA_FFWidget::CXFA_FFWidget(CXFA_FFPageView* pPageView,
+                             CXFA_WidgetAcc* pDataAcc)
+    : CXFA_ContentLayoutItem(pDataAcc->GetNode()),
+      m_pPageView(pPageView),
+      m_pDataAcc(pDataAcc) {
+  m_rtWidget.Set(0, 0, 0, 0);
+}
+CXFA_FFWidget::~CXFA_FFWidget() {}
+IXFA_PageView* CXFA_FFWidget::GetPageView() {
+  return m_pPageView;
+}
+void CXFA_FFWidget::SetPageView(IXFA_PageView* pPageView) {
+  m_pPageView = static_cast<CXFA_FFPageView*>(pPageView);
+}
+void CXFA_FFWidget::GetWidgetRect(CFX_RectF& rtWidget) {
+  if ((m_dwStatus & XFA_WIDGETSTATUS_RectCached) == 0) {
+    m_dwStatus |= XFA_WIDGETSTATUS_RectCached;
+    GetRect(m_rtWidget);
+  }
+  rtWidget = m_rtWidget;
+}
+CFX_RectF CXFA_FFWidget::ReCacheWidgetRect() {
+  m_dwStatus |= XFA_WIDGETSTATUS_RectCached;
+  GetRect(m_rtWidget);
+  return m_rtWidget;
+}
+void CXFA_FFWidget::GetRectWithoutRotate(CFX_RectF& rtWidget) {
+  GetWidgetRect(rtWidget);
+  FX_FLOAT fValue = 0;
+  switch (m_pDataAcc->GetRotate()) {
+    case 90:
+      rtWidget.top = rtWidget.bottom();
+      fValue = rtWidget.width;
+      rtWidget.width = rtWidget.height;
+      rtWidget.height = fValue;
+      break;
+    case 180:
+      rtWidget.left = rtWidget.right();
+      rtWidget.top = rtWidget.bottom();
+      break;
+    case 270:
+      rtWidget.left = rtWidget.right();
+      fValue = rtWidget.width;
+      rtWidget.width = rtWidget.height;
+      rtWidget.height = fValue;
+      break;
+  }
+}
+FX_DWORD CXFA_FFWidget::GetStatus() {
+  return m_dwStatus;
+}
+
+void CXFA_FFWidget::ModifyStatus(FX_DWORD dwAdded, FX_DWORD dwRemoved) {
+  m_dwStatus = (m_dwStatus & ~dwRemoved) | dwAdded;
+}
+
+FX_BOOL CXFA_FFWidget::GetBBox(CFX_RectF& rtBox,
+                               FX_DWORD dwStatus,
+                               FX_BOOL bDrawFocus) {
+  if (bDrawFocus)
+    return FALSE;
+  if (m_pPageView)
+    m_pPageView->GetPageViewRect(rtBox);
+  return TRUE;
+}
+
+CXFA_WidgetAcc* CXFA_FFWidget::GetDataAcc() {
+  return m_pDataAcc;
+}
+FX_BOOL CXFA_FFWidget::GetToolTip(CFX_WideString& wsToolTip) {
+  if (CXFA_Assist assist = m_pDataAcc->GetAssist()) {
+    if (CXFA_ToolTip toolTip = assist.GetToolTip()) {
+      return toolTip.GetTip(wsToolTip);
+    }
+  }
+  return GetCaptionText(wsToolTip);
+}
+void CXFA_FFWidget::RenderWidget(CFX_Graphics* pGS,
+                                 CFX_Matrix* pMatrix,
+                                 FX_DWORD dwStatus,
+                                 int32_t iRotate) {
+  if (!IsMatchVisibleStatus(dwStatus)) {
+    return;
+  }
+  CXFA_Border border = m_pDataAcc->GetBorder();
+  if (border) {
+    CFX_RectF rtBorder;
+    GetRectWithoutRotate(rtBorder);
+    CXFA_Margin margin = border.GetMargin();
+    if (margin) {
+      XFA_RectWidthoutMargin(rtBorder, margin);
+    }
+    rtBorder.Normalize();
+    DrawBorder(pGS, border, rtBorder, pMatrix);
+  }
+}
+FX_BOOL CXFA_FFWidget::IsLoaded() {
+  return m_pPageView != NULL;
+}
+FX_BOOL CXFA_FFWidget::LoadWidget() {
+  PerformLayout();
+  return TRUE;
+}
+void CXFA_FFWidget::UnloadWidget() {}
+FX_BOOL CXFA_FFWidget::PerformLayout() {
+  ReCacheWidgetRect();
+  return TRUE;
+}
+FX_BOOL CXFA_FFWidget::UpdateFWLData() {
+  return FALSE;
+}
+void CXFA_FFWidget::UpdateWidgetProperty() {}
+void CXFA_FFWidget::DrawBorder(CFX_Graphics* pGS,
+                               CXFA_Box box,
+                               const CFX_RectF& rtBorder,
+                               CFX_Matrix* pMatrix,
+                               FX_DWORD dwFlags) {
+  XFA_DrawBox(box, pGS, rtBorder, pMatrix, dwFlags);
+}
+void CXFA_FFWidget::InvalidateWidget(const CFX_RectF* pRect) {
+  if (!pRect) {
+    CFX_RectF rtWidget;
+    GetBBox(rtWidget, XFA_WIDGETSTATUS_Focused);
+    rtWidget.Inflate(2, 2);
+    GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, rtWidget,
+                                               XFA_INVALIDATE_CurrentPage);
+  } else {
+    GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, *pRect,
+                                               XFA_INVALIDATE_CurrentPage);
+  }
+}
+void CXFA_FFWidget::AddInvalidateRect(const CFX_RectF* pRect) {
+  CFX_RectF rtWidget;
+  if (pRect) {
+    rtWidget = *pRect;
+  } else {
+    GetBBox(rtWidget, XFA_WIDGETSTATUS_Focused);
+    rtWidget.Inflate(2, 2);
+  }
+  m_pDocView->AddInvalidateRect(m_pPageView, rtWidget);
+}
+FX_BOOL CXFA_FFWidget::GetCaptionText(CFX_WideString& wsCap) {
+  CXFA_TextLayout* pCapTextlayout = m_pDataAcc->GetCaptionTextLayout();
+  if (!pCapTextlayout) {
+    return FALSE;
+  }
+  pCapTextlayout->GetText(wsCap);
+  return TRUE;
+}
+FX_BOOL CXFA_FFWidget::IsFocused() {
+  return m_dwStatus & XFA_WIDGETSTATUS_Focused;
+}
+FX_BOOL CXFA_FFWidget::OnMouseEnter() {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnMouseExit() {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnLButtonDown(FX_DWORD dwFlags,
+                                     FX_FLOAT fx,
+                                     FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnLButtonDblClk(FX_DWORD dwFlags,
+                                       FX_FLOAT fx,
+                                       FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnMouseWheel(FX_DWORD dwFlags,
+                                    int16_t zDelta,
+                                    FX_FLOAT fx,
+                                    FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnRButtonDown(FX_DWORD dwFlags,
+                                     FX_FLOAT fx,
+                                     FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnRButtonDblClk(FX_DWORD dwFlags,
+                                       FX_FLOAT fx,
+                                       FX_FLOAT fy) {
+  return FALSE;
+}
+
+FX_BOOL CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) {
+  CXFA_FFWidget* pParent = GetParent();
+  if (pParent && !pParent->IsAncestorOf(pOldWidget)) {
+    pParent->OnSetFocus(pOldWidget);
+  }
+  m_dwStatus |= XFA_WIDGETSTATUS_Focused;
+  CXFA_EventParam eParam;
+  eParam.m_eType = XFA_EVENT_Enter;
+  eParam.m_pTarget = m_pDataAcc;
+  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Enter, &eParam);
+  return TRUE;
+}
+FX_BOOL CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) {
+  m_dwStatus &= ~XFA_WIDGETSTATUS_Focused;
+  EventKillFocus();
+  if (pNewWidget) {
+    CXFA_FFWidget* pParent = GetParent();
+    if (pParent && !pParent->IsAncestorOf(pNewWidget)) {
+      pParent->OnKillFocus(pNewWidget);
+    }
+  }
+  return TRUE;
+}
+FX_BOOL CXFA_FFWidget::OnKeyDown(FX_DWORD dwKeyCode, FX_DWORD dwFlags) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnKeyUp(FX_DWORD dwKeyCode, FX_DWORD dwFlags) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnChar(FX_DWORD dwChar, FX_DWORD dwFlags) {
+  return FALSE;
+}
+FX_DWORD CXFA_FFWidget::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) {
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::OnSetCursor(FX_FLOAT fx, FX_FLOAT fy) {
+  return FALSE;
+}
+void CXFA_FFWidget::Rotate2Normal(FX_FLOAT& fx, FX_FLOAT& fy) {
+  CFX_Matrix mt;
+  GetRotateMatrix(mt);
+  if (mt.IsIdentity()) {
+    return;
+  }
+  CFX_Matrix mtReverse;
+  mtReverse.SetReverse(mt);
+  mtReverse.TransformPoint(fx, fy);
+}
+static void XFA_GetMatrix(CFX_Matrix& m,
+                          int32_t iRotate,
+                          int32_t at,
+                          const CFX_RectF& rt) {
+  if (!iRotate) {
+    return;
+  }
+  FX_FLOAT fAnchorX, fAnchorY;
+  switch (at) {
+    case XFA_ATTRIBUTEENUM_TopLeft:
+      fAnchorX = rt.left, fAnchorY = rt.top;
+      break;
+    case XFA_ATTRIBUTEENUM_TopCenter:
+      fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.top;
+      break;
+    case XFA_ATTRIBUTEENUM_TopRight:
+      fAnchorX = rt.right(), fAnchorY = rt.top;
+      break;
+    case XFA_ATTRIBUTEENUM_MiddleLeft:
+      fAnchorX = rt.left, fAnchorY = (rt.top + rt.bottom()) / 2;
+      break;
+    case XFA_ATTRIBUTEENUM_MiddleCenter:
+      fAnchorX = (rt.left + rt.right()) / 2,
+      fAnchorY = (rt.top + rt.bottom()) / 2;
+      break;
+    case XFA_ATTRIBUTEENUM_MiddleRight:
+      fAnchorX = rt.right(), fAnchorY = (rt.top + rt.bottom()) / 2;
+      break;
+    case XFA_ATTRIBUTEENUM_BottomLeft:
+      fAnchorX = rt.left, fAnchorY = rt.bottom();
+      break;
+    case XFA_ATTRIBUTEENUM_BottomCenter:
+      fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.bottom();
+      break;
+    case XFA_ATTRIBUTEENUM_BottomRight:
+      fAnchorX = rt.right(), fAnchorY = rt.bottom();
+      break;
+  }
+  switch (iRotate) {
+    case 90:
+      m.a = 0, m.b = -1, m.c = 1, m.d = 0, m.e = fAnchorX - fAnchorY,
+      m.f = fAnchorX + fAnchorY;
+      break;
+    case 180:
+      m.a = -1, m.b = 0, m.c = 0, m.d = -1, m.e = fAnchorX * 2,
+      m.f = fAnchorY * 2;
+      break;
+    case 270:
+      m.a = 0, m.b = 1, m.c = -1, m.d = 0, m.e = fAnchorX + fAnchorY,
+      m.f = fAnchorY - fAnchorX;
+      break;
+  }
+}
+void CXFA_FFWidget::GetRotateMatrix(CFX_Matrix& mt) {
+  mt.Set(1, 0, 0, 1, 0, 0);
+  int32_t iRotate = m_pDataAcc->GetRotate();
+  if (!iRotate) {
+    return;
+  }
+  CFX_RectF rcWidget;
+  GetRectWithoutRotate(rcWidget);
+  XFA_ATTRIBUTEENUM at = XFA_ATTRIBUTEENUM_TopLeft;
+  XFA_GetMatrix(mt, iRotate, at, rcWidget);
+}
+FX_BOOL CXFA_FFWidget::IsLayoutRectEmpty() {
+  CFX_RectF rtLayout;
+  GetRectWithoutRotate(rtLayout);
+  return rtLayout.width < 0.1f && rtLayout.height < 0.1f;
+}
+CXFA_FFWidget* CXFA_FFWidget::GetParent() {
+  CXFA_Node* pParentNode =
+      m_pDataAcc->GetNode()->GetNodeItem(XFA_NODEITEM_Parent);
+  if (pParentNode) {
+    CXFA_WidgetAcc* pParentWidgetAcc =
+        (CXFA_WidgetAcc*)pParentNode->GetWidgetData();
+    if (pParentWidgetAcc) {
+      return pParentWidgetAcc->GetNextWidget(NULL);
+    }
+  }
+  return NULL;
+}
+FX_BOOL CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) {
+  if (!pWidget) {
+    return FALSE;
+  }
+  CXFA_Node* pNode = m_pDataAcc->GetNode();
+  CXFA_Node* pChildNode = pWidget->GetDataAcc()->GetNode();
+  while (pChildNode) {
+    if (pChildNode == pNode) {
+      return TRUE;
+    }
+    pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_Parent);
+  }
+  return FALSE;
+}
+FX_BOOL CXFA_FFWidget::PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy) {
+  CFX_RectF rtWidget;
+  GetWidgetRect(rtWidget);
+  if (rtWidget.Contains(fx, fy)) {
+    return TRUE;
+  }
+  return FALSE;
+}
+CXFA_FFDocView* CXFA_FFWidget::GetDocView() {
+  return m_pDocView;
+}
+CXFA_FFDoc* CXFA_FFWidget::GetDoc() {
+  return (CXFA_FFDoc*)m_pDocView->GetDoc();
+}
+CXFA_FFApp* CXFA_FFWidget::GetApp() {
+  return GetDoc()->GetApp();
+}
+IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() {
+  return GetApp()->GetAppProvider();
+}
+void CXFA_FFWidget::GetMinMaxWidth(FX_FLOAT fMinWidth, FX_FLOAT fMaxWidth) {
+  fMinWidth = fMaxWidth = 0;
+  FX_FLOAT fWidth = 0;
+  if (m_pDataAcc->GetWidth(fWidth)) {
+    fMinWidth = fMaxWidth = fWidth;
+  } else {
+    m_pDataAcc->GetMinWidth(fMinWidth);
+    m_pDataAcc->GetMaxWidth(fMaxWidth);
+  }
+}
+void CXFA_FFWidget::GetMinMaxHeight(FX_FLOAT fMinHeight, FX_FLOAT fMaxHeight) {
+  fMinHeight = fMaxHeight = 0;
+  FX_FLOAT fHeight = 0;
+  if (m_pDataAcc->GetHeight(fHeight)) {
+    fMinHeight = fMaxHeight = fHeight;
+  } else {
+    m_pDataAcc->GetMinHeight(fMinHeight);
+    m_pDataAcc->GetMaxHeight(fMaxHeight);
+  }
+}
+FX_BOOL CXFA_FFWidget::IsMatchVisibleStatus(FX_DWORD dwStatus) {
+  return m_dwStatus & XFA_WIDGETSTATUS_Visible;
+}
+void CXFA_FFWidget::EventKillFocus() {
+  if (m_dwStatus & XFA_WIDGETSTATUS_Access) {
+    m_dwStatus &= ~XFA_WIDGETSTATUS_Access;
+    return;
+  }
+  CXFA_EventParam eParam;
+  eParam.m_eType = XFA_EVENT_Exit;
+  eParam.m_pTarget = m_pDataAcc;
+  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Exit, &eParam);
+}
+FX_BOOL CXFA_FFWidget::IsButtonDown() {
+  return (m_dwStatus & XFA_WIDGETSTATUS_ButtonDown) != 0;
+}
+void CXFA_FFWidget::SetButtonDown(FX_BOOL bSet) {
+  bSet ? m_dwStatus |= XFA_WIDGETSTATUS_ButtonDown
+       : m_dwStatus &= ~XFA_WIDGETSTATUS_ButtonDown;
+}
+int32_t XFA_StrokeTypeSetLineDash(CFX_Graphics* pGraphics,
+                                  int32_t iStrokeType,
+                                  int32_t iCapType) {
+  switch (iStrokeType) {
+    case XFA_ATTRIBUTEENUM_DashDot: {
+      FX_FLOAT dashArray[] = {4, 1, 2, 1};
+      if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
+        dashArray[1] = 2;
+        dashArray[3] = 2;
+      }
+      pGraphics->SetLineDash(0, dashArray, 4);
+      return FX_DASHSTYLE_DashDot;
+    }
+    case XFA_ATTRIBUTEENUM_DashDotDot: {
+      FX_FLOAT dashArray[] = {4, 1, 2, 1, 2, 1};
+      if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
+        dashArray[1] = 2;
+        dashArray[3] = 2;
+        dashArray[5] = 2;
+      }
+      pGraphics->SetLineDash(0, dashArray, 6);
+      return FX_DASHSTYLE_DashDotDot;
+    }
+    case XFA_ATTRIBUTEENUM_Dashed: {
+      FX_FLOAT dashArray[] = {5, 1};
+      if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
+        dashArray[1] = 2;
+      }
+      pGraphics->SetLineDash(0, dashArray, 2);
+      return FX_DASHSTYLE_Dash;
+    }
+    case XFA_ATTRIBUTEENUM_Dotted: {
+      FX_FLOAT dashArray[] = {2, 1};
+      if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
+        dashArray[1] = 2;
+      }
+      pGraphics->SetLineDash(0, dashArray, 2);
+      return FX_DASHSTYLE_Dot;
+    }
+    default:
+      break;
+  }
+  pGraphics->SetLineDash(FX_DASHSTYLE_Solid);
+  return FX_DASHSTYLE_Solid;
+}
+CFX_GraphStateData::LineCap XFA_LineCapToFXGE(int32_t iLineCap) {
+  switch (iLineCap) {
+    case XFA_ATTRIBUTEENUM_Round:
+      return CFX_GraphStateData::LineCapRound;
+    case XFA_ATTRIBUTEENUM_Butt:
+      return CFX_GraphStateData::LineCapButt;
+    default:
+      break;
+  }
+  return CFX_GraphStateData::LineCapSquare;
+}
+class CXFA_ImageRenderer {
+ public:
+  CXFA_ImageRenderer();
+  ~CXFA_ImageRenderer();
+  FX_BOOL Start(CFX_RenderDevice* pDevice,
+                CFX_DIBSource* pDIBSource,
+                FX_ARGB bitmap_argb,
+                int bitmap_alpha,
+                const CFX_Matrix* pImage2Device,
+                FX_DWORD flags,
+                int blendType = FXDIB_BLEND_NORMAL);
+  FX_BOOL Continue(IFX_Pause* pPause);
+
+ protected:
+  CFX_RenderDevice* m_pDevice;
+  int m_Status;
+  CFX_Matrix m_ImageMatrix;
+  CFX_DIBSource* m_pDIBSource;
+  CFX_DIBitmap* m_pCloneConvert;
+  int m_BitmapAlpha;
+  FX_ARGB m_FillArgb;
+  FX_DWORD m_Flags;
+  CFX_ImageTransformer* m_pTransformer;
+  void* m_DeviceHandle;
+  int32_t m_BlendType;
+  FX_BOOL m_Result;
+  FX_BOOL m_bPrint;
+  FX_BOOL StartDIBSource();
+  void CompositeDIBitmap(CFX_DIBitmap* pDIBitmap,
+                         int left,
+                         int top,
+                         FX_ARGB mask_argb,
+                         int bitmap_alpha,
+                         int blend_mode,
+                         int Transparency);
+};
+CXFA_ImageRenderer::CXFA_ImageRenderer() {
+  m_pDevice = NULL;
+  m_Status = 0;
+  m_pDIBSource = NULL;
+  m_pCloneConvert = NULL;
+  m_BitmapAlpha = 255;
+  m_FillArgb = 0;
+  m_Flags = 0;
+  m_pTransformer = NULL;
+  m_DeviceHandle = NULL;
+  m_BlendType = FXDIB_BLEND_NORMAL;
+  m_Result = TRUE;
+  m_bPrint = FALSE;
+}
+CXFA_ImageRenderer::~CXFA_ImageRenderer() {
+  if (m_pCloneConvert) {
+    delete m_pCloneConvert;
+  }
+  if (m_pTransformer) {
+    delete m_pTransformer;
+  }
+  if (m_DeviceHandle) {
+    m_pDevice->CancelDIBits(m_DeviceHandle);
+  }
+}
+FX_BOOL CXFA_ImageRenderer::Start(CFX_RenderDevice* pDevice,
+                                  CFX_DIBSource* pDIBSource,
+                                  FX_ARGB bitmap_argb,
+                                  int bitmap_alpha,
+                                  const CFX_Matrix* pImage2Device,
+                                  FX_DWORD flags,
+                                  int blendType) {
+  m_pDevice = pDevice;
+  m_pDIBSource = pDIBSource;
+  m_FillArgb = bitmap_argb;
+  m_BitmapAlpha = bitmap_alpha;
+  m_ImageMatrix = *pImage2Device;
+  m_Flags = flags;
+  m_BlendType = blendType;
+  return StartDIBSource();
+}
+FX_BOOL CXFA_ImageRenderer::StartDIBSource() {
+  if (m_pDevice->StartDIBits(m_pDIBSource, m_BitmapAlpha, m_FillArgb,
+                             &m_ImageMatrix, m_Flags, m_DeviceHandle, 0, NULL,
+                             m_BlendType)) {
+    if (m_DeviceHandle) {
+      m_Status = 3;
+      return TRUE;
+    }
+    return FALSE;
+  }
+  CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect();
+  FX_RECT image_rect = image_rect_f.GetOutterRect();
+  int dest_width = image_rect.Width();
+  int dest_height = image_rect.Height();
+  if ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) ||
+      (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) {
+    if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {
+      m_Result = FALSE;
+      return FALSE;
+    }
+    CFX_DIBSource* pDib = m_pDIBSource;
+    if (m_pDIBSource->HasAlpha() &&
+        !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) &&
+        !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
+      m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb);
+      if (!m_pCloneConvert) {
+        m_Result = FALSE;
+        return FALSE;
+      }
+      pDib = m_pCloneConvert;
+    }
+    FX_RECT clip_box = m_pDevice->GetClipBox();
+    clip_box.Intersect(image_rect);
+    m_Status = 2;
+    m_pTransformer = new CFX_ImageTransformer;
+    m_pTransformer->Start(pDib, &m_ImageMatrix, m_Flags, &clip_box);
+    return TRUE;
+  }
+  if (m_ImageMatrix.a < 0) {
+    dest_width = -dest_width;
+  }
+  if (m_ImageMatrix.d > 0) {
+    dest_height = -dest_height;
+  }
+  int dest_left, dest_top;
+  dest_left = dest_width > 0 ? image_rect.left : image_rect.right;
+  dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom;
+  if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) {
+    if (m_pDevice->StretchDIBits(m_pDIBSource, dest_left, dest_top, dest_width,
+                                 dest_height, m_Flags, NULL, m_BlendType)) {
+      return FALSE;
+    }
+  }
+  if (m_pDIBSource->IsAlphaMask()) {
+    if (m_BitmapAlpha != 255) {
+      m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha);
+    }
+    if (m_pDevice->StretchBitMask(m_pDIBSource, dest_left, dest_top, dest_width,
+                                  dest_height, m_FillArgb, m_Flags)) {
+      return FALSE;
+    }
+  }
+  if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {
+    m_Result = FALSE;
+    return TRUE;
+  }
+  FX_RECT clip_box = m_pDevice->GetClipBox();
+  FX_RECT dest_rect = clip_box;
+  dest_rect.Intersect(image_rect);
+  FX_RECT dest_clip(
+      dest_rect.left - image_rect.left, dest_rect.top - image_rect.top,
+      dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top);
+  CFX_DIBitmap* pStretched =
+      m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip);
+  if (pStretched) {
+    CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top, m_FillArgb,
+                      m_BitmapAlpha, m_BlendType, FALSE);
+    delete pStretched;
+    pStretched = NULL;
+  }
+  return FALSE;
+}
+FX_BOOL CXFA_ImageRenderer::Continue(IFX_Pause* pPause) {
+  if (m_Status == 2) {
+    if (m_pTransformer->Continue(pPause)) {
+      return TRUE;
+    }
+    CFX_DIBitmap* pBitmap = m_pTransformer->m_Storer.Detach();
+    if (pBitmap == NULL) {
+      return FALSE;
+    }
+    if (pBitmap->IsAlphaMask()) {
+      if (m_BitmapAlpha != 255) {
+        m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha);
+      }
+      m_Result = m_pDevice->SetBitMask(pBitmap, m_pTransformer->m_ResultLeft,
+                                       m_pTransformer->m_ResultTop, m_FillArgb);
+    } else {
+      if (m_BitmapAlpha != 255) {
+        pBitmap->MultiplyAlpha(m_BitmapAlpha);
+      }
+      m_Result = m_pDevice->SetDIBits(pBitmap, m_pTransformer->m_ResultLeft,
+                                      m_pTransformer->m_ResultTop, m_BlendType);
+    }
+    delete pBitmap;
+    return FALSE;
+  } else if (m_Status == 3) {
+    return m_pDevice->ContinueDIBits(m_DeviceHandle, pPause);
+  }
+  return FALSE;
+}
+void CXFA_ImageRenderer::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap,
+                                           int left,
+                                           int top,
+                                           FX_ARGB mask_argb,
+                                           int bitmap_alpha,
+                                           int blend_mode,
+                                           int Transparency) {
+  if (pDIBitmap == NULL) {
+    return;
+  }
+  FX_BOOL bIsolated = Transparency & PDFTRANS_ISOLATED;
+  FX_BOOL bGroup = Transparency & PDFTRANS_GROUP;
+  if (blend_mode == FXDIB_BLEND_NORMAL) {
+    if (!pDIBitmap->IsAlphaMask()) {
+      if (bitmap_alpha < 255) {
+        pDIBitmap->MultiplyAlpha(bitmap_alpha);
+      }
+      if (m_pDevice->SetDIBits(pDIBitmap, left, top)) {
+        return;
+      }
+    } else {
+      FX_DWORD fill_argb = (mask_argb);
+      if (bitmap_alpha < 255) {
+        ((uint8_t*)&fill_argb)[3] =
+            ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255;
+      }
+      if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) {
+        return;
+      }
+    }
+  }
+  FX_BOOL bBackAlphaRequired = blend_mode && bIsolated;
+  FX_BOOL bGetBackGround =
+      ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) ||
+      (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) &&
+       (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired);
+  if (bGetBackGround) {
+    if (bIsolated || !bGroup) {
+      if (pDIBitmap->IsAlphaMask()) {
+        return;
+      }
+      m_pDevice->SetDIBits(pDIBitmap, left, top, blend_mode);
+    } else {
+      FX_RECT rect(left, top, left + pDIBitmap->GetWidth(),
+                   top + pDIBitmap->GetHeight());
+      rect.Intersect(m_pDevice->GetClipBox());
+      CFX_DIBitmap* pClone = NULL;
+      FX_BOOL bClone = FALSE;
+      if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) {
+        bClone = TRUE;
+        pClone = m_pDevice->GetBackDrop()->Clone(&rect);
+        CFX_DIBitmap* pForeBitmap = m_pDevice->GetBitmap();
+        pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
+                                pForeBitmap, rect.left, rect.top);
+        left = left >= 0 ? 0 : left;
+        top = top >= 0 ? 0 : top;
+        if (!pDIBitmap->IsAlphaMask())
+          pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
+                                  pDIBitmap, left, top, blend_mode);
+        else
+          pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(),
+                                pDIBitmap, mask_argb, left, top, blend_mode);
+      } else {
+        pClone = pDIBitmap;
+      }
+      if (m_pDevice->GetBackDrop()) {
+        m_pDevice->SetDIBits(pClone, rect.left, rect.top);
+      } else {
+        if (pDIBitmap->IsAlphaMask()) {
+          return;
+        }
+        m_pDevice->SetDIBits(pDIBitmap, rect.left, rect.top, blend_mode);
+      }
+      if (bClone) {
+        delete pClone;
+      }
+    }
+    return;
+  }
+  if (pDIBitmap->HasAlpha() &&
+      !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) {
+    CFX_DIBitmap* pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb);
+    if (!pCloneConvert) {
+      return;
+    }
+    CXFA_ImageRenderer imageRender;
+    FX_BOOL bRet = imageRender.Start(m_pDevice, pCloneConvert, m_FillArgb,
+                                     m_BitmapAlpha, &m_ImageMatrix, m_Flags);
+    while (bRet) {
+      bRet = imageRender.Continue(NULL);
+    }
+    delete pCloneConvert;
+    return;
+  }
+}
+void XFA_DrawImage(CFX_Graphics* pGS,
+                   const CFX_RectF& rtImage,
+                   CFX_Matrix* pMatrix,
+                   CFX_DIBitmap* pDIBitmap,
+                   int32_t iAspect,
+                   int32_t iImageXDpi,
+                   int32_t iImageYDpi,
+                   int32_t iHorzAlign,
+                   int32_t iVertAlign) {
+  if (rtImage.IsEmpty()) {
+    return;
+  }
+  if (!pDIBitmap || !pDIBitmap->GetBuffer()) {
+    return;
+  }
+  FX_FLOAT fWidth =
+      XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetWidth(), (FX_FLOAT)iImageXDpi);
+  FX_FLOAT fHeight =
+      XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetHeight(), (FX_FLOAT)iImageYDpi);
+  CFX_RectF rtFit;
+  rtFit.Set(rtImage.left, rtImage.top, fWidth, fHeight);
+  switch (iAspect) {
+    case XFA_ATTRIBUTEENUM_Fit: {
+      FX_FLOAT f1 = rtImage.height / rtFit.height;
+      FX_FLOAT f2 = rtImage.width / rtFit.width;
+      f1 = std::min(f1, f2);
+      rtFit.height = rtFit.height * f1;
+      rtFit.width = rtFit.width * f1;
+    } break;
+    case XFA_ATTRIBUTEENUM_Actual:
+      break;
+    case XFA_ATTRIBUTEENUM_Height: {
+      FX_FLOAT f1 = rtImage.height / rtFit.height;
+      rtFit.height = rtImage.height;
+      rtFit.width = f1 * rtFit.width;
+    } break;
+    case XFA_ATTRIBUTEENUM_None:
+      rtFit.height = rtImage.height;
+      rtFit.width = rtImage.width;
+      break;
+    case XFA_ATTRIBUTEENUM_Width: {
+      FX_FLOAT f1 = rtImage.width / rtFit.width;
+      rtFit.width = rtImage.width;
+      rtFit.height = rtFit.height * f1;
+    } break;
+  }
+  if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) {
+    rtFit.left += (rtImage.width - rtFit.width) / 2;
+  } else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) {
+    rtFit.left = rtImage.right() - rtFit.width;
+  }
+  if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) {
+    rtFit.top += (rtImage.height - rtFit.height) / 2;
+  } else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) {
+    rtFit.top = rtImage.bottom() - rtImage.height;
+  }
+  CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
+  pRenderDevice->SaveState();
+  CFX_PathData path;
+  path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top);
+  pRenderDevice->SetClip_PathFill(&path, pMatrix, FXFILL_WINDING);
+  CFX_Matrix mtImage(1, 0, 0, -1, 0, 1);
+  mtImage.Concat(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top);
+  mtImage.Concat(*pMatrix);
+  CXFA_ImageRenderer imageRender;
+  FX_BOOL bRet = imageRender.Start(pRenderDevice, pDIBitmap, 0, 255, &mtImage,
+                                   FXDIB_INTERPOL);
+  while (bRet) {
+    bRet = imageRender.Continue(NULL);
+  }
+  pRenderDevice->RestoreState();
+}
+
+static const uint8_t g_inv_base64[128] = {
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62,  255,
+    255, 255, 63,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  255, 255,
+    255, 255, 255, 255, 255, 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
+    10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
+    25,  255, 255, 255, 255, 255, 255, 26,  27,  28,  29,  30,  31,  32,  33,
+    34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
+    49,  50,  51,  255, 255, 255, 255, 255,
+};
+
+static uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) {
+  uint8_t* pCP;
+  int32_t i = 0, j = 0;
+  if (iLen == 0) {
+    iLen = FXSYS_strlen((FX_CHAR*)pStr);
+  }
+  pCP = FX_Alloc(uint8_t, iLen + 1);
+  for (; i < iLen; i++) {
+    if ((pStr[i] & 128) == 0) {
+      if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') {
+        pCP[j++] = pStr[i];
+      }
+    }
+  }
+  pCP[j] = '\0';
+  return pCP;
+}
+static int32_t XFA_Base64Decode(const FX_CHAR* pStr, uint8_t* pOutBuffer) {
+  if (pStr == NULL) {
+    return 0;
+  }
+  uint8_t* pBuffer =
+      XFA_RemoveBase64Whitespace((uint8_t*)pStr, FXSYS_strlen((FX_CHAR*)pStr));
+  if (pBuffer == NULL) {
+    return 0;
+  }
+  int32_t iLen = FXSYS_strlen((FX_CHAR*)pBuffer);
+  int32_t i = 0, j = 0;
+  FX_DWORD dwLimb = 0;
+  for (; i + 3 < iLen; i += 4) {
+    if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' ||
+        pBuffer[i + 3] == '=') {
+      if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') {
+        break;
+      }
+      if (pBuffer[i + 2] == '=') {
+        dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 6) |
+                 ((FX_DWORD)g_inv_base64[pBuffer[i + 1]]);
+        pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF;
+        j++;
+      } else {
+        dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 12) |
+                 ((FX_DWORD)g_inv_base64[pBuffer[i + 1]] << 6) |
+                 ((FX_DWORD)g_inv_base64[pBuffer[i + 2]]);
+        pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF;
+        pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF;
+        j += 2;
+      }
+    } else {
+      dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 18) |
+               ((FX_DWORD)g_inv_base64[pBuffer[i + 1]] << 12) |
+               ((FX_DWORD)g_inv_base64[pBuffer[i + 2]] << 6) |
+               ((FX_DWORD)g_inv_base64[pBuffer[i + 3]]);
+      pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff;
+      pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff;
+      pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff;
+      j += 3;
+    }
+  }
+  FX_Free(pBuffer);
+  return j;
+}
+static FX_CHAR g_base64_chars[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+FX_CHAR* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len) {
+  FX_CHAR* out = NULL;
+  int i, j;
+  FX_DWORD limb;
+  out = FX_Alloc(FX_CHAR, ((buf_len * 8 + 5) / 6) + 5);
+  for (i = 0, j = 0, limb = 0; i + 2 < buf_len; i += 3, j += 4) {
+    limb = ((FX_DWORD)buf[i] << 16) | ((FX_DWORD)buf[i + 1] << 8) |
+           ((FX_DWORD)buf[i + 2]);
+    out[j] = g_base64_chars[(limb >> 18) & 63];
+    out[j + 1] = g_base64_chars[(limb >> 12) & 63];
+    out[j + 2] = g_base64_chars[(limb >> 6) & 63];
+    out[j + 3] = g_base64_chars[(limb)&63];
+  }
+  switch (buf_len - i) {
+    case 0:
+      break;
+    case 1:
+      limb = ((FX_DWORD)buf[i]);
+      out[j++] = g_base64_chars[(limb >> 2) & 63];
+      out[j++] = g_base64_chars[(limb << 4) & 63];
+      out[j++] = '=';
+      out[j++] = '=';
+      break;
+    case 2:
+      limb = ((FX_DWORD)buf[i] << 8) | ((FX_DWORD)buf[i + 1]);
+      out[j++] = g_base64_chars[(limb >> 10) & 63];
+      out[j++] = g_base64_chars[(limb >> 4) & 63];
+      out[j++] = g_base64_chars[(limb << 2) & 63];
+      out[j++] = '=';
+      break;
+    default:
+      break;
+  }
+  out[j] = '\0';
+  return out;
+}
+FXCODEC_IMAGE_TYPE XFA_GetImageType(const CFX_WideStringC& wsType) {
+  CFX_WideString wsContentType(wsType);
+  wsContentType.MakeLower();
+  if (wsContentType == FX_WSTRC(L"image/jpg")) {
+    return FXCODEC_IMAGE_JPG;
+  }
+  if (wsContentType == FX_WSTRC(L"image/png")) {
+    return FXCODEC_IMAGE_PNG;
+  }
+  if (wsContentType == FX_WSTRC(L"image/gif")) {
+    return FXCODEC_IMAGE_GIF;
+  }
+  if (wsContentType == FX_WSTRC(L"image/bmp")) {
+    return FXCODEC_IMAGE_BMP;
+  }
+  if (wsContentType == FX_WSTRC(L"image/tif")) {
+    return FXCODEC_IMAGE_TIF;
+  }
+  return FXCODEC_IMAGE_UNKNOWN;
+}
+CFX_DIBitmap* XFA_LoadImageData(CXFA_FFDoc* pDoc,
+                                CXFA_Image* pImage,
+                                FX_BOOL& bNameImage,
+                                int32_t& iImageXDpi,
+                                int32_t& iImageYDpi) {
+  CFX_WideString wsHref;
+  pImage->GetHref(wsHref);
+  CFX_WideString wsImage;
+  pImage->GetContent(wsImage);
+  if (wsHref.IsEmpty() && wsImage.IsEmpty()) {
+    return NULL;
+  }
+  CFX_WideString wsContentType;
+  pImage->GetContentType(wsContentType);
+  FXCODEC_IMAGE_TYPE type = XFA_GetImageType(wsContentType);
+  CFX_ByteString bsContent;
+  uint8_t* pImageBuffer = NULL;
+  IFX_FileRead* pImageFileRead = NULL;
+  if (wsImage.GetLength() > 0) {
+    XFA_ATTRIBUTEENUM iEncoding =
+        (XFA_ATTRIBUTEENUM)pImage->GetTransferEncoding();
+    if (iEncoding == XFA_ATTRIBUTEENUM_Base64) {
+      CFX_ByteString bsData = wsImage.UTF8Encode();
+      int32_t iLength = bsData.GetLength();
+      pImageBuffer = FX_Alloc(uint8_t, iLength);
+      int32_t iRead = XFA_Base64Decode((const FX_CHAR*)bsData, pImageBuffer);
+      if (iRead > 0) {
+        pImageFileRead = FX_CreateMemoryStream(pImageBuffer, iRead);
+      }
+    } else {
+      bsContent = CFX_ByteString::FromUnicode(wsImage);
+      pImageFileRead = FX_CreateMemoryStream(
+          (uint8_t*)(const uint8_t*)bsContent, bsContent.GetLength());
+    }
+  } else {
+    CFX_WideString wsURL = wsHref;
+    if (wsURL.Left(7) != FX_WSTRC(L"http://") &&
+        wsURL.Left(6) != FX_WSTRC(L"ftp://")) {
+      CFX_DIBitmap* pBitmap =
+          pDoc->GetPDFNamedImage(wsURL, iImageXDpi, iImageYDpi);
+      if (pBitmap) {
+        bNameImage = TRUE;
+        return pBitmap;
+      }
+    }
+    pImageFileRead = pDoc->GetDocProvider()->OpenLinkedFile(pDoc, wsURL);
+  }
+  if (!pImageFileRead) {
+    FX_Free(pImageBuffer);
+    return NULL;
+  }
+  bNameImage = FALSE;
+  CFX_DIBitmap* pBitmap =
+      XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi);
+  FX_Free(pImageBuffer);
+  pImageFileRead->Release();
+  return pBitmap;
+}
+static FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type,
+                                     int32_t iComponents,
+                                     int32_t iBitsPerComponent) {
+  FXDIB_Format dibFormat = FXDIB_Argb;
+  switch (type) {
+    case FXCODEC_IMAGE_BMP:
+    case FXCODEC_IMAGE_JPG:
+    case FXCODEC_IMAGE_TIF: {
+      dibFormat = FXDIB_Rgb32;
+      int32_t bpp = iComponents * iBitsPerComponent;
+      if (bpp <= 24) {
+        dibFormat = FXDIB_Rgb;
+      }
+    } break;
+    case FXCODEC_IMAGE_PNG:
+    default:
+      break;
+  }
+  return dibFormat;
+}
+CFX_DIBitmap* XFA_LoadImageFromBuffer(IFX_FileRead* pImageFileRead,
+                                      FXCODEC_IMAGE_TYPE type,
+                                      int32_t& iImageXDpi,
+                                      int32_t& iImageYDpi) {
+  CFX_GEModule* pGeModule = CFX_GEModule::Get();
+  if (!pGeModule) {
+    return NULL;
+  }
+  CCodec_ModuleMgr* pCodecMgr = pGeModule->GetCodecModule();
+  if (!pCodecMgr) {
+    return NULL;
+  }
+  CFX_DIBAttribute dibAttr;
+  CFX_DIBitmap* pBitmap = NULL;
+  ICodec_ProgressiveDecoder* pProgressiveDecoder =
+      pCodecMgr->CreateProgressiveDecoder();
+  pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr);
+  switch (dibAttr.m_wDPIUnit) {
+    case FXCODEC_RESUNIT_CENTIMETER:
+      dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f);
+      dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f);
+      break;
+    case FXCODEC_RESUNIT_METER:
+      dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (FX_FLOAT)100 * 2.54f);
+      dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (FX_FLOAT)100 * 2.54f);
+      break;
+    default:
+      break;
+  }
+  iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96);
+  iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96);
+  if (pProgressiveDecoder->GetWidth() > 0 &&
+      pProgressiveDecoder->GetHeight() > 0) {
+    type = pProgressiveDecoder->GetType();
+    int32_t iComponents = pProgressiveDecoder->GetNumComponents();
+    int32_t iBpc = pProgressiveDecoder->GetBPC();
+    FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc);
+    pBitmap = new CFX_DIBitmap();
+    pBitmap->Create(pProgressiveDecoder->GetWidth(),
+                    pProgressiveDecoder->GetHeight(), dibFormat);
+    pBitmap->Clear(0xffffffff);
+    int32_t nFrames;
+    if ((pProgressiveDecoder->GetFrames(nFrames) ==
+         FXCODEC_STATUS_DECODE_READY) &&
+        (nFrames > 0)) {
+      pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(),
+                                       pBitmap->GetHeight());
+      pProgressiveDecoder->ContinueDecode();
+    }
+  }
+  delete pProgressiveDecoder;
+  return pBitmap;
+}
+void XFA_RectWidthoutMargin(CFX_RectF& rt, const CXFA_Margin& mg, FX_BOOL bUI) {
+  if (!mg) {
+    return;
+  }
+  FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset;
+  mg.GetLeftInset(fLeftInset);
+  mg.GetTopInset(fTopInset);
+  mg.GetRightInset(fRightInset);
+  mg.GetBottomInset(fBottomInset);
+  rt.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
+}
+CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
+  XFA_ELEMENT iType = pLayoutItem->GetFormNode()->GetClassID();
+  if (XFA_IsCreateWidget(iType)) {
+    return static_cast<CXFA_FFWidget*>(pLayoutItem);
+  }
+  return nullptr;
+}
+FX_BOOL XFA_IsCreateWidget(XFA_ELEMENT iType) {
+  return iType == XFA_ELEMENT_Field || iType == XFA_ELEMENT_Draw ||
+         iType == XFA_ELEMENT_Subform || iType == XFA_ELEMENT_ExclGroup;
+}
+static void XFA_BOX_GetPath_Arc(CXFA_Box box,
+                                CFX_RectF rtDraw,
+                                CFX_Path& fillPath,
+                                FX_DWORD dwFlags) {
+  FX_FLOAT a, b;
+  a = rtDraw.width / 2.0f;
+  b = rtDraw.height / 2.0f;
+  if (box.IsCircular() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
+    a = b = std::min(a, b);
+  }
+  CFX_PointF center = rtDraw.Center();
+  rtDraw.left = center.x - a;
+  rtDraw.top = center.y - b;
+  rtDraw.width = a + a;
+  rtDraw.height = b + b;
+  FX_FLOAT startAngle = 0, sweepAngle = 360;
+  FX_BOOL bStart = box.GetStartAngle(startAngle);
+  FX_BOOL bEnd = box.GetSweepAngle(sweepAngle);
+  if (!bStart && !bEnd) {
+    fillPath.AddEllipse(rtDraw);
+    return;
+  }
+  startAngle = -startAngle * FX_PI / 180.0f;
+  sweepAngle = -sweepAngle * FX_PI / 180.0f;
+  fillPath.AddArc(rtDraw.left, rtDraw.top, rtDraw.width, rtDraw.height,
+                  startAngle, sweepAngle);
+}
+static void XFA_BOX_GetPath(CXFA_Box box,
+                            const CXFA_StrokeArray& strokes,
+                            CFX_RectF rtWidget,
+                            CFX_Path& path,
+                            int32_t nIndex,
+                            FX_BOOL bStart,
+                            FX_BOOL bCorner) {
+  FXSYS_assert(nIndex >= 0 && nIndex < 8);
+  FX_BOOL bInverted, bRound;
+  FX_FLOAT fRadius1, fRadius2, sx, sy, vx, vy, nx, ny, offsetY, offsetX,
+      offsetEX, offsetEY;
+  CFX_PointF cpStart, cp, cp1, cp2;
+  CFX_RectF rtRadius;
+  int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex;
+  CXFA_Corner corner1(strokes[n].GetNode());
+  CXFA_Corner corner2(strokes[(n + 2) % 8].GetNode());
+  fRadius1 = bCorner ? corner1.GetRadius() : 0;
+  fRadius2 = bCorner ? corner2.GetRadius() : 0;
+  bInverted = corner1.IsInverted();
+  offsetY = 0.0f;
+  offsetX = 0.0f;
+  bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round;
+  FX_FLOAT halfAfter = 0.0f;
+  FX_FLOAT halfBefore = 0.0f;
+  CXFA_Stroke stroke = strokes[nIndex];
+  if (stroke.IsCorner()) {
+    CXFA_Stroke edgeBefore = strokes[(nIndex + 1 * 8 - 1) % 8];
+    CXFA_Stroke edgeAfter = strokes[nIndex + 1];
+    if (stroke.IsInverted()) {
+      if (!stroke.SameStyles(edgeBefore)) {
+        halfBefore = edgeBefore.GetThickness() / 2;
+      }
+      if (!stroke.SameStyles(edgeAfter)) {
+        halfAfter = edgeAfter.GetThickness() / 2;
+      }
+    }
+  } else {
+    CXFA_Stroke edgeBefore = strokes[(nIndex + 8 - 2) % 8];
+    CXFA_Stroke edgeAfter = strokes[(nIndex + 2) % 8];
+    if (!bRound && !bInverted) {
+      { halfBefore = edgeBefore.GetThickness() / 2; }
+      { halfAfter = edgeAfter.GetThickness() / 2; }
+    }
+  }
+  offsetEX = 0.0f;
+  offsetEY = 0.0f;
+  if (bRound) {
+    sy = FX_PI / 2;
+  }
+  switch (nIndex) {
+    case 0:
+    case 1:
+      cp1 = rtWidget.TopLeft();
+      cp2 = rtWidget.TopRight();
+      if (nIndex == 0) {
+        cpStart.x = cp1.x - halfBefore;
+        cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter;
+      } else {
+        cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y,
+        offsetEX = halfAfter;
+      }
+      vx = 1, vy = 1;
+      nx = -1, ny = 0;
+      if (bRound) {
+        sx = bInverted ? FX_PI / 2 : FX_PI;
+      } else {
+        sx = 1, sy = 0;
+      }
+      break;
+    case 2:
+    case 3:
+      cp1 = rtWidget.TopRight();
+      cp2 = rtWidget.BottomRight();
+      if (nIndex == 2) {
+        cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore,
+        offsetX = halfAfter;
+      } else {
+        cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore,
+        offsetEY = halfAfter;
+      }
+      vx = -1, vy = 1;
+      nx = 0, ny = -1;
+      if (bRound) {
+        sx = bInverted ? FX_PI : FX_PI * 3 / 2;
+      } else {
+        sx = 0, sy = 1;
+      }
+      break;
+    case 4:
+    case 5:
+      cp1 = rtWidget.BottomRight();
+      cp2 = rtWidget.BottomLeft();
+      if (nIndex == 4) {
+        cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1,
+        offsetY = halfAfter;
+      } else {
+        cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y,
+        offsetEX = -halfAfter;
+      }
+      vx = -1, vy = -1;
+      nx = 1, ny = 0;
+      if (bRound) {
+        sx = bInverted ? FX_PI * 3 / 2 : 0;
+      } else {
+        sx = -1, sy = 0;
+      }
+      break;
+    case 6:
+    case 7:
+      cp1 = rtWidget.BottomLeft();
+      cp2 = rtWidget.TopLeft();
+      if (nIndex == 6) {
+        cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore,
+        offsetX = -halfAfter;
+      } else {
+        cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore,
+        offsetEY = -halfAfter;
+      }
+      vx = 1, vy = -1;
+      nx = 0, ny = 1;
+      if (bRound) {
+        sx = bInverted ? 0 : FX_PI / 2;
+      } else {
+        sx = 0, sy = -1;
+      }
+      break;
+  }
+  if (bStart) {
+    path.MoveTo(cpStart.x, cpStart.y);
+  }
+  if (nIndex & 1) {
+    path.LineTo(cp2.x + fRadius2 * nx + offsetEX,
+                cp2.y + fRadius2 * ny + offsetEY);
+    return;
+  }
+  if (bRound) {
+    if (fRadius1 < 0) {
+      sx -= FX_PI;
+    }
+    if (bInverted) {
+      sy *= -1;
+    }
+    rtRadius.Set(cp1.x + offsetX * 2, cp1.y + offsetY * 2,
+                 fRadius1 * 2 * vx - offsetX * 2,
+                 fRadius1 * 2 * vy - offsetY * 2);
+    rtRadius.Normalize();
+    if (bInverted) {
+      rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
+    }
+    path.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width, rtRadius.height, sx,
+               sy);
+  } else {
+    if (bInverted) {
+      cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy;
+    } else {
+      cp = cp1;
+    }
+    path.LineTo(cp.x, cp.y);
+    path.LineTo(cp1.x + fRadius1 * sx + offsetX,
+                cp1.y + fRadius1 * sy + offsetY);
+  }
+}
+static void XFA_BOX_GetFillPath(CXFA_Box box,
+                                const CXFA_StrokeArray& strokes,
+                                CFX_RectF rtWidget,
+                                CFX_Path& fillPath,
+                                FX_WORD dwFlags) {
+  if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
+    CXFA_Edge edge = box.GetEdge(0);
+    FX_FLOAT fThickness = edge.GetThickness();
+    if (fThickness < 0) {
+      fThickness = 0;
+    }
+    FX_FLOAT fHalf = fThickness / 2;
+    int32_t iHand = box.GetHand();
+    if (iHand == XFA_ATTRIBUTEENUM_Left) {
+      rtWidget.Inflate(fHalf, fHalf);
+    } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+      rtWidget.Deflate(fHalf, fHalf);
+    }
+    XFA_BOX_GetPath_Arc(box, rtWidget, fillPath, dwFlags);
+    return;
+  }
+  FX_BOOL bSameStyles = TRUE;
+  int32_t i;
+  CXFA_Stroke stroke1 = strokes[0];
+  for (i = 1; i < 8; i++) {
+    CXFA_Stroke stroke2 = strokes[i];
+    if (!stroke1.SameStyles(stroke2)) {
+      bSameStyles = FALSE;
+      break;
+    }
+    stroke1 = stroke2;
+  }
+  if (bSameStyles) {
+    stroke1 = strokes[0];
+    for (i = 2; i < 8; i += 2) {
+      CXFA_Stroke stroke2 = strokes[i];
+      if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence |
+                                           XFA_STROKE_SAMESTYLE_Corner)) {
+        bSameStyles = FALSE;
+        break;
+      }
+      stroke1 = stroke2;
+    }
+    if (bSameStyles) {
+      stroke1 = strokes[0];
+      if (stroke1.IsInverted()) {
+        bSameStyles = FALSE;
+      }
+      if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) {
+        bSameStyles = FALSE;
+      }
+    }
+  }
+  if (bSameStyles) {
+    fillPath.AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width,
+                          rtWidget.height);
+    return;
+  }
+  FX_BOOL bInverted, bRound;
+  FX_FLOAT fRadius1, fRadius2, sx, sy, vx, vy, nx, ny;
+  CFX_PointF cp, cp1, cp2;
+  CFX_RectF rtRadius;
+  for (int32_t i = 0; i < 8; i += 2) {
+    CXFA_Corner corner1(strokes[i].GetNode());
+    CXFA_Corner corner2(strokes[(i + 2) % 8].GetNode());
+    fRadius1 = corner1.GetRadius();
+    fRadius2 = corner2.GetRadius();
+    bInverted = corner1.IsInverted();
+    bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round;
+    if (bRound) {
+      sy = FX_PI / 2;
+    }
+    switch (i) {
+      case 0:
+        cp1 = rtWidget.TopLeft();
+        cp2 = rtWidget.TopRight();
+        vx = 1, vy = 1;
+        nx = -1, ny = 0;
+        if (bRound) {
+          sx = bInverted ? FX_PI / 2 : FX_PI;
+        } else {
+          sx = 1, sy = 0;
+        }
+        break;
+      case 2:
+        cp1 = rtWidget.TopRight();
+        cp2 = rtWidget.BottomRight();
+        vx = -1, vy = 1;
+        nx = 0, ny = -1;
+        if (bRound) {
+          sx = bInverted ? FX_PI : FX_PI * 3 / 2;
+        } else {
+          sx = 0, sy = 1;
+        }
+        break;
+      case 4:
+        cp1 = rtWidget.BottomRight();
+        cp2 = rtWidget.BottomLeft();
+        vx = -1, vy = -1;
+        nx = 1, ny = 0;
+        if (bRound) {
+          sx = bInverted ? FX_PI * 3 / 2 : 0;
+        } else {
+          sx = -1, sy = 0;
+        }
+        break;
+      case 6:
+        cp1 = rtWidget.BottomLeft();
+        cp2 = rtWidget.TopLeft();
+        vx = 1, vy = -1;
+        nx = 0, ny = 1;
+        if (bRound) {
+          sx = bInverted ? 0 : FX_PI / 2;
+        } else {
+          sx = 0, sy = -1;
+        }
+        break;
+    }
+    if (i == 0) {
+      fillPath.MoveTo(cp1.x, cp1.y + fRadius1);
+    }
+    if (bRound) {
+      if (fRadius1 < 0) {
+        sx -= FX_PI;
+      }
+      if (bInverted) {
+        sy *= -1;
+      }
+      rtRadius.Set(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy);
+      rtRadius.Normalize();
+      if (bInverted) {
+        rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
+      }
+      fillPath.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width,
+                     rtRadius.height, sx, sy);
+    } else {
+      if (bInverted) {
+        cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy;
+      } else {
+        cp = cp1;
+      }
+      fillPath.LineTo(cp.x, cp.y);
+      fillPath.LineTo(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy);
+    }
+    fillPath.LineTo(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny);
+  }
+}
+static void XFA_BOX_Fill_Radial(CXFA_Box box,
+                                CFX_Graphics* pGS,
+                                CFX_Path& fillPath,
+                                CFX_RectF rtFill,
+                                CFX_Matrix* pMatrix) {
+  CXFA_Fill fill = box.GetFill();
+  FX_ARGB crStart, crEnd;
+  crStart = fill.GetColor();
+  int32_t iType = fill.GetRadial(crEnd);
+  CFX_Shading shading;
+  if (iType != XFA_ATTRIBUTEENUM_ToEdge) {
+    FX_ARGB temp = crEnd;
+    crEnd = crStart;
+    crStart = temp;
+  }
+  shading.CreateRadial(rtFill.Center(), rtFill.Center(), 0,
+                       FXSYS_sqrt(rtFill.Width() * rtFill.Width() +
+                                  rtFill.Height() * rtFill.Height()) /
+                           2,
+                       TRUE, TRUE, crStart, crEnd);
+  CFX_Color cr(&shading);
+  pGS->SetFillColor(&cr);
+  pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
+}
+static void XFA_BOX_Fill_Pattern(CXFA_Box box,
+                                 CFX_Graphics* pGS,
+                                 CFX_Path& fillPath,
+                                 CFX_RectF rtFill,
+                                 CFX_Matrix* pMatrix) {
+  CXFA_Fill fill = box.GetFill();
+  FX_ARGB crStart, crEnd;
+  crStart = fill.GetColor();
+  int32_t iType = fill.GetPattern(crEnd);
+  int32_t iHatch = FX_HATCHSTYLE_Cross;
+  switch (iType) {
+    case XFA_ATTRIBUTEENUM_CrossDiagonal:
+      iHatch = FX_HATCHSTYLE_DiagonalCross;
+      break;
+    case XFA_ATTRIBUTEENUM_DiagonalLeft:
+      iHatch = FX_HATCHSTYLE_ForwardDiagonal;
+      break;
+    case XFA_ATTRIBUTEENUM_DiagonalRight:
+      iHatch = FX_HATCHSTYLE_BackwardDiagonal;
+      break;
+    case XFA_ATTRIBUTEENUM_Horizontal:
+      iHatch = FX_HATCHSTYLE_Horizontal;
+      break;
+    case XFA_ATTRIBUTEENUM_Vertical:
+      iHatch = FX_HATCHSTYLE_Vertical;
+      break;
+    default:
+      break;
+  }
+  CFX_Pattern pattern;
+  pattern.Create(iHatch, crEnd, crStart);
+  CFX_Color cr(&pattern);
+  pGS->SetFillColor(&cr);
+  pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
+}
+static void XFA_BOX_Fill_Linear(CXFA_Box box,
+                                CFX_Graphics* pGS,
+                                CFX_Path& fillPath,
+                                CFX_RectF rtFill,
+                                CFX_Matrix* pMatrix) {
+  CXFA_Fill fill = box.GetFill();
+  FX_ARGB crStart = fill.GetColor();
+  FX_ARGB crEnd;
+  int32_t iType = fill.GetLinear(crEnd);
+  CFX_PointF ptStart;
+  CFX_PointF ptEnd;
+  switch (iType) {
+    case XFA_ATTRIBUTEENUM_ToRight:
+      ptStart = CFX_PointF(rtFill.left, rtFill.top);
+      ptEnd = CFX_PointF(rtFill.right(), rtFill.top);
+      break;
+    case XFA_ATTRIBUTEENUM_ToBottom:
+      ptStart = CFX_PointF(rtFill.left, rtFill.top);
+      ptEnd = CFX_PointF(rtFill.left, rtFill.bottom());
+      break;
+    case XFA_ATTRIBUTEENUM_ToLeft:
+      ptStart = CFX_PointF(rtFill.right(), rtFill.top);
+      ptEnd = CFX_PointF(rtFill.left, rtFill.top);
+      break;
+    case XFA_ATTRIBUTEENUM_ToTop:
+      ptStart = CFX_PointF(rtFill.left, rtFill.bottom());
+      ptEnd = CFX_PointF(rtFill.left, rtFill.top);
+      break;
+    default:
+      break;
+  }
+  CFX_Shading shading;
+  shading.CreateAxial(ptStart, ptEnd, FALSE, FALSE, crStart, crEnd);
+  CFX_Color cr(&shading);
+  pGS->SetFillColor(&cr);
+  pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
+}
+static void XFA_BOX_Fill(CXFA_Box box,
+                         const CXFA_StrokeArray& strokes,
+                         CFX_Graphics* pGS,
+                         const CFX_RectF& rtWidget,
+                         CFX_Matrix* pMatrix,
+                         FX_DWORD dwFlags) {
+  CXFA_Fill fill = box.GetFill();
+  if (!fill || fill.GetPresence() != XFA_ATTRIBUTEENUM_Visible) {
+    return;
+  }
+  pGS->SaveGraphState();
+  CFX_Path fillPath;
+  fillPath.Create();
+  XFA_BOX_GetFillPath(box, strokes, rtWidget, fillPath,
+                      (dwFlags & XFA_DRAWBOX_ForceRound) != 0);
+  fillPath.Close();
+  int32_t eType = fill.GetFillType();
+  switch (eType) {
+    case XFA_ELEMENT_Radial:
+      XFA_BOX_Fill_Radial(box, pGS, fillPath, rtWidget, pMatrix);
+      break;
+    case XFA_ELEMENT_Pattern:
+      XFA_BOX_Fill_Pattern(box, pGS, fillPath, rtWidget, pMatrix);
+      break;
+    case XFA_ELEMENT_Linear:
+      XFA_BOX_Fill_Linear(box, pGS, fillPath, rtWidget, pMatrix);
+      break;
+    default: {
+      FX_ARGB cr;
+      if (eType == XFA_ELEMENT_Stipple) {
+        int32_t iRate = fill.GetStipple(cr);
+        if (iRate == 0) {
+          iRate = 100;
+        }
+        int32_t a = 0;
+        FX_COLORREF rgb;
+        ArgbDecode(cr, a, rgb);
+        cr = ArgbEncode(iRate * a / 100, rgb);
+      } else {
+        cr = fill.GetColor();
+      }
+      CFX_Color fillColor(cr);
+      pGS->SetFillColor(&fillColor);
+      pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
+    } break;
+  }
+  pGS->RestoreGraphState();
+}
+static void XFA_BOX_StrokePath(CXFA_Stroke stroke,
+                               CFX_Path* pPath,
+                               CFX_Graphics* pGS,
+                               CFX_Matrix* pMatrix) {
+  if (!stroke || !stroke.IsVisible()) {
+    return;
+  }
+  FX_FLOAT fThickness = stroke.GetThickness();
+  if (fThickness < 0.001f) {
+    return;
+  }
+  pGS->SaveGraphState();
+  if (stroke.IsCorner() && fThickness > 2 * stroke.GetRadius()) {
+    fThickness = 2 * stroke.GetRadius();
+  }
+  pGS->SetLineWidth(fThickness, TRUE);
+  pGS->SetLineCap(CFX_GraphStateData::LineCapButt);
+  XFA_StrokeTypeSetLineDash(pGS, stroke.GetStrokeType(),
+                            XFA_ATTRIBUTEENUM_Butt);
+  CFX_Color fxColor(stroke.GetColor());
+  pGS->SetStrokeColor(&fxColor);
+  pGS->StrokePath(pPath, pMatrix);
+  pGS->RestoreGraphState();
+}
+static void XFA_BOX_StrokeArc(CXFA_Box box,
+                              CFX_Graphics* pGS,
+                              CFX_RectF rtWidget,
+                              CFX_Matrix* pMatrix,
+                              FX_DWORD dwFlags) {
+  CXFA_Edge edge = box.GetEdge(0);
+  if (!edge || !edge.IsVisible()) {
+    return;
+  }
+  FX_BOOL bVisible = FALSE;
+  FX_FLOAT fThickness = 0;
+  int32_t i3DType = box.Get3DStyle(bVisible, fThickness);
+  if (i3DType) {
+    if (bVisible && fThickness >= 0.001f) {
+      dwFlags |= XFA_DRAWBOX_Lowered3D;
+    }
+  }
+  FX_FLOAT fHalf = edge.GetThickness() / 2;
+  if (fHalf < 0) {
+    fHalf = 0;
+  }
+  int32_t iHand = box.GetHand();
+  if (iHand == XFA_ATTRIBUTEENUM_Left) {
+    rtWidget.Inflate(fHalf, fHalf);
+  } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+    rtWidget.Deflate(fHalf, fHalf);
+  }
+  if ((dwFlags & XFA_DRAWBOX_ForceRound) == 0 ||
+      (dwFlags & XFA_DRAWBOX_Lowered3D) == 0) {
+    if (fHalf < 0.001f) {
+      return;
+    }
+    CFX_Path arcPath;
+    arcPath.Create();
+    XFA_BOX_GetPath_Arc(box, rtWidget, arcPath, dwFlags);
+    XFA_BOX_StrokePath(edge, &arcPath, pGS, pMatrix);
+    return;
+  }
+  pGS->SaveGraphState();
+  pGS->SetLineWidth(fHalf);
+  FX_FLOAT a, b;
+  a = rtWidget.width / 2.0f;
+  b = rtWidget.height / 2.0f;
+  if (dwFlags & XFA_DRAWBOX_ForceRound) {
+    a = b = std::min(a, b);
+  }
+  CFX_PointF center = rtWidget.Center();
+  rtWidget.left = center.x - a;
+  rtWidget.top = center.y - b;
+  rtWidget.width = a + a;
+  rtWidget.height = b + b;
+  FX_FLOAT startAngle = 0, sweepAngle = 360;
+  startAngle = startAngle * FX_PI / 180.0f;
+  sweepAngle = -sweepAngle * FX_PI / 180.0f;
+  CFX_Path arcPath;
+  arcPath.Create();
+  arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height,
+                 3.0f * FX_PI / 4.0f, FX_PI);
+  CFX_Color cr(0xFF808080);
+  pGS->SetStrokeColor(&cr);
+  pGS->StrokePath(&arcPath, pMatrix);
+  arcPath.Clear();
+  arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height,
+                 -1.0f * FX_PI / 4.0f, FX_PI);
+  cr.Set(0xFFFFFFFF);
+  pGS->SetStrokeColor(&cr);
+  pGS->StrokePath(&arcPath, pMatrix);
+  rtWidget.Deflate(fHalf, fHalf);
+  arcPath.Clear();
+  arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height,
+                 3.0f * FX_PI / 4.0f, FX_PI);
+  cr.Set(0xFF404040);
+  pGS->SetStrokeColor(&cr);
+  pGS->StrokePath(&arcPath, pMatrix);
+  arcPath.Clear();
+  arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height,
+                 -1.0f * FX_PI / 4.0f, FX_PI);
+  cr.Set(0xFFC0C0C0);
+  pGS->SetStrokeColor(&cr);
+  pGS->StrokePath(&arcPath, pMatrix);
+  pGS->RestoreGraphState();
+}
+static void XFA_Draw3DRect(CFX_Graphics* pGraphic,
+                           const CFX_RectF& rt,
+                           FX_FLOAT fLineWidth,
+                           CFX_Matrix* pMatrix,
+                           FX_ARGB argbTopLeft,
+                           FX_ARGB argbBottomRight) {
+  CFX_Color crLT(argbTopLeft);
+  pGraphic->SetFillColor(&crLT);
+  FX_FLOAT fBottom = rt.bottom();
+  FX_FLOAT fRight = rt.right();
+  CFX_Path pathLT;
+  pathLT.Create();
+  pathLT.MoveTo(rt.left, fBottom);
+  pathLT.LineTo(rt.left, rt.top);
+  pathLT.LineTo(fRight, rt.top);
+  pathLT.LineTo(fRight - fLineWidth, rt.top + fLineWidth);
+  pathLT.LineTo(rt.left + fLineWidth, rt.top + fLineWidth);
+  pathLT.LineTo(rt.left + fLineWidth, fBottom - fLineWidth);
+  pathLT.LineTo(rt.left, fBottom);
+  pGraphic->FillPath(&pathLT, FXFILL_WINDING, pMatrix);
+  CFX_Color crRB(argbBottomRight);
+  pGraphic->SetFillColor(&crRB);
+  CFX_Path pathRB;
+  pathRB.Create();
+  pathRB.MoveTo(fRight, rt.top);
+  pathRB.LineTo(fRight, fBottom);
+  pathRB.LineTo(rt.left, fBottom);
+  pathRB.LineTo(rt.left + fLineWidth, fBottom - fLineWidth);
+  pathRB.LineTo(fRight - fLineWidth, fBottom - fLineWidth);
+  pathRB.LineTo(fRight - fLineWidth, rt.top + fLineWidth);
+  pathRB.LineTo(fRight, rt.top);
+  pGraphic->FillPath(&pathRB, FXFILL_WINDING, pMatrix);
+}
+static void XFA_BOX_Stroke_3DRect_Lowered(CFX_Graphics* pGS,
+                                          CFX_RectF rt,
+                                          FX_FLOAT fThickness,
+                                          CFX_Matrix* pMatrix) {
+  FX_FLOAT fHalfWidth = fThickness / 2.0f;
+  CFX_RectF rtInner(rt);
+  rtInner.Deflate(fHalfWidth, fHalfWidth);
+  CFX_Color cr(0xFF000000);
+  pGS->SetFillColor(&cr);
+  CFX_Path path;
+  path.Create();
+  path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
+  path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
+  pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
+  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF808080, 0xFFC0C0C0);
+}
+static void XFA_BOX_Stroke_3DRect_Raised(CFX_Graphics* pGS,
+                                         CFX_RectF rt,
+                                         FX_FLOAT fThickness,
+                                         CFX_Matrix* pMatrix) {
+  FX_FLOAT fHalfWidth = fThickness / 2.0f;
+  CFX_RectF rtInner(rt);
+  rtInner.Deflate(fHalfWidth, fHalfWidth);
+  CFX_Color cr(0xFF000000);
+  pGS->SetFillColor(&cr);
+  CFX_Path path;
+  path.Create();
+  path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
+  path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
+  pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
+  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080);
+}
+static void XFA_BOX_Stroke_3DRect_Etched(CFX_Graphics* pGS,
+                                         CFX_RectF rt,
+                                         FX_FLOAT fThickness,
+                                         CFX_Matrix* pMatrix) {
+  FX_FLOAT fHalfWidth = fThickness / 2.0f;
+  XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFFFFFFFF);
+  CFX_RectF rtInner(rt);
+  rtInner.Deflate(fHalfWidth, fHalfWidth);
+  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080);
+}
+static void XFA_BOX_Stroke_3DRect_Embossed(CFX_Graphics* pGS,
+                                           CFX_RectF rt,
+                                           FX_FLOAT fThickness,
+                                           CFX_Matrix* pMatrix) {
+  FX_FLOAT fHalfWidth = fThickness / 2.0f;
+  XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFF000000);
+  CFX_RectF rtInner(rt);
+  rtInner.Deflate(fHalfWidth, fHalfWidth);
+  XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF000000, 0xFF808080);
+}
+static void XFA_BOX_Stroke_Rect(CXFA_Box box,
+                                const CXFA_StrokeArray& strokes,
+                                CFX_Graphics* pGS,
+                                CFX_RectF rtWidget,
+                                CFX_Matrix* pMatrix) {
+  FX_BOOL bVisible = FALSE;
+  FX_FLOAT fThickness = 0;
+  int32_t i3DType = box.Get3DStyle(bVisible, fThickness);
+  if (i3DType) {
+    if (!bVisible || fThickness < 0.001f) {
+      return;
+    }
+    switch (i3DType) {
+      case XFA_ATTRIBUTEENUM_Lowered:
+        XFA_BOX_Stroke_3DRect_Lowered(pGS, rtWidget, fThickness, pMatrix);
+        break;
+      case XFA_ATTRIBUTEENUM_Raised:
+        XFA_BOX_Stroke_3DRect_Raised(pGS, rtWidget, fThickness, pMatrix);
+        break;
+      case XFA_ATTRIBUTEENUM_Etched:
+        XFA_BOX_Stroke_3DRect_Etched(pGS, rtWidget, fThickness, pMatrix);
+        break;
+      case XFA_ATTRIBUTEENUM_Embossed:
+        XFA_BOX_Stroke_3DRect_Embossed(pGS, rtWidget, fThickness, pMatrix);
+        break;
+    }
+    return;
+  }
+  FX_BOOL bClose = FALSE;
+  FX_BOOL bSameStyles = TRUE;
+  int32_t i;
+  CXFA_Stroke stroke1 = strokes[0];
+  for (i = 1; i < 8; i++) {
+    CXFA_Stroke stroke2 = strokes[i];
+    if (!stroke1.SameStyles(stroke2)) {
+      bSameStyles = FALSE;
+      break;
+    }
+    stroke1 = stroke2;
+  }
+  if (bSameStyles) {
+    stroke1 = strokes[0];
+    bClose = TRUE;
+    for (i = 2; i < 8; i += 2) {
+      CXFA_Stroke stroke2 = strokes[i];
+      if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence |
+                                           XFA_STROKE_SAMESTYLE_Corner)) {
+        bSameStyles = FALSE;
+        break;
+      }
+      stroke1 = stroke2;
+    }
+    if (bSameStyles) {
+      stroke1 = strokes[0];
+      if (stroke1.IsInverted()) {
+        bSameStyles = FALSE;
+      }
+      if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) {
+        bSameStyles = FALSE;
+      }
+    }
+  }
+  FX_BOOL bStart = TRUE;
+  CFX_Path path;
+  path.Create();
+  for (i = 0; i < 8; i++) {
+    CXFA_Stroke stroke1 = strokes[i];
+    if ((i % 1) == 0 && stroke1.GetRadius() < 0) {
+      FX_BOOL bEmpty = path.IsEmpty();
+      if (!bEmpty) {
+        XFA_BOX_StrokePath(stroke1, &path, pGS, pMatrix);
+        path.Clear();
+      }
+      bStart = TRUE;
+      continue;
+    }
+    XFA_BOX_GetPath(box, strokes, rtWidget, path, i, bStart, !bSameStyles);
+    CXFA_Stroke stroke2 = strokes[(i + 1) % 8];
+    bStart = !stroke1.SameStyles(stroke2);
+    if (bStart) {
+      XFA_BOX_StrokePath(stroke1, &path, pGS, pMatrix);
+      path.Clear();
+    }
+  }
+  FX_BOOL bEmpty = path.IsEmpty();
+  if (!bEmpty) {
+    if (bClose) {
+      path.Close();
+    }
+    XFA_BOX_StrokePath(strokes[7], &path, pGS, pMatrix);
+  }
+}
+static void XFA_BOX_Stroke(CXFA_Box box,
+                           const CXFA_StrokeArray& strokes,
+                           CFX_Graphics* pGS,
+                           CFX_RectF rtWidget,
+                           CFX_Matrix* pMatrix,
+                           FX_DWORD dwFlags) {
+  if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
+    XFA_BOX_StrokeArc(box, pGS, rtWidget, pMatrix, dwFlags);
+    return;
+  }
+  bool bVisible = false;
+  for (int32_t j = 0; j < 4; j++) {
+    if (strokes[j * 2 + 1].IsVisible()) {
+      bVisible = true;
+      break;
+    }
+  }
+  if (!bVisible) {
+    return;
+  }
+  for (int32_t i = 1; i < 8; i += 2) {
+    CXFA_Edge edge(strokes[i].GetNode());
+    FX_FLOAT fThickness = edge.GetThickness();
+    if (fThickness < 0) {
+      fThickness = 0;
+    }
+    FX_FLOAT fHalf = fThickness / 2;
+    int32_t iHand = box.GetHand();
+    switch (i) {
+      case 1:
+        if (iHand == XFA_ATTRIBUTEENUM_Left) {
+          rtWidget.top -= fHalf;
+          rtWidget.height += fHalf;
+        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+          rtWidget.top += fHalf;
+          rtWidget.height -= fHalf;
+        }
+        break;
+      case 3:
+        if (iHand == XFA_ATTRIBUTEENUM_Left) {
+          rtWidget.width += fHalf;
+        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+          rtWidget.width -= fHalf;
+        }
+        break;
+      case 5:
+        if (iHand == XFA_ATTRIBUTEENUM_Left) {
+          rtWidget.height += fHalf;
+        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+          rtWidget.height -= fHalf;
+        }
+        break;
+      case 7:
+        if (iHand == XFA_ATTRIBUTEENUM_Left) {
+          rtWidget.left -= fHalf;
+          rtWidget.width += fHalf;
+        } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
+          rtWidget.left += fHalf;
+          rtWidget.width -= fHalf;
+        }
+        break;
+    }
+  }
+  XFA_BOX_Stroke_Rect(box, strokes, pGS, rtWidget, pMatrix);
+}
+void XFA_DrawBox(CXFA_Box box,
+                 CFX_Graphics* pGS,
+                 const CFX_RectF& rtWidget,
+                 CFX_Matrix* pMatrix,
+                 FX_DWORD dwFlags) {
+  if (!box || box.GetPresence() != XFA_ATTRIBUTEENUM_Visible) {
+    return;
+  }
+  int32_t iType = box.GetClassID();
+  if (iType != XFA_ELEMENT_Arc && iType != XFA_ELEMENT_Border &&
+      iType != XFA_ELEMENT_Rectangle) {
+    return;
+  }
+  CXFA_StrokeArray strokes;
+  if (!(dwFlags & XFA_DRAWBOX_ForceRound) && iType != XFA_ELEMENT_Arc) {
+    box.GetStrokes(strokes);
+  }
+  XFA_BOX_Fill(box, strokes, pGS, rtWidget, pMatrix, dwFlags);
+  XFA_BOX_Stroke(box, strokes, pGS, rtWidget, pMatrix, dwFlags);
+}
diff --git a/xfa/fxfa/app/xfa_ffwidget.h b/xfa/fxfa/app/xfa_ffwidget.h
new file mode 100644
index 0000000..3782e3b
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffwidget.h
@@ -0,0 +1,187 @@
+// 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_FXFA_APP_XFA_FFWIDGET_H_
+#define XFA_FXFA_APP_XFA_FFWIDGET_H_
+
+#include <vector>
+
+#include "core/include/fxcodec/fx_codec_def.h"
+#include "core/include/fxge/fx_ge.h"
+#include "xfa/fxfa/parser/xfa_doclayout.h"
+#include "xfa/include/fxfa/fxfa.h"
+
+class CXFA_FFPageView;
+class CXFA_FFDocView;
+class CXFA_FFDoc;
+class CXFA_FFApp;
+
+inline FX_FLOAT XFA_UnitPx2Pt(FX_FLOAT fPx, FX_FLOAT fDpi) {
+  return fPx * 72.0f / fDpi;
+}
+#define XFA_FLOAT_PERCISION 0.001f
+enum XFA_WIDGETITEM {
+  XFA_WIDGETITEM_Parent,
+  XFA_WIDGETITEM_FirstChild,
+  XFA_WIDGETITEM_NextSibling,
+  XFA_WIDGETITEM_PrevSibling,
+};
+class CXFA_CalcData {
+ public:
+  CXFA_CalcData() : m_iRefCount(0) {}
+  ~CXFA_CalcData() { m_Globals.RemoveAll(); }
+  CFX_PtrArray m_Globals;
+  int32_t m_iRefCount;
+};
+class CXFA_FFWidget : public IXFA_Widget,
+                      public CFX_PrivateData,
+                      public CXFA_ContentLayoutItem {
+ public:
+  CXFA_FFWidget(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc);
+  virtual ~CXFA_FFWidget();
+  IXFA_PageView* GetPageView();
+  void SetPageView(IXFA_PageView* pPageView);
+  void GetWidgetRect(CFX_RectF& rtWidget);
+  CFX_RectF ReCacheWidgetRect();
+  FX_DWORD GetStatus();
+  void ModifyStatus(FX_DWORD dwAdded, FX_DWORD dwRemoved);
+  virtual FX_BOOL GetBBox(CFX_RectF& rtBox,
+                          FX_DWORD dwStatus,
+                          FX_BOOL bDrawFocus = FALSE);
+  CXFA_WidgetAcc* GetDataAcc();
+  FX_BOOL GetToolTip(CFX_WideString& wsToolTip);
+  virtual void RenderWidget(CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_DWORD dwStatus = 0,
+                            int32_t iRotate = 0);
+
+  virtual FX_BOOL IsLoaded();
+  virtual FX_BOOL LoadWidget();
+  virtual void UnloadWidget();
+  virtual FX_BOOL PerformLayout();
+  virtual FX_BOOL UpdateFWLData();
+  virtual void UpdateWidgetProperty();
+  virtual FX_BOOL OnMouseEnter();
+  virtual FX_BOOL OnMouseExit();
+  virtual FX_BOOL OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnLButtonDblClk(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnMouseWheel(FX_DWORD dwFlags,
+                               int16_t zDelta,
+                               FX_FLOAT fx,
+                               FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonDblClk(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy);
+
+  virtual FX_BOOL OnSetFocus(CXFA_FFWidget* pOldWidget);
+  virtual FX_BOOL OnKillFocus(CXFA_FFWidget* pNewWidget);
+  virtual FX_BOOL OnKeyDown(FX_DWORD dwKeyCode, FX_DWORD dwFlags);
+  virtual FX_BOOL OnKeyUp(FX_DWORD dwKeyCode, FX_DWORD dwFlags);
+  virtual FX_BOOL OnChar(FX_DWORD dwChar, FX_DWORD dwFlags);
+  virtual FX_DWORD OnHitTest(FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnSetCursor(FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL CanUndo() { return FALSE; }
+  virtual FX_BOOL CanRedo() { return FALSE; }
+  virtual FX_BOOL Undo() { return FALSE; }
+  virtual FX_BOOL Redo() { return FALSE; }
+  virtual FX_BOOL CanCopy() { return FALSE; }
+  virtual FX_BOOL CanCut() { return FALSE; }
+  virtual FX_BOOL CanPaste() { return FALSE; }
+  virtual FX_BOOL CanSelectAll() { return FALSE; }
+  virtual FX_BOOL CanDelete() { return CanCut(); }
+  virtual FX_BOOL CanDeSelect() { return CanCopy(); }
+  virtual FX_BOOL Copy(CFX_WideString& wsCopy) { return FALSE; }
+  virtual FX_BOOL Cut(CFX_WideString& wsCut) { return FALSE; }
+  virtual FX_BOOL Paste(const CFX_WideString& wsPaste) { return FALSE; }
+  virtual FX_BOOL SelectAll() { return FALSE; }
+  virtual FX_BOOL Delete() { return FALSE; }
+  virtual FX_BOOL DeSelect() { return FALSE; }
+  virtual FX_BOOL GetSuggestWords(CFX_PointF pointf,
+                                  std::vector<CFX_ByteString>& sSuggest) {
+    return FALSE;
+  }
+  virtual FX_BOOL ReplaceSpellCheckWord(CFX_PointF pointf,
+                                        const CFX_ByteStringC& bsReplace) {
+    return FALSE;
+  }
+  CXFA_FFDocView* GetDocView();
+  void SetDocView(CXFA_FFDocView* pDocView) { m_pDocView = pDocView; }
+  CXFA_FFDoc* GetDoc();
+  CXFA_FFApp* GetApp();
+  IXFA_AppProvider* GetAppProvider();
+  void InvalidateWidget(const CFX_RectF* pRect = NULL);
+  void AddInvalidateRect(const CFX_RectF* pRect = NULL);
+  FX_BOOL GetCaptionText(CFX_WideString& wsCap);
+  FX_BOOL IsFocused();
+  void Rotate2Normal(FX_FLOAT& fx, FX_FLOAT& fy);
+  void GetRotateMatrix(CFX_Matrix& mt);
+  FX_BOOL IsLayoutRectEmpty();
+  CXFA_FFWidget* GetParent();
+  FX_BOOL IsAncestorOf(CXFA_FFWidget* pWidget);
+
+ protected:
+  virtual FX_BOOL PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy);
+  void DrawBorder(CFX_Graphics* pGS,
+                  CXFA_Box box,
+                  const CFX_RectF& rtBorder,
+                  CFX_Matrix* pMatrix,
+                  FX_DWORD dwFlags = 0);
+  void GetMinMaxWidth(FX_FLOAT fMinWidth, FX_FLOAT fMaxWidth);
+  void GetMinMaxHeight(FX_FLOAT fMinHeight, FX_FLOAT fMaxHeight);
+  void GetRectWithoutRotate(CFX_RectF& rtWidget);
+  FX_BOOL IsMatchVisibleStatus(FX_DWORD dwStatus);
+
+  void EventKillFocus();
+  FX_BOOL IsButtonDown();
+  void SetButtonDown(FX_BOOL bSet);
+  CXFA_FFDocView* m_pDocView;
+  CXFA_FFPageView* m_pPageView;
+  CXFA_WidgetAcc* m_pDataAcc;
+  CFX_RectF m_rtWidget;
+};
+int32_t XFA_StrokeTypeSetLineDash(CFX_Graphics* pGraphics,
+                                  int32_t iStrokeType,
+                                  int32_t iCapType);
+CFX_GraphStateData::LineCap XFA_LineCapToFXGE(int32_t iLineCap);
+void XFA_DrawImage(CFX_Graphics* pGS,
+                   const CFX_RectF& rtImage,
+                   CFX_Matrix* pMatrix,
+                   CFX_DIBitmap* pDIBitmap,
+                   int32_t iAspect,
+                   int32_t iImageXDpi,
+                   int32_t iImageYDpi,
+                   int32_t iHorzAlign = XFA_ATTRIBUTEENUM_Left,
+                   int32_t iVertAlign = XFA_ATTRIBUTEENUM_Top);
+CFX_DIBitmap* XFA_LoadImageData(CXFA_FFDoc* pDoc,
+                                CXFA_Image* pImage,
+                                FX_BOOL& bNameImage,
+                                int32_t& iImageXDpi,
+                                int32_t& iImageYDpi);
+CFX_DIBitmap* XFA_LoadImageFromBuffer(IFX_FileRead* pImageFileRead,
+                                      FXCODEC_IMAGE_TYPE type,
+                                      int32_t& iImageXDpi,
+                                      int32_t& iImageYDpi);
+FXCODEC_IMAGE_TYPE XFA_GetImageType(const CFX_WideStringC& wsType);
+FX_CHAR* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len);
+void XFA_RectWidthoutMargin(CFX_RectF& rt,
+                            const CXFA_Margin& mg,
+                            FX_BOOL bUI = FALSE);
+FX_FLOAT XFA_GetEdgeThickness(const CXFA_StrokeArray& strokes,
+                              FX_BOOL b3DStyle,
+                              int32_t nIndex);
+CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem);
+FX_BOOL XFA_IsCreateWidget(XFA_ELEMENT iType);
+#define XFA_DRAWBOX_ForceRound 1
+#define XFA_DRAWBOX_Lowered3D 2
+void XFA_DrawBox(CXFA_Box box,
+                 CFX_Graphics* pGS,
+                 const CFX_RectF& rtWidget,
+                 CFX_Matrix* pMatrix,
+                 FX_DWORD dwFlags = 0);
+
+#endif  // XFA_FXFA_APP_XFA_FFWIDGET_H_
diff --git a/xfa/fxfa/app/xfa_ffwidgetacc.cpp b/xfa/fxfa/app/xfa_ffwidgetacc.cpp
new file mode 100644
index 0000000..500235d
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffwidgetacc.cpp
@@ -0,0 +1,1714 @@
+// 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/fxfa/app/xfa_ffwidgetacc.h"
+
+#include <algorithm>
+
+#include "xfa/fde/tto/fde_textout.h"
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffcheckbutton.h"
+#include "xfa/fxfa/app/xfa_ffchoicelist.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffpageview.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_fontmgr.h"
+#include "xfa/fxfa/app/xfa_fwladapter.h"
+#include "xfa/fxfa/app/xfa_textlayout.h"
+#include "xfa/fxfa/parser/xfa_localevalue.h"
+#include "xfa/fxfa/parser/xfa_script.h"
+
+static void XFA_FFDeleteCalcData(void* pData) {
+  if (pData) {
+    delete ((CXFA_CalcData*)pData);
+  }
+}
+static XFA_MAPDATABLOCKCALLBACKINFO gs_XFADeleteCalcData = {
+    XFA_FFDeleteCalcData, NULL};
+class CXFA_WidgetLayoutData {
+ public:
+  CXFA_WidgetLayoutData() : m_fWidgetHeight(-1) {}
+  virtual ~CXFA_WidgetLayoutData() {}
+  virtual void Release() { delete this; }
+  FX_FLOAT m_fWidgetHeight;
+};
+class CXFA_TextLayoutData : public CXFA_WidgetLayoutData {
+ public:
+  CXFA_TextLayoutData() : m_pTextLayout(NULL), m_pTextProvider(NULL) {}
+  ~CXFA_TextLayoutData() {
+    if (m_pTextLayout) {
+      delete m_pTextLayout;
+    }
+    m_pTextLayout = NULL;
+    if (m_pTextProvider) {
+      delete m_pTextProvider;
+    }
+    m_pTextProvider = NULL;
+  }
+  void LoadText(CXFA_WidgetAcc* pAcc) {
+    if (m_pTextLayout)
+      return;
+
+    m_pTextProvider = new CXFA_TextProvider(pAcc, XFA_TEXTPROVIDERTYPE_Text);
+    m_pTextLayout = new CXFA_TextLayout(m_pTextProvider);
+  }
+  CXFA_TextLayout* m_pTextLayout;
+  CXFA_TextProvider* m_pTextProvider;
+};
+class CXFA_ImageLayoutData : public CXFA_WidgetLayoutData {
+ public:
+  CXFA_ImageLayoutData()
+      : m_pDIBitmap(NULL),
+        m_bNamedImage(FALSE),
+        m_iImageXDpi(0),
+        m_iImageYDpi(0) {}
+
+  ~CXFA_ImageLayoutData() {
+    if (m_pDIBitmap && !m_bNamedImage) {
+      delete m_pDIBitmap;
+    }
+    m_pDIBitmap = NULL;
+  }
+
+  FX_BOOL LoadImageData(CXFA_WidgetAcc* pAcc) {
+    if (m_pDIBitmap) {
+      return TRUE;
+    }
+    CXFA_Value value = pAcc->GetFormValue();
+    if (!value) {
+      return FALSE;
+    }
+    CXFA_Image imageObj = value.GetImage();
+    if (!imageObj) {
+      return FALSE;
+    }
+    CXFA_FFDoc* pFFDoc = pAcc->GetDoc();
+    pAcc->SetImageImage(XFA_LoadImageData(pFFDoc, &imageObj, m_bNamedImage,
+                                          m_iImageXDpi, m_iImageYDpi));
+    return m_pDIBitmap != NULL;
+  }
+
+  CFX_DIBitmap* m_pDIBitmap;
+  FX_BOOL m_bNamedImage;
+  int32_t m_iImageXDpi;
+  int32_t m_iImageYDpi;
+};
+class CXFA_FieldLayoutData : public CXFA_WidgetLayoutData {
+ public:
+  CXFA_FieldLayoutData()
+      : m_pCapTextLayout(NULL),
+        m_pCapTextProvider(NULL),
+        m_pTextOut(NULL),
+        m_pFieldSplitArray(NULL) {}
+  ~CXFA_FieldLayoutData() {
+    if (m_pCapTextLayout) {
+      delete m_pCapTextLayout;
+    }
+    m_pCapTextLayout = NULL;
+    if (m_pCapTextProvider) {
+      delete m_pCapTextProvider;
+    }
+    m_pCapTextProvider = NULL;
+    if (m_pTextOut) {
+      m_pTextOut->Release();
+    }
+    m_pTextOut = NULL;
+    if (m_pFieldSplitArray) {
+      m_pFieldSplitArray->RemoveAll();
+      delete m_pFieldSplitArray;
+      m_pFieldSplitArray = NULL;
+    }
+  }
+  FX_BOOL LoadCaption(CXFA_WidgetAcc* pAcc) {
+    if (m_pCapTextLayout) {
+      return TRUE;
+    }
+    CXFA_Caption caption = pAcc->GetCaption();
+    if (caption && caption.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) {
+      m_pCapTextProvider =
+          new CXFA_TextProvider(pAcc, XFA_TEXTPROVIDERTYPE_Caption);
+      m_pCapTextLayout = new CXFA_TextLayout(m_pCapTextProvider);
+      return TRUE;
+    }
+    return FALSE;
+  }
+  CXFA_TextLayout* m_pCapTextLayout;
+  CXFA_TextProvider* m_pCapTextProvider;
+  IFDE_TextOut* m_pTextOut;
+  CFX_FloatArray* m_pFieldSplitArray;
+};
+class CXFA_TextEditData : public CXFA_FieldLayoutData {
+ public:
+};
+class CXFA_ImageEditData : public CXFA_FieldLayoutData {
+ public:
+  CXFA_ImageEditData()
+      : m_pDIBitmap(NULL),
+        m_bNamedImage(FALSE),
+        m_iImageXDpi(0),
+        m_iImageYDpi(0) {}
+
+  ~CXFA_ImageEditData() {
+    if (m_pDIBitmap && !m_bNamedImage) {
+      delete m_pDIBitmap;
+    }
+    m_pDIBitmap = NULL;
+  }
+  FX_BOOL LoadImageData(CXFA_WidgetAcc* pAcc) {
+    if (m_pDIBitmap) {
+      return TRUE;
+    }
+    CXFA_Value value = pAcc->GetFormValue();
+    if (!value) {
+      return FALSE;
+    }
+    CXFA_Image imageObj = value.GetImage();
+    CXFA_FFDoc* pFFDoc = pAcc->GetDoc();
+    pAcc->SetImageEditImage(XFA_LoadImageData(pFFDoc, &imageObj, m_bNamedImage,
+                                              m_iImageXDpi, m_iImageYDpi));
+    return m_pDIBitmap != NULL;
+  }
+  CFX_DIBitmap* m_pDIBitmap;
+  FX_BOOL m_bNamedImage;
+  int32_t m_iImageXDpi;
+  int32_t m_iImageYDpi;
+};
+CXFA_WidgetAcc::CXFA_WidgetAcc(CXFA_FFDocView* pDocView, CXFA_Node* pNode)
+    : CXFA_WidgetData(pNode),
+      m_pDocView(pDocView),
+      m_pLayoutData(NULL),
+      m_nRecursionDepth(0) {}
+CXFA_WidgetAcc::~CXFA_WidgetAcc() {
+  if (m_pLayoutData) {
+    m_pLayoutData->Release();
+    m_pLayoutData = NULL;
+  }
+}
+FX_BOOL CXFA_WidgetAcc::GetName(CFX_WideString& wsName, int32_t iNameType) {
+  if (iNameType == 0) {
+    m_pNode->TryCData(XFA_ATTRIBUTE_Name, wsName);
+    return !wsName.IsEmpty();
+  }
+  m_pNode->GetSOMExpression(wsName);
+  if (iNameType == 2 && wsName.GetLength() >= 15) {
+    CFX_WideStringC wsPre = FX_WSTRC(L"xfa[0].form[0].");
+    if (wsPre == CFX_WideStringC(wsName, wsPre.GetLength())) {
+      wsName.Delete(0, wsPre.GetLength());
+    }
+  }
+  return TRUE;
+}
+CXFA_Node* CXFA_WidgetAcc::GetDatasets() {
+  return m_pNode->GetBindData();
+}
+FX_BOOL CXFA_WidgetAcc::ProcessValueChanged() {
+  m_pDocView->AddValidateWidget(this);
+  m_pDocView->AddCalculateWidgetAcc(this);
+  m_pDocView->RunCalculateWidgets();
+  m_pDocView->RunValidate();
+  return TRUE;
+}
+void CXFA_WidgetAcc::ResetData() {
+  CFX_WideString wsValue;
+  XFA_ELEMENT eUIType = (XFA_ELEMENT)GetUIType();
+  switch (eUIType) {
+    case XFA_ELEMENT_ImageEdit: {
+      CXFA_Value imageValue = GetDefaultValue();
+      CXFA_Image image = imageValue.GetImage();
+      CFX_WideString wsContentType, wsHref;
+      if (image) {
+        image.GetContent(wsValue);
+        image.GetContentType(wsContentType);
+        image.GetHref(wsHref);
+      }
+      SetImageEdit(wsContentType, wsHref, wsValue);
+    } break;
+    case XFA_ELEMENT_ExclGroup: {
+      CXFA_Node* pNextChild = m_pNode->GetNodeItem(
+          XFA_NODEITEM_FirstChild, XFA_OBJECTTYPE_ContainerNode);
+      while (pNextChild) {
+        CXFA_Node* pChild = pNextChild;
+        CXFA_WidgetAcc* pAcc = (CXFA_WidgetAcc*)pChild->GetWidgetData();
+        if (!pAcc) {
+          continue;
+        }
+        CXFA_Value defValue(NULL);
+        if (wsValue.IsEmpty() && (defValue = pAcc->GetDefaultValue())) {
+          defValue.GetChildValueContent(wsValue);
+          SetValue(wsValue, XFA_VALUEPICTURE_Raw);
+          pAcc->SetValue(wsValue, XFA_VALUEPICTURE_Raw);
+        } else {
+          CXFA_Node* pItems = pChild->GetChild(0, XFA_ELEMENT_Items);
+          if (!pItems) {
+            continue;
+          }
+          CFX_WideString itemText;
+          if (pItems->CountChildren(XFA_ELEMENT_UNKNOWN) > 1) {
+            itemText = pItems->GetChild(1, XFA_ELEMENT_UNKNOWN)->GetContent();
+          }
+          pAcc->SetValue(itemText, XFA_VALUEPICTURE_Raw);
+        }
+        pNextChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling,
+                                         XFA_OBJECTTYPE_ContainerNode);
+      }
+    } break;
+    case XFA_ELEMENT_ChoiceList:
+      ClearAllSelections();
+    default:
+      if (CXFA_Value defValue = GetDefaultValue()) {
+        defValue.GetChildValueContent(wsValue);
+      }
+      SetValue(wsValue, XFA_VALUEPICTURE_Raw);
+      break;
+  }
+}
+void CXFA_WidgetAcc::SetImageEdit(const CFX_WideStringC& wsContentType,
+                                  const CFX_WideStringC& wsHref,
+                                  const CFX_WideStringC& wsData) {
+  CXFA_Image image = GetFormValue().GetImage();
+  if (image) {
+    image.SetContentType(wsContentType);
+    image.SetHref(wsHref);
+  }
+  CFX_WideString wsFormatValue(wsData);
+  GetFormatDataValue(wsData, wsFormatValue);
+  m_pNode->SetContent(wsData, wsFormatValue, TRUE);
+  CXFA_Node* pBind = GetDatasets();
+  if (!pBind) {
+    image.SetTransferEncoding(XFA_ATTRIBUTEENUM_Base64);
+    return;
+  }
+  pBind->SetCData(XFA_ATTRIBUTE_ContentType, wsContentType);
+  CXFA_Node* pHrefNode = pBind->GetNodeItem(XFA_NODEITEM_FirstChild);
+  if (pHrefNode) {
+    pHrefNode->SetCData(XFA_ATTRIBUTE_Value, wsHref);
+  } else {
+    IFDE_XMLNode* pXMLNode = pBind->GetXMLMappingNode();
+    FXSYS_assert(pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element);
+    ((IFDE_XMLElement*)pXMLNode)->SetString(FX_WSTRC(L"href"), wsHref);
+  }
+}
+
+CXFA_WidgetAcc* CXFA_WidgetAcc::GetExclGroup() {
+  CXFA_Node* pExcl = m_pNode->GetNodeItem(XFA_NODEITEM_Parent);
+  if (!pExcl || pExcl->GetClassID() != XFA_ELEMENT_ExclGroup) {
+    return NULL;
+  }
+  return (CXFA_WidgetAcc*)pExcl->GetWidgetData();
+}
+CXFA_FFDocView* CXFA_WidgetAcc::GetDocView() {
+  return m_pDocView;
+}
+CXFA_FFDoc* CXFA_WidgetAcc::GetDoc() {
+  return (CXFA_FFDoc*)m_pDocView->GetDoc();
+}
+CXFA_FFApp* CXFA_WidgetAcc::GetApp() {
+  return GetDoc()->GetApp();
+}
+IXFA_AppProvider* CXFA_WidgetAcc::GetAppProvider() {
+  return GetApp()->GetAppProvider();
+}
+int32_t CXFA_WidgetAcc::ProcessEvent(int32_t iActivity,
+                                     CXFA_EventParam* pEventParam) {
+  if (GetClassID() == XFA_ELEMENT_Draw) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  int32_t iRet = XFA_EVENTERROR_NotExist;
+  CXFA_NodeArray eventArray;
+  int32_t iCounts =
+      GetEventByActivity(iActivity, eventArray, pEventParam->m_bIsFormReady);
+  for (int32_t i = 0; i < iCounts; i++) {
+    CXFA_Event event(eventArray[i]);
+    int32_t result = ProcessEvent(event, pEventParam);
+    if (i == 0) {
+      iRet = result;
+    } else if (result == XFA_EVENTERROR_Sucess) {
+      iRet = result;
+    }
+  }
+  return iRet;
+}
+int32_t CXFA_WidgetAcc::ProcessEvent(CXFA_Event& event,
+                                     CXFA_EventParam* pEventParam) {
+  if (!event) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  switch (event.GetEventType()) {
+    case XFA_ELEMENT_Execute:
+      break;
+    case XFA_ELEMENT_Script: {
+      CXFA_Script script = event.GetScript();
+      return ExecuteScript(script, pEventParam);
+    } break;
+    case XFA_ELEMENT_SignData:
+      break;
+    case XFA_ELEMENT_Submit: {
+      CXFA_Submit submit = event.GetSubmit();
+      return GetDoc()->GetDocProvider()->SubmitData(GetDoc(), submit);
+    }
+    default:
+      break;
+  }
+  return XFA_EVENTERROR_NotExist;
+}
+int32_t CXFA_WidgetAcc::ProcessCalculate() {
+  if (GetClassID() == XFA_ELEMENT_Draw) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  CXFA_Calculate calc = GetCalculate();
+  if (!calc) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  if (GetNode()->HasFlag(XFA_NODEFLAG_UserInteractive)) {
+    return XFA_EVENTERROR_Disabled;
+  }
+  CXFA_EventParam EventParam;
+  EventParam.m_eType = XFA_EVENT_Calculate;
+  CXFA_Script script = calc.GetScript();
+  int32_t iRet = ExecuteScript(script, &EventParam);
+  if (iRet == XFA_EVENTERROR_Sucess) {
+    if (GetRawValue() != EventParam.m_wsResult) {
+      const bool bNotify = GetDoc()->GetDocType() == XFA_DOCTYPE_Static;
+      SetValue(EventParam.m_wsResult, XFA_VALUEPICTURE_Raw);
+      UpdateUIDisplay();
+      if (bNotify) {
+        NotifyEvent(XFA_WIDGETEVENT_PostContentChanged, NULL, NULL, NULL);
+      }
+      iRet = XFA_EVENTERROR_Sucess;
+    }
+  }
+  return iRet;
+}
+void CXFA_WidgetAcc::ProcessScriptTestValidate(CXFA_Validate validate,
+                                               int32_t iRet,
+                                               FXJSE_HVALUE pRetValue,
+                                               FX_BOOL bVersionFlag) {
+  if (iRet == XFA_EVENTERROR_Sucess && pRetValue) {
+    if (FXJSE_Value_IsBoolean(pRetValue) && !FXJSE_Value_ToBoolean(pRetValue)) {
+      IXFA_AppProvider* pAppProvider = GetAppProvider();
+      if (!pAppProvider) {
+        return;
+      }
+      CFX_WideString wsTitle;
+      pAppProvider->LoadString(XFA_IDS_AppName, wsTitle);
+      CFX_WideString wsScriptMsg;
+      validate.GetScriptMessageText(wsScriptMsg);
+      int32_t eScriptTest = validate.GetScriptTest();
+      if (eScriptTest == XFA_ATTRIBUTEENUM_Warning) {
+        if (GetNode()->HasFlag(XFA_NODEFLAG_UserInteractive)) {
+          return;
+        }
+        if (wsScriptMsg.IsEmpty()) {
+          GetValidateMessage(pAppProvider, wsScriptMsg, FALSE, bVersionFlag);
+        }
+        if (bVersionFlag) {
+          pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning,
+                               XFA_MB_OK);
+          return;
+        }
+        if (pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning,
+                                 XFA_MB_YesNo) == XFA_IDYes) {
+          GetNode()->SetFlag(XFA_NODEFLAG_UserInteractive, TRUE, FALSE);
+        }
+      } else {
+        if (wsScriptMsg.IsEmpty()) {
+          GetValidateMessage(pAppProvider, wsScriptMsg, TRUE, bVersionFlag);
+        }
+        pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK);
+      }
+    }
+  }
+}
+int32_t CXFA_WidgetAcc::ProcessFormatTestValidate(CXFA_Validate validate,
+                                                  FX_BOOL bVersionFlag) {
+  CFX_WideString wsRawValue = GetRawValue();
+  if (!wsRawValue.IsEmpty()) {
+    CFX_WideString wsPicture;
+    validate.GetPicture(wsPicture);
+    if (wsPicture.IsEmpty()) {
+      return XFA_EVENTERROR_NotExist;
+    }
+    IFX_Locale* pLocale = GetLocal();
+    if (!pLocale) {
+      return XFA_EVENTERROR_NotExist;
+    }
+    CXFA_LocaleValue lcValue = XFA_GetLocaleValue(this);
+    if (!lcValue.ValidateValue(lcValue.GetValue(), wsPicture, pLocale)) {
+      IXFA_AppProvider* pAppProvider = GetAppProvider();
+      if (!pAppProvider) {
+        return XFA_EVENTERROR_NotExist;
+      }
+      CFX_WideString wsFormatMsg;
+      validate.GetFormatMessageText(wsFormatMsg);
+      CFX_WideString wsTitle;
+      pAppProvider->LoadString(XFA_IDS_AppName, wsTitle);
+      int32_t eFormatTest = validate.GetFormatTest();
+      if (eFormatTest == XFA_ATTRIBUTEENUM_Error) {
+        if (wsFormatMsg.IsEmpty()) {
+          GetValidateMessage(pAppProvider, wsFormatMsg, TRUE, bVersionFlag);
+        }
+        pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK);
+        return XFA_EVENTERROR_Sucess;
+      }
+      if (GetNode()->HasFlag(XFA_NODEFLAG_UserInteractive)) {
+        return XFA_EVENTERROR_NotExist;
+      }
+      if (wsFormatMsg.IsEmpty()) {
+        GetValidateMessage(pAppProvider, wsFormatMsg, FALSE, bVersionFlag);
+      }
+      if (bVersionFlag) {
+        pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning,
+                             XFA_MB_OK);
+        return XFA_EVENTERROR_Sucess;
+      }
+      if (pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning,
+                               XFA_MB_YesNo) == XFA_IDYes) {
+        GetNode()->SetFlag(XFA_NODEFLAG_UserInteractive, TRUE, FALSE);
+      }
+      return XFA_EVENTERROR_Sucess;
+    }
+  }
+  return XFA_EVENTERROR_NotExist;
+}
+int32_t CXFA_WidgetAcc::ProcessNullTestValidate(CXFA_Validate validate,
+                                                int32_t iFlags,
+                                                FX_BOOL bVersionFlag) {
+  CFX_WideString wsValue;
+  GetValue(wsValue, XFA_VALUEPICTURE_Raw);
+  if (!wsValue.IsEmpty()) {
+    return XFA_EVENTERROR_Sucess;
+  }
+  if (m_bIsNull && (m_bPreNull == m_bIsNull)) {
+    return XFA_EVENTERROR_Sucess;
+  }
+  int32_t eNullTest = validate.GetNullTest();
+  CFX_WideString wsNullMsg;
+  validate.GetNullMessageText(wsNullMsg);
+  if (iFlags & 0x01) {
+    int32_t iRet = XFA_EVENTERROR_Sucess;
+    if (eNullTest != XFA_ATTRIBUTEENUM_Disabled) {
+      iRet = XFA_EVENTERROR_Error;
+    }
+    if (!wsNullMsg.IsEmpty()) {
+      if (eNullTest != XFA_ATTRIBUTEENUM_Disabled) {
+        m_pDocView->m_arrNullTestMsg.Add(wsNullMsg);
+        return XFA_EVENTERROR_Error;
+      }
+      return XFA_EVENTERROR_Sucess;
+    }
+    return iRet;
+  }
+  if (wsNullMsg.IsEmpty() && bVersionFlag &&
+      eNullTest != XFA_ATTRIBUTEENUM_Disabled) {
+    return XFA_EVENTERROR_Error;
+  }
+  IXFA_AppProvider* pAppProvider = GetAppProvider();
+  if (!pAppProvider) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  CFX_WideString wsCaptionName;
+  CFX_WideString wsTitle;
+  pAppProvider->LoadString(XFA_IDS_AppName, wsTitle);
+  switch (eNullTest) {
+    case XFA_ATTRIBUTEENUM_Error: {
+      if (wsNullMsg.IsEmpty()) {
+        GetValidateCaptionName(wsCaptionName, bVersionFlag);
+        CFX_WideString wsError;
+        pAppProvider->LoadString(XFA_IDS_ValidateNullError, wsError);
+        wsNullMsg.Format(wsError, (const FX_WCHAR*)wsCaptionName);
+      }
+      pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Status, XFA_MB_OK);
+      return XFA_EVENTERROR_Error;
+    }
+    case XFA_ATTRIBUTEENUM_Warning: {
+      if (GetNode()->HasFlag(XFA_NODEFLAG_UserInteractive)) {
+        return TRUE;
+      }
+      if (wsNullMsg.IsEmpty()) {
+        GetValidateCaptionName(wsCaptionName, bVersionFlag);
+        CFX_WideString wsWarning;
+        pAppProvider->LoadString(XFA_IDS_ValidateNullWarning, wsWarning);
+        wsNullMsg.Format(wsWarning, (const FX_WCHAR*)wsCaptionName,
+                         (const FX_WCHAR*)wsCaptionName);
+      }
+      if (pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Warning,
+                               XFA_MB_YesNo) == XFA_IDYes) {
+        GetNode()->SetFlag(XFA_NODEFLAG_UserInteractive, TRUE, FALSE);
+      }
+      return XFA_EVENTERROR_Error;
+    }
+    case XFA_ATTRIBUTEENUM_Disabled:
+    default:
+      break;
+  }
+  return XFA_EVENTERROR_Sucess;
+}
+void CXFA_WidgetAcc::GetValidateCaptionName(CFX_WideString& wsCaptionName,
+                                            FX_BOOL bVersionFlag) {
+  if (!bVersionFlag) {
+    CXFA_Caption caption = GetCaption();
+    if (caption) {
+      CXFA_Value capValue = caption.GetValue();
+      if (capValue) {
+        CXFA_Text capText = capValue.GetText();
+        if (capText) {
+          capText.GetContent(wsCaptionName);
+        }
+      }
+    }
+  }
+  if (wsCaptionName.IsEmpty()) {
+    GetName(wsCaptionName);
+  }
+}
+void CXFA_WidgetAcc::GetValidateMessage(IXFA_AppProvider* pAppProvider,
+                                        CFX_WideString& wsMessage,
+                                        FX_BOOL bError,
+                                        FX_BOOL bVersionFlag) {
+  CFX_WideString wsCaptionName;
+  GetValidateCaptionName(wsCaptionName, bVersionFlag);
+  CFX_WideString wsError;
+  if (bVersionFlag) {
+    pAppProvider->LoadString(XFA_IDS_ValidateFailed, wsError);
+    wsMessage.Format(wsError, (const FX_WCHAR*)wsCaptionName);
+    return;
+  }
+  if (bError) {
+    pAppProvider->LoadString(XFA_IDS_ValidateError, wsError);
+    wsMessage.Format(wsError, (const FX_WCHAR*)wsCaptionName);
+    return;
+  }
+  CFX_WideString wsWarning;
+  pAppProvider->LoadString(XFA_IDS_ValidateWarning, wsWarning);
+  wsMessage.Format(wsWarning, (const FX_WCHAR*)wsCaptionName,
+                   (const FX_WCHAR*)wsCaptionName);
+}
+int32_t CXFA_WidgetAcc::ProcessValidate(int32_t iFlags) {
+  if (GetClassID() == XFA_ELEMENT_Draw) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  CXFA_Validate validate = GetValidate();
+  if (!validate) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  FX_BOOL bInitDoc = validate.GetNode()->HasFlag(XFA_NODEFLAG_NeedsInitApp);
+  FX_BOOL bStatus =
+      m_pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End;
+  int32_t iFormat = 0;
+  FXJSE_HVALUE pRetValue = NULL;
+  int32_t iRet = XFA_EVENTERROR_NotExist;
+  CXFA_Script script = validate.GetScript();
+  if (script) {
+    CXFA_EventParam eParam;
+    eParam.m_eType = XFA_EVENT_Validate;
+    eParam.m_pTarget = this;
+    iRet = ExecuteScript(script, &eParam,
+                         ((bInitDoc || bStatus) && GetRawValue().IsEmpty())
+                             ? nullptr
+                             : &pRetValue);
+  }
+  XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode();
+  FX_BOOL bVersionFlag = FALSE;
+  if (version < XFA_VERSION_208) {
+    bVersionFlag = TRUE;
+  }
+  if (bInitDoc) {
+    validate.GetNode()->SetFlag(XFA_NODEFLAG_NeedsInitApp, FALSE, FALSE);
+  } else {
+    iFormat = ProcessFormatTestValidate(validate, bVersionFlag);
+    if (!bVersionFlag) {
+      bVersionFlag = GetDoc()->GetXFADoc()->HasFlag(XFA_DOCFLAG_Scripting);
+    }
+    iRet |= ProcessNullTestValidate(validate, iFlags, bVersionFlag);
+  }
+  if (iFormat != XFA_EVENTERROR_Sucess) {
+    ProcessScriptTestValidate(validate, iRet, pRetValue, bVersionFlag);
+  }
+  if (pRetValue) {
+    FXJSE_Value_Release(pRetValue);
+  }
+  return iRet | iFormat;
+}
+int32_t CXFA_WidgetAcc::ExecuteScript(CXFA_Script script,
+                                      CXFA_EventParam* pEventParam,
+                                      FXJSE_HVALUE* pRetValue) {
+  static const uint32_t MAX_RECURSION_DEPTH = 2;
+  if (m_nRecursionDepth > MAX_RECURSION_DEPTH)
+    return XFA_EVENTERROR_Sucess;
+  FXSYS_assert(pEventParam);
+  if (!script) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  if (script.GetRunAt() == XFA_ATTRIBUTEENUM_Server) {
+    return XFA_EVENTERROR_Disabled;
+  }
+  CFX_WideString wsExpression;
+  script.GetExpression(wsExpression);
+  if (wsExpression.IsEmpty()) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  XFA_SCRIPTTYPE eScriptType = script.GetContentType();
+  if (eScriptType == XFA_SCRIPTTYPE_Unkown) {
+    return XFA_EVENTERROR_Sucess;
+  }
+  CXFA_FFDoc* pDoc = GetDoc();
+  IXFA_ScriptContext* pContext = pDoc->GetXFADoc()->GetScriptContext();
+  pContext->SetEventParam(*pEventParam);
+  pContext->SetRunAtType((XFA_ATTRIBUTEENUM)script.GetRunAt());
+  CXFA_NodeArray refNodes;
+  if (pEventParam->m_eType == XFA_EVENT_InitCalculate ||
+      pEventParam->m_eType == XFA_EVENT_Calculate) {
+    pContext->SetNodesOfRunScript(&refNodes);
+  }
+  FXJSE_HVALUE hRetValue = FXJSE_Value_Create(pContext->GetRuntime());
+  ++m_nRecursionDepth;
+  FX_BOOL bRet = pContext->RunScript((XFA_SCRIPTLANGTYPE)eScriptType,
+                                     wsExpression, hRetValue, m_pNode);
+  --m_nRecursionDepth;
+  int32_t iRet = XFA_EVENTERROR_Error;
+  if (bRet) {
+    iRet = XFA_EVENTERROR_Sucess;
+    if (pEventParam->m_eType == XFA_EVENT_Calculate ||
+        pEventParam->m_eType == XFA_EVENT_InitCalculate) {
+      if (!FXJSE_Value_IsUndefined(hRetValue)) {
+        if (!FXJSE_Value_IsNull(hRetValue)) {
+          CFX_ByteString bsString;
+          FXJSE_Value_ToUTF8String(hRetValue, bsString);
+          pEventParam->m_wsResult =
+              CFX_WideString::FromUTF8(bsString, bsString.GetLength());
+        }
+        iRet = XFA_EVENTERROR_Sucess;
+      } else {
+        iRet = XFA_EVENTERROR_Error;
+      }
+      if (pEventParam->m_eType == XFA_EVENT_InitCalculate) {
+        if ((iRet == XFA_EVENTERROR_Sucess) &&
+            (GetRawValue() != pEventParam->m_wsResult)) {
+          SetValue(pEventParam->m_wsResult, XFA_VALUEPICTURE_Raw);
+          m_pDocView->AddValidateWidget(this);
+        }
+      }
+      int32_t iRefs = refNodes.GetSize();
+      for (int32_t r = 0; r < iRefs; r++) {
+        CXFA_WidgetAcc* pRefAcc = (CXFA_WidgetAcc*)refNodes[r]->GetWidgetData();
+        if (pRefAcc && pRefAcc == this) {
+          continue;
+        }
+        CXFA_Node* pRefNode = refNodes[r];
+        CXFA_CalcData* pGlobalData =
+            (CXFA_CalcData*)pRefNode->GetUserData(XFA_CalcData);
+        if (!pGlobalData) {
+          pGlobalData = new CXFA_CalcData;
+          pRefNode->SetUserData(XFA_CalcData, pGlobalData,
+                                &gs_XFADeleteCalcData);
+        }
+        if (pGlobalData->m_Globals.Find(this) < 0) {
+          pGlobalData->m_Globals.Add(this);
+        }
+      }
+    }
+  }
+  if (pRetValue) {
+    *pRetValue = hRetValue;
+  } else {
+    FXJSE_Value_Release(hRetValue);
+  }
+  pContext->SetNodesOfRunScript(NULL);
+  return iRet;
+}
+CXFA_FFWidget* CXFA_WidgetAcc::GetNextWidget(CXFA_FFWidget* pWidget) {
+  CXFA_LayoutItem* pLayout = nullptr;
+  if (pWidget) {
+    pLayout = pWidget->GetNext();
+  } else {
+    pLayout = m_pDocView->GetXFALayout()->GetLayoutItem(m_pNode);
+  }
+  return static_cast<CXFA_FFWidget*>(pLayout);
+}
+void CXFA_WidgetAcc::UpdateUIDisplay(CXFA_FFWidget* pExcept) {
+  CXFA_FFWidget* pWidget = NULL;
+  while ((pWidget = GetNextWidget(pWidget))) {
+    if (pWidget == pExcept || !pWidget->IsLoaded() ||
+        (GetUIType() != XFA_ELEMENT_CheckButton && pWidget->IsFocused())) {
+      continue;
+    }
+    pWidget->UpdateFWLData();
+    pWidget->AddInvalidateRect();
+  }
+}
+void CXFA_WidgetAcc::NotifyEvent(FX_DWORD dwEvent,
+                                 CXFA_FFWidget* pWidget,
+                                 void* pParam,
+                                 void* pAdditional) {
+  IXFA_DocProvider* pDocProvider = GetDoc()->GetDocProvider();
+  if (pWidget) {
+    pDocProvider->WidgetEvent(pWidget, this, dwEvent, pParam, pAdditional);
+  } else {
+    pWidget = GetNextWidget(pWidget);
+    if (pWidget == NULL) {
+      pDocProvider->WidgetEvent(NULL, this, dwEvent, pParam, pAdditional);
+      return;
+    }
+    while (pWidget) {
+      pDocProvider->WidgetEvent(pWidget, this, dwEvent, pParam, pAdditional);
+      pWidget = GetNextWidget(pWidget);
+    }
+  }
+}
+void CXFA_WidgetAcc::CalcCaptionSize(CFX_SizeF& szCap) {
+  CXFA_Caption caption = GetCaption();
+  if (!caption || caption.GetPresence() != XFA_ATTRIBUTEENUM_Visible) {
+    return;
+  }
+  LoadCaption();
+  XFA_ELEMENT eUIType = (XFA_ELEMENT)GetUIType();
+  int32_t iCapPlacement = caption.GetPlacementType();
+  FX_FLOAT fCapReserve = caption.GetReserve();
+  const bool bVert = iCapPlacement == XFA_ATTRIBUTEENUM_Top ||
+                     iCapPlacement == XFA_ATTRIBUTEENUM_Bottom;
+  const bool bReserveExit = fCapReserve > 0.01;
+  CXFA_TextLayout* pCapTextLayout =
+      ((CXFA_FieldLayoutData*)m_pLayoutData)->m_pCapTextLayout;
+  if (pCapTextLayout) {
+    if (!bVert && eUIType != XFA_ELEMENT_Button) {
+      szCap.x = fCapReserve;
+    }
+    CFX_SizeF minSize;
+    pCapTextLayout->CalcSize(minSize, szCap, szCap);
+    if (bReserveExit) {
+      bVert ? szCap.y = fCapReserve : szCap.x = fCapReserve;
+    }
+  } else {
+    FX_FLOAT fFontSize = 10.0f;
+    if (CXFA_Font font = caption.GetFont()) {
+      fFontSize = font.GetFontSize();
+    } else if (CXFA_Font widgetfont = GetFont()) {
+      fFontSize = widgetfont.GetFontSize();
+    }
+    if (bVert) {
+      szCap.y = fCapReserve > 0 ? fCapReserve : fFontSize;
+    } else {
+      szCap.x = fCapReserve > 0 ? fCapReserve : 0;
+      szCap.y = fFontSize;
+    }
+  }
+  if (CXFA_Margin mgCap = caption.GetMargin()) {
+    FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset;
+    mgCap.GetLeftInset(fLeftInset);
+    mgCap.GetTopInset(fTopInset);
+    mgCap.GetRightInset(fRightInset);
+    mgCap.GetBottomInset(fBottomInset);
+    if (bReserveExit) {
+      bVert ? (szCap.x += fLeftInset + fRightInset)
+            : (szCap.y += fTopInset + fBottomInset);
+    } else {
+      szCap.x += fLeftInset + fRightInset;
+      szCap.y += fTopInset + fBottomInset;
+    }
+  }
+}
+FX_BOOL CXFA_WidgetAcc::CalculateFieldAutoSize(CFX_SizeF& size) {
+  CFX_SizeF szCap;
+  CalcCaptionSize(szCap);
+  CFX_RectF rtUIMargin;
+  GetUIMargin(rtUIMargin);
+  size.x += rtUIMargin.left + rtUIMargin.width;
+  size.y += rtUIMargin.top + rtUIMargin.height;
+  if (szCap.x > 0 && szCap.y > 0) {
+    int32_t iCapPlacement = GetCaption().GetPlacementType();
+    switch (iCapPlacement) {
+      case XFA_ATTRIBUTEENUM_Left:
+      case XFA_ATTRIBUTEENUM_Right:
+      case XFA_ATTRIBUTEENUM_Inline: {
+        size.x += szCap.x;
+        size.y = std::max(size.y, szCap.y);
+      } break;
+      case XFA_ATTRIBUTEENUM_Top:
+      case XFA_ATTRIBUTEENUM_Bottom: {
+        size.y += szCap.y;
+        size.x = std::max(size.x, szCap.x);
+      }
+      default:
+        break;
+    }
+  }
+  return CalculateWidgetAutoSize(size);
+}
+FX_BOOL CXFA_WidgetAcc::CalculateWidgetAutoSize(CFX_SizeF& size) {
+  CXFA_Margin mgWidget = GetMargin();
+  if (mgWidget) {
+    FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset;
+    mgWidget.GetLeftInset(fLeftInset);
+    mgWidget.GetTopInset(fTopInset);
+    mgWidget.GetRightInset(fRightInset);
+    mgWidget.GetBottomInset(fBottomInset);
+    size.x += fLeftInset + fRightInset;
+    size.y += fTopInset + fBottomInset;
+  }
+  CXFA_Para para = GetPara();
+  if (para) {
+    size.x += para.GetMarginLeft();
+    size.x += para.GetTextIndent();
+  }
+  FX_FLOAT fVal = 0, fMin = 0, fMax = 0;
+  if (GetWidth(fVal)) {
+    size.x = fVal;
+  } else {
+    if (GetMinWidth(fMin)) {
+      size.x = std::max(size.x, fMin);
+    }
+    if (GetMaxWidth(fMax) && fMax > 0) {
+      size.x = std::min(size.x, fMax);
+    }
+  }
+  fVal = 0, fMin = 0, fMax = 0;
+  if (GetHeight(fVal)) {
+    size.y = fVal;
+  } else {
+    if (GetMinHeight(fMin)) {
+      size.y = std::max(size.y, fMin);
+    }
+    if (GetMaxHeight(fMax) && fMax > 0) {
+      size.y = std::min(size.y, fMax);
+    }
+  }
+  return TRUE;
+}
+void CXFA_WidgetAcc::CalculateTextContentSize(CFX_SizeF& size) {
+  FX_FLOAT fFontSize = GetFontSize();
+  CFX_WideString wsText;
+  GetValue(wsText, XFA_VALUEPICTURE_Display);
+  if (wsText.IsEmpty()) {
+    size.y += fFontSize;
+    return;
+  }
+  FX_WCHAR wcEnter = '\n';
+  FX_WCHAR wsLast = wsText.GetAt(wsText.GetLength() - 1);
+  if (wsLast == wcEnter) {
+    wsText = wsText + wcEnter;
+  }
+  if (!((CXFA_FieldLayoutData*)m_pLayoutData)->m_pTextOut) {
+    ((CXFA_FieldLayoutData*)m_pLayoutData)->m_pTextOut = IFDE_TextOut::Create();
+    IFDE_TextOut* pTextOut = ((CXFA_FieldLayoutData*)m_pLayoutData)->m_pTextOut;
+    pTextOut->SetFont(GetFDEFont());
+    pTextOut->SetFontSize(fFontSize);
+    pTextOut->SetLineBreakTolerance(fFontSize * 0.2f);
+    pTextOut->SetLineSpace(GetLineHeight());
+    FX_DWORD dwStyles = FDE_TTOSTYLE_LastLineHeight;
+    if (GetUIType() == XFA_ELEMENT_TextEdit && IsMultiLine()) {
+      dwStyles |= FDE_TTOSTYLE_LineWrap;
+    }
+    pTextOut->SetStyles(dwStyles);
+  }
+  ((CXFA_FieldLayoutData*)m_pLayoutData)
+      ->m_pTextOut->CalcLogicSize(wsText, wsText.GetLength(), size);
+}
+FX_BOOL CXFA_WidgetAcc::CalculateTextEditAutoSize(CFX_SizeF& size) {
+  if (size.x > 0) {
+    CFX_SizeF szOrz = size;
+    CFX_SizeF szCap;
+    CalcCaptionSize(szCap);
+    FX_BOOL bCapExit = szCap.x > 0.01 && szCap.y > 0.01;
+    int32_t iCapPlacement = XFA_ATTRIBUTEENUM_Unknown;
+    if (bCapExit) {
+      iCapPlacement = GetCaption().GetPlacementType();
+      switch (iCapPlacement) {
+        case XFA_ATTRIBUTEENUM_Left:
+        case XFA_ATTRIBUTEENUM_Right:
+        case XFA_ATTRIBUTEENUM_Inline: {
+          size.x -= szCap.x;
+        }
+        default:
+          break;
+      }
+    }
+    CFX_RectF rtUIMargin;
+    GetUIMargin(rtUIMargin);
+    size.x -= rtUIMargin.left + rtUIMargin.width;
+    CXFA_Margin mgWidget = GetMargin();
+    if (mgWidget) {
+      FX_FLOAT fLeftInset, fRightInset;
+      mgWidget.GetLeftInset(fLeftInset);
+      mgWidget.GetRightInset(fRightInset);
+      size.x -= fLeftInset + fRightInset;
+    }
+    CalculateTextContentSize(size);
+    size.y += rtUIMargin.top + rtUIMargin.height;
+    if (bCapExit) {
+      switch (iCapPlacement) {
+        case XFA_ATTRIBUTEENUM_Left:
+        case XFA_ATTRIBUTEENUM_Right:
+        case XFA_ATTRIBUTEENUM_Inline: {
+          size.y = std::max(size.y, szCap.y);
+        } break;
+        case XFA_ATTRIBUTEENUM_Top:
+        case XFA_ATTRIBUTEENUM_Bottom: {
+          size.y += szCap.y;
+        }
+        default:
+          break;
+      }
+    }
+    size.x = szOrz.x;
+    return CalculateWidgetAutoSize(size);
+  }
+  CalculateTextContentSize(size);
+  return CalculateFieldAutoSize(size);
+}
+FX_BOOL CXFA_WidgetAcc::CalculateCheckButtonAutoSize(CFX_SizeF& size) {
+  FX_FLOAT fCheckSize = GetCheckButtonSize();
+  size.x = size.y = fCheckSize;
+  return CalculateFieldAutoSize(size);
+}
+FX_BOOL CXFA_WidgetAcc::CalculatePushButtonAutoSize(CFX_SizeF& size) {
+  CalcCaptionSize(size);
+  return CalculateWidgetAutoSize(size);
+}
+FX_BOOL CXFA_WidgetAcc::CalculateImageAutoSize(CFX_SizeF& size) {
+  if (!GetImageImage()) {
+    LoadImageImage();
+  }
+  size.clear();
+  if (CFX_DIBitmap* pBitmap = GetImageImage()) {
+    CFX_RectF rtImage, rtFit;
+    rtImage.Set(0, 0, 0, 0);
+    rtFit.Set(0, 0, 0, 0);
+    int32_t iImageXDpi = 0;
+    int32_t iImageYDpi = 0;
+    GetImageDpi(iImageXDpi, iImageYDpi);
+    rtImage.width =
+        XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetWidth(), (FX_FLOAT)iImageXDpi);
+    rtImage.height =
+        XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetHeight(), (FX_FLOAT)iImageYDpi);
+    if (GetWidth(rtFit.width)) {
+      GetWidthWithoutMargin(rtFit.width);
+    } else {
+      rtFit.width = rtImage.width;
+    }
+    if (GetHeight(rtFit.height)) {
+      GetHeightWithoutMargin(rtFit.height);
+    } else {
+      rtFit.height = rtImage.height;
+    }
+    size.x = rtFit.width;
+    size.y = rtFit.height;
+  }
+  return CalculateWidgetAutoSize(size);
+}
+FX_BOOL CXFA_WidgetAcc::CalculateImageEditAutoSize(CFX_SizeF& size) {
+  if (!GetImageEditImage()) {
+    LoadImageEditImage();
+  }
+  size.clear();
+  if (CFX_DIBitmap* pBitmap = GetImageEditImage()) {
+    CFX_RectF rtImage, rtFit;
+    rtImage.Set(0, 0, 0, 0);
+    rtFit.Set(0, 0, 0, 0);
+    int32_t iImageXDpi = 0;
+    int32_t iImageYDpi = 0;
+    GetImageEditDpi(iImageXDpi, iImageYDpi);
+    rtImage.width =
+        XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetWidth(), (FX_FLOAT)iImageXDpi);
+    rtImage.height =
+        XFA_UnitPx2Pt((FX_FLOAT)pBitmap->GetHeight(), (FX_FLOAT)iImageYDpi);
+    if (GetWidth(rtFit.width)) {
+      GetWidthWithoutMargin(rtFit.width);
+    } else {
+      rtFit.width = rtImage.width;
+    }
+    if (GetHeight(rtFit.height)) {
+      GetHeightWithoutMargin(rtFit.height);
+    } else {
+      rtFit.height = rtImage.height;
+    }
+    size.x = rtFit.width;
+    size.y = rtFit.height;
+  }
+  return CalculateFieldAutoSize(size);
+}
+FX_BOOL CXFA_WidgetAcc::LoadImageImage() {
+  InitLayoutData();
+  return ((CXFA_ImageLayoutData*)m_pLayoutData)->LoadImageData(this);
+}
+FX_BOOL CXFA_WidgetAcc::LoadImageEditImage() {
+  InitLayoutData();
+  return ((CXFA_ImageEditData*)m_pLayoutData)->LoadImageData(this);
+}
+void CXFA_WidgetAcc::GetImageDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) {
+  iImageXDpi = ((CXFA_ImageLayoutData*)m_pLayoutData)->m_iImageXDpi;
+  iImageYDpi = ((CXFA_ImageLayoutData*)m_pLayoutData)->m_iImageYDpi;
+}
+void CXFA_WidgetAcc::GetImageEditDpi(int32_t& iImageXDpi, int32_t& iImageYDpi) {
+  iImageXDpi = ((CXFA_ImageEditData*)m_pLayoutData)->m_iImageXDpi;
+  iImageYDpi = ((CXFA_ImageEditData*)m_pLayoutData)->m_iImageYDpi;
+}
+FX_BOOL CXFA_WidgetAcc::CalculateTextAutoSize(CFX_SizeF& size) {
+  LoadText();
+  CXFA_TextLayout* pTextLayout =
+      ((CXFA_TextLayoutData*)m_pLayoutData)->m_pTextLayout;
+  if (pTextLayout) {
+    size.x = pTextLayout->StartLayout(size.x);
+    size.y = pTextLayout->GetLayoutHeight();
+  }
+  return CalculateWidgetAutoSize(size);
+}
+void CXFA_WidgetAcc::LoadText() {
+  InitLayoutData();
+  ((CXFA_TextLayoutData*)m_pLayoutData)->LoadText(this);
+}
+FX_FLOAT CXFA_WidgetAcc::CalculateWidgetAutoWidth(FX_FLOAT fWidthCalc) {
+  CXFA_Margin mgWidget = GetMargin();
+  if (mgWidget) {
+    FX_FLOAT fLeftInset, fRightInset;
+    mgWidget.GetLeftInset(fLeftInset);
+    mgWidget.GetRightInset(fRightInset);
+    fWidthCalc += fLeftInset + fRightInset;
+  }
+  FX_FLOAT fMin = 0, fMax = 0;
+  if (GetMinWidth(fMin)) {
+    fWidthCalc = std::max(fWidthCalc, fMin);
+  }
+  if (GetMaxWidth(fMax) && fMax > 0) {
+    fWidthCalc = std::min(fWidthCalc, fMax);
+  }
+  return fWidthCalc;
+}
+FX_FLOAT CXFA_WidgetAcc::GetWidthWithoutMargin(FX_FLOAT fWidthCalc) {
+  CXFA_Margin mgWidget = GetMargin();
+  if (mgWidget) {
+    FX_FLOAT fLeftInset, fRightInset;
+    mgWidget.GetLeftInset(fLeftInset);
+    mgWidget.GetRightInset(fRightInset);
+    fWidthCalc -= fLeftInset + fRightInset;
+  }
+  return fWidthCalc;
+}
+FX_FLOAT CXFA_WidgetAcc::CalculateWidgetAutoHeight(FX_FLOAT fHeightCalc) {
+  CXFA_Margin mgWidget = GetMargin();
+  if (mgWidget) {
+    FX_FLOAT fTopInset, fBottomInset;
+    mgWidget.GetTopInset(fTopInset);
+    mgWidget.GetBottomInset(fBottomInset);
+    fHeightCalc += fTopInset + fBottomInset;
+  }
+  FX_FLOAT fMin = 0, fMax = 0;
+  if (GetMinHeight(fMin)) {
+    fHeightCalc = std::max(fHeightCalc, fMin);
+  }
+  if (GetMaxHeight(fMax) && fMax > 0) {
+    fHeightCalc = std::min(fHeightCalc, fMax);
+  }
+  return fHeightCalc;
+}
+FX_FLOAT CXFA_WidgetAcc::GetHeightWithoutMargin(FX_FLOAT fHeightCalc) {
+  CXFA_Margin mgWidget = GetMargin();
+  if (mgWidget) {
+    FX_FLOAT fTopInset, fBottomInset;
+    mgWidget.GetTopInset(fTopInset);
+    mgWidget.GetBottomInset(fBottomInset);
+    fHeightCalc -= fTopInset + fBottomInset;
+  }
+  return fHeightCalc;
+}
+void CXFA_WidgetAcc::StartWidgetLayout(FX_FLOAT& fCalcWidth,
+                                       FX_FLOAT& fCalcHeight) {
+  InitLayoutData();
+  XFA_ELEMENT eUIType = GetUIType();
+  if (eUIType == XFA_ELEMENT_Text) {
+    m_pLayoutData->m_fWidgetHeight = -1;
+    GetHeight(m_pLayoutData->m_fWidgetHeight);
+    StartTextLayout(fCalcWidth, fCalcHeight);
+    return;
+  }
+  if (fCalcWidth > 0 && fCalcHeight > 0) {
+    return;
+  }
+  m_pLayoutData->m_fWidgetHeight = -1;
+  FX_FLOAT fWidth = 0;
+  if (fCalcWidth > 0 && fCalcHeight < 0) {
+    if (!GetHeight(fCalcHeight)) {
+      CalculateAccWidthAndHeight(eUIType, fCalcWidth, fCalcHeight);
+    }
+    m_pLayoutData->m_fWidgetHeight = fCalcHeight;
+    return;
+  }
+  if (fCalcWidth < 0 && fCalcHeight < 0) {
+    if (!GetWidth(fWidth) || !GetHeight(fCalcHeight)) {
+      CalculateAccWidthAndHeight(eUIType, fWidth, fCalcHeight);
+    }
+    fCalcWidth = fWidth;
+  }
+  m_pLayoutData->m_fWidgetHeight = fCalcHeight;
+}
+void CXFA_WidgetAcc::CalculateAccWidthAndHeight(XFA_ELEMENT eUIType,
+                                                FX_FLOAT& fWidth,
+                                                FX_FLOAT& fCalcHeight) {
+  CFX_SizeF sz(fWidth, m_pLayoutData->m_fWidgetHeight);
+  switch (eUIType) {
+    case XFA_ELEMENT_Barcode:
+    case XFA_ELEMENT_ChoiceList:
+    case XFA_ELEMENT_Signature:
+      CalculateFieldAutoSize(sz);
+      break;
+    case XFA_ELEMENT_ImageEdit:
+      CalculateImageEditAutoSize(sz);
+      break;
+    case XFA_ELEMENT_Button:
+      CalculatePushButtonAutoSize(sz);
+      break;
+    case XFA_ELEMENT_CheckButton:
+      CalculateCheckButtonAutoSize(sz);
+      break;
+    case XFA_ELEMENT_DateTimeEdit:
+    case XFA_ELEMENT_NumericEdit:
+    case XFA_ELEMENT_PasswordEdit:
+    case XFA_ELEMENT_TextEdit:
+      CalculateTextEditAutoSize(sz);
+      break;
+    case XFA_ELEMENT_Image:
+      CalculateImageAutoSize(sz);
+      break;
+    case XFA_ELEMENT_Arc:
+    case XFA_ELEMENT_Line:
+    case XFA_ELEMENT_Rectangle:
+    case XFA_ELEMENT_Subform:
+    case XFA_ELEMENT_ExclGroup:
+      CalculateWidgetAutoSize(sz);
+      break;
+    default:
+      break;
+  }
+  fWidth = sz.x;
+  m_pLayoutData->m_fWidgetHeight = sz.y;
+  fCalcHeight = sz.y;
+}
+FX_BOOL CXFA_WidgetAcc::FindSplitPos(int32_t iBlockIndex,
+                                     FX_FLOAT& fCalcHeight) {
+  XFA_ELEMENT eUIType = (XFA_ELEMENT)GetUIType();
+  if (eUIType == XFA_ELEMENT_Subform) {
+    return FALSE;
+  }
+  if (eUIType != XFA_ELEMENT_Text && eUIType != XFA_ELEMENT_TextEdit &&
+      eUIType != XFA_ELEMENT_NumericEdit &&
+      eUIType != XFA_ELEMENT_PasswordEdit) {
+    fCalcHeight = 0;
+    return TRUE;
+  }
+  FX_FLOAT fTopInset = 0;
+  FX_FLOAT fBottomInset = 0;
+  if (iBlockIndex == 0) {
+    CXFA_Margin mgWidget = GetMargin();
+    if (mgWidget) {
+      mgWidget.GetTopInset(fTopInset);
+      mgWidget.GetBottomInset(fBottomInset);
+    }
+    CFX_RectF rtUIMargin;
+    GetUIMargin(rtUIMargin);
+    fTopInset += rtUIMargin.top;
+    fBottomInset += rtUIMargin.width;
+  }
+  if (eUIType == XFA_ELEMENT_Text) {
+    FX_FLOAT fHeight = fCalcHeight;
+    if (iBlockIndex == 0) {
+      fCalcHeight = fCalcHeight - fTopInset;
+      if (fCalcHeight < 0) {
+        fCalcHeight = 0;
+      }
+    }
+    CXFA_TextLayout* pTextLayout =
+        ((CXFA_TextLayoutData*)m_pLayoutData)->m_pTextLayout;
+    pTextLayout->DoLayout(iBlockIndex, fCalcHeight, fCalcHeight,
+                          m_pLayoutData->m_fWidgetHeight - fTopInset);
+    if (fCalcHeight != 0) {
+      if (iBlockIndex == 0) {
+        fCalcHeight = fCalcHeight + fTopInset;
+      }
+      if (fabs(fHeight - fCalcHeight) < XFA_FLOAT_PERCISION) {
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+  XFA_ATTRIBUTEENUM iCapPlacement = XFA_ATTRIBUTEENUM_Unknown;
+  FX_FLOAT fCapReserve = 0;
+  if (iBlockIndex == 0) {
+    CXFA_Caption caption = GetCaption();
+    if (caption && caption.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) {
+      iCapPlacement = (XFA_ATTRIBUTEENUM)caption.GetPlacementType();
+      fCapReserve = caption.GetReserve();
+    }
+    if (iCapPlacement == XFA_ATTRIBUTEENUM_Top &&
+        fCalcHeight < fCapReserve + fTopInset) {
+      fCalcHeight = 0;
+      return TRUE;
+    }
+    if (iCapPlacement == XFA_ATTRIBUTEENUM_Bottom &&
+        m_pLayoutData->m_fWidgetHeight - fCapReserve - fBottomInset) {
+      fCalcHeight = 0;
+      return TRUE;
+    }
+    if (iCapPlacement != XFA_ATTRIBUTEENUM_Top) {
+      fCapReserve = 0;
+    }
+  }
+  int32_t iLinesCount = 0;
+  FX_FLOAT fHeight = m_pLayoutData->m_fWidgetHeight;
+  CFX_WideString wsText;
+  GetValue(wsText, XFA_VALUEPICTURE_Display);
+  if (wsText.IsEmpty()) {
+    iLinesCount = 1;
+  } else {
+    if (!((CXFA_FieldLayoutData*)m_pLayoutData)->m_pTextOut) {
+      FX_FLOAT fWidth = 0;
+      GetWidth(fWidth);
+      CalculateAccWidthAndHeight(eUIType, fWidth, fHeight);
+    }
+    iLinesCount =
+        ((CXFA_FieldLayoutData*)m_pLayoutData)->m_pTextOut->GetTotalLines();
+  }
+  if (!((CXFA_FieldLayoutData*)m_pLayoutData)->m_pFieldSplitArray) {
+    ((CXFA_FieldLayoutData*)m_pLayoutData)->m_pFieldSplitArray =
+        new CFX_FloatArray;
+  }
+  CFX_FloatArray* pFieldArray =
+      ((CXFA_FieldLayoutData*)m_pLayoutData)->m_pFieldSplitArray;
+  int32_t iFieldSplitCount = pFieldArray->GetSize();
+  for (int32_t i = 0; i < iBlockIndex * 3; i += 3) {
+    iLinesCount -= (int32_t)pFieldArray->GetAt(i + 1);
+    fHeight -= pFieldArray->GetAt(i + 2);
+  }
+  if (iLinesCount == 0) {
+    return FALSE;
+  }
+  FX_FLOAT fLineHeight = GetLineHeight();
+  FX_FLOAT fFontSize = GetFontSize();
+  FX_FLOAT fTextHeight = iLinesCount * fLineHeight - fLineHeight + fFontSize;
+  FX_FLOAT fSpaceAbove = 0;
+  FX_FLOAT fStartOffset = 0;
+  if (fHeight > 0.1f && iBlockIndex == 0) {
+    fStartOffset = fTopInset;
+    fHeight -= (fTopInset + fBottomInset);
+    if (CXFA_Para para = GetPara()) {
+      fSpaceAbove = para.GetSpaceAbove();
+      FX_FLOAT fSpaceBelow = para.GetSpaceBelow();
+      fHeight -= (fSpaceAbove + fSpaceBelow);
+      switch (para.GetVerticalAlign()) {
+        case XFA_ATTRIBUTEENUM_Top:
+          fStartOffset += fSpaceAbove;
+          break;
+        case XFA_ATTRIBUTEENUM_Middle:
+          fStartOffset += ((fHeight - fTextHeight) / 2 + fSpaceAbove);
+          break;
+        case XFA_ATTRIBUTEENUM_Bottom:
+          fStartOffset += (fHeight - fTextHeight + fSpaceAbove);
+          break;
+      }
+    }
+    if (fStartOffset < 0.1f) {
+      fStartOffset = 0;
+    }
+  }
+  for (int32_t i = iBlockIndex - 1; iBlockIndex > 0 && i < iBlockIndex; i++) {
+    fStartOffset = pFieldArray->GetAt(i * 3) - pFieldArray->GetAt(i * 3 + 2);
+    if (fStartOffset < 0.1f) {
+      fStartOffset = 0;
+    }
+  }
+  if (iFieldSplitCount / 3 == (iBlockIndex + 1)) {
+    pFieldArray->SetAt(0, fStartOffset);
+  } else {
+    pFieldArray->Add(fStartOffset);
+  }
+  XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode();
+  FX_BOOL bCanSplitNoContent = FALSE;
+  XFA_ATTRIBUTEENUM eLayoutMode;
+  GetNode()
+      ->GetNodeItem(XFA_NODEITEM_Parent)
+      ->TryEnum(XFA_ATTRIBUTE_Layout, eLayoutMode, TRUE);
+  if ((eLayoutMode == XFA_ATTRIBUTEENUM_Position ||
+       eLayoutMode == XFA_ATTRIBUTEENUM_Tb ||
+       eLayoutMode == XFA_ATTRIBUTEENUM_Row ||
+       eLayoutMode == XFA_ATTRIBUTEENUM_Table) &&
+      version > XFA_VERSION_208) {
+    bCanSplitNoContent = TRUE;
+  }
+  if ((eLayoutMode == XFA_ATTRIBUTEENUM_Tb ||
+       eLayoutMode == XFA_ATTRIBUTEENUM_Row ||
+       eLayoutMode == XFA_ATTRIBUTEENUM_Table) &&
+      version <= XFA_VERSION_208) {
+    if (fStartOffset < fCalcHeight) {
+      bCanSplitNoContent = TRUE;
+    } else {
+      fCalcHeight = 0;
+      return TRUE;
+    }
+  }
+  if (bCanSplitNoContent) {
+    if ((fCalcHeight - fTopInset - fSpaceAbove < fLineHeight)) {
+      fCalcHeight = 0;
+      return TRUE;
+    }
+    if (fStartOffset + XFA_FLOAT_PERCISION >= fCalcHeight) {
+      if (iFieldSplitCount / 3 == (iBlockIndex + 1)) {
+        pFieldArray->SetAt(iBlockIndex * 3 + 1, 0);
+        pFieldArray->SetAt(iBlockIndex * 3 + 2, fCalcHeight);
+      } else {
+        pFieldArray->Add(0);
+        pFieldArray->Add(fCalcHeight);
+      }
+      return FALSE;
+    }
+    if (fCalcHeight - fStartOffset < fLineHeight) {
+      fCalcHeight = fStartOffset;
+      if (iFieldSplitCount / 3 == (iBlockIndex + 1)) {
+        pFieldArray->SetAt(iBlockIndex * 3 + 1, 0);
+        pFieldArray->SetAt(iBlockIndex * 3 + 2, fCalcHeight);
+      } else {
+        pFieldArray->Add(0);
+        pFieldArray->Add(fCalcHeight);
+      }
+      return TRUE;
+    }
+    FX_FLOAT fTextNum =
+        fCalcHeight + XFA_FLOAT_PERCISION - fCapReserve - fStartOffset;
+    int32_t iLineNum =
+        (int32_t)((fTextNum + (fLineHeight - fFontSize)) / fLineHeight);
+    if (iLineNum >= iLinesCount) {
+      if (fCalcHeight - fStartOffset - fTextHeight >= fFontSize) {
+        if (iFieldSplitCount / 3 == (iBlockIndex + 1)) {
+          pFieldArray->SetAt(iBlockIndex * 3 + 1, (FX_FLOAT)iLinesCount);
+          pFieldArray->SetAt(iBlockIndex * 3 + 2, fCalcHeight);
+        } else {
+          pFieldArray->Add((FX_FLOAT)iLinesCount);
+          pFieldArray->Add(fCalcHeight);
+        }
+        return FALSE;
+      }
+      if (fHeight - fStartOffset - fTextHeight < fFontSize) {
+        iLineNum -= 1;
+        if (iLineNum == 0) {
+          fCalcHeight = 0;
+          return TRUE;
+        }
+      } else {
+        iLineNum = (int32_t)(fTextNum / fLineHeight);
+      }
+    }
+    if (iLineNum > 0) {
+      FX_FLOAT fSplitHeight =
+          iLineNum * fLineHeight + fCapReserve + fStartOffset;
+      if (iFieldSplitCount / 3 == (iBlockIndex + 1)) {
+        pFieldArray->SetAt(iBlockIndex * 3 + 1, (FX_FLOAT)iLineNum);
+        pFieldArray->SetAt(iBlockIndex * 3 + 2, fSplitHeight);
+      } else {
+        pFieldArray->Add((FX_FLOAT)iLineNum);
+        pFieldArray->Add(fSplitHeight);
+      }
+      if (fabs(fSplitHeight - fCalcHeight) < XFA_FLOAT_PERCISION) {
+        return FALSE;
+      }
+      fCalcHeight = fSplitHeight;
+      return TRUE;
+    }
+  }
+  fCalcHeight = 0;
+  return TRUE;
+}
+void CXFA_WidgetAcc::InitLayoutData() {
+  if (m_pLayoutData) {
+    return;
+  }
+  switch (GetUIType()) {
+    case XFA_ELEMENT_Text:
+      m_pLayoutData = new CXFA_TextLayoutData;
+      return;
+    case XFA_ELEMENT_TextEdit:
+      m_pLayoutData = new CXFA_TextEditData;
+      return;
+    case XFA_ELEMENT_Image:
+      m_pLayoutData = new CXFA_ImageLayoutData;
+      return;
+    case XFA_ELEMENT_ImageEdit:
+      m_pLayoutData = new CXFA_ImageEditData;
+      return;
+    default:
+      break;
+  }
+  if (GetClassID() == XFA_ELEMENT_Field) {
+    m_pLayoutData = new CXFA_FieldLayoutData;
+  } else {
+    m_pLayoutData = new CXFA_WidgetLayoutData;
+  }
+}
+void CXFA_WidgetAcc::StartTextLayout(FX_FLOAT& fCalcWidth,
+                                     FX_FLOAT& fCalcHeight) {
+  LoadText();
+  CXFA_TextLayout* pTextLayout =
+      ((CXFA_TextLayoutData*)m_pLayoutData)->m_pTextLayout;
+  FX_FLOAT fTextHeight = 0;
+  if (fCalcWidth > 0 && fCalcHeight > 0) {
+    FX_FLOAT fWidth = GetWidthWithoutMargin(fCalcWidth);
+    pTextLayout->StartLayout(fWidth);
+    fTextHeight = fCalcHeight;
+    fTextHeight = GetHeightWithoutMargin(fTextHeight);
+    pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight);
+    return;
+  }
+  if (fCalcWidth > 0 && fCalcHeight < 0) {
+    FX_FLOAT fWidth = GetWidthWithoutMargin(fCalcWidth);
+    pTextLayout->StartLayout(fWidth);
+  }
+  if (fCalcWidth < 0 && fCalcHeight < 0) {
+    FX_FLOAT fMaxWidth = -1;
+    FX_BOOL bRet = GetWidth(fMaxWidth);
+    if (bRet) {
+      FX_FLOAT fWidth = GetWidthWithoutMargin(fMaxWidth);
+      pTextLayout->StartLayout(fWidth);
+    } else {
+      FX_FLOAT fWidth = pTextLayout->StartLayout(fMaxWidth);
+      fMaxWidth = CalculateWidgetAutoWidth(fWidth);
+      fWidth = GetWidthWithoutMargin(fMaxWidth);
+      pTextLayout->StartLayout(fWidth);
+    }
+    fCalcWidth = fMaxWidth;
+  }
+  if (m_pLayoutData->m_fWidgetHeight < 0) {
+    m_pLayoutData->m_fWidgetHeight = pTextLayout->GetLayoutHeight();
+    m_pLayoutData->m_fWidgetHeight =
+        CalculateWidgetAutoHeight(m_pLayoutData->m_fWidgetHeight);
+  }
+  fTextHeight = m_pLayoutData->m_fWidgetHeight;
+  fTextHeight = GetHeightWithoutMargin(fTextHeight);
+  pTextLayout->DoLayout(0, fTextHeight, -1, fTextHeight);
+  fCalcHeight = m_pLayoutData->m_fWidgetHeight;
+}
+FX_BOOL CXFA_WidgetAcc::LoadCaption() {
+  InitLayoutData();
+  return ((CXFA_FieldLayoutData*)m_pLayoutData)->LoadCaption(this);
+}
+CXFA_TextLayout* CXFA_WidgetAcc::GetCaptionTextLayout() {
+  return m_pLayoutData
+             ? ((CXFA_FieldLayoutData*)m_pLayoutData)->m_pCapTextLayout
+             : NULL;
+}
+CXFA_TextLayout* CXFA_WidgetAcc::GetTextLayout() {
+  return m_pLayoutData ? ((CXFA_TextLayoutData*)m_pLayoutData)->m_pTextLayout
+                       : NULL;
+}
+CFX_DIBitmap* CXFA_WidgetAcc::GetImageImage() {
+  return m_pLayoutData ? ((CXFA_ImageLayoutData*)m_pLayoutData)->m_pDIBitmap
+                       : NULL;
+}
+CFX_DIBitmap* CXFA_WidgetAcc::GetImageEditImage() {
+  return m_pLayoutData ? ((CXFA_ImageEditData*)m_pLayoutData)->m_pDIBitmap
+                       : NULL;
+}
+void CXFA_WidgetAcc::SetImageImage(CFX_DIBitmap* newImage) {
+  if (((CXFA_ImageLayoutData*)m_pLayoutData)->m_pDIBitmap == newImage) {
+    return;
+  }
+  if (((CXFA_ImageLayoutData*)m_pLayoutData)->m_pDIBitmap &&
+      !((CXFA_ImageLayoutData*)m_pLayoutData)->m_bNamedImage) {
+    delete ((CXFA_ImageLayoutData*)m_pLayoutData)->m_pDIBitmap;
+    ((CXFA_ImageLayoutData*)m_pLayoutData)->m_pDIBitmap = NULL;
+  }
+  ((CXFA_ImageLayoutData*)m_pLayoutData)->m_pDIBitmap = newImage;
+}
+void CXFA_WidgetAcc::SetImageEditImage(CFX_DIBitmap* newImage) {
+  if (((CXFA_ImageEditData*)m_pLayoutData)->m_pDIBitmap == newImage) {
+    return;
+  }
+  if (((CXFA_ImageEditData*)m_pLayoutData)->m_pDIBitmap &&
+      !((CXFA_ImageEditData*)m_pLayoutData)->m_bNamedImage) {
+    delete ((CXFA_ImageEditData*)m_pLayoutData)->m_pDIBitmap;
+    ((CXFA_ImageEditData*)m_pLayoutData)->m_pDIBitmap = NULL;
+  }
+  ((CXFA_ImageEditData*)m_pLayoutData)->m_pDIBitmap = newImage;
+}
+CXFA_WidgetLayoutData* CXFA_WidgetAcc::GetWidgetLayoutData() {
+  return m_pLayoutData;
+}
+IFX_Font* CXFA_WidgetAcc::GetFDEFont() {
+  CFX_WideStringC wsFontName = FX_WSTRC(L"Courier");
+  FX_DWORD dwFontStyle = 0;
+  if (CXFA_Font font = GetFont()) {
+    if (font.IsBold()) {
+      dwFontStyle |= FX_FONTSTYLE_Bold;
+    }
+    if (font.IsItalic()) {
+      dwFontStyle |= FX_FONTSTYLE_Italic;
+    }
+    font.GetTypeface(wsFontName);
+  }
+  CXFA_FFDoc* pDoc = GetDoc();
+  return pDoc->GetApp()->GetXFAFontMgr()->GetFont(pDoc, wsFontName,
+                                                  dwFontStyle);
+}
+FX_FLOAT CXFA_WidgetAcc::GetFontSize() {
+  FX_FLOAT fFontSize = 10.0f;
+  if (CXFA_Font font = GetFont()) {
+    fFontSize = font.GetFontSize();
+  }
+  return fFontSize < 0.1f ? 10.0f : fFontSize;
+}
+FX_FLOAT CXFA_WidgetAcc::GetLineHeight() {
+  FX_FLOAT fLineHeight = 0;
+  if (CXFA_Para para = GetPara()) {
+    fLineHeight = para.GetLineHeight();
+  }
+  if (fLineHeight < 1) {
+    fLineHeight = GetFontSize() * 1.2f;
+  }
+  return fLineHeight;
+}
+FX_ARGB CXFA_WidgetAcc::GetTextColor() {
+  if (CXFA_Font font = GetFont()) {
+    return font.GetColor();
+  }
+  return 0xFF000000;
+}
+CXFA_Node* CXFA_TextProvider::GetTextNode(FX_BOOL& bRichText) {
+  bRichText = FALSE;
+  if (m_pTextNode) {
+    if (m_pTextNode->GetClassID() == XFA_ELEMENT_ExData) {
+      CFX_WideString wsContentType;
+      m_pTextNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType,
+                                FALSE);
+      if (wsContentType.Equal(FX_WSTRC(L"text/html"))) {
+        bRichText = TRUE;
+      }
+    }
+    return m_pTextNode;
+  }
+  if (m_eType == XFA_TEXTPROVIDERTYPE_Text) {
+    CXFA_Node* pElementNode = m_pWidgetAcc->GetNode();
+    CXFA_Node* pValueNode = pElementNode->GetChild(0, XFA_ELEMENT_Value);
+    if (!pValueNode) {
+      return NULL;
+    }
+    CXFA_Node* pChildNode = pValueNode->GetNodeItem(XFA_NODEITEM_FirstChild);
+    if (pChildNode && pChildNode->GetClassID() == XFA_ELEMENT_ExData) {
+      CFX_WideString wsContentType;
+      pChildNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, FALSE);
+      if (wsContentType.Equal(FX_WSTRC(L"text/html"))) {
+        bRichText = TRUE;
+      }
+    }
+    return pChildNode;
+  } else if (m_eType == XFA_TEXTPROVIDERTYPE_Datasets) {
+    CXFA_Node* pBind = m_pWidgetAcc->GetDatasets();
+    IFDE_XMLNode* pXMLNode = pBind->GetXMLMappingNode();
+    FXSYS_assert(pXMLNode);
+    for (IFDE_XMLNode* pXMLChild =
+             pXMLNode->GetNodeItem(IFDE_XMLNode::FirstChild);
+         pXMLChild;
+         pXMLChild = pXMLChild->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+      if (pXMLChild->GetType() == FDE_XMLNODE_Element) {
+        IFDE_XMLElement* pElement = (IFDE_XMLElement*)pXMLChild;
+        if (XFA_RecognizeRichText(pElement)) {
+          bRichText = TRUE;
+        }
+      }
+    }
+    return pBind;
+  } else if (m_eType == XFA_TEXTPROVIDERTYPE_Caption) {
+    CXFA_Node* pCaptionNode =
+        m_pWidgetAcc->GetNode()->GetChild(0, XFA_ELEMENT_Caption);
+    if (pCaptionNode == NULL) {
+      return NULL;
+    }
+    CXFA_Node* pValueNode = pCaptionNode->GetChild(0, XFA_ELEMENT_Value);
+    if (pValueNode == NULL) {
+      return NULL;
+    }
+    CXFA_Node* pChildNode = pValueNode->GetNodeItem(XFA_NODEITEM_FirstChild);
+    if (pChildNode && pChildNode->GetClassID() == XFA_ELEMENT_ExData) {
+      CFX_WideString wsContentType;
+      pChildNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, FALSE);
+      if (wsContentType.Equal(FX_WSTRC(L"text/html"))) {
+        bRichText = TRUE;
+      }
+    }
+    return pChildNode;
+  }
+  CXFA_Node* pItemNode =
+      m_pWidgetAcc->GetNode()->GetChild(0, XFA_ELEMENT_Items);
+  if (pItemNode == NULL) {
+    return NULL;
+  }
+  CXFA_Node* pNode = pItemNode->GetNodeItem(XFA_NODEITEM_FirstChild);
+  while (pNode) {
+    CFX_WideStringC wsName;
+    pNode->TryCData(XFA_ATTRIBUTE_Name, wsName);
+    if (m_eType == XFA_TEXTPROVIDERTYPE_Rollover &&
+        wsName == FX_WSTRC(L"rollover")) {
+      return pNode;
+    }
+    if (m_eType == XFA_TEXTPROVIDERTYPE_Down && wsName == FX_WSTRC(L"down")) {
+      return pNode;
+    }
+    pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling);
+  }
+  return NULL;
+}
+CXFA_Para CXFA_TextProvider::GetParaNode() {
+  if (m_eType == XFA_TEXTPROVIDERTYPE_Text) {
+    return m_pWidgetAcc->GetPara();
+  }
+  CXFA_Node* pNode = m_pWidgetAcc->GetNode()->GetChild(0, XFA_ELEMENT_Caption);
+  return CXFA_Para(pNode->GetChild(0, XFA_ELEMENT_Para));
+}
+CXFA_Font CXFA_TextProvider::GetFontNode() {
+  if (m_eType == XFA_TEXTPROVIDERTYPE_Text) {
+    return m_pWidgetAcc->GetFont();
+  }
+  CXFA_Node* pNode = m_pWidgetAcc->GetNode()->GetChild(0, XFA_ELEMENT_Caption);
+  pNode = pNode->GetChild(0, XFA_ELEMENT_Font);
+  if (pNode) {
+    return CXFA_Font(pNode);
+  }
+  return m_pWidgetAcc->GetFont();
+}
+FX_BOOL CXFA_TextProvider::IsCheckButtonAndAutoWidth() {
+  XFA_ELEMENT eType = m_pWidgetAcc->GetUIType();
+  if (eType == XFA_ELEMENT_CheckButton) {
+    FX_FLOAT fWidth = 0;
+    return !m_pWidgetAcc->GetWidth(fWidth);
+  }
+  return FALSE;
+}
+FX_BOOL CXFA_TextProvider::GetEmbbedObj(FX_BOOL bURI,
+                                        FX_BOOL bRaw,
+                                        const CFX_WideString& wsAttr,
+                                        CFX_WideString& wsValue) {
+  if (m_eType != XFA_TEXTPROVIDERTYPE_Text) {
+    return FALSE;
+  }
+  if (bURI) {
+    CXFA_Node* pWidgetNode = m_pWidgetAcc->GetNode();
+    CXFA_Node* pParent = pWidgetNode->GetNodeItem(XFA_NODEITEM_Parent);
+    CXFA_Document* pDocument = pWidgetNode->GetDocument();
+    CXFA_Node* pIDNode = NULL;
+    CXFA_WidgetAcc* pEmbAcc = NULL;
+    if (pParent) {
+      pIDNode = pDocument->GetNodeByID(pParent, wsAttr);
+    }
+    if (!pIDNode) {
+      pIDNode = pDocument->GetNodeByID(
+          ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Form)), wsAttr);
+    }
+    if (pIDNode) {
+      pEmbAcc = (CXFA_WidgetAcc*)pIDNode->GetWidgetData();
+    }
+    if (pEmbAcc) {
+      pEmbAcc->GetValue(wsValue, XFA_VALUEPICTURE_Display);
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
diff --git a/xfa/fxfa/app/xfa_ffwidgetacc.h b/xfa/fxfa/app/xfa_ffwidgetacc.h
new file mode 100644
index 0000000..722256a
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffwidgetacc.h
@@ -0,0 +1,44 @@
+// 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_FXFA_APP_XFA_FFWIDGETACC_H_
+#define XFA_FXFA_APP_XFA_FFWIDGETACC_H_
+
+#include "xfa/fxfa/app/xfa_textlayout.h"
+
+enum XFA_TEXTPROVIDERTYPE {
+  XFA_TEXTPROVIDERTYPE_Text,
+  XFA_TEXTPROVIDERTYPE_Datasets,
+  XFA_TEXTPROVIDERTYPE_Caption,
+  XFA_TEXTPROVIDERTYPE_Rollover,
+  XFA_TEXTPROVIDERTYPE_Down,
+};
+class CXFA_TextProvider : public IXFA_TextProvider {
+ public:
+  CXFA_TextProvider(CXFA_WidgetAcc* pWidgetAcc,
+                    XFA_TEXTPROVIDERTYPE eType,
+                    CXFA_Node* pTextNode = NULL)
+      : m_pWidgetAcc(pWidgetAcc), m_eType(eType), m_pTextNode(pTextNode) {
+    FXSYS_assert(m_pWidgetAcc);
+  }
+  virtual ~CXFA_TextProvider() {}
+  virtual CXFA_Node* GetTextNode(FX_BOOL& bRichText);
+  virtual CXFA_Para GetParaNode();
+  virtual CXFA_Font GetFontNode();
+  virtual FX_BOOL IsCheckButtonAndAutoWidth();
+  virtual CXFA_FFDoc* GetDocNode() { return m_pWidgetAcc->GetDoc(); }
+  virtual FX_BOOL GetEmbbedObj(FX_BOOL bURI,
+                               FX_BOOL bRaw,
+                               const CFX_WideString& wsAttr,
+                               CFX_WideString& wsValue);
+
+ protected:
+  CXFA_WidgetAcc* m_pWidgetAcc;
+  XFA_TEXTPROVIDERTYPE m_eType;
+  CXFA_Node* m_pTextNode;
+};
+
+#endif  // XFA_FXFA_APP_XFA_FFWIDGETACC_H_
diff --git a/xfa/fxfa/app/xfa_ffwidgethandler.cpp b/xfa/fxfa/app/xfa_ffwidgethandler.cpp
new file mode 100644
index 0000000..b775643
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffwidgethandler.cpp
@@ -0,0 +1,634 @@
+// 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/fxfa/app/xfa_ffwidgethandler.h"
+
+#include <vector>
+
+#include "xfa/fxfa/app/xfa_ffchoicelist.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_fwladapter.h"
+#include "xfa/fxfa/parser/xfa_parser.h"
+
+CXFA_FFWidgetHandler::CXFA_FFWidgetHandler(CXFA_FFDocView* pDocView)
+    : m_pDocView(pDocView) {}
+CXFA_FFWidgetHandler::~CXFA_FFWidgetHandler() {}
+IXFA_PageView* CXFA_FFWidgetHandler::GetPageView(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->GetPageView();
+}
+void CXFA_FFWidgetHandler::GetRect(IXFA_Widget* hWidget, CFX_RectF& rt) {
+  static_cast<CXFA_FFWidget*>(hWidget)->GetWidgetRect(rt);
+}
+FX_DWORD CXFA_FFWidgetHandler::GetStatus(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->GetStatus();
+}
+FX_BOOL CXFA_FFWidgetHandler::GetBBox(IXFA_Widget* hWidget,
+                                      CFX_RectF& rtBox,
+                                      FX_DWORD dwStatus,
+                                      FX_BOOL bDrawFocus) {
+  return static_cast<CXFA_FFWidget*>(hWidget)
+      ->GetBBox(rtBox, dwStatus, bDrawFocus);
+}
+CXFA_WidgetAcc* CXFA_FFWidgetHandler::GetDataAcc(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->GetDataAcc();
+}
+void CXFA_FFWidgetHandler::GetName(IXFA_Widget* hWidget,
+                                   CFX_WideString& wsName,
+                                   int32_t iNameType) {
+  static_cast<CXFA_FFWidget*>(hWidget)->GetDataAcc()->GetName(wsName,
+                                                              iNameType);
+}
+FX_BOOL CXFA_FFWidgetHandler::GetToolTip(IXFA_Widget* hWidget,
+                                         CFX_WideString& wsToolTip) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->GetToolTip(wsToolTip);
+}
+void CXFA_FFWidgetHandler::SetPrivateData(IXFA_Widget* hWidget,
+                                          void* module_id,
+                                          void* pData,
+                                          PD_CALLBACK_FREEDATA callback) {
+  static_cast<CXFA_FFWidget*>(hWidget)
+      ->SetPrivateData(module_id, pData, callback);
+}
+void* CXFA_FFWidgetHandler::GetPrivateData(IXFA_Widget* hWidget,
+                                           void* module_id) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->GetPrivateData(module_id);
+}
+FX_BOOL CXFA_FFWidgetHandler::OnMouseEnter(IXFA_Widget* hWidget) {
+  m_pDocView->LockUpdate();
+  FX_BOOL bRet = static_cast<CXFA_FFWidget*>(hWidget)->OnMouseEnter();
+  m_pDocView->UnlockUpdate();
+  m_pDocView->UpdateDocView();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnMouseExit(IXFA_Widget* hWidget) {
+  m_pDocView->LockUpdate();
+  FX_BOOL bRet = static_cast<CXFA_FFWidget*>(hWidget)->OnMouseExit();
+  m_pDocView->UnlockUpdate();
+  m_pDocView->UpdateDocView();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnLButtonDown(IXFA_Widget* hWidget,
+                                            FX_DWORD dwFlags,
+                                            FX_FLOAT fx,
+                                            FX_FLOAT fy) {
+  m_pDocView->LockUpdate();
+  static_cast<CXFA_FFWidget*>(hWidget)->Rotate2Normal(fx, fy);
+  FX_BOOL bRet =
+      static_cast<CXFA_FFWidget*>(hWidget)->OnLButtonDown(dwFlags, fx, fy);
+  if (bRet && m_pDocView->SetFocus(hWidget)) {
+    ((CXFA_FFDoc*)m_pDocView->GetDoc())
+        ->GetDocProvider()
+        ->SetFocusWidget(m_pDocView->GetDoc(), (IXFA_Widget*)hWidget);
+  }
+  m_pDocView->UnlockUpdate();
+  m_pDocView->UpdateDocView();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnLButtonUp(IXFA_Widget* hWidget,
+                                          FX_DWORD dwFlags,
+                                          FX_FLOAT fx,
+                                          FX_FLOAT fy) {
+  m_pDocView->LockUpdate();
+  static_cast<CXFA_FFWidget*>(hWidget)->Rotate2Normal(fx, fy);
+  m_pDocView->m_bLayoutEvent = TRUE;
+  FX_BOOL bRet =
+      static_cast<CXFA_FFWidget*>(hWidget)->OnLButtonUp(dwFlags, fx, fy);
+  m_pDocView->UnlockUpdate();
+  m_pDocView->UpdateDocView();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnLButtonDblClk(IXFA_Widget* hWidget,
+                                              FX_DWORD dwFlags,
+                                              FX_FLOAT fx,
+                                              FX_FLOAT fy) {
+  static_cast<CXFA_FFWidget*>(hWidget)->Rotate2Normal(fx, fy);
+  FX_BOOL bRet =
+      static_cast<CXFA_FFWidget*>(hWidget)->OnLButtonDblClk(dwFlags, fx, fy);
+  m_pDocView->RunInvalidate();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnMouseMove(IXFA_Widget* hWidget,
+                                          FX_DWORD dwFlags,
+                                          FX_FLOAT fx,
+                                          FX_FLOAT fy) {
+  static_cast<CXFA_FFWidget*>(hWidget)->Rotate2Normal(fx, fy);
+  FX_BOOL bRet =
+      static_cast<CXFA_FFWidget*>(hWidget)->OnMouseMove(dwFlags, fx, fy);
+  m_pDocView->RunInvalidate();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnMouseWheel(IXFA_Widget* hWidget,
+                                           FX_DWORD dwFlags,
+                                           int16_t zDelta,
+                                           FX_FLOAT fx,
+                                           FX_FLOAT fy) {
+  static_cast<CXFA_FFWidget*>(hWidget)->Rotate2Normal(fx, fy);
+  FX_BOOL bRet = static_cast<CXFA_FFWidget*>(hWidget)
+                     ->OnMouseWheel(dwFlags, zDelta, fx, fy);
+  m_pDocView->RunInvalidate();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnRButtonDown(IXFA_Widget* hWidget,
+                                            FX_DWORD dwFlags,
+                                            FX_FLOAT fx,
+                                            FX_FLOAT fy) {
+  static_cast<CXFA_FFWidget*>(hWidget)->Rotate2Normal(fx, fy);
+  FX_BOOL bRet =
+      static_cast<CXFA_FFWidget*>(hWidget)->OnRButtonDown(dwFlags, fx, fy);
+  if (bRet && m_pDocView->SetFocus(hWidget)) {
+    ((CXFA_FFDoc*)m_pDocView->GetDoc())
+        ->GetDocProvider()
+        ->SetFocusWidget(m_pDocView->GetDoc(), (IXFA_Widget*)hWidget);
+  }
+  m_pDocView->RunInvalidate();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnRButtonUp(IXFA_Widget* hWidget,
+                                          FX_DWORD dwFlags,
+                                          FX_FLOAT fx,
+                                          FX_FLOAT fy) {
+  static_cast<CXFA_FFWidget*>(hWidget)->Rotate2Normal(fx, fy);
+  FX_BOOL bRet =
+      static_cast<CXFA_FFWidget*>(hWidget)->OnRButtonUp(dwFlags, fx, fy);
+  m_pDocView->RunInvalidate();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnRButtonDblClk(IXFA_Widget* hWidget,
+                                              FX_DWORD dwFlags,
+                                              FX_FLOAT fx,
+                                              FX_FLOAT fy) {
+  static_cast<CXFA_FFWidget*>(hWidget)->Rotate2Normal(fx, fy);
+  FX_BOOL bRet =
+      static_cast<CXFA_FFWidget*>(hWidget)->OnRButtonDblClk(dwFlags, fx, fy);
+  m_pDocView->RunInvalidate();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnKeyDown(IXFA_Widget* hWidget,
+                                        FX_DWORD dwKeyCode,
+                                        FX_DWORD dwFlags) {
+  FX_BOOL bRet =
+      static_cast<CXFA_FFWidget*>(hWidget)->OnKeyDown(dwKeyCode, dwFlags);
+  m_pDocView->RunInvalidate();
+  m_pDocView->UpdateDocView();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnKeyUp(IXFA_Widget* hWidget,
+                                      FX_DWORD dwKeyCode,
+                                      FX_DWORD dwFlags) {
+  FX_BOOL bRet =
+      static_cast<CXFA_FFWidget*>(hWidget)->OnKeyUp(dwKeyCode, dwFlags);
+  m_pDocView->RunInvalidate();
+  return bRet;
+}
+FX_BOOL CXFA_FFWidgetHandler::OnChar(IXFA_Widget* hWidget,
+                                     FX_DWORD dwChar,
+                                     FX_DWORD dwFlags) {
+  FX_BOOL bRet = static_cast<CXFA_FFWidget*>(hWidget)->OnChar(dwChar, dwFlags);
+  m_pDocView->RunInvalidate();
+  return bRet;
+}
+FX_DWORD CXFA_FFWidgetHandler::OnHitTest(IXFA_Widget* hWidget,
+                                         FX_FLOAT fx,
+                                         FX_FLOAT fy) {
+  if (!(static_cast<CXFA_FFWidget*>(hWidget)->GetStatus() &
+        XFA_WIDGETSTATUS_Visible)) {
+    return FWL_WGTHITTEST_Unknown;
+  }
+  static_cast<CXFA_FFWidget*>(hWidget)->Rotate2Normal(fx, fy);
+  return static_cast<CXFA_FFWidget*>(hWidget)->OnHitTest(fx, fy);
+}
+FX_BOOL CXFA_FFWidgetHandler::OnSetCursor(IXFA_Widget* hWidget,
+                                          FX_FLOAT fx,
+                                          FX_FLOAT fy) {
+  static_cast<CXFA_FFWidget*>(hWidget)->Rotate2Normal(fx, fy);
+  return static_cast<CXFA_FFWidget*>(hWidget)->OnSetCursor(fx, fy);
+}
+void CXFA_FFWidgetHandler::RenderWidget(IXFA_Widget* hWidget,
+                                        CFX_Graphics* pGS,
+                                        CFX_Matrix* pMatrix,
+                                        FX_BOOL bHighlight) {
+  static_cast<CXFA_FFWidget*>(hWidget)->RenderWidget(
+      pGS, pMatrix, bHighlight ? XFA_WIDGETSTATUS_Highlight : 0, 0);
+}
+FX_BOOL CXFA_FFWidgetHandler::HasEvent(CXFA_WidgetAcc* pWidgetAcc,
+                                       XFA_EVENTTYPE eEventType) {
+  if (!pWidgetAcc || eEventType == XFA_EVENT_Unknown) {
+    return FALSE;
+  }
+  if (pWidgetAcc->GetClassID() == XFA_ELEMENT_Draw) {
+    return FALSE;
+  }
+  switch (eEventType) {
+    case XFA_EVENT_Calculate: {
+      CXFA_Calculate calc = pWidgetAcc->GetCalculate();
+      if (!calc) {
+        return FALSE;
+      }
+      if (calc.GetScript()) {
+        return TRUE;
+      }
+      return FALSE;
+    }
+    case XFA_EVENT_Validate: {
+      CXFA_Validate val = pWidgetAcc->GetValidate();
+      if (!val) {
+        return FALSE;
+      }
+      if (val.GetScript()) {
+        return TRUE;
+      }
+      return FALSE;
+    }
+    default:
+      break;
+  }
+  CXFA_NodeArray eventArray;
+  return pWidgetAcc->GetEventByActivity(gs_EventActivity[eEventType],
+                                        eventArray);
+}
+int32_t CXFA_FFWidgetHandler::ProcessEvent(CXFA_WidgetAcc* pWidgetAcc,
+                                           CXFA_EventParam* pParam) {
+  if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  if (!pWidgetAcc || pWidgetAcc->GetClassID() == XFA_ELEMENT_Draw) {
+    return XFA_EVENTERROR_NotExist;
+  }
+  switch (pParam->m_eType) {
+    case XFA_EVENT_Calculate:
+      return pWidgetAcc->ProcessCalculate();
+    case XFA_EVENT_Validate:
+      if (((CXFA_FFDoc*)m_pDocView->GetDoc())
+              ->GetDocProvider()
+              ->IsValidationsEnabled(m_pDocView->GetDoc())) {
+        return pWidgetAcc->ProcessValidate();
+      }
+      return XFA_EVENTERROR_Disabled;
+    case XFA_EVENT_InitCalculate: {
+      CXFA_Calculate calc = pWidgetAcc->GetCalculate();
+      if (!calc) {
+        return XFA_EVENTERROR_NotExist;
+      }
+      if (pWidgetAcc->GetNode()->HasFlag(XFA_NODEFLAG_UserInteractive)) {
+        return XFA_EVENTERROR_Disabled;
+      }
+      CXFA_Script script = calc.GetScript();
+      return pWidgetAcc->ExecuteScript(script, pParam);
+    }
+    default:
+      break;
+  }
+  int32_t iRet =
+      pWidgetAcc->ProcessEvent(gs_EventActivity[pParam->m_eType], pParam);
+  return iRet;
+}
+IXFA_Widget* CXFA_FFWidgetHandler::CreateWidget(IXFA_Widget* hParent,
+                                                XFA_WIDGETTYPE eType,
+                                                IXFA_Widget* hBefore) {
+  CXFA_Node* pParentFormItem =
+      hParent ? static_cast<CXFA_FFWidget*>(hParent)->GetDataAcc()->GetNode()
+              : NULL;
+  CXFA_Node* pBeforeFormItem =
+      hBefore ? static_cast<CXFA_FFWidget*>(hBefore)->GetDataAcc()->GetNode()
+              : NULL;
+  CXFA_Node* pNewFormItem =
+      CreateWidgetFormItem(eType, pParentFormItem, pBeforeFormItem);
+  if (pNewFormItem == NULL) {
+    return NULL;
+  }
+  pNewFormItem->GetTemplateNode()->SetFlag(XFA_NODEFLAG_Initialized);
+  pNewFormItem->SetFlag(XFA_NODEFLAG_Initialized);
+  m_pDocView->RunLayout();
+  CXFA_LayoutItem* pLayout =
+      m_pDocView->GetXFALayout()->GetLayoutItem(pNewFormItem);
+  return (IXFA_Widget*)pLayout;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateWidgetFormItem(
+    XFA_WIDGETTYPE eType,
+    CXFA_Node* pParent,
+    CXFA_Node* pBefore) const {
+  switch (eType) {
+    case XFA_WIDGETTYPE_Barcode:
+      return NULL;
+    case XFA_WIDGETTYPE_PushButton:
+      return CreatePushButton(pParent, pBefore);
+    case XFA_WIDGETTYPE_CheckButton:
+      return CreateCheckButton(pParent, pBefore);
+    case XFA_WIDGETTYPE_ExcludeGroup:
+      return CreateExclGroup(pParent, pBefore);
+    case XFA_WIDGETTYPE_RadioButton:
+      return CreateRadioButton(pParent, pBefore);
+    case XFA_WIDGETTYPE_Arc:
+      return CreateArc(pParent, pBefore);
+    case XFA_WIDGETTYPE_Rectangle:
+      return CreateRectangle(pParent, pBefore);
+    case XFA_WIDGETTYPE_Image:
+      return CreateImage(pParent, pBefore);
+    case XFA_WIDGETTYPE_Line:
+      return CreateLine(pParent, pBefore);
+    case XFA_WIDGETTYPE_Text:
+      return CreateText(pParent, pBefore);
+    case XFA_WIDGETTYPE_DatetimeEdit:
+      return CreateDatetimeEdit(pParent, pBefore);
+    case XFA_WIDGETTYPE_DecimalField:
+      return CreateDecimalField(pParent, pBefore);
+    case XFA_WIDGETTYPE_NumericField:
+      return CreateNumericField(pParent, pBefore);
+    case XFA_WIDGETTYPE_Signature:
+      return CreateSignature(pParent, pBefore);
+    case XFA_WIDGETTYPE_TextEdit:
+      return CreateTextEdit(pParent, pBefore);
+    case XFA_WIDGETTYPE_DropdownList:
+      return CreateDropdownList(pParent, pBefore);
+    case XFA_WIDGETTYPE_ListBox:
+      return CreateListBox(pParent, pBefore);
+    case XFA_WIDGETTYPE_ImageField:
+      return CreateImageField(pParent, pBefore);
+    case XFA_WIDGETTYPE_PasswordEdit:
+      return CreatePasswordEdit(pParent, pBefore);
+    case XFA_WIDGETTYPE_Subform:
+      return CreateSubform(pParent, pBefore);
+    default:
+      break;
+  }
+  return NULL;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreatePushButton(CXFA_Node* pParent,
+                                                  CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateField(XFA_ELEMENT_Button, pParent, pBefore);
+  CXFA_Node* pCaption = CreateCopyNode(XFA_ELEMENT_Caption, pField);
+  CXFA_Node* pValue = CreateCopyNode(XFA_ELEMENT_Value, pCaption);
+  CXFA_Node* pText = CreateCopyNode(XFA_ELEMENT_Text, pValue);
+  pText->SetContent(FX_WSTRC(L"Button"), FX_WSTRC(L"Button"), FALSE);
+  CXFA_Node* pPara = CreateCopyNode(XFA_ELEMENT_Para, pCaption);
+  pPara->SetEnum(XFA_ATTRIBUTE_VAlign, XFA_ATTRIBUTEENUM_Middle, FALSE);
+  pPara->SetEnum(XFA_ATTRIBUTE_HAlign, XFA_ATTRIBUTEENUM_Center, FALSE);
+  CreateFontNode(pCaption);
+  CXFA_Node* pBorder = CreateCopyNode(XFA_ELEMENT_Border, pField);
+  pBorder->SetEnum(XFA_ATTRIBUTE_Hand, XFA_ATTRIBUTEENUM_Right, FALSE);
+  CXFA_Node* pEdge = CreateCopyNode(XFA_ELEMENT_Edge, pBorder);
+  pEdge->SetEnum(XFA_ATTRIBUTE_Stroke, XFA_ATTRIBUTEENUM_Raised, FALSE);
+  CXFA_Node* pFill = CreateCopyNode(XFA_ELEMENT_Fill, pBorder);
+  CXFA_Node* pColor = CreateCopyNode(XFA_ELEMENT_Color, pFill);
+  pColor->SetCData(XFA_ATTRIBUTE_Value, FX_WSTRC(L"212, 208, 200"), FALSE);
+  CXFA_Node* pBind = CreateCopyNode(XFA_ELEMENT_Bind, pField);
+  pBind->SetEnum(XFA_ATTRIBUTE_Match, XFA_ATTRIBUTEENUM_None);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateCheckButton(CXFA_Node* pParent,
+                                                   CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateField(XFA_ELEMENT_CheckButton, pParent, pBefore);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateExclGroup(CXFA_Node* pParent,
+                                                 CXFA_Node* pBefore) const {
+  return CreateFormItem(XFA_ELEMENT_ExclGroup, pParent, pBefore);
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateRadioButton(CXFA_Node* pParent,
+                                                   CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateField(XFA_ELEMENT_CheckButton, pParent, pBefore);
+  CXFA_Node* pUi = pField->GetFirstChildByClass(XFA_ELEMENT_Ui);
+  CXFA_Node* pWidget = pUi->GetFirstChildByClass(XFA_ELEMENT_CheckButton);
+  pWidget->SetEnum(XFA_ATTRIBUTE_Shape, XFA_ATTRIBUTEENUM_Round);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateDatetimeEdit(CXFA_Node* pParent,
+                                                    CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateField(XFA_ELEMENT_DateTimeEdit, pParent, pBefore);
+  CreateValueNode(XFA_ELEMENT_Date, pField);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateDecimalField(CXFA_Node* pParent,
+                                                    CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateNumericField(pParent, pBefore);
+  CreateValueNode(XFA_ELEMENT_Decimal, pField);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateNumericField(CXFA_Node* pParent,
+                                                    CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateField(XFA_ELEMENT_NumericEdit, pParent, pBefore);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateSignature(CXFA_Node* pParent,
+                                                 CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateField(XFA_ELEMENT_Signature, pParent, pBefore);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateTextEdit(CXFA_Node* pParent,
+                                                CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateField(XFA_ELEMENT_TextEdit, pParent, pBefore);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateDropdownList(CXFA_Node* pParent,
+                                                    CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateField(XFA_ELEMENT_ChoiceList, pParent, pBefore);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateListBox(CXFA_Node* pParent,
+                                               CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateDropdownList(pParent, pBefore);
+  CXFA_Node* pUi = pField->GetNodeItem(XFA_NODEITEM_FirstChild);
+  CXFA_Node* pListBox = pUi->GetNodeItem(XFA_NODEITEM_FirstChild);
+  pListBox->SetEnum(XFA_ATTRIBUTE_Open, XFA_ATTRIBUTEENUM_Always);
+  pListBox->SetEnum(XFA_ATTRIBUTE_CommitOn, XFA_ATTRIBUTEENUM_Exit);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateImageField(CXFA_Node* pParent,
+                                                  CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateField(XFA_ELEMENT_ImageEdit, pParent, pBefore);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreatePasswordEdit(CXFA_Node* pParent,
+                                                    CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateField(XFA_ELEMENT_PasswordEdit, pParent, pBefore);
+  CXFA_Node* pBind = CreateCopyNode(XFA_ELEMENT_Bind, pField);
+  pBind->SetEnum(XFA_ATTRIBUTE_Match, XFA_ATTRIBUTEENUM_None, FALSE);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateField(XFA_ELEMENT eElement,
+                                             CXFA_Node* pParent,
+                                             CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateFormItem(XFA_ELEMENT_Field, pParent, pBefore);
+  CreateCopyNode(eElement, CreateCopyNode(XFA_ELEMENT_Ui, pField));
+  CreateFontNode(pField);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateArc(CXFA_Node* pParent,
+                                           CXFA_Node* pBefore) const {
+  return CreateDraw(XFA_ELEMENT_Arc, pParent, pBefore);
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateRectangle(CXFA_Node* pParent,
+                                                 CXFA_Node* pBefore) const {
+  return CreateDraw(XFA_ELEMENT_Rectangle, pParent, pBefore);
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateImage(CXFA_Node* pParent,
+                                             CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateDraw(XFA_ELEMENT_Image, pParent, pBefore);
+  CreateCopyNode(XFA_ELEMENT_ImageEdit, CreateCopyNode(XFA_ELEMENT_Ui, pField));
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateLine(CXFA_Node* pParent,
+                                            CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateDraw(XFA_ELEMENT_Line, pParent, pBefore);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateText(CXFA_Node* pParent,
+                                            CXFA_Node* pBefore) const {
+  CXFA_Node* pField = CreateDraw(XFA_ELEMENT_Text, pParent, pBefore);
+  CreateCopyNode(XFA_ELEMENT_TextEdit, CreateCopyNode(XFA_ELEMENT_Ui, pField));
+  CreateFontNode(pField);
+  return pField;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateDraw(XFA_ELEMENT eElement,
+                                            CXFA_Node* pParent,
+                                            CXFA_Node* pBefore) const {
+  CXFA_Node* pDraw = CreateFormItem(XFA_ELEMENT_Draw, pParent, pBefore);
+  CreateValueNode(eElement, pDraw);
+  return pDraw;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateSubform(CXFA_Node* pParent,
+                                               CXFA_Node* pBefore) const {
+  CXFA_Node* pSubform = CreateFormItem(XFA_ELEMENT_Subform, pParent, pBefore);
+  return pSubform;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateFormItem(XFA_ELEMENT eElement,
+                                                CXFA_Node* pParent,
+                                                CXFA_Node* pBefore) const {
+  CXFA_Node* pTemplateParent = pParent ? pParent->GetTemplateNode() : NULL;
+  CXFA_Node* pNewFormItem = pTemplateParent->CloneTemplateToForm(FALSE);
+  if (pParent)
+    pParent->InsertChild(pNewFormItem, pBefore);
+  return pNewFormItem;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateCopyNode(XFA_ELEMENT eElement,
+                                                CXFA_Node* pParent,
+                                                CXFA_Node* pBefore) const {
+  CXFA_Node* pTemplateParent = pParent ? pParent->GetTemplateNode() : NULL;
+  CXFA_Node* pNewNode =
+      CreateTemplateNode(eElement, pTemplateParent,
+                         pBefore ? pBefore->GetTemplateNode() : NULL)
+          ->Clone(FALSE);
+  if (pParent)
+    pParent->InsertChild(pNewNode, pBefore);
+  return pNewNode;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateTemplateNode(XFA_ELEMENT eElement,
+                                                    CXFA_Node* pParent,
+                                                    CXFA_Node* pBefore) const {
+  CXFA_Document* pXFADoc = GetXFADoc();
+  CXFA_Node* pNewTemplateNode = pXFADoc->GetParser()->GetFactory()->CreateNode(
+      XFA_XDPPACKET_Template, eElement);
+  if (pParent)
+    pParent->InsertChild(pNewTemplateNode, pBefore);
+  return pNewTemplateNode;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateFontNode(CXFA_Node* pParent) const {
+  CXFA_Node* pFont = CreateCopyNode(XFA_ELEMENT_Font, pParent);
+  pFont->SetCData(XFA_ATTRIBUTE_Typeface, FX_WSTRC(L"Myriad Pro"), FALSE);
+  return pFont;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateMarginNode(CXFA_Node* pParent,
+                                                  FX_DWORD dwFlags,
+                                                  FX_FLOAT fInsets[4]) const {
+  CXFA_Node* pMargin = CreateCopyNode(XFA_ELEMENT_Margin, pParent);
+  if (dwFlags & 0x01) {
+    pMargin->SetMeasure(XFA_ATTRIBUTE_LeftInset,
+                        CXFA_Measurement(fInsets[0], XFA_UNIT_Pt), FALSE);
+  }
+  if (dwFlags & 0x02) {
+    pMargin->SetMeasure(XFA_ATTRIBUTE_TopInset,
+                        CXFA_Measurement(fInsets[1], XFA_UNIT_Pt), FALSE);
+  }
+  if (dwFlags & 0x04) {
+    pMargin->SetMeasure(XFA_ATTRIBUTE_RightInset,
+                        CXFA_Measurement(fInsets[2], XFA_UNIT_Pt), FALSE);
+  }
+  if (dwFlags & 0x08) {
+    pMargin->SetMeasure(XFA_ATTRIBUTE_BottomInset,
+                        CXFA_Measurement(fInsets[3], XFA_UNIT_Pt), FALSE);
+  }
+  return pMargin;
+}
+CXFA_Node* CXFA_FFWidgetHandler::CreateValueNode(XFA_ELEMENT eValue,
+                                                 CXFA_Node* pParent) const {
+  CXFA_Node* pValue = CreateCopyNode(XFA_ELEMENT_Value, pParent);
+  CreateCopyNode(eValue, pValue);
+  return pValue;
+}
+IXFA_ObjFactory* CXFA_FFWidgetHandler::GetObjFactory() const {
+  return GetXFADoc()->GetParser()->GetFactory();
+}
+CXFA_Document* CXFA_FFWidgetHandler::GetXFADoc() const {
+  return ((CXFA_FFDoc*)(m_pDocView->GetDoc()))->GetXFADoc();
+}
+CXFA_FFMenuHandler::CXFA_FFMenuHandler() {}
+CXFA_FFMenuHandler::~CXFA_FFMenuHandler() {}
+FX_BOOL CXFA_FFMenuHandler::CanCopy(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->CanCopy();
+}
+FX_BOOL CXFA_FFMenuHandler::CanCut(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->CanCut();
+}
+FX_BOOL CXFA_FFMenuHandler::CanPaste(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->CanPaste();
+}
+FX_BOOL CXFA_FFMenuHandler::CanSelectAll(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->CanSelectAll();
+}
+FX_BOOL CXFA_FFMenuHandler::CanDelete(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->CanDelete();
+}
+FX_BOOL CXFA_FFMenuHandler::CanDeSelect(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->CanDeSelect();
+}
+FX_BOOL CXFA_FFMenuHandler::Copy(IXFA_Widget* hWidget, CFX_WideString& wsText) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->Copy(wsText);
+}
+FX_BOOL CXFA_FFMenuHandler::Cut(IXFA_Widget* hWidget, CFX_WideString& wsText) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->Cut(wsText);
+}
+FX_BOOL CXFA_FFMenuHandler::Paste(IXFA_Widget* hWidget,
+                                  const CFX_WideString& wsText) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->Paste(wsText);
+}
+FX_BOOL CXFA_FFMenuHandler::SelectAll(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->SelectAll();
+}
+FX_BOOL CXFA_FFMenuHandler::Delete(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->Delete();
+}
+FX_BOOL CXFA_FFMenuHandler::DeSelect(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->DeSelect();
+}
+FX_BOOL CXFA_FFMenuHandler::CanUndo(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->CanUndo();
+}
+FX_BOOL CXFA_FFMenuHandler::CanRedo(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->CanRedo();
+}
+FX_BOOL CXFA_FFMenuHandler::Undo(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->Undo();
+}
+FX_BOOL CXFA_FFMenuHandler::Redo(IXFA_Widget* hWidget) {
+  return static_cast<CXFA_FFWidget*>(hWidget)->Redo();
+}
+FX_BOOL CXFA_FFMenuHandler::GetSuggestWords(
+    IXFA_Widget* hWidget,
+    CFX_PointF pointf,
+    std::vector<CFX_ByteString>& sSuggest) {
+  return static_cast<CXFA_FFWidget*>(hWidget)
+      ->GetSuggestWords(pointf, sSuggest);
+}
+FX_BOOL CXFA_FFMenuHandler::ReplaceSpellCheckWord(
+    IXFA_Widget* hWidget,
+    CFX_PointF pointf,
+    const CFX_ByteStringC& bsReplace) {
+  return static_cast<CXFA_FFWidget*>(hWidget)
+      ->ReplaceSpellCheckWord(pointf, bsReplace);
+}
diff --git a/xfa/fxfa/app/xfa_ffwidgethandler.h b/xfa/fxfa/app/xfa_ffwidgethandler.h
new file mode 100644
index 0000000..a9998b3
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffwidgethandler.h
@@ -0,0 +1,176 @@
+// 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_FXFA_APP_XFA_FFWIDGETHANDLER_H_
+#define XFA_FXFA_APP_XFA_FFWIDGETHANDLER_H_
+
+#include <vector>
+
+#include "xfa/fxfa/parser/xfa_document.h"
+#include "xfa/include/fxfa/fxfa.h"
+
+class CXFA_FFDocView;
+
+class CXFA_FFWidgetHandler : public IXFA_WidgetHandler {
+ public:
+  CXFA_FFWidgetHandler(CXFA_FFDocView* pDocView);
+  ~CXFA_FFWidgetHandler();
+  virtual IXFA_Widget* CreateWidget(IXFA_Widget* hParent,
+                                    XFA_WIDGETTYPE eType,
+                                    IXFA_Widget* hBefore = NULL);
+  virtual IXFA_PageView* GetPageView(IXFA_Widget* hWidget);
+  virtual void GetRect(IXFA_Widget* hWidget, CFX_RectF& rt);
+  virtual FX_DWORD GetStatus(IXFA_Widget* hWidget);
+  virtual FX_BOOL GetBBox(IXFA_Widget* hWidget,
+                          CFX_RectF& rtBox,
+                          FX_DWORD dwStatus,
+                          FX_BOOL bDrawFocus = FALSE);
+  virtual CXFA_WidgetAcc* GetDataAcc(IXFA_Widget* hWidget);
+  virtual void GetName(IXFA_Widget* hWidget,
+                       CFX_WideString& wsName,
+                       int32_t iNameType = 0);
+  virtual FX_BOOL GetToolTip(IXFA_Widget* hWidget, CFX_WideString& wsToolTip);
+  virtual void SetPrivateData(IXFA_Widget* hWidget,
+                              void* module_id,
+                              void* pData,
+                              PD_CALLBACK_FREEDATA callback);
+  virtual void* GetPrivateData(IXFA_Widget* hWidget, void* module_id);
+  virtual FX_BOOL OnMouseEnter(IXFA_Widget* hWidget);
+  virtual FX_BOOL OnMouseExit(IXFA_Widget* hWidget);
+  virtual FX_BOOL OnLButtonDown(IXFA_Widget* hWidget,
+                                FX_DWORD dwFlags,
+                                FX_FLOAT fx,
+                                FX_FLOAT fy);
+  virtual FX_BOOL OnLButtonUp(IXFA_Widget* hWidget,
+                              FX_DWORD dwFlags,
+                              FX_FLOAT fx,
+                              FX_FLOAT fy);
+  virtual FX_BOOL OnLButtonDblClk(IXFA_Widget* hWidget,
+                                  FX_DWORD dwFlags,
+                                  FX_FLOAT fx,
+                                  FX_FLOAT fy);
+  virtual FX_BOOL OnMouseMove(IXFA_Widget* hWidget,
+                              FX_DWORD dwFlags,
+                              FX_FLOAT fx,
+                              FX_FLOAT fy);
+  virtual FX_BOOL OnMouseWheel(IXFA_Widget* hWidget,
+                               FX_DWORD dwFlags,
+                               int16_t zDelta,
+                               FX_FLOAT fx,
+                               FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonDown(IXFA_Widget* hWidget,
+                                FX_DWORD dwFlags,
+                                FX_FLOAT fx,
+                                FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonUp(IXFA_Widget* hWidget,
+                              FX_DWORD dwFlags,
+                              FX_FLOAT fx,
+                              FX_FLOAT fy);
+  virtual FX_BOOL OnRButtonDblClk(IXFA_Widget* hWidget,
+                                  FX_DWORD dwFlags,
+                                  FX_FLOAT fx,
+                                  FX_FLOAT fy);
+
+  virtual FX_BOOL OnKeyDown(IXFA_Widget* hWidget,
+                            FX_DWORD dwKeyCode,
+                            FX_DWORD dwFlags);
+  virtual FX_BOOL OnKeyUp(IXFA_Widget* hWidget,
+                          FX_DWORD dwKeyCode,
+                          FX_DWORD dwFlags);
+  virtual FX_BOOL OnChar(IXFA_Widget* hWidget,
+                         FX_DWORD dwChar,
+                         FX_DWORD dwFlags);
+  virtual FX_DWORD OnHitTest(IXFA_Widget* hWidget, FX_FLOAT fx, FX_FLOAT fy);
+  virtual FX_BOOL OnSetCursor(IXFA_Widget* hWidget, FX_FLOAT fx, FX_FLOAT fy);
+  virtual void RenderWidget(IXFA_Widget* hWidget,
+                            CFX_Graphics* pGS,
+                            CFX_Matrix* pMatrix = NULL,
+                            FX_BOOL bHighlight = FALSE);
+  virtual FX_BOOL HasEvent(CXFA_WidgetAcc* pWidgetAcc,
+                           XFA_EVENTTYPE eEventType);
+  virtual int32_t ProcessEvent(CXFA_WidgetAcc* pWidgetAcc,
+                               CXFA_EventParam* pParam);
+
+ protected:
+  CXFA_Node* CreateWidgetFormItem(XFA_WIDGETTYPE eType,
+                                  CXFA_Node* pParent,
+                                  CXFA_Node* pBefore) const;
+
+  CXFA_Node* CreatePushButton(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateCheckButton(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateExclGroup(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateRadioButton(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateDatetimeEdit(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateDecimalField(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateNumericField(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateSignature(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateTextEdit(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateDropdownList(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateListBox(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateImageField(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreatePasswordEdit(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateField(XFA_ELEMENT eElement,
+                         CXFA_Node* pParent,
+                         CXFA_Node* pBefore) const;
+  CXFA_Node* CreateArc(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateRectangle(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateImage(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateLine(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateText(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateDraw(XFA_ELEMENT eElement,
+                        CXFA_Node* pParent,
+                        CXFA_Node* pBefore) const;
+
+  CXFA_Node* CreateSubform(CXFA_Node* pParent, CXFA_Node* pBefore) const;
+  CXFA_Node* CreateFormItem(XFA_ELEMENT eElement,
+                            CXFA_Node* pParent,
+                            CXFA_Node* pBefore) const;
+  CXFA_Node* CreateCopyNode(XFA_ELEMENT eElement,
+                            CXFA_Node* pParent,
+                            CXFA_Node* pBefore = NULL) const;
+  CXFA_Node* CreateTemplateNode(XFA_ELEMENT eElement,
+                                CXFA_Node* pParent,
+                                CXFA_Node* pBefore) const;
+  CXFA_Node* CreateFontNode(CXFA_Node* pParent) const;
+  CXFA_Node* CreateMarginNode(CXFA_Node* pParent,
+                              FX_DWORD dwFlags,
+                              FX_FLOAT fInsets[4]) const;
+  CXFA_Node* CreateValueNode(XFA_ELEMENT eValue, CXFA_Node* pParent) const;
+  IXFA_ObjFactory* GetObjFactory() const;
+  CXFA_Document* GetXFADoc() const;
+
+  CXFA_FFDocView* m_pDocView;
+};
+
+class CXFA_FFMenuHandler : public IXFA_MenuHandler {
+ public:
+  CXFA_FFMenuHandler();
+  ~CXFA_FFMenuHandler();
+  virtual FX_BOOL CanCopy(IXFA_Widget* hWidget);
+  virtual FX_BOOL CanCut(IXFA_Widget* hWidget);
+  virtual FX_BOOL CanPaste(IXFA_Widget* hWidget);
+  virtual FX_BOOL CanSelectAll(IXFA_Widget* hWidget);
+  virtual FX_BOOL CanDelete(IXFA_Widget* hWidget);
+  virtual FX_BOOL CanDeSelect(IXFA_Widget* hWidget);
+  virtual FX_BOOL Copy(IXFA_Widget* hWidget, CFX_WideString& wsText);
+  virtual FX_BOOL Cut(IXFA_Widget* hWidget, CFX_WideString& wsText);
+  virtual FX_BOOL Paste(IXFA_Widget* hWidget, const CFX_WideString& wsText);
+  virtual FX_BOOL SelectAll(IXFA_Widget* hWidget);
+  virtual FX_BOOL Delete(IXFA_Widget* hWidget);
+  virtual FX_BOOL DeSelect(IXFA_Widget* hWidget);
+  virtual FX_BOOL CanUndo(IXFA_Widget* hWidget);
+  virtual FX_BOOL CanRedo(IXFA_Widget* hWidget);
+  virtual FX_BOOL Undo(IXFA_Widget* hWidget);
+  virtual FX_BOOL Redo(IXFA_Widget* hWidget);
+  virtual FX_BOOL GetSuggestWords(IXFA_Widget* hWidget,
+                                  CFX_PointF pointf,
+                                  std::vector<CFX_ByteString>& sSuggest);
+  virtual FX_BOOL ReplaceSpellCheckWord(IXFA_Widget* hWidget,
+                                        CFX_PointF pointf,
+                                        const CFX_ByteStringC& bsReplace);
+};
+
+#endif  //  XFA_FXFA_APP_XFA_FFWIDGETHANDLER_H_
diff --git a/xfa/fxfa/app/xfa_fontmgr.cpp b/xfa/fxfa/app/xfa_fontmgr.cpp
new file mode 100644
index 0000000..dda8f5b
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fontmgr.cpp
@@ -0,0 +1,2089 @@
+// 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/fxfa/app/xfa_fontmgr.h"
+
+#include <algorithm>
+
+#include "core/include/fpdfapi/cpdf_dictionary.h"
+#include "core/include/fpdfapi/cpdf_document.h"
+#include "core/include/fpdfapi/fpdf_resource.h"
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+static const XFA_FONTINFO g_XFAFontsMap[] = {
+    {0x01d5d33e, L"SimSun", L"Arial", 0, 936},
+    {0x01e4f102, L"YouYuan", L"Arial", 1, 936},
+    {0x030549dc, L"LiSu", L"Arial", 1, 936},
+    {0x032edd44, L"Simhei", L"Arial", 1, 936},
+    {0x03eac6fc, L"PoorRichard-Regular", L"Arial", 2, 1252},
+    {0x03ed90e6, L"Nina", L"Arial", 0, 1252},
+    {0x077b56b3, L"KingsoftPhoneticPlain", L"Arial", 0, 1252},
+    {0x078ed524, L"MicrosoftSansSerif", L"Arial", 0, 1252},
+    {0x089b18a9, L"Arial", L"Arial", 0, 1252},
+    {0x0b2cad72, L"MonotypeCorsiva", L"Arial", 8, 1252},
+    {0x0bb003e7, L"Kartika", L"Arial", 2, 1252},
+    {0x0bb469df, L"VinerHandITC", L"Arial", 8, 1252},
+    {0x0bc1a851, L"SegoeUI", L"Arial", 0, 1252},
+    {0x0c112ebd, L"KozukaGothicPro-VIM", L"Arial", 0, 1252},
+    {0x0cfcb9c1, L"AdobeThai", L"Kokila,Arial Narrow", 0, 847},
+    {0x0e7de0f9, L"Playbill", L"Arial", 0, 1252},
+    {0x0eff47c3, L"STHupo", L"Arial", 0, 936},
+    {0x107ad374, L"Constantia", L"Arial", 2, 1252},
+    {0x12194c2d, L"KunstlerScript", L"Arial", 8, 1252},
+    {0x135ef6a1, L"MinionProSmBd",
+     L"Bell MT,Corbel,Times New Roman,Cambria,Berlin Sans FB", 0, 1252},
+    {0x158c4049, L"Garamond", L"Arial", 2, 1252},
+    {0x160ecb24, L"STZhongsong", L"Arial", 0, 936},
+    {0x161ed07e, L"MSGothic", L"Arial", 1, 1252},
+    {0x171d1ed1, L"SnapITC-Regular", L"Arial", 0, 1252},
+    {0x18d1188f, L"Cambria", L"Arial", 2, 1252},
+    {0x18eaf350, L"ArialUnicodeMS", L"Arial", 0, 936},
+    {0x1a92d115, L"MingLiU", L"Arial", 1, 1252},
+    {0x1cc217c6, L"TrebuchetMS", L"Arial", 0, 1252},
+    {0x1d649596, L"BasemicTimes", L"Arial", 0, 1252},
+    {0x1e34ee60, L"BellMT", L"Arial", 2, 1252},
+    {0x1eb36945, L"CooperBlack", L"Arial", 2, 1252},
+    {0x1ef7787d, L"BatangChe", L"Arial", 1, 1252},
+    {0x20b3bd3a, L"BrushScriptMT", L"Arial", 8, 1252},
+    {0x220877aa, L"Candara", L"Arial", 0, 1252},
+    {0x22135007, L"FreestyleScript-Regular", L"Arial", 8, 1252},
+    {0x251059c3, L"Chiller", L"Arial", 0, 1252},
+    {0x25bed6dd, L"MSReferenceSansSerif", L"Arial", 0, 1252},
+    {0x28154c81, L"Parchment-Regular", L"Arial", 8, 1252},
+    {0x29711eb9, L"STLiti", L"Arial", 0, 936},
+    {0x2b1993b4, L"Basemic", L"Arial", 0, 1252},
+    {0x2b316339, L"NiagaraSolid-Reg", L"Arial", 0, 1252},
+    {0x2c147529, L"FootlightMTLight", L"Arial", 0, 1252},
+    {0x2c198928, L"HarlowSolid", L"Arial", 0, 1252},
+    {0x2c6ac6b2, L"LucidaBright", L"Arial", 2, 1252},
+    {0x2c9f38e2, L"KozukaMinchoPro-VIR", L"Arial", 0, 1252},
+    {0x2d5a47b0, L"STCaiyun", L"Arial", 0, 936},
+    {0x2def26bf, L"BernardMT-Condensed", L"Arial", 0, 1252},
+    {0x2fd8930b, L"KozukaMinchoPr6NR", L"Arial", 0, 1252},
+    {0x3115525a, L"FangSong_GB2312", L"Arial", 0, 1252},
+    {0x31327817, L"MyriadPro",
+     L"Calibri,Corbel,Candara,Cambria Math,Franklin Gothic Medium,Arial "
+     L"Narrow,Times New Roman",
+     0, 1252},
+    {0x32244975, L"Helvetica", L"Arial", 0, 1252},
+    {0x32ac995c, L"Terminal", L"Arial", 0, 1252},
+    {0x338d648a, L"NiagaraEngraved-Reg", L"Arial", 0, 1252},
+    {0x33bb65f2, L"Sylfaen", L"Arial", 2, 1252},
+    {0x3402c30e, L"MSPMincho", L"Arial", 2, 1252},
+    {0x3412bf31, L"SimSun-PUA", L"Arial", 0, 936},
+    {0x36eb39b9, L"BerlinSansFB", L"Arial", 0, 1252},
+    {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252},
+    {0x3864c4f6, L"HighTowerText", L"Arial", 2, 1252},
+    {0x3a257d03, L"FangSong_GB2312", L"Arial", 0, 1252},
+    {0x3cdae668, L"FreestyleScript", L"Arial", 8, 1252},
+    {0x3d55aed7, L"Jokerman", L"Arial", 0, 1252},
+    {0x3d5b4385, L"PMingLiU", L"Arial", 2, 1252},
+    {0x3d9b7669, L"EstrangeloEdessa", L"Arial", 0, 1252},
+    {0x3e532d74, L"FranklinGothicMedium", L"Arial", 0, 1252},
+    {0x3e6aa32d, L"NSimSun", L"Arial", 1, 936},
+    {0x3f6c36a8, L"Gautami", L"Arial", 0, 1252},
+    {0x3ff32662, L"Chiller-Regular", L"Arial", 0, 1252},
+    {0x409de312, L"ModernNo.20", L"Arial", 2, 1252},
+    {0x41443c5e, L"Georgia", L"Arial", 2, 1252},
+    {0x4160ade5, L"BellGothicStdBlack",
+     L"Arial,Arial Unicode MS,Book Antiqua,Dotum,Georgia", 0, 1252},
+    {0x421976c4, L"Modern-Regular", L"Arial", 2, 1252},
+    {0x422a7252, L"Stencil", L"Arial", 0, 1252},
+    {0x42c8554f, L"Fixedsys", L"Arial", 0, 1252},
+    {0x435cb41d, L"Roman", L"Arial", 0, 1252},
+    {0x47882383, L"CourierNew", L"Arial", 1, 1252},
+    {0x480a2338, L"BerlinSansFBDemi", L"Arial", 0, 1252},
+    {0x480bf7a4, L"CourierStd", L"Courier New,Verdana", 0, 1252},
+    {0x481ad6ed, L"VladimirScript", L"Arial", 8, 1252},
+    {0x4911577a, L"YouYuan", L"Arial", 1, 936},
+    {0x4a788d72, L"STXingkai", L"Arial", 0, 936},
+    {0x4bf88566, L"SegoeCondensed", L"Arial", 0, 1252},
+    {0x4ccf51a4, L"BerlinSansFB-Reg", L"Arial", 0, 1252},
+    {0x4ea967ce, L"GulimChe", L"Arial", 1, 1252},
+    {0x4f68bd79, L"LetterGothicStd", L"Courier New,Verdana", 0, 1252},
+    {0x51a0d0e6, L"KozukaGothicPr6NM", L"Arial", 0, 1252},
+    {0x531b3dea, L"BasemicSymbol", L"Arial", 0, 1252},
+    {0x5333fd39, L"CalifornianFB-Reg", L"Arial", 2, 1252},
+    {0x53561a54, L"FZYTK--GBK1-0", L"Arial", 0, 936},
+    {0x55e0dde6, L"LucidaSansTypewriter", L"Arial", 0, 1252},
+    {0x574d4d3d, L"AdobeArabic", L"Arial Narrow", 0, 1252},
+    {0x5792e759, L"STKaiti", L"Arial", 0, 936},
+    {0x5921978e, L"LucidaSansUnicode", L"Arial", 0, 1252},
+    {0x594e2da4, L"Vrinda", L"Arial", 0, 1252},
+    {0x59baa9a2, L"KaiTi_GB2312", L"Arial", 0, 1252},
+    {0x5cfedf4f, L"BaskOldFace", L"Arial", 0, 1252},
+    {0x5f97921c, L"AdobeMyungjoStdM",
+     L"Batang,Bookman Old Style,Consolas,STZhongsong", 0, 936},
+    {0x5fefbfad, L"Batang", L"Arial", 2, 1252},
+    {0x605342b9, L"DotumChe", L"Arial", 1, 1252},
+    {0x608c5f9a, L"KaiTi_GB2312", L"Arial", 0, 936},
+    {0x61efd0d1, L"MaturaMTScriptCapitals", L"Arial", 0, 1252},
+    {0x626608a9, L"MVBoli", L"Arial", 0, 1252},
+    {0x630501a3, L"SmallFonts", L"Arial", 0, 1252},
+    {0x65d0e2a9, L"FZYTK--GBK1-0", L"Arial", 0, 936},
+    {0x669f29e1, L"FZSTK--GBK1-0", L"Arial", 0, 936},
+    {0x673a9e5f, L"Tunga", L"Arial", 0, 1252},
+    {0x691aa4ce, L"NiagaraSolid", L"Arial", 0, 1252},
+    {0x696259b7, L"Corbel", L"Arial", 0, 1252},
+    {0x696ee9be, L"STXihei", L"Arial", 0, 936},
+    {0x6c59cf69, L"Dotum", L"Arial", 0, 1252},
+    {0x707fa561, L"Gungsuh", L"Arial", 2, 1252},
+    {0x71416bb2, L"ZWAdobeF", L"Arial", 0, 1252},
+    {0x71b41801, L"Verdana", L"Arial", 0, 1252},
+    {0x73f25e4c, L"PalatinoLinotype", L"Arial", 0, 1252},
+    {0x73f4d19f, L"NiagaraEngraved", L"Arial", 0, 1252},
+    {0x74001694, L"MyriadProBlack", L"Book Antiqua,Constantia,Dotum,Georgia", 0,
+     1252},
+    {0x74b14d8f, L"Haettenschweiler", L"Arial", 0, 1252},
+    {0x74cb44ee, L"NSimSun", L"Arial", 1, 936},
+    {0x76b4d7ff, L"Shruti", L"Arial", 0, 1252},
+    {0x788b3533, L"Webdings", L"Arial", 6, 42},
+    {0x797dde99, L"MSSerif", L"Arial", 0, 1252},
+    {0x7a0f9e9e, L"MSMincho", L"Arial", 1, 1252},
+    {0x7b439caf, L"OldEnglishTextMT", L"Arial", 0, 1252},
+    {0x8213a433, L"LucidaSans-Typewriter", L"Arial", 0, 1252},
+    {0x82fec929, L"AdobeSongStdL",
+     L"Centaur,Calibri,STSong,Bell MT,Garamond,Times New Roman", 0, 936},
+    {0x83581825, L"Modern", L"Arial", 0, 1252},
+    {0x835a2823, L"Algerian", L"Arial", 0, 1252},
+    {0x83dab9f5, L"Script", L"Arial", 0, 1252},
+    {0x847b56da, L"Tahoma", L"Arial", 0, 1252},
+    {0x8a783cb2, L"SimSun-PUA", L"Arial", 0, 1252},
+    {0x8b5cac0e, L"Onyx", L"Arial", 0, 1252},
+    {0x8c6a499e, L"Gulim", L"Arial", 0, 1252},
+    {0x8e0af790, L"JuiceITC", L"Arial", 0, 1252},
+    {0x8e8d43b2, L"Centaur", L"Arial", 2, 1252},
+    {0x8ee4dcca, L"BookshelfSymbol7", L"Arial", 0, 1252},
+    {0x90794800, L"BellGothicStdLight", L"Bell MT,Calibri,Times New Roman", 0,
+     1252},
+    {0x909b516a, L"Century", L"Arial", 2, 1252},
+    {0x92ae370d, L"MSOutlook", L"Arial", 4, 42},
+    {0x93c9fbf1, L"LucidaFax", L"Arial", 2, 1252},
+    {0x9565085e, L"BookAntiqua", L"Arial", 2, 1252},
+    {0x9856d95d, L"AdobeMingStdL", L"Arial,Arial Unicode MS,Cambria,BatangChe",
+     0, 949},
+    {0x9bbadd6b, L"ColonnaMT", L"Arial", 0, 1252},
+    {0x9cbd16a4, L"ShowcardGothic-Reg", L"Arial", 0, 1252},
+    {0x9d73008e, L"MSSansSerif", L"Arial", 0, 1252},
+    {0xa0607db1, L"GungsuhChe", L"Arial", 1, 1252},
+    {0xa0bcf6a1, L"LatinWide", L"Arial", 2, 1252},
+    {0xa1429b36, L"Symbol", L"Arial", 6, 42},
+    {0xa1fa5abc, L"Wingdings2", L"Arial", 6, 42},
+    {0xa1fa5abd, L"Wingdings3", L"Arial", 6, 42},
+    {0xa427bad4, L"InformalRoman-Regular", L"Arial", 8, 1252},
+    {0xa8b92ece, L"FZSTK--GBK1-0", L"Arial", 0, 936},
+    {0xa8d83ece, L"CalifornianFB", L"Arial", 2, 1252},
+    {0xaa3e082c, L"Kingsoft-Phonetic", L"Arial", 0, 1252},
+    {0xaa6bcabe, L"HarlowSolidItalic", L"Arial", 0, 1252},
+    {0xade5337c, L"MSUIGothic", L"Arial", 0, 1252},
+    {0xb08dd941, L"WideLatin", L"Arial", 2, 1252},
+    {0xb207f05d, L"PoorRichard", L"Arial", 2, 1252},
+    {0xb3bc492f, L"JuiceITC-Regular", L"Arial", 0, 1252},
+    {0xb5545399, L"Marlett", L"Arial", 4, 42},
+    {0xb5dd1ebb, L"BritannicBold", L"Arial", 0, 1252},
+    {0xb699c1c5, L"LucidaCalligraphy-Italic", L"Arial", 0, 1252},
+    {0xb725d629, L"TimesNewRoman", L"Arial", 2, 1252},
+    {0xb7eaebeb, L"AdobeHeitiStdR", L"Batang,Century,Dotum", 0, 936},
+    {0xbd29c486, L"BerlinSansFBDemi-Bold", L"Arial", 0, 1252},
+    {0xbe8a8db4, L"BookshelfSymbolSeven", L"Arial", 0, 1252},
+    {0xc16c0118, L"AdobeHebrew", L"Bell MT,Berlin Sans FB,Calibri", 0, 1252},
+    {0xc318b0af, L"MyriadProLight", L"Calibri,STFangsong,Times New Roman", 0,
+     1252},
+    {0xc65e5659, L"CambriaMath", L"Arial", 2, 1252},
+    {0xc75c8f05, L"LucidaConsole", L"Arial", 1, 1252},
+    {0xca7c35d6, L"Calibri", L"Arial", 0, 1252},
+    {0xcb053f53, L"MicrosoftYaHei", L"Arial", 0, 936},
+    {0xcb7190f9, L"Magneto-Bold", L"Arial", 0, 1252},
+    {0xcca00cc5, L"System", L"Arial", 0, 1252},
+    {0xccad6f76, L"Jokerman-Regular", L"Arial", 0, 1252},
+    {0xccc5818c, L"EuroSign", L"Arial", 0, 1252},
+    {0xcf3d7234, L"LucidaHandwriting-Italic", L"Arial", 0, 1252},
+    {0xcf7b8fdb, L"MinionPro",
+     L"Bell MT,Corbel,Times New Roman,Cambria,Berlin Sans FB", 0, 1252},
+    {0xcfe5755f, L"Simhei", L"Arial", 1, 936},
+    {0xd011f4ee, L"MSPGothic", L"Arial", 0, 1252},
+    {0xd060e7ef, L"Vivaldi", L"Arial", 8, 1252},
+    {0xd07edec1, L"FranklinGothic-Medium", L"Arial", 0, 1252},
+    {0xd107243f, L"SimSun", L"Arial", 0, 936},
+    {0xd1881562, L"ArialNarrow", L"Arial Narrow", 0, 1252},
+    {0xd22b7dce, L"BodoniMTPosterCompressed", L"Arial", 0, 1252},
+    {0xd22bfa60, L"ComicSansMS", L"Arial", 8, 1252},
+    {0xd3bd0e35, L"Bauhaus93", L"Arial", 0, 1252},
+    {0xd429ee7a, L"STFangsong", L"Arial", 0, 936},
+    {0xd6679c12, L"BernardMTCondensed", L"Arial", 0, 1252},
+    {0xd8e8a027, L"LucidaSans", L"Arial", 0, 1252},
+    {0xd9fe7761, L"HighTowerText-Reg", L"Arial", 2, 1252},
+    {0xda7e551e, L"STSong", L"Arial", 0, 936},
+    {0xdaa6842d, L"STZhongsong", L"Arial", 0, 936},
+    {0xdaaab93f, L"STFangsong", L"Arial", 0, 936},
+    {0xdaeb0713, L"STSong", L"Arial", 0, 936},
+    {0xdafedbef, L"STCaiyun", L"Arial", 0, 936},
+    {0xdb00a3d9, L"Broadway", L"Arial", 0, 1252},
+    {0xdb1f5ad4, L"STXinwei", L"Arial", 0, 936},
+    {0xdb326e7f, L"STKaiti", L"Arial", 0, 936},
+    {0xdb69595a, L"STHupo", L"Arial", 0, 936},
+    {0xdba0082c, L"STXihei", L"Arial", 0, 936},
+    {0xdbd0ab18, L"STXingkai", L"Arial", 0, 936},
+    {0xdc1a7db1, L"STLiti", L"Arial", 0, 936},
+    {0xdc33075f, L"KristenITC-Regular", L"Arial", 8, 1252},
+    {0xdcc7009c, L"Harrington", L"Arial", 0, 1252},
+    {0xdd712466, L"ArialBlack", L"Arial", 0, 1252},
+    {0xdde87b3e, L"Impact", L"Arial", 0, 1252},
+    {0xdf69fb32, L"SnapITC", L"Arial", 0, 1252},
+    {0xdf8b25e8, L"CenturyGothic", L"Arial", 0, 1252},
+    {0xe0f705c0, L"KristenITC", L"Arial", 8, 1252},
+    {0xe1427573, L"Raavi", L"Arial", 0, 1252},
+    {0xe2cea0cb, L"Magneto", L"Arial", 0, 1252},
+    {0xe36a9e17, L"Ravie", L"Arial", 0, 1252},
+    {0xe433f8e2, L"Parchment", L"Arial", 8, 1252},
+    {0xe43dff4a, L"Wingdings", L"Arial", 4, 42},
+    {0xe4e2c405, L"MTExtra", L"Arial", 6, 42},
+    {0xe618cc35, L"InformalRoman", L"Arial", 8, 1252},
+    {0xe6c27ffc, L"Mistral", L"Arial", 8, 1252},
+    {0xe7ebf4b9, L"Courier", L"Courier New", 0, 1252},
+    {0xe8bc4a9d, L"MSReferenceSpecialty", L"Arial", 0, 1252},
+    {0xe90fb013, L"TempusSansITC", L"Arial", 0, 1252},
+    {0xec637b42, L"Consolas", L"Verdana", 1, 1252},
+    {0xed3a683b, L"STXinwei", L"Arial", 0, 936},
+    {0xef264cd1, L"LucidaHandwriting", L"Arial", 0, 1252},
+    {0xf086bca2, L"BaskervilleOldFace", L"Arial", 0, 1252},
+    {0xf1028030, L"Mangal", L"Arial", 2, 1252},
+    {0xf1da7eb9, L"ShowcardGothic", L"Arial", 0, 1252},
+    {0xf210f06a, L"ArialMT", L"Arial", 0, 1252},
+    {0xf477f16a, L"Latha", L"Arial", 0, 1252},
+    {0xf616f3dd, L"LiSu", L"Arial", 1, 936},
+    {0xfa479aa6, L"MicrosoftYaHei", L"Arial", 0, 936},
+    {0xfcd19697, L"BookmanOldStyle", L"Arial", 0, 1252},
+    {0xfe209a82, L"LucidaCalligraphy", L"Arial", 0, 1252},
+    {0xfef135f8, L"AdobeHeitiStd-Regular", L"Batang,Century,Dotum", 0, 936},
+};
+#elif _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
+static const XFA_FONTINFO g_XFAFontsMap[] = {
+    {0x01d5d33e, L"SimSun",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR "
+     L"PL UMing TW MBE",
+     0, 936},
+    {0x01e4f102, L"YouYuan",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR "
+     L"PL UMing TW MBE",
+     1, 936},
+    {0x030549dc, L"LiSu",
+     L"WenQuanYi Zen Hei,WenQuanYi Zen Hei Sharp,WenQuanYi Zen Hei "
+     L"Mono,WenQuanYi Micro Hei",
+     1, 936},
+    {0x032edd44, L"Simhei",
+     L"WenQuanYi Zen Hei,WenQuanYi Zen Hei Sharp,WenQuanYi Zen Hei "
+     L"Mono,WenQuanYi Micro Hei",
+     1, 936},
+    {0x03eac6fc, L"PoorRichard-Regular", L"Droid Sans Japanese,FreeSerif", 2,
+     1252},
+    {0x03ed90e6, L"Nina", L"FreeSerif", 0, 1252},
+    {0x077b56b3, L"KingsoftPhoneticPlain",
+     L"Tibetan Machine Uni,LKLUG,Samyak Gujarati,Droid Sans Thai,Droid Sans "
+     L"Armenian,Untitled1,utkal,Lohit Oriya",
+     0, 1252},
+    {0x078ed524, L"MicrosoftSansSerif",
+     L"Droid Sans Japanese,FreeSerif,WenQuanYi Micro Hei", 0, 1252},
+    {0x089b18a9, L"Arial",
+     L"Droid Sans Japanese,DejaVu Sans Condensed,FreeSerif,WenQuanYi Micro Hei",
+     0, 1252},
+    {0x0b2cad72, L"MonotypeCorsiva", L"Droid Sans Japanese,FreeSerif", 8, 1252},
+    {0x0bb003e7, L"Kartika",
+     L"FreeSans,Liberation Sans,Liberation Sans Narrow,Nimbus Sans "
+     L"L,Garuda,FreeSerif,WenQuanYi Micro Hei",
+     2, 1252},
+    {0x0bb469df, L"VinerHandITC",
+     L"Droid Sans Japanese,Ubuntu,Liberation Sans,Liberation Serif", 8, 1252},
+    {0x0bc1a851, L"SegoeUI", L"Droid Sans Japanese,DejaVu Sans", 0, 1252},
+    {0x0c112ebd, L"KozukaGothicPro-VIM", L"FreeSerif", 0, 1252},
+    {0x0cfcb9c1, L"AdobeThai", L"Droid Sans Japanese,Waree", 0, 847},
+    {0x0e7de0f9, L"Playbill",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid "
+     L"Sans Ethiopic,Droid Sans Japanese,FreeSerif",
+     0, 1252},
+    {0x0eff47c3, L"STHupo", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0,
+     936},
+    {0x107ad374, L"Constantia",
+     L"Droid Sans Japanese,FreeSerif,WenQuanYi Micro Hei,Ubuntu", 2, 1252},
+    {0x12194c2d, L"KunstlerScript", L"Droid Sans Japanese,Liberation Serif", 8,
+     1252},
+    {0x135ef6a1, L"MinionProSmBd", L"Liberation Serif", 0, 1252},
+    {0x158c4049, L"Garamond",
+     L"Droid Sans Japanese,Liberation Serif,Ubuntu,FreeSerif", 2, 1252},
+    {0x160ecb24, L"STZhongsong",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0x161ed07e, L"MSGothic",
+     L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,AR PL "
+     L"UMing CN,AR PL UMing HK,AR PL UMing TW",
+     1, 1252},
+    {0x171d1ed1, L"SnapITC-Regular",
+     L"Liberation Sans Narrow,Ubuntu Condensed,Nimbus Sans L,DejaVu Sans", 0,
+     1252},
+    {0x18d1188f, L"Cambria", L"Droid Sans Japanese,FreeSerif,FreeMono", 2,
+     1252},
+    {0x18eaf350, L"ArialUnicodeMS",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0x1a92d115, L"MingLiU",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     1, 1252},
+    {0x1cc217c6, L"TrebuchetMS",
+     L"Droid Sans Japanese,Liberation Serif,FreeSerif,Ubuntu", 0, 1252},
+    {0x1d649596, L"BasemicTimes",
+     L"Liberation Serif,Times New Roman,Droid Sans Japanese,FreeSerif,Ubuntu",
+     0, 1252},
+    {0x1e34ee60, L"BellMT",
+     L"KacstQurn,Droid Sans Japanese,Ubuntu,Liberation Serif", 2, 1252},
+    {0x1eb36945, L"CooperBlack",
+     L"KacstQurn,Droid Sans Japanese,FreeMono,Liberation Mono, WenQuanYi Micro "
+     L"Hei Mono",
+     2, 1252},
+    {0x1ef7787d, L"BatangChe",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing "
+     L"TW,WenQuanYi Zen Hei,WenQuanYi Micro Hei",
+     1, 1252},
+    {0x20b3bd3a, L"BrushScriptMT",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,Droid Sans "
+     L"Japanese,URW Chancery L,Liberation Sans",
+     8, 1252},
+    {0x220877aa, L"Candara", L"Droid Sans Japanese,DejaVu Sans", 0, 1252},
+    {0x22135007, L"FreestyleScript-Regular",
+     L"KacstQurn,Droid Sans Japanese,Liberation Sans", 8, 1252},
+    {0x251059c3, L"Chiller",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,Droid Sans "
+     L"Japanese,Liberation Sans",
+     0, 1252},
+    {0x25bed6dd, L"MSReferenceSansSerif",
+     L"DejaVu Sans Condensed,Ubuntu Condensed,Droid Sans Japanese,AR PL UKai "
+     L"HK",
+     0, 1252},
+    {0x28154c81, L"Parchment-Regular", L"Droid Sans Japanese,Liberation Sans",
+     8, 1252},
+    {0x29711eb9, L"STLiti", L"AR PL UKai HK", 0, 936},
+    {0x2b1993b4, L"Basemic",
+     L"Liberation Serif,Droid Sans Japanese,Liberation Sans", 0, 1252},
+    {0x2b316339, L"NiagaraSolid-Reg", L"Droid Sans Japanese,Liberation Sans", 0,
+     1252},
+    {0x2c147529, L"FootlightMTLight",
+     L"KacstQurn,Droid Sans Japanese,Liberation Sans", 0, 1252},
+    {0x2c198928, L"HarlowSolid",
+     L"KacstQurn,Droid Sans Japanese,Liberation Sans", 0, 1252},
+    {0x2c6ac6b2, L"LucidaBright",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid "
+     L"Sans Japanese,Liberation Sans",
+     2, 1252},
+    {0x2c9f38e2, L"KozukaMinchoPro-VIR", L"DejaVu Sans", 0, 1252},
+    {0x2d5a47b0, L"STCaiyun", L"AR PL UKai HK", 0, 936},
+    {0x2def26bf, L"BernardMT-Condensed",
+     L"KacstQurn,Droid Sans Japanese,DejaVu Serif", 0, 1252},
+    {0x2fd8930b, L"KozukaMinchoPr6NR", L"DejaVu Serif", 0, 1252},
+    {0x3115525a, L"FangSong_GB2312",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 1252},
+    {0x31327817, L"MyriadPro",
+     L"Ubuntu Condensed,Droid Sans Japanese, FreeSerif", 0, 1252},
+    {0x32244975, L"Helvetica",
+     L"Ubuntu,DejaVu Sans Condensed,Liberation Sans,Liberation Sans "
+     L"Narrow,Nimbus Sans L",
+     0, 1252},
+    {0x32ac995c, L"Terminal", L"DejaVu Serif", 0, 1252},
+    {0x338d648a, L"NiagaraEngraved-Reg", L"Droid Sans Japanese,DejaVu Serif", 0,
+     1252},
+    {0x33bb65f2, L"Sylfaen", L"Droid Sans Japanese,DejaVu Sans", 2, 1252},
+    {0x3402c30e, L"MSPMincho",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 2,
+     1252},
+    {0x3412bf31, L"SimSun-PUA",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing CN,AR PL UMing HK", 0,
+     936},
+    {0x36eb39b9, L"BerlinSansFB",
+     L"Droid Sans Japanese,Liberation Serif,Ubuntu,FreeSerif", 0, 1252},
+    {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252},
+    {0x3864c4f6, L"HighTowerText", L"Droid Sans Japanese,DejaVu Serif", 2,
+     1252},
+    {0x3a257d03, L"FangSong_GB2312",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei", 0, 1252},
+    {0x3c7d1d07, L"Garamond3LTStd",
+     L"Droid Sans Japanese,Ubuntu Condensed,DejaVu Sans Condensed,Liberation "
+     L"Serif,Ubuntu,FreeSerif",
+     2, 1252},
+    {0x3cdae668, L"FreestyleScript",
+     L"KacstQurn,Droid Sans Japanese,DejaVu Sans", 8, 1252},
+    {0x3d55aed7, L"Jokerman", L"Droid Sans Japanese,DejaVu Sans", 0, 1252},
+    {0x3d5b4385, L"PMingLiU",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     2, 1252},
+    {0x3d9b7669, L"EstrangeloEdessa", L"Droid Sans Japanese,DejaVu Sans", 0,
+     1252},
+    {0x3e532d74, L"FranklinGothicMedium", L"Droid Sans Japanese,Ubuntu", 0,
+     1252},
+    {0x3e6aa32d, L"NSimSun",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     1, 936},
+    {0x3f6c36a8, L"Gautami",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic, mry_KacstQurn,Droid Sans "
+     L"Japanese,FreeSans",
+     0, 1252},
+    {0x3ff32662, L"Chiller-Regular",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,FreeSans", 0, 1252},
+    {0x409de312, L"ModernNo.20",
+     L"KacstQurn,Droid Sans Japanese,Nimbus Sans L,Nimbus Sans L,FreeSans", 2,
+     1252},
+    {0x41443c5e, L"Georgia", L"Droid Sans Japanese,FreeSans", 2, 1252},
+    {0x4160ade5, L"BellGothicStdBlack", L"FreeSans", 0, 1252},
+    {0x421976c4, L"Modern-Regular", L"FreeSans", 2, 1252},
+    {0x422a7252, L"Stencil", L"Droid Sans Japanese,FreeSans,Liberation Sans", 0,
+     1252},
+    {0x42c8554f, L"Fixedsys", L"FreeSerif", 0, 1252},
+    {0x435cb41d, L"Roman", L"FreeSerif", 0, 1252},
+    {0x47882383, L"CourierNew",
+     L"FreeMono,WenQuanYi Micro Hei Mono,AR PL UKai CN,AR PL UKai HK,AR PL "
+     L"UKai TW,AR PL UKai TW MBE,DejaVu Sans",
+     1, 1252},
+    {0x480a2338, L"BerlinSansFBDemi", L"Droid Sans Japanese,Liberation Serif",
+     0, 1252},
+    {0x480bf7a4, L"CourierStd", L"DejaVu Sans", 0, 1252},
+    {0x481ad6ed, L"VladimirScript", L"Droid Sans Japanese,DejaVu Serif", 8,
+     1252},
+    {0x4911577a, L"YouYuan",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 1,
+     936},
+    {0x4a788d72, L"STXingkai", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0,
+     936},
+    {0x4bf88566, L"SegoeCondensed", L"FreeSerif", 0, 1252},
+    {0x4ccf51a4, L"BerlinSansFB-Reg", L"Droid Sans Japanese,Liberation Serif",
+     0, 1252},
+    {0x4ea967ce, L"GulimChe",
+     L"WenQuanYi Zen Hei Mono,AR PL UKai CN,AR PL UKai HK,AR PL UKai TW,AR PL "
+     L"UKai TW MBE",
+     1, 1252},
+    {0x4f68bd79, L"LetterGothicStd",
+     L"FreeMono,Liberation Mono,Andale Mono,WenQuanYi Micro Hei Mono", 0, 1252},
+    {0x51a0d0e6, L"KozukaGothicPr6NM", L"FreeSerif", 0, 1252},
+    {0x531b3dea, L"BasemicSymbol", L"FreeSerif", 0, 1252},
+    {0x5333fd39, L"CalifornianFB-Reg",
+     L"Droid Sans Japanese,URW Chancery L,FreeSerif", 2, 1252},
+    {0x53561a54, L"FZYTK--GBK1-0",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0x55e0dde6, L"LucidaSansTypewriter",
+     L"Ubuntu Mono,DejaVu Sans Mono,Nimbus Mono L,Liberation Mono,Courier 10 "
+     L"Pitch,FreeMono",
+     0, 1252},
+    {0x574d4d3d, L"AdobeArabic", L"Droid Sans Japanese,DejaVu Sans", 0, 1252},
+    {0x5792e759, L"STKaiti", L"WenQuanYi Micro Hei Mono", 0, 936},
+    {0x5921978e, L"LucidaSansUnicode", L"Droid Sans Japanese,DejaVu Sans", 0,
+     1252},
+    {0x594e2da4, L"Vrinda",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Arabic "
+     L"Naskh,mry_KacstQurn,Droid Sans Japanese,FreeSans,FreeSerif",
+     0, 1252},
+    {0x59baa9a2, L"KaiTi_GB2312",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 1252},
+    {0x5cfedf4f, L"BaskOldFace",
+     L"KacstQurn,Droid Sans Japanese,Ubuntu,Liberation Serif", 0, 1252},
+    {0x5e16ac91, L"TrajanPro",
+     L"Nimbus Sans L,AR PL UMing HK,AR PL UKai HK,AR PL UMing TW,AR PL UMing "
+     L"TW MBE,DejaVu Sans,DejaVu Serif",
+     0, 1252},
+    {0x5f388196, L"ITCLegacySansStdMedium",
+     L"Liberation Serif,FreeSerif,FreeSans,Ubuntu", 0, 1252},
+    {0x5f97921c, L"AdobeMyungjoStdM",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0x5fefbfad, L"Batang",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     2, 1252},
+    {0x605342b9, L"DotumChe",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 1,
+     1252},
+    {0x608c5f9a, L"KaiTi_GB2312",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0x61efd0d1, L"MaturaMTScriptCapitals",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid "
+     L"Sans Japanese,DejaVu Serif,DejaVu Sans",
+     0, 1252},
+    {0x626608a9, L"MVBoli",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans "
+     L"Ethiopic,Droid Sans Japanese,DejaVu Sans",
+     0, 1252},
+    {0x630501a3, L"SmallFonts", L"DejaVu Serif", 0, 1252},
+    {0x65d0e2a9, L"FZYTK--GBK1-0",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0x669f29e1, L"FZSTK--GBK1-0",
+     L"AR PL UMing CN,AR PL UKai CN, AR PL UMing HK", 0, 936},
+    {0x673a9e5f, L"Tunga",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans "
+     L"Japanese,DejaVu Serif",
+     0, 1252},
+    {0x691aa4ce, L"NiagaraSolid", L"Droid Sans Japanese,DejaVu Serif", 0, 1252},
+    {0x696259b7, L"Corbel", L"Droid Sans Japanese,DejaVu Sans", 0, 1252},
+    {0x696ee9be, L"STXihei", L"WenQuanYi Micro Hei Mono", 0, 936},
+    {0x6c59cf69, L"Dotum", L"WenQuanYi Zen Hei Mono", 0, 1252},
+    {0x707fa561, L"Gungsuh", L"WenQuanYi Zen Hei Mono", 2, 1252},
+    {0x71416bb2, L"ZWAdobeF",
+     L"KacstArt,KacstBookm,KacstDecorative,KacstDigital,KacstFarsi,KacstLetter,"
+     L"KacstOffice,Dingbats,FreeSerif",
+     0, 1252},
+    {0x71b41801, L"Verdana",
+     L"DejaVu Sans Condensed,Ubuntu Condensed,Droid Sans Japanese,DejaVu Sans",
+     0, 1252},
+    {0x73f25e4c, L"PalatinoLinotype", L"Droid Sans Japanese,FreeSerif", 0,
+     1252},
+    {0x73f4d19f, L"NiagaraEngraved", L"Droid Sans Japanese,FreeSerif", 0, 1252},
+    {0x74001694, L"MyriadProBlack", L"Droid Sans Japanese,AR PL UKai HK", 0,
+     1252},
+    {0x74b14d8f, L"Haettenschweiler", L"Droid Sans Japanese,DejaVu Serif", 0,
+     1252},
+    {0x74cb44ee, L"NSimSun", L"WenQuanYi Zen Hei Mono", 1, 936},
+    {0x76b4d7ff, L"Shruti",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans "
+     L"Japanese,FreeSans",
+     0, 1252},
+    {0x788b3533, L"Webdings", L"FreeSans", 6, 42},
+    {0x797dde99, L"MSSerif", L"FreeSans", 0, 1252},
+    {0x7a0f9e9e, L"MSMincho",
+     L"WenQuanYi Micro Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW",
+     1, 1252},
+    {0x7b439caf, L"OldEnglishTextMT",
+     L"Droid Sans Japanese,Liberation Sans,Ubuntu", 0, 1252},
+    {0x8213a433, L"LucidaSans-Typewriter",
+     L"Ubuntu Mono,Liberation Mono,DejaVu Sans Mono", 0, 1252},
+    {0x82fec929, L"AdobeSongStdL",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0x83581825, L"Modern", L"FreeSans", 0, 1252},
+    {0x835a2823, L"Algerian",
+     L"KacstQurn,Droid Sans Japanese,FreeSans,Liberation Sans,Ubuntu", 0, 1252},
+    {0x83dab9f5, L"Script", L"FreeSans", 0, 1252},
+    {0x847b56da, L"Tahoma",
+     L"Droid Sans Japanese,DejaVu Sans Condensed,FreeSerif", 0, 1252},
+    {0x8a783cb2, L"SimSun-PUA",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 1252},
+    {0x8b5cac0e, L"Onyx", L"Droid Sans Japanese,Liberation Sans", 0, 1252},
+    {0x8c6a499e, L"Gulim",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 1252},
+    {0x8e0af790, L"JuiceITC", L"Droid Sans Japanese,Liberation Sans", 0, 1252},
+    {0x8e8d43b2, L"Centaur",
+     L"KacstQurn,Droid Sans Japanese,Khmer OS,Khmer OS System", 2, 1252},
+    {0x8ee4dcca, L"BookshelfSymbol7", L"Liberation Sans", 0, 1252},
+    {0x90794800, L"BellGothicStdLight", L"Liberation Sans", 0, 1252},
+    {0x909b516a, L"Century",
+     L"Droid Sans Japanese,Liberation Sans,Liberation Mono,Liberation Serif", 2,
+     1252},
+    {0x92ae370d, L"MSOutlook", L"Liberation Sans", 4, 42},
+    {0x93c9fbf1, L"LucidaFax",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans "
+     L"Ethiopic,mry_KacstQurn,Liberation Sans",
+     2, 1252},
+    {0x9565085e, L"BookAntiqua",
+     L"Droid Sans Japanese,Liberation Sans,Liberation Serif", 2, 1252},
+    {0x9856d95d, L"AdobeMingStdL", L"AR PL UMing HK", 0, 949},
+    {0x9bbadd6b, L"ColonnaMT",
+     L"KacstQurn,Droid Sans Japanese,Khmer OS,Khmer OS System", 0, 1252},
+    {0x9cbd16a4, L"ShowcardGothic-Reg",
+     L"Droid Sans Japanese,Liberation Sans,Ubuntu", 0, 1252},
+    {0x9d73008e, L"MSSansSerif", L"FreeSerif", 0, 1252},
+    {0xa0607db1, L"GungsuhChe",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     1, 1252},
+    {0xa0bcf6a1, L"LatinWide", L"FreeSerif", 2, 1252},
+    {0xa1429b36, L"Symbol", L"FreeSerif", 6, 42},
+    {0xa1fa5abc, L"Wingdings2", L"FreeSerif", 6, 42},
+    {0xa1fa5abd, L"Wingdings3", L"FreeSerif", 6, 42},
+    {0xa427bad4, L"InformalRoman-Regular",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans "
+     L"Japanese,FreeSerif",
+     8, 1252},
+    {0xa8b92ece, L"FZSTK--GBK1-0", L"AR PL UMing CN", 0, 936},
+    {0xa8d83ece, L"CalifornianFB", L"Droid Sans Japanese,FreeSerif", 2, 1252},
+    {0xaa3e082c, L"Kingsoft-Phonetic",
+     L"Tibetan Machine Uni,LKLUG,Samyak Gujarati,Droid Sans "
+     L"Thai,utkal,Kedage,Mallige,AR PL UKai CN",
+     0, 1252},
+    {0xaa6bcabe, L"HarlowSolidItalic",
+     L"KacstQurn,Droid Sans Japanese,Liberation Serif", 0, 1252},
+    {0xade5337c, L"MSUIGothic",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 1252},
+    {0xb08dd941, L"WideLatin",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid "
+     L"Sans Japanese,Liberation Serif",
+     2, 1252},
+    {0xb12765e0, L"ITCLegacySansStdBook",
+     L"AR PL UMing HK,AR PL UKai HK,FreeSerif,Ubuntu,FreeSans", 0, 1252},
+    {0xb207f05d, L"PoorRichard", L"Droid Sans Japanese,Liberation Serif", 2,
+     1252},
+    {0xb3bc492f, L"JuiceITC-Regular", L"Droid Sans Japanese,Liberation Serif",
+     0, 1252},
+    {0xb5545399, L"Marlett", L"Liberation Serif", 4, 42},
+    {0xb5dd1ebb, L"BritannicBold",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans "
+     L"Ethiopic,mry_KacstQurn,Liberation Serif",
+     0, 1252},
+    {0xb699c1c5, L"LucidaCalligraphy-Italic",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid "
+     L"Sans Japanese,DejaVu Serif",
+     0, 1252},
+    {0xb725d629, L"TimesNewRoman", L"Droid Sans Japanese,Liberation Sans", 2,
+     1252},
+    {0xb7eaebeb, L"AdobeHeitiStdR",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0xbd29c486, L"BerlinSansFBDemi-Bold", L"Droid Sans Japanese,DejaVu Serif",
+     0, 1252},
+    {0xbe8a8db4, L"BookshelfSymbolSeven", L"DejaVu Sans", 0, 1252},
+    {0xc16c0118, L"AdobeHebrew", L"Droid Sans Japanese,Ubuntu,Liberation Serif",
+     0, 1252},
+    {0xc318b0af, L"MyriadProLight",
+     L"Droid Sans Japanese,AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0,
+     1252},
+    {0xc65e5659, L"CambriaMath", L"Droid Sans Japanese,FreeSerif,FreeMono", 2,
+     1252},
+    {0xc75c8f05, L"LucidaConsole",
+     L"Liberation Mono,DejaVu Sans Mono,FreeMono,WenQuanYi Micro Hei Mono", 1,
+     1252},
+    {0xca7c35d6, L"Calibri", L"Droid Sans Japanese,DejaVu Sans", 0, 1252},
+    {0xcb053f53, L"MicrosoftYaHei",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0xcb7190f9, L"Magneto-Bold",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans "
+     L"Japanese,DejaVu Serif",
+     0, 1252},
+    {0xcca00cc5, L"System", L"DejaVu Sans", 0, 1252},
+    {0xccad6f76, L"Jokerman-Regular", L"Droid Sans Japanese,DejaVu Sans", 0,
+     1252},
+    {0xccc5818c, L"EuroSign", L"DejaVu Serif", 0, 1252},
+    {0xcf3d7234, L"LucidaHandwriting-Italic",
+     L"Liberation Sans Narrow,Ubuntu Condensed,Nimbus Sans L,DejaVu Serif", 0,
+     1252},
+    {0xcf7b8fdb, L"MinionPro", L"DejaVu Sans", 0, 1252},
+    {0xcfe5755f, L"Simhei",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     1, 936},
+    {0xd011f4ee, L"MSPGothic",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW", 0,
+     1252},
+    {0xd060e7ef, L"Vivaldi",
+     L"KacstQurn,Droid Sans Japanese,Liberation Sans,Ubuntu", 8, 1252},
+    {0xd07edec1, L"FranklinGothic-Medium", L"Droid Sans Japanese,Ubuntu", 0,
+     1252},
+    {0xd107243f, L"SimSun", L"WenQuanYi Zen Hei Mono", 0, 936},
+    {0xd1881562, L"ArialNarrow",
+     L"Liberation Sans Narrow,Droid Sans Japanese,FreeSerif", 0, 1252},
+    {0xd22b7dce, L"BodoniMTPosterCompressed",
+     L"Droid Sans Japanese,DejaVu Serif", 0, 1252},
+    {0xd22bfa60, L"ComicSansMS",
+     L"Droid Sans Japanese,FreeMono,Liberation Mono", 8, 1252},
+    {0xd3bd0e35, L"Bauhaus93",
+     L"KacstQurn,Droid Sans Japanese,Liberation Sans,Ubuntu", 0, 1252},
+    {0xd429ee7a, L"STFangsong", L"WenQuanYi Micro Hei Mono", 0, 936},
+    {0xd6679c12, L"BernardMTCondensed",
+     L"KacstQurn,Droid Sans Japanese,Nimbus Sans L,URW Chancery "
+     L"L,KacstOne,Liberation Sans",
+     0, 1252},
+    {0xd8e8a027, L"LucidaSans",
+     L"Liberation Sans Narrow,Nimbus Sans L,KacstQurn,Droid Arabic Naskh,Droid "
+     L"Sans Ethiopic,DejaVu Serif Condensed,Liberation Mono,Ubuntu",
+     0, 1252},
+    {0xd9fe7761, L"HighTowerText-Reg",
+     L"Droid Sans Japanese,Ubuntu,Liberation Serif", 2, 1252},
+    {0xda7e551e, L"STSong", L"WenQuanYi Micro Hei Mono", 0, 936},
+    {0xdaa6842d, L"STZhongsong",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0xdaaab93f, L"STFangsong",
+     L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen "
+     L"Hei,WenQuanYi Zen Hei Sharp",
+     0, 936},
+    {0xdaeb0713, L"STSong",
+     L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen "
+     L"Hei,WenQuanYi Zen Hei Sharp",
+     0, 936},
+    {0xdafedbef, L"STCaiyun", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0,
+     936},
+    {0xdb00a3d9, L"Broadway",
+     L"KacstQurn,Droid Sans Japanese,DejaVu Sans,FreeMono,Liberation Mono", 0,
+     1252},
+    {0xdb1f5ad4, L"STXinwei", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0,
+     936},
+    {0xdb326e7f, L"STKaiti",
+     L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen "
+     L"Hei,WenQuanYi Zen Hei Sharp",
+     0, 936},
+    {0xdb69595a, L"STHupo",
+     L"WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen "
+     L"Hei,WenQuanYi Zen Hei Sharp",
+     0, 936},
+    {0xdba0082c, L"STXihei",
+     L" WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei Mono,WenQuanYi Zen "
+     L"Hei,WenQuanYi Zen Hei Sharp",
+     0, 936},
+    {0xdbd0ab18, L"STXingkai", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0,
+     936},
+    {0xdc1a7db1, L"STLiti", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0,
+     936},
+    {0xdc33075f, L"KristenITC-Regular",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu Sans "
+     L"Condensed,Ubuntu,Liberation Sans",
+     8, 1252},
+    {0xdcc7009c, L"Harrington",
+     L"KacstQurn,Droid Sans Japanese,Liberation Serif,FreeSerif,Ubuntu", 0,
+     1252},
+    {0xdd712466, L"ArialBlack",
+     L"Droid Sans Japanese,DejaVu Sans,DejaVu Serif,FreeMono", 0, 1252},
+    {0xdde87b3e, L"Impact", L"Droid Sans Japanese,DejaVu Serif", 0, 1252},
+    {0xdf69fb32, L"SnapITC",
+     L"Liberation Sans Narrow,Ubuntu Condensed,DejaVu Sans,DejaVu "
+     L"Serif,FreeMono",
+     0, 1252},
+    {0xdf8b25e8, L"CenturyGothic",
+     L"Droid Sans Japanese,Liberation Mono,Liberation Sans,Liberation Serif", 0,
+     1252},
+    {0xe0f705c0, L"KristenITC",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu Sans "
+     L"Condensed,Ubuntu,Liberation Sans",
+     8, 1252},
+    {0xe1427573, L"Raavi",
+     L"Droid Arabic Naskh,Droid Sans "
+     L"Ethiopic,mry_KacstQurn,FreeSerif,Liberation Serif,Khmer OS",
+     0, 1252},
+    {0xe2cea0cb, L"Magneto",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu "
+     L"Serif,DejaVu Serif Condensed,DejaVu Sans",
+     0, 1252},
+    {0xe36a9e17, L"Ravie",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,DejaVu "
+     L"Serif,DejaVu Sans,FreeMono",
+     0, 1252},
+    {0xe433f8e2, L"Parchment", L"Droid Sans Japanese,DejaVu Serif", 8, 1252},
+    {0xe43dff4a, L"Wingdings", L"DejaVu Serif", 4, 42},
+    {0xe4e2c405, L"MTExtra", L"DejaVu Serif", 6, 42},
+    {0xe618cc35, L"InformalRoman",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid Sans "
+     L"Japanese,Nimbus Sans L,DejaVu Sans Condensed,Ubuntu,Liberation Sans",
+     8, 1252},
+    {0xe6c27ffc, L"Mistral", L"Droid Sans Japanese,DejaVu Serif", 8, 1252},
+    {0xe7ebf4b9, L"Courier", L"DejaVu Sans,DejaVu Sans Condensed,FreeSerif", 0,
+     1252},
+    {0xe8bc4a9d, L"MSReferenceSpecialty", L"DejaVu Serif", 0, 1252},
+    {0xe90fb013, L"TempusSansITC",
+     L"Droid Sans Japanese,Ubuntu,Liberation Serif,FreeSerif", 0, 1252},
+    {0xec637b42, L"Consolas",
+     L"DejaVu Sans Condensed,AR PL UKai CN,AR PL UKai HK,AR PL UKai "
+     L"TW,FreeSerif,FreeSans",
+     1, 1252},
+    {0xed3a683b, L"STXinwei", L"AR PL UKai HK,AR PL UMing HK,AR PL UKai CN", 0,
+     936},
+    {0xef264cd1, L"LucidaHandwriting",
+     L"Liberation Sans Narrow,Ubuntu Condensed,Nimbus Sans "
+     L"L,KacstQurn,Liberation Mono",
+     0, 1252},
+    {0xf086bca2, L"BaskervilleOldFace",
+     L"KacstQurn,Droid Sans Japanese,Liberation Serif,Ubuntu,FreeSerif", 0,
+     1252},
+    {0xf1028030, L"Mangal",
+     L"FreeSans,TSCu_Paranar,Garuda,Liberation Sans,Liberation Sans "
+     L"Narrow,Nimbus Sans L",
+     2, 1252},
+    {0xf1da7eb9, L"ShowcardGothic",
+     L"Droid Sans Japanese,DejaVu Serif Condensed,DejaVu Sans "
+     L"Condensed,Liberation Sans,Ubuntu",
+     0, 1252},
+    {0xf210f06a, L"ArialMT",
+     L"Liberation Sans,Liberation Sans Narrow,FreeSans,Nimbus Sans L,Khmer OS "
+     L"System,Khmer OS",
+     0, 1252},
+    {0xf477f16a, L"Latha",
+     L"Liberation Sans Narrow,Nimbus Sans L,Droid Arabic "
+     L"Naskh,mry_KacstQurn,FreeSerif,Nimbus Sans L",
+     0, 1252},
+    {0xf616f3dd, L"LiSu",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR "
+     L"PL UMing TW MBE",
+     1, 936},
+    {0xfa479aa6, L"MicrosoftYaHei",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+    {0xfcd19697, L"BookmanOldStyle",
+     L"Droid Sans Japanese,Liberation Mono,Liberation Sans,Liberation Serif", 0,
+     1252},
+    {0xfe209a82, L"LucidaCalligraphy",
+     L"KacstQurn,Droid Arabic Naskh,Droid Sans Ethiopic,mry_KacstQurn,Droid "
+     L"Sans Japanese,DejaVu Serif,DejaVu Sans,FreeMono",
+     0, 1252},
+    {0xfef135f8, L"AdobeHeitiStd-Regular",
+     L"WenQuanYi Zen Hei Mono,WenQuanYi Zen Hei,WenQuanYi Zen Hei "
+     L"Sharp,WenQuanYi Micro Hei",
+     0, 936},
+};
+#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+static const XFA_FONTINFO g_XFAFontsMap[] = {
+    {0x01d5d33e, L"SimSun", L"STHeiti,Heiti TC,STFangsong", 0, 936},
+    {0x01e4f102, L"YouYuan", L"STHeiti,Heiti TC,STFangsong", 1, 936},
+    {0x030549dc, L"LiSu", L"STHeiti,Heiti TC,STFangsong", 1, 936},
+    {0x032edd44, L"Simhei", L"STHeiti,Heiti TC,STFangsong", 1, 936},
+    {0x03eac6fc, L"PoorRichard-Regular",
+     L"Noteworthy,Avenir Next Condensed,Impact", 2, 1252},
+    {0x03ed90e6, L"Nina", L"Microsoft Sans Serif", 0, 1252},
+    {0x077b56b3, L"KingsoftPhoneticPlain",
+     L"LastResort,Apple "
+     L"Chancery,STIXVariants,STIXSizeOneSym,STIXSizeOneSym,Apple Braille",
+     0, 1252},
+    {0x078ed524, L"MicrosoftSansSerif", L"Songti SC,Apple Symbols", 0, 1252},
+    {0x089b18a9, L"Arial",
+     L"Arial Unicode MS,Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0x0b2cad72, L"MonotypeCorsiva", L"Arial Narrow,Impact", 8, 1252},
+    {0x0bb003e7, L"Kartika",
+     L"Arial Unicode MS,Microsoft Sans Serif,Arial Narrow,Damascus", 2, 1252},
+    {0x0bb469df, L"VinerHandITC", L"Comic Sans MS,Songti SC,STSong", 8, 1252},
+    {0x0bc1a851, L"SegoeUI", L"Apple Symbols", 0, 1252},
+    {0x0c112ebd, L"KozukaGothicPro-VIM", L"Microsoft Sans Serif,Apple Symbols",
+     0, 1252},
+    {0x0cfcb9c1, L"AdobeThai", L"Avenir Next Condensed Ultra Light", 0, 847},
+    {0x0e7de0f9, L"Playbill", L"STIXNonUnicode", 0, 1252},
+    {0x0eff47c3, L"STHupo", L"Kaiti SC,Songti SC,STHeiti", 0, 936},
+    {0x107ad374, L"Constantia", L"Arial Unicode MS,Palatino,Baskerville", 2,
+     1252},
+    {0x12194c2d, L"KunstlerScript",
+     L"Avenir Next Condensed Demi Bold,Arial Narrow", 8, 1252},
+    {0x135ef6a1, L"MinionProSmBd", L"Microsoft Sans Serif,Apple Symbols", 0,
+     1252},
+    {0x158c4049, L"Garamond", L"Impact,Arial Narrow", 2, 1252},
+    {0x160ecb24, L"STZhongsong", L"STFangsong,Songti SC", 0, 936},
+    {0x161ed07e, L"MSGothic",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing "
+     L"TW,Microsoft Sans Serif,Apple Symbols",
+     1, 1252},
+    {0x171d1ed1, L"SnapITC-Regular", L"STHeiti,Arial Black", 0, 1252},
+    {0x18d1188f, L"Cambria", L"Arial Unicode MS", 2, 1252},
+    {0x18eaf350, L"ArialUnicodeMS", L"Microsoft Sans Serif,Apple Symbols", 0,
+     936},
+    {0x1a92d115, L"MingLiU", L"Heiti SC,STHeiti", 1, 1252},
+    {0x1cc217c6, L"TrebuchetMS", L"Damascus,Impact,Arial Narrow", 0, 1252},
+    {0x1d649596, L"BasemicTimes", L"Liberation Serif,Impact,Arial Narrow", 0,
+     1252},
+    {0x1e34ee60, L"BellMT",
+     L"Papyrus,STIXNonUnicode,Microsoft Sans Serif,Avenir Light", 2, 1252},
+    {0x1eb36945, L"CooperBlack",
+     L"Marion,STIXNonUnicode,Arial Rounded MT Bold,Lucida Grande", 2, 1252},
+    {0x1ef7787d, L"BatangChe",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,,AR PL UMing HK,AR PL UMing TW,AR "
+     L"PL UMing TW MBE,Arial Unicode MS,Heiti TC",
+     1, 1252},
+    {0x20b3bd3a, L"BrushScriptMT",
+     L"STIXNonUnicode,Damascus,Arial Narrow,Avenir Next Condensed,Cochin", 8,
+     1252},
+    {0x220877aa, L"Candara", L"Cochin,Baskerville,Marion", 0, 1252},
+    {0x22135007, L"FreestyleScript-Regular",
+     L"STIXNonUnicode,Nadeem,Zapf Dingbats", 8, 1252},
+    {0x251059c3, L"Chiller",
+     L"Zapf Dingbats,Damascus,STIXNonUnicode,Papyrus,KufiStandardGK,Baghdad", 0,
+     1252},
+    {0x25bed6dd, L"MSReferenceSansSerif",
+     L"Tahoma,Apple Symbols,Apple LiGothic,Arial Unicode MS,Lucida "
+     L"Grande,Microsoft Sans Serif",
+     0, 1252},
+    {0x28154c81, L"Parchment-Regular", L"Microsoft Sans Serif,Apple Symbols", 8,
+     1252},
+    {0x29711eb9, L"STLiti", L"Kaiti SC,Songti SC", 0, 936},
+    {0x2b1993b4, L"Basemic", L"Impact,Arial Narrow", 0, 1252},
+    {0x2b316339, L"NiagaraSolid-Reg", L"Microsoft Sans Serif,Apple Symbols", 0,
+     1252},
+    {0x2c147529, L"FootlightMTLight",
+     L"STIXNonUnicode,Avenir Next Condensed Heavy,PT Sans,Noteworthy", 0, 1252},
+    {0x2c198928, L"HarlowSolid",
+     L"Avenir Medium,Avenir Next Medium,Arial Unicode MS", 0, 1252},
+    {0x2c6ac6b2, L"LucidaBright",
+     L"PT Sans Narrow,Papyrus,Damascus,STIXNonUnicode,Arial Rounded MT "
+     L"Bold,Comic Sans MS,Avenir Next",
+     2, 1252},
+    {0x2c9f38e2, L"KozukaMinchoPro-VIR", L"Microsoft Sans Serif,Apple Symbols",
+     0, 1252},
+    {0x2d5a47b0, L"STCaiyun", L"Kaiti SC,Songti SC", 0, 936},
+    {0x2def26bf, L"BernardMT-Condensed",
+     L"Impact,Avenir Next Condensed Demi Bold,American Typewriter", 0, 1252},
+    {0x2fd8930b, L"KozukaMinchoPr6NR", L"Microsoft Sans Serif,Apple Symbols", 0,
+     1252},
+    {0x3115525a, L"FangSong_GB2312", L"Hiragino Sans GB,STHeiti", 0, 1252},
+    {0x31327817, L"MyriadPro", L"Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0x32244975, L"Helvetica",
+     L"Arial Narrow,Arial Unicode MS,Damascus,STIXNonUnicode", 0, 1252},
+    {0x32ac995c, L"Terminal", L"Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0x338d648a, L"NiagaraEngraved-Reg", L"Microsoft Sans Serif,Apple Symbols",
+     0, 1252},
+    {0x33bb65f2, L"Sylfaen", L"Arial Unicode MS,Marion", 2, 1252},
+    {0x3402c30e, L"MSPMincho", L"Arial Unicode MS,Apple SD Gothic Neo", 2,
+     1252},
+    {0x3412bf31, L"SimSun-PUA", L"STHeiti,Heiti TC,STFangsong", 0, 936},
+    {0x36eb39b9, L"BerlinSansFB", L"American Typewriter,Impact", 0, 1252},
+    {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252},
+    {0x3864c4f6, L"HighTowerText", L"STIXGeneral,.Helvetica Neue Desk UI", 2,
+     1252},
+    {0x3a257d03, L"FangSong_GB2312", L"Hiragino Sans GB,STHeiti", 0, 1252},
+    {0x3cdae668, L"FreestyleScript", L"Nadeem,Zapf Dingbats,STIXNonUnicode", 8,
+     1252},
+    {0x3d55aed7, L"Jokerman",
+     L"Papyrus,Lucida Grande,Heiti TC,American Typewriter", 0, 1252},
+    {0x3d5b4385, L"PMingLiU", L"Heiti SC,STHeiti", 2, 1252},
+    {0x3d9b7669, L"EstrangeloEdessa", L"American Typewriter,Marion", 0, 1252},
+    {0x3e532d74, L"FranklinGothicMedium", L"Impact,Arial Narrow", 0, 1252},
+    {0x3e6aa32d, L"NSimSun", L"STHeiti,STFangsong", 1, 936},
+    {0x3f6c36a8, L"Gautami",
+     L"Damascus,STIXNonUnicode,STIXGeneral,American Typewriter", 0, 1252},
+    {0x3ff32662, L"Chiller-Regular", L"Papyrus,KufiStandardGK,Baghdad", 0,
+     1252},
+    {0x409de312, L"ModernNo.20", L"Avenir Next Condensed,Impact", 2, 1252},
+    {0x41443c5e, L"Georgia", L".Helvetica Neue Desk UI,Arial Unicode MS", 2,
+     1252},
+    {0x4160ade5, L"BellGothicStdBlack", L"Microsoft Sans Serif,Apple Symbols",
+     0, 1252},
+    {0x421976c4, L"Modern-Regular", L"Impact", 2, 1252},
+    {0x422a7252, L"Stencil", L"STIXNonUnicode,Songti SC,Georgia,Baskerville", 0,
+     1252},
+    {0x42c8554f, L"Fixedsys", L"Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0x435cb41d, L"Roman", L"Arial Narrow", 0, 1252},
+    {0x47882383, L"CourierNew", L"PCMyungjo,Osaka,Arial Unicode MS,Songti SC",
+     1, 1252},
+    {0x480a2338, L"BerlinSansFBDemi",
+     L"STIXNonUnicode,American Typewriter,Avenir Next Condensed Heavy", 0,
+     1252},
+    {0x480bf7a4, L"CourierStd", L"Courier New", 0, 1252},
+    {0x481ad6ed, L"VladimirScript",
+     L"STIXNonUnicode,Avenir Next Condensed,Impact", 8, 1252},
+    {0x4911577a, L"YouYuan", L"STHeiti,Heiti TC", 1, 936},
+    {0x4a788d72, L"STXingkai", L"Kaiti SC,Songti SC", 0, 936},
+    {0x4bf88566, L"SegoeCondensed", L"Microsoft Sans Serif,Apple Symbols", 0,
+     1252},
+    {0x4ccf51a4, L"BerlinSansFB-Reg",
+     L"STIXNonUnicode,American Typewriter,Impact", 0, 1252},
+    {0x4ea967ce, L"GulimChe", L"Arial Unicode MS,Heiti TC,STFangsong", 1, 1252},
+    {0x4f68bd79, L"LetterGothicStd",
+     L"Courier New,Andale Mono,Ayuthaya,PCMyungjo,Osaka", 0, 1252},
+    {0x51a0d0e6, L"KozukaGothicPr6NM", L"Microsoft Sans Serif,Apple Symbols", 0,
+     1252},
+    {0x531b3dea, L"BasemicSymbol", L"Microsoft Sans Serif,Apple Symbols", 0,
+     1252},
+    {0x5333fd39, L"CalifornianFB-Reg",
+     L"American Typewriter,Avenir Next Condensed,Impact", 2, 1252},
+    {0x53561a54, L"FZYTK--GBK1-0", L"STFangsong,Songti SC,STSong", 0, 936},
+    {0x55e0dde6, L"LucidaSansTypewriter", L"Menlo,Courier New,Andale Mono", 0,
+     1252},
+    {0x574d4d3d, L"AdobeArabic", L"Arial Narrow", 0, 1252},
+    {0x5792e759, L"STKaiti", L"Songti SC,Arial Unicode MS", 0, 936},
+    {0x5921978e, L"LucidaSansUnicode", L"Lucida Grande,Arial Unicode MS,Menlo",
+     0, 1252},
+    {0x594e2da4, L"Vrinda", L"Geeza Pro,Damascus,STIXGeneral,Gill Sans", 0,
+     1252},
+    {0x59baa9a2, L"KaiTi_GB2312", L"Hiragino Sans GB,STHeiti", 0, 1252},
+    {0x5cfedf4f, L"BaskOldFace",
+     L"Avenir Next Condensed Heavy,PT Sans,Avenir Next Condensed", 0, 1252},
+    {0x5e16ac91, L"TrajanPro", L"Arial Narrow,PT Sans Narrow,Damascus", 0,
+     1252},
+    {0x5f97921c, L"AdobeMyungjoStdM",
+     L"AppleMyungjo,AppleGothic,Arial Unicode MS", 0, 936},
+    {0x5fefbfad, L"Batang", L"Arial Unicode MS,Songti SC", 2, 1252},
+    {0x605342b9, L"DotumChe", L"Arial Unicode MS,Heiti TC", 1, 1252},
+    {0x608c5f9a, L"KaiTi_GB2312", L"Hiragino Sans GB,STHeiti,Heiti TC", 0, 936},
+    {0x61efd0d1, L"MaturaMTScriptCapitals",
+     L"Kokonor,Damascus,STIXNonUnicode,STHeiti,Arial Black,Avenir Next Heavy",
+     0, 1252},
+    {0x626608a9, L"MVBoli",
+     L"Apple Braille,Geeza Pro,Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0x630501a3, L"SmallFonts", L"Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0x65d0e2a9, L"FZYTK--GBK1-0", L"STFangsong,Songti SC,STSong", 0, 936},
+    {0x669f29e1, L"FZSTK--GBK1-0", L"STHeiti,Heiti TC", 0, 936},
+    {0x673a9e5f, L"Tunga",
+     L"Damascus,STIXNonUnicode,Avenir Next Condensed,Avenir Next Condensed "
+     L"Ultra Light,Futura",
+     0, 1252},
+    {0x691aa4ce, L"NiagaraSolid", L"Microsoft Sans Serif,Apple Symbols", 0,
+     1252},
+    {0x696259b7, L"Corbel", L"Cochin,Baskerville,Marion", 0, 1252},
+    {0x696ee9be, L"STXihei", L"STHeiti,Heiti TC,Songti SC,Arial Unicode MS", 0,
+     936},
+    {0x6c59cf69, L"Dotum", L"Arial Unicode MS,Songti SC", 0, 1252},
+    {0x707fa561, L"Gungsuh", L"Arial Unicode MS,Heiti TC", 2, 1252},
+    {0x71416bb2, L"ZWAdobeF",
+     L"STIXSizeFourSym,STIXSizeThreeSym,STIXSizeTwoSym,STIXSizeOneSym", 0,
+     1252},
+    {0x71b41801, L"Verdana",
+     L"Tahoma,Marion,Apple Symbols,.Helvetica Neue Desk UI,Lucida "
+     L"Grande,Courier New",
+     0, 1252},
+    {0x73f25e4c, L"PalatinoLinotype", L"Palatino,Arial Unicode MS", 0, 1252},
+    {0x73f4d19f, L"NiagaraEngraved", L"Microsoft Sans Serif,Apple Symbols", 0,
+     1252},
+    {0x74001694, L"MyriadProBlack", L"Palatino,Baskerville,Marion,Cochin", 0,
+     1252},
+    {0x74b14d8f, L"Haettenschweiler", L"Microsoft Sans Serif,Apple Symbols", 0,
+     1252},
+    {0x74cb44ee, L"NSimSun", L"STHeiti,Heiti TC,STFangsong", 1, 936},
+    {0x76b4d7ff, L"Shruti",
+     L"Damascus,STIXNonUnicode,Arial Unicode MS,American Typewriter", 0, 1252},
+    {0x788b3533, L"Webdings", L"Microsoft Sans Serif,Apple Symbols", 6, 42},
+    {0x797dde99, L"MSSerif", L"Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0x7a0f9e9e, L"MSMincho",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR "
+     L"PL UMing TW MBE,Arial Unicode MS,Apple SD Gothic Neo",
+     1, 1252},
+    {0x7b439caf, L"OldEnglishTextMT",
+     L"STIXNonUnicode,Arial Unicode MS,Baskerville,Avenir Next Medium", 0,
+     1252},
+    {0x8213a433, L"LucidaSans-Typewriter",
+     L"Comic Sans MS,Avenir Next,Arial Rounded MT Bold", 0, 1252},
+    {0x82fec929, L"AdobeSongStdL", L"Heiti TC,STHeiti", 0, 936},
+    {0x83581825, L"Modern", L"Avenir Next Condensed,Impact", 0, 1252},
+    {0x835a2823, L"Algerian",
+     L"STIXNonUnicode,Baskerville,Avenir Next Medium,American Typewriter", 0,
+     1252},
+    {0x83dab9f5, L"Script", L"Arial Narrow", 0, 1252},
+    {0x847b56da, L"Tahoma", L"Songti SC,Apple Symbols", 0, 1252},
+    {0x8a783cb2, L"SimSun-PUA", L"STHeiti,Heiti TC,STFangsong", 0, 1252},
+    {0x8b5cac0e, L"Onyx", L"Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0x8c6a499e, L"Gulim", L"Arial Unicode MS,Songti SC", 0, 1252},
+    {0x8e0af790, L"JuiceITC", L"Nadeem,Al Bayan", 0, 1252},
+    {0x8e8d43b2, L"Centaur", L"Avenir Next Condensed,Noteworthy,Impact", 2,
+     1252},
+    {0x8ee4dcca, L"BookshelfSymbol7", L"Microsoft Sans Serif,Apple Symbols", 0,
+     1252},
+    {0x90794800, L"BellGothicStdLight", L"Microsoft Sans Serif,Apple Symbols",
+     0, 1252},
+    {0x909b516a, L"Century", L"Damascus,Andale Mono,Songti SC,Arial Unicode MS",
+     2, 1252},
+    {0x92ae370d, L"MSOutlook", L"Microsoft Sans Serif,Apple Symbols", 4, 42},
+    {0x93c9fbf1, L"LucidaFax",
+     L"PT Sans Narrow,Papyrus,Kokonor,Geeza Pro,Arial Rounded MT Bold,Lucida "
+     L"Grande,Futura",
+     2, 1252},
+    {0x9565085e, L"BookAntiqua", L"Palatino,Microsoft Sans Serif,Apple Symbols",
+     2, 1252},
+    {0x9856d95d, L"AdobeMingStdL", L"AHiragino Sans GB,Heiti TC,STHeiti", 0,
+     949},
+    {0x9bbadd6b, L"ColonnaMT", L"Noteworthy,Avenir Next Condensed,Impact", 0,
+     1252},
+    {0x9cbd16a4, L"ShowcardGothic-Reg",
+     L"Arial Unicode MS,Georgia,American Typewriter", 0, 1252},
+    {0x9d73008e, L"MSSansSerif", L"Songti SC,Apple Symbols", 0, 1252},
+    {0xa0607db1, L"GungsuhChe",
+     L"WenQuanYi Zen Hei Mono,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR "
+     L"PL UMing TW MBE,Arial Unicode MS,Heiti TC,STFangsong",
+     1, 1252},
+    {0xa0bcf6a1, L"LatinWide", L"Zapfino,Arial Black,STHeiti", 2, 1252},
+    {0xa1429b36, L"Symbol", L"Microsoft Sans Serif,Apple Symbols", 6, 42},
+    {0xa1fa5abc, L"Wingdings2", L"Microsoft Sans Serif,Apple Symbols", 6, 42},
+    {0xa1fa5abd, L"Wingdings3", L"Microsoft Sans Serif,Apple Symbols", 6, 42},
+    {0xa427bad4, L"InformalRoman-Regular",
+     L"STIXNonUnicode,Arial Narrow,Avenir Next Condensed Demi Bold", 8, 1252},
+    {0xa8b92ece, L"FZSTK--GBK1-0", L"STHeiti,Heiti TC,STFangsong", 0, 936},
+    {0xa8d83ece, L"CalifornianFB",
+     L"American Typewriter,Avenir Next Condensed,Impact", 2, 1252},
+    {0xaa3e082c, L"Kingsoft-Phonetic",
+     L"STIXVariants,STIXSizeOneSym,Apple Braille", 0, 1252},
+    {0xaa6bcabe, L"HarlowSolidItalic",
+     L"STIXNonUnicode,Avenir Medium,Avenir Next Medium,Arial Unicode MS", 0,
+     1252},
+    {0xade5337c, L"MSUIGothic", L"Arial Unicode MS,Apple SD Gothic Neo", 0,
+     1252},
+    {0xb08dd941, L"WideLatin",
+     L"Marion,Papyrus,Nanum Pen Script,Zapf Dingbats,Damascus,Zapfino,Arial "
+     L"Black,STHeiti",
+     2, 1252},
+    {0xb12765e0, L"ITCLegacySansStdBook",
+     L"LastResort,.Helvetica Neue Desk UI,Arial Unicode MS,Palatino", 0, 1252},
+    {0xb207f05d, L"PoorRichard", L"Noteworthy,Avenir Next Condensed,Impact", 2,
+     1252},
+    {0xb3bc492f, L"JuiceITC-Regular", L"Nadeem,Al Bayan,STIXNonUnicode", 0,
+     1252},
+    {0xb5545399, L"Marlett", L"Microsoft Sans Serif,Apple Symbols", 4, 42},
+    {0xb5dd1ebb, L"BritannicBold",
+     L"Damascus,STIXNonUnicode,Avenir Next Condensed Heavy,PT Sans", 0, 1252},
+    {0xb699c1c5, L"LucidaCalligraphy-Italic", L"STHeiti,Arial Black", 0, 1252},
+    {0xb725d629, L"TimesNewRoman", L"Microsoft Sans Serif,Apple Symbols", 2,
+     1252},
+    {0xb7eaebeb, L"AdobeHeitiStdR", L"Heiti TC,STHeiti", 0, 936},
+    {0xbd29c486, L"BerlinSansFBDemi-Bold",
+     L"American Typewriter,Avenir Next Condensed Heavy", 0, 1252},
+    {0xbe8a8db4, L"BookshelfSymbolSeven", L"Microsoft Sans Serif,Apple Symbols",
+     0, 1252},
+    {0xc16c0118, L"AdobeHebrew",
+     L".Helvetica Neue Desk UI,Palatino,American Typewriter", 0, 1252},
+    {0xc318b0af, L"MyriadProLight", L"Palatino,Baskerville,Marion", 0, 1252},
+    {0xc65e5659, L"CambriaMath", L"Arial Unicode MS", 2, 1252},
+    {0xc75c8f05, L"LucidaConsole", L"Courier New,Menlo,Andale Mono", 1, 1252},
+    {0xca7c35d6, L"Calibri", L"Apple Symbols,HeadLineA", 0, 1252},
+    {0xcb053f53, L"MicrosoftYaHei", L"Arial Unicode MS", 0, 936},
+    {0xcb7190f9, L"Magneto-Bold", L"Lucida Grande", 0, 1252},
+    {0xcca00cc5, L"System", L"Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0xccad6f76, L"Jokerman-Regular", L"Lucida Grande", 0, 1252},
+    {0xccc5818c, L"EuroSign", L"Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0xcf3d7234, L"LucidaHandwriting-Italic",
+     L"Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0xcf7b8fdb, L"MinionPro",
+     L"Bell MT,Corbel,Times New Roman,Cambria,Berlin Sans FB", 0, 1252},
+    {0xcfe5755f, L"Simhei", L"STHeiti,Heiti TC,STFangsong", 1, 936},
+    {0xd011f4ee, L"MSPGothic", L"Arial Unicode MS,Apple SD Gothic Neo", 0,
+     1252},
+    {0xd060e7ef, L"Vivaldi",
+     L"STIXNonUnicode,Arial Unicode MS,Avenir Medium,Avenir Next Medium", 8,
+     1252},
+    {0xd07edec1, L"FranklinGothic-Medium", L"Impact,Arial Narrow", 0, 1252},
+    {0xd107243f, L"SimSun", L"STHeiti,Heiti TC,STFangsong", 0, 936},
+    {0xd1881562, L"ArialNarrow", L"PT Sans Narrow,Apple Symbols", 0, 1252},
+    {0xd22b7dce, L"BodoniMTPosterCompressed",
+     L"Microsoft Sans Serif,Apple Symbols", 0, 1252},
+    {0xd22bfa60, L"ComicSansMS",
+     L"Damascus,Georgia,.Helvetica Neue Desk UI,Lucida Grande,Arial Unicode MS",
+     8, 1252},
+    {0xd3bd0e35, L"Bauhaus93",
+     L"STIXNonUnicode,Arial Unicode MS,Avenir Next,Avenir", 0, 1252},
+    {0xd429ee7a, L"STFangsong", L"Songti SC,Arial Unicode MS", 0, 936},
+    {0xd6679c12, L"BernardMTCondensed",
+     L"Impact,Avenir Next Condensed Demi Bold", 0, 1252},
+    {0xd8e8a027, L"LucidaSans",
+     L"Arial Narrow,Khmer MN,Kokonor,Damascus,Microsoft Sans Serif,Apple "
+     L"Symbols",
+     0, 1252},
+    {0xd9fe7761, L"HighTowerText-Reg",
+     L"STIXGeneral,.Helvetica Neue Desk UI,Trebuchet MS", 2, 1252},
+    {0xda7e551e, L"STSong", L"Arial Unicode MS", 0, 936},
+    {0xdaa6842d, L"STZhongsong", L"STFangsong,Songti SC,STSong", 0, 936},
+    {0xdaaab93f, L"STFangsong", L"Songti SC,Arial Unicode MS", 0, 936},
+    {0xdaeb0713, L"STSong", L"Songti SC,Arial Unicode MS", 0, 936},
+    {0xdafedbef, L"STCaiyun", L"Kaiti SC,Songti SC,STHeiti", 0, 936},
+    {0xdb00a3d9, L"Broadway",
+     L"Papyrus,STIXNonUnicode,Arial Black,Avenir Next Heavy,Heiti TC", 0, 1252},
+    {0xdb1f5ad4, L"STXinwei", L"Kaiti SC,Songti SC,STHeiti", 0, 936},
+    {0xdb326e7f, L"STKaiti", L"Songti SC,Arial Unicode MS", 0, 936},
+    {0xdb69595a, L"STHupo", L"Kaiti SC,Songti SC,STHeiti", 0, 936},
+    {0xdba0082c, L"STXihei", L"Songti SC,Arial Unicode MS", 0, 936},
+    {0xdbd0ab18, L"STXingkai", L"Kaiti SC,Songti SC", 0, 936},
+    {0xdc1a7db1, L"STLiti", L"Kaiti SC,Songti SC", 0, 936},
+    {0xdc33075f, L"KristenITC-Regular",
+     L"STIXNonUnicode,Damascus,Songti SC,STSong", 8, 1252},
+    {0xdcc7009c, L"Harrington",
+     L"STIXNonUnicode,Avenir Next Condensed Heavy,Noteworthy", 0, 1252},
+    {0xdd712466, L"ArialBlack", L"Geeza Pro,Damascus,Songti SC,STSong", 0,
+     1252},
+    {0xdde87b3e, L"Impact", L"Arial Narrow,Marion", 0, 1252},
+    {0xdf69fb32, L"SnapITC",
+     L"Arial Narrow,PT Sans Narrow,Marion,STHeiti,Arial Black", 0, 1252},
+    {0xdf8b25e8, L"CenturyGothic",
+     L"Damascus,Andale Mono,Songti SC,Arial Unicode MS", 0, 1252},
+    {0xe0f705c0, L"KristenITC", L"Songti SC,STSong", 8, 1252},
+    {0xe1427573, L"Raavi",
+     L"Damascus,STIXNonUnicode,Marion,Papyrus,Avenir Next Condensed "
+     L"Heavy,American Typewriter",
+     0, 1252},
+    {0xe2cea0cb, L"Magneto",
+     L"STIXNonUnicode,Damascus,Geeza Pro,Lucida Grande,Georgia,Heiti TC", 0,
+     1252},
+    {0xe36a9e17, L"Ravie", L"STHeiti,Arial Black", 0, 1252},
+    {0xe433f8e2, L"Parchment", L"Microsoft Sans Serif,Apple Symbols", 8, 1252},
+    {0xe43dff4a, L"Wingdings", L"Microsoft Sans Serif,Apple Symbols", 4, 42},
+    {0xe4e2c405, L"MTExtra", L"Microsoft Sans Serif,Apple Symbols", 6, 42},
+    {0xe618cc35, L"InformalRoman", L"Arial Narrow", 8, 1252},
+    {0xe6c27ffc, L"Mistral", L"Apple Symbols", 8, 1252},
+    {0xe7ebf4b9, L"Courier", L"Courier New", 0, 1252},
+    {0xe8bc4a9d, L"MSReferenceSpecialty", L"Microsoft Sans Serif,Apple Symbols",
+     0, 1252},
+    {0xe90fb013, L"TempusSansITC",
+     L"STIXNonUnicode,Microsoft Sans Serif,Avenir Light", 0, 1252},
+    {0xec637b42, L"Consolas",
+     L"AR PL UKai CN,AR PL UKai HK,AR PL UKai TW,AR PL UKai TW MBE,AR PL UMing "
+     L"CN,AR PL UMing HK,Microsoft Sans Serif,Tahoma",
+     1, 1252},
+    {0xed3a683b, L"STXinwei", L"Kaiti SC,Songti SC,", 0, 936},
+    {0xef264cd1, L"LucidaHandwriting",
+     L"Arial Narrow,Avenir Next Condensed Demi Bold,Avenir Next "
+     L"Condensed,Avenir Next Condensed Medium,STHeiti,Arial Black",
+     0, 1252},
+    {0xf086bca2, L"BaskervilleOldFace",
+     L"STIXNonUnicode,Avenir Next Condensed Heavy,PT Sans", 0, 1252},
+    {0xf1028030, L"Mangal",
+     L"Arial Unicode MS,Microsoft Sans Serif,Arial Narrow,Tahoma", 2, 1252},
+    {0xf1da7eb9, L"ShowcardGothic",
+     L"Papyrus,Arial Unicode MS,Georgia,American Typewriter", 0, 1252},
+    {0xf210f06a, L"ArialMT",
+     L"Arial Unicode MS,Arial Narrow,STIXNonUnicode,Damascus,Avenir Next "
+     L"Condensed Demi Bold,Avenir Next Condensed Medium,Avenir Next Condensed",
+     0, 1252},
+    {0xf477f16a, L"Latha",
+     L"Arial Narrow,Damascus,STIXNonUnicode,American Typewriter", 0, 1252},
+    {0xf616f3dd, L"LiSu", L"STHeiti,Heiti TC,STFangsong", 1, 936},
+    {0xfa479aa6, L"MicrosoftYaHei", L"Arial Unicode MS", 0, 936},
+    {0xfcd19697, L"BookmanOldStyle",
+     L"Geeza Pro,Damascus,Andale Mono,Songti SC,Arial Unicode MS", 0, 1252},
+    {0xfe209a82, L"LucidaCalligraphy",
+     L"Kokonor,Damascus,STIXNonUnicode,STHeiti,Arial Black", 0, 1252},
+    {0xfef135f8, L"AdobeHeitiStd-Regular", L"Heiti TC,STHeiti", 0, 936},
+};
+#elif _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
+static const XFA_FONTINFO g_XFAFontsMap[] = {
+    {0x01d5d33e, L"SimSun", L"Droid Sans Fallback", 0, 936},
+    {0x01e4f102, L"YouYuan", L"Droid Sans Fallback", 1, 936},
+    {0x030549dc, L"LiSu", L"Droid Sans Fallback", 1, 936},
+    {0x032edd44, L"Simhei", L"Droid Sans Fallback", 1, 936},
+    {0x03eac6fc, L"PoorRichard-Regular",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback,Droid Arabic "
+     L"Naskh,Droid Sans Ethiopic",
+     2, 1252},
+    {0x03ed90e6, L"Nina",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x077b56b3, L"KingsoftPhoneticPlain",
+     L"Droid Sans Thai,Droid Sans Armenian,Droid Arabic Naskh,Droid Sans "
+     L"Ethiopic,Droid Sans Fallback",
+     0, 1252},
+    {0x078ed524, L"MicrosoftSansSerif", L"Droid Sans Fallback", 0, 1252},
+    {0x089b18a9, L"Arial", L"Droid Sans Fallback", 0, 1252},
+    {0x0b2cad72, L"MonotypeCorsiva",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252},
+    {0x0bb003e7, L"Kartika",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans "
+     L"Mono",
+     2, 1252},
+    {0x0bb469df, L"VinerHandITC",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 8, 1252},
+    {0x0bc1a851, L"SegoeUI", L"Droid Sans Fallback", 0, 1252},
+    {0x0c112ebd, L"KozukaGothicPro-VIM",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x0cfcb9c1, L"AdobeThai",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 847},
+    {0x0e7de0f9, L"Playbill",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0x0eff47c3, L"STHupo", L"Droid Sans Fallback", 0, 936},
+    {0x107ad374, L"Constantia",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x12194c2d, L"KunstlerScript",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252},
+    {0x135ef6a1, L"MinionProSmBd",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x158c4049, L"Garamond",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x160ecb24, L"STZhongsong", L"Droid Sans Fallback", 0, 936},
+    {0x161ed07e, L"MSGothic", L"Droid Sans Fallback", 1, 1252},
+    {0x171d1ed1, L"SnapITC-Regular",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x18d1188f, L"Cambria", L"Droid Sans Fallback", 2, 1252},
+    {0x18eaf350, L"ArialUnicodeMS", L"Droid Sans Fallback", 0, 936},
+    {0x1a92d115, L"MingLiU", L"Droid Sans Fallback", 1, 1252},
+    {0x1cc217c6, L"TrebuchetMS",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x1d649596, L"BasemicTimes",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x1e34ee60, L"BellMT",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x1eb36945, L"CooperBlack",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x1ef7787d, L"BatangChe", L"Droid Sans Fallback", 1, 1252},
+    {0x20b3bd3a, L"BrushScriptMT", L"Droid Arabic Naskh,Droid Sans Ethiopic", 8,
+     1252},
+    {0x220877aa, L"Candara",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x22135007, L"FreestyleScript-Regular",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252},
+    {0x251059c3, L"Chiller",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif", 0, 1252},
+    {0x25bed6dd, L"MSReferenceSansSerif", L"Droid Sans Fallback", 0, 1252},
+    {0x28154c81, L"Parchment-Regular",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252},
+    {0x29711eb9, L"STLiti", L"Droid Sans Fallback", 0, 936},
+    {0x2b1993b4, L"Basemic",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x2b316339, L"NiagaraSolid-Reg",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x2c147529, L"FootlightMTLight",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x2c198928, L"HarlowSolid",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x2c6ac6b2, L"LucidaBright",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 2, 1252},
+    {0x2c9f38e2, L"KozukaMinchoPro-VIR",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x2d5a47b0, L"STCaiyun", L"Droid Sans Fallback", 0, 936},
+    {0x2def26bf, L"BernardMT-Condensed",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x2fd8930b, L"KozukaMinchoPr6NR",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x3115525a, L"FangSong_GB2312", L"Droid Sans Fallback", 0, 1252},
+    {0x31327817, L"MyriadPro",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x32244975, L"Helvetica",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 0, 1252},
+    {0x32ac995c, L"Terminal",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x338d648a, L"NiagaraEngraved-Reg",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x33bb65f2, L"Sylfaen",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x3402c30e, L"MSPMincho", L"Droid Sans Fallback", 2, 1252},
+    {0x3412bf31, L"SimSun-PUA", L"Droid Sans Fallback", 0, 936},
+    {0x36eb39b9, L"BerlinSansFB",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x36f42055, L"UniversATT", L"Microsoft Sans Serif", 0, 1252},
+    {0x3864c4f6, L"HighTowerText",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x3a257d03, L"FangSong_GB2312", L"Droid Sans Fallback", 0, 1252},
+    {0x3cdae668, L"FreestyleScript",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252},
+    {0x3d55aed7, L"Jokerman",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x3d5b4385, L"PMingLiU", L"Droid Sans Fallback", 2, 1252},
+    {0x3d9b7669, L"EstrangeloEdessa",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x3e532d74, L"FranklinGothicMedium",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x3e6aa32d, L"NSimSun", L"Droid Sans Fallback", 1, 936},
+    {0x3f6c36a8, L"Gautami",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans "
+     L"Mono,Droid Sans Fallback",
+     0, 1252},
+    {0x3ff32662, L"Chiller-Regular",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x409de312, L"ModernNo.20",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x41443c5e, L"Georgia",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x4160ade5, L"BellGothicStdBlack",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x421976c4, L"Modern-Regular",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x422a7252, L"Stencil",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x42c8554f, L"Fixedsys",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x435cb41d, L"Roman",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x47882383, L"CourierNew", L"Droid Sans Fallback", 1, 1252},
+    {0x480a2338, L"BerlinSansFBDemi",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x480bf7a4, L"CourierStd", L"Droid Sans Fallback", 0, 1252},
+    {0x481ad6ed, L"VladimirScript",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252},
+    {0x4911577a, L"YouYuan", L"Droid Sans Fallback", 1, 936},
+    {0x4a788d72, L"STXingkai", L"Droid Sans Fallback", 0, 936},
+    {0x4bf88566, L"SegoeCondensed",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x4ccf51a4, L"BerlinSansFB-Reg",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x4ea967ce, L"GulimChe", L"Droid Sans Fallback", 1, 1252},
+    {0x4f68bd79, L"LetterGothicStd",
+     L"Droid Sans Mono,Droid Arabic Naskh,Droid Sans Ethiopic,Droid Sans "
+     L"Mono,Droid Serif,Droid Sans Fallback",
+     0, 1252},
+    {0x51a0d0e6, L"KozukaGothicPr6NM",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x531b3dea, L"BasemicSymbol",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x5333fd39, L"CalifornianFB-Reg",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x53561a54, L"FZYTK--GBK1-0", L"Droid Sans Fallback", 0, 936},
+    {0x55e0dde6, L"LucidaSansTypewriter",
+     L"Droid Sans Mono,Droid Arabic Naskh,Droid Sans Ethiopic", 0, 1252},
+    {0x574d4d3d, L"AdobeArabic",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x5792e759, L"STKaiti", L"Droid Sans Fallback", 0, 936},
+    {0x5921978e, L"LucidaSansUnicode", L"Droid Sans Fallback", 0, 1252},
+    {0x594e2da4, L"Vrinda",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0x59baa9a2, L"KaiTi_GB2312", L"Droid Sans Fallback", 0, 1252},
+    {0x5cfedf4f, L"BaskOldFace",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x5f97921c, L"AdobeMyungjoStdM", L"Droid Sans Fallback", 0, 936},
+    {0x5fefbfad, L"Batang", L"Droid Sans Fallback", 2, 1252},
+    {0x605342b9, L"DotumChe", L"Droid Sans Fallback", 1, 1252},
+    {0x608c5f9a, L"KaiTi_GB2312", L"Droid Sans Fallback", 0, 936},
+    {0x61efd0d1, L"MaturaMTScriptCapitals",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0x626608a9, L"MVBoli",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0x630501a3, L"SmallFonts",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x65d0e2a9, L"FZYTK--GBK1-0", L"Droid Sans Fallback", 0, 936},
+    {0x669f29e1, L"FZSTK--GBK1-0", L"Droid Sans Fallback", 0, 936},
+    {0x673a9e5f, L"Tunga",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans "
+     L"Mono,Droid Sans Fallback",
+     0, 1252},
+    {0x691aa4ce, L"NiagaraSolid",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x696259b7, L"Corbel",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x696ee9be, L"STXihei", L"Droid Sans Fallback", 0, 936},
+    {0x6c59cf69, L"Dotum", L"Droid Sans Fallback", 0, 1252},
+    {0x707fa561, L"Gungsuh", L"Droid Sans Fallback", 2, 1252},
+    {0x71416bb2, L"ZWAdobeF",
+     L"Droid Arabic Naskh,Droid Sans Armenian,Droid Sans Ethiopic,Droid Sans "
+     L"Georgian,Droid Sans Hebrew,Droid Sans Thai",
+     0, 1252},
+    {0x71b41801, L"Verdana",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x73f25e4c, L"PalatinoLinotype", L"Droid Sans Fallback", 0, 1252},
+    {0x73f4d19f, L"NiagaraEngraved",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x74001694, L"MyriadProBlack", L"Book Antiqua,Constantia,Dotum,Georgia", 0,
+     1252},
+    {0x74b14d8f, L"Haettenschweiler",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x74cb44ee, L"NSimSun", L"Droid Sans Fallback", 1, 936},
+    {0x76b4d7ff, L"Shruti",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0x788b3533, L"Webdings",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42},
+    {0x797dde99, L"MSSerif",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x7a0f9e9e, L"MSMincho", L"Droid Sans Fallback", 1, 1252},
+    {0x7b439caf, L"OldEnglishTextMT",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x8213a433, L"LucidaSans-Typewriter",
+     L"Droid Sans Mono,Droid Serif,Roboto,Droid Sans Fallback", 0, 1252},
+    {0x82fec929, L"AdobeSongStdL", L"Droid Sans Fallback", 0, 936},
+    {0x83581825, L"Modern",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x835a2823, L"Algerian",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x83dab9f5, L"Script",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x847b56da, L"Tahoma", L"Droid Sans Fallback", 0, 1252},
+    {0x8a783cb2, L"SimSun-PUA", L"Droid Sans Fallback", 0, 1252},
+    {0x8b5cac0e, L"Onyx",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x8c6a499e, L"Gulim", L"Droid Sans Fallback", 0, 1252},
+    {0x8e0af790, L"JuiceITC",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x8e8d43b2, L"Centaur",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x8ee4dcca, L"BookshelfSymbol7",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x90794800, L"BellGothicStdLight",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x909b516a, L"Century",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x92ae370d, L"MSOutlook",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 4, 42},
+    {0x93c9fbf1, L"LucidaFax",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans "
+     L"Mono",
+     2, 1252},
+    {0x9565085e, L"BookAntiqua",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0x9856d95d, L"AdobeMingStdL", L"Droid Sans Fallback", 0, 949},
+    {0x9bbadd6b, L"ColonnaMT",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0x9cbd16a4, L"ShowcardGothic-Reg",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallbac", 0, 1252},
+    {0x9d73008e, L"MSSansSerif",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xa0607db1, L"GungsuhChe", L"Droid Sans Fallback", 1, 1252},
+    {0xa0bcf6a1, L"LatinWide",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0xa1429b36, L"Symbol",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42},
+    {0xa1fa5abc, L"Wingdings2",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42},
+    {0xa1fa5abd, L"Wingdings3",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42},
+    {0xa427bad4, L"InformalRoman-Regular",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic", 8, 1252},
+    {0xa8b92ece, L"FZSTK--GBK1-0", L"Droid Sans Fallback", 0, 936},
+    {0xa8d83ece, L"CalifornianFB",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0xaa3e082c, L"Kingsoft-Phonetic",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xaa6bcabe, L"HarlowSolidItalic",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xade5337c, L"MSUIGothic",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xb08dd941, L"WideLatin",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans "
+     L"Mono",
+     2, 1252},
+    {0xb207f05d, L"PoorRichard",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0xb3bc492f, L"JuiceITC-Regular",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xb5545399, L"Marlett",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 4, 42},
+    {0xb5dd1ebb, L"BritannicBold", L"Droid Arabic Naskh,Droid Sans Ethiopic", 0,
+     1252},
+    {0xb699c1c5, L"LucidaCalligraphy-Italic",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xb725d629, L"TimesNewRoman", L"Droid Sans Fallback", 2, 1252},
+    {0xb7eaebeb, L"AdobeHeitiStdR", L"Droid Sans Fallback", 0, 936},
+    {0xbd29c486, L"BerlinSansFBDemi-Bold",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xbe8a8db4, L"BookshelfSymbolSeven",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xc16c0118, L"AdobeHebrew",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback,Droid Arabic "
+     L"Naskh,Droid Sans Ethiopic",
+     0, 1252},
+    {0xc318b0af, L"MyriadProLight",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xc65e5659, L"CambriaMath", L"Droid Sans Fallback", 2, 1252},
+    {0xc75c8f05, L"LucidaConsole",
+     L"Droid Sans Mono,Droid Serif,Roboto,Droid Sans Fallback", 1, 1252},
+    {0xca7c35d6, L"Calibri", L"Droid Sans Fallback", 0, 1252},
+    {0xcb053f53, L"MicrosoftYaHei", L"Droid Sans Fallback", 0, 936},
+    {0xcb7190f9, L"Magneto-Bold",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xcca00cc5, L"System",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xccad6f76, L"Jokerman-Regular",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xccc5818c, L"EuroSign",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xcf3d7234, L"LucidaHandwriting-Italic",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xcf7b8fdb, L"MinionPro",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xcfe5755f, L"Simhei", L"Droid Sans Fallback", 1, 936},
+    {0xd011f4ee, L"MSPGothic", L"Droid Sans Fallback", 0, 1252},
+    {0xd060e7ef, L"Vivaldi",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 8, 1252},
+    {0xd07edec1, L"FranklinGothic-Medium",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xd107243f, L"SimSun", L"Droid Sans Fallback", 0, 936},
+    {0xd1881562, L"ArialNarrow",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xd22b7dce, L"BodoniMTPosterCompressed",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xd22bfa60, L"ComicSansMS", L"Droid Serif,Roboto,Droid Sans Fallback", 8,
+     1252},
+    {0xd3bd0e35, L"Bauhaus93",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xd429ee7a, L"STFangsong", L"Droid Sans Fallback", 0, 936},
+    {0xd6679c12, L"BernardMTCondensed",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xd8e8a027, L"LucidaSans",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 0, 1252},
+    {0xd9fe7761, L"HighTowerText-Reg",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 2, 1252},
+    {0xda7e551e, L"STSong", L"Droid Sans Fallback", 0, 936},
+    {0xdaa6842d, L"STZhongsong", L"Droid Sans Fallback", 0, 936},
+    {0xdaaab93f, L"STFangsong", L"Droid Sans Fallback", 0, 936},
+    {0xdaeb0713, L"STSong",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 936},
+    {0xdafedbef, L"STCaiyun", L"Droid Sans Fallback", 0, 936},
+    {0xdb00a3d9, L"Broadway",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xdb1f5ad4, L"STXinwei", L"Droid Sans Fallback", 0, 936},
+    {0xdb326e7f, L"STKaiti", L"Droid Sans Fallback", 0, 936},
+    {0xdb69595a, L"STHupo", L"Droid Sans Fallback", 0, 936},
+    {0xdba0082c, L"STXihei", L"Droid Sans Fallback", 0, 936},
+    {0xdbd0ab18, L"STXingkai", L"Droid Sans Fallback", 0, 936},
+    {0xdc1a7db1, L"STLiti", L"Droid Sans Fallback", 0, 936},
+    {0xdc33075f, L"KristenITC-Regular",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 8, 1252},
+    {0xdcc7009c, L"Harrington",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xdd712466, L"ArialBlack",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xdde87b3e, L"Impact",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xdf69fb32, L"SnapITC",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0xdf8b25e8, L"CenturyGothic",
+     L"Droid Serif,Roboto,Droid Serif,Droid Sans Mono", 0, 1252},
+    {0xe0f705c0, L"KristenITC",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto", 8, 1252},
+    {0xe1427573, L"Raavi",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0xe2cea0cb, L"Magneto",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0xe36a9e17, L"Ravie",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0xe433f8e2, L"Parchment",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252},
+    {0xe43dff4a, L"Wingdings",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 4, 42},
+    {0xe4e2c405, L"MTExtra",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 6, 42},
+    {0xe618cc35, L"InformalRoman",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif", 8, 1252},
+    {0xe6c27ffc, L"Mistral",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 8, 1252},
+    {0xe7ebf4b9, L"Courier", L"Droid Sans Fallback", 0, 1252},
+    {0xe8bc4a9d, L"MSReferenceSpecialty",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xe90fb013, L"TempusSansITC",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xec637b42, L"Consolas", L"Droid Sans Fallback", 1, 1252},
+    {0xed3a683b, L"STXinwei", L"Droid Sans Fallback", 0, 936},
+    {0xef264cd1, L"LucidaHandwriting",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0xf086bca2, L"BaskervilleOldFace",
+     L"Roboto,Droid Serif,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xf1028030, L"Mangal",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans "
+     L"Mono",
+     2, 1252},
+    {0xf1da7eb9, L"ShowcardGothic",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallbac", 0, 1252},
+    {0xf210f06a, L"ArialMT",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif", 0, 1252},
+    {0xf477f16a, L"Latha",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Roboto,Droid Serif,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0xf616f3dd, L"LiSu", L"Droid Sans Fallback", 1, 936},
+    {0xfa479aa6, L"MicrosoftYaHei", L"Droid Sans Fallback", 0, 936},
+    {0xfcd19697, L"BookmanOldStyle",
+     L"Droid Serif,Roboto,Droid Sans Mono,Droid Sans Fallback", 0, 1252},
+    {0xfe209a82, L"LucidaCalligraphy",
+     L"Droid Arabic Naskh,Droid Sans Ethiopic,Droid Serif,Roboto,Droid Sans "
+     L"Mono",
+     0, 1252},
+    {0xfef135f8, L"AdobeHeitiStd-Regular", L"Droid Sans Fallback", 0, 936},
+};
+#endif
+void XFA_LocalFontNameToEnglishName(const CFX_WideStringC& wsLocalName,
+                                    CFX_WideString& wsEnglishName) {
+  wsEnglishName = wsLocalName;
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ || \
+    _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ ||   \
+    _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ ||   \
+    _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
+  FX_DWORD dwLocalNameHash = FX_HashCode_String_GetW(
+      wsLocalName.GetPtr(), wsLocalName.GetLength(), TRUE);
+  int32_t iStart = 0;
+  int32_t iEnd = sizeof(g_XFAFontsMap) / sizeof(XFA_FONTINFO) - 1;
+  int32_t iMid = 0;
+  do {
+    iMid = (iStart + iEnd) / 2;
+    FX_DWORD dwFontNameHash = g_XFAFontsMap[iMid].dwFontNameHash;
+    if (dwFontNameHash == dwLocalNameHash) {
+      wsEnglishName = g_XFAFontsMap[iMid].pPsName;
+      break;
+    } else if (dwFontNameHash < dwLocalNameHash) {
+      iStart = iMid + 1;
+    } else {
+      iEnd = iMid - 1;
+    }
+  } while (iEnd >= iStart);
+#endif
+}
+const XFA_FONTINFO* XFA_GetFontINFOByFontName(
+    const CFX_WideStringC& wsFontName) {
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ || \
+    _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ ||   \
+    _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ ||   \
+    _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
+  CFX_WideString wsFontNameTemp = wsFontName;
+  wsFontNameTemp.Remove(L' ');
+  FX_DWORD dwCurFontNameHash =
+      FX_HashCode_String_GetW(wsFontNameTemp, wsFontNameTemp.GetLength(), TRUE);
+  int32_t iStart = 0;
+  int32_t iEnd = sizeof(g_XFAFontsMap) / sizeof(XFA_FONTINFO) - 1;
+  int32_t iMid = 0;
+  const XFA_FONTINFO* pFontInfo = NULL;
+  do {
+    iMid = (iStart + iEnd) / 2;
+    FX_DWORD dwFontNameHash = g_XFAFontsMap[iMid].dwFontNameHash;
+    if (dwFontNameHash == dwCurFontNameHash) {
+      pFontInfo = &g_XFAFontsMap[iMid];
+      break;
+    } else if (dwFontNameHash < dwCurFontNameHash) {
+      iStart = iMid + 1;
+    } else {
+      iEnd = iMid - 1;
+    }
+  } while (iEnd >= iStart);
+  return pFontInfo;
+#else
+  return NULL;
+#endif
+}
+// static
+IXFA_FontMgr* IXFA_FontMgr::CreateDefault() {
+  return new CXFA_DefFontMgr;
+}
+// virtual
+IXFA_FontMgr::~IXFA_FontMgr() {}
+CXFA_DefFontMgr::~CXFA_DefFontMgr() {
+  int32_t iCounts = m_CacheFonts.GetSize();
+  for (int32_t i = 0; i < iCounts; i++) {
+    ((IFX_Font*)m_CacheFonts[i])->Release();
+  }
+  m_CacheFonts.RemoveAll();
+}
+
+IFX_Font* CXFA_DefFontMgr::GetFont(IXFA_Doc* hDoc,
+                                   const CFX_WideStringC& wsFontFamily,
+                                   FX_DWORD dwFontStyles,
+                                   FX_WORD wCodePage) {
+  CFX_WideString wsFontName = wsFontFamily;
+  IFX_FontMgr* pFDEFontMgr =
+      static_cast<CXFA_FFDoc*>(hDoc)->GetApp()->GetFDEFontMgr();
+  IFX_Font* pFont = pFDEFontMgr->LoadFont(wsFontName, dwFontStyles, wCodePage);
+  if (!pFont) {
+    const XFA_FONTINFO* pCurFont = XFA_GetFontINFOByFontName(wsFontName);
+    if (pCurFont && pCurFont->pReplaceFont) {
+      FX_DWORD dwStyle = 0;
+      if (dwFontStyles & FX_FONTSTYLE_Bold) {
+        dwStyle |= FX_FONTSTYLE_Bold;
+      }
+      if (dwFontStyles & FX_FONTSTYLE_Italic) {
+        dwStyle |= FX_FONTSTYLE_Italic;
+      }
+      const FX_WCHAR* pReplace = pCurFont->pReplaceFont;
+      int32_t iLength = FXSYS_wcslen(pReplace);
+      while (iLength > 0) {
+        const FX_WCHAR* pNameText = pReplace;
+        while (*pNameText != L',' && iLength > 0) {
+          pNameText++;
+          iLength--;
+        }
+        CFX_WideString wsReplace =
+            CFX_WideString(pReplace, pNameText - pReplace);
+        pFont = pFDEFontMgr->LoadFont(wsReplace, dwStyle, wCodePage);
+        if (pFont) {
+          break;
+        }
+        iLength--;
+        pNameText++;
+        pReplace = pNameText;
+      }
+    }
+  }
+  if (pFont) {
+    m_CacheFonts.Add(pFont);
+  }
+  return pFont;
+}
+
+IFX_Font* CXFA_DefFontMgr::GetDefaultFont(IXFA_Doc* hDoc,
+                                          const CFX_WideStringC& wsFontFamily,
+                                          FX_DWORD dwFontStyles,
+                                          FX_WORD wCodePage) {
+  IFX_FontMgr* pFDEFontMgr = ((CXFA_FFDoc*)hDoc)->GetApp()->GetFDEFontMgr();
+  IFX_Font* pFont =
+      pFDEFontMgr->LoadFont(L"Arial Narrow", dwFontStyles, wCodePage);
+  if (!pFont)
+    pFont =
+        pFDEFontMgr->LoadFont((const FX_WCHAR*)NULL, dwFontStyles, wCodePage);
+  FXSYS_assert(pFont);
+  if (pFont) {
+    m_CacheFonts.Add(pFont);
+  }
+  return pFont;
+}
+struct XFA_PDFFONTNAME {
+  const FX_CHAR* lpPsName;
+  const FX_CHAR* lpNormal;
+  const FX_CHAR* lpBold;
+  const FX_CHAR* lpItalic;
+  const FX_CHAR* lpBoldItalic;
+};
+const XFA_PDFFONTNAME g_XFAPDFFontName[] = {
+    {"Adobe PI Std", "AdobePIStd", "AdobePIStd", "AdobePIStd", "AdobePIStd"},
+    {"Myriad Pro Light", "MyriadPro-Light", "MyriadPro-Semibold",
+     "MyriadPro-LightIt", "MyriadPro-SemiboldIt"},
+};
+CXFA_PDFFontMgr::CXFA_PDFFontMgr(CXFA_FFDoc* pDoc) {
+  m_pDoc = pDoc;
+}
+CXFA_PDFFontMgr::~CXFA_PDFFontMgr() {
+  m_FDE2PDFFont.RemoveAll();
+  for (const auto& pair : m_FontMap) {
+    if (pair.second)
+      pair.second->Release();
+  }
+}
+IFX_Font* CXFA_PDFFontMgr::FindFont(CFX_ByteString strPsName,
+                                    FX_BOOL bBold,
+                                    FX_BOOL bItalic,
+                                    CPDF_Font** pDstPDFFont,
+                                    FX_BOOL bStrictMatch) {
+  CPDF_Document* pDoc = m_pDoc->GetPDFDoc();
+  if (pDoc == NULL) {
+    return NULL;
+  }
+  CPDF_Dictionary* pFontSetDict =
+      pDoc->GetRoot()->GetDictBy("AcroForm")->GetDictBy("DR");
+  if (!pFontSetDict) {
+    return NULL;
+  }
+  pFontSetDict = (CPDF_Dictionary*)pFontSetDict->GetDictBy("Font");
+  if (!pFontSetDict) {
+    return NULL;
+  }
+  strPsName.Remove(' ');
+  IFX_FontMgr* pFDEFontMgr = m_pDoc->GetApp()->GetFDEFontMgr();
+  for (const auto& it : *pFontSetDict) {
+    const CFX_ByteString& key = it.first;
+    CPDF_Object* pObj = it.second;
+    if (!PsNameMatchDRFontName(strPsName, bBold, bItalic, key, bStrictMatch)) {
+      continue;
+    }
+    CPDF_Object* pDirect = pObj->GetDirect();
+    if (!pDirect || !pDirect->IsDictionary()) {
+      return NULL;
+    }
+    CPDF_Dictionary* pFontDict = (CPDF_Dictionary*)pDirect;
+    if (pFontDict->GetStringBy("Type") != "Font") {
+      return NULL;
+    }
+    CPDF_Font* pPDFFont = pDoc->LoadFont(pFontDict);
+    if (!pPDFFont) {
+      return NULL;
+    }
+    if (!pPDFFont->IsEmbedded()) {
+      *pDstPDFFont = pPDFFont;
+      return NULL;
+    }
+    return IFX_Font::LoadFont(&pPDFFont->m_Font, pFDEFontMgr);
+  }
+  return NULL;
+}
+IFX_Font* CXFA_PDFFontMgr::GetFont(const CFX_WideStringC& wsFontFamily,
+                                   FX_DWORD dwFontStyles,
+                                   CPDF_Font** pPDFFont,
+                                   FX_BOOL bStrictMatch) {
+  FX_DWORD dwHashCode =
+      FX_HashCode_String_GetW(wsFontFamily.GetPtr(), wsFontFamily.GetLength());
+  CFX_ByteString strKey;
+  strKey.Format("%u%u", dwHashCode, dwFontStyles);
+  auto it = m_FontMap.find(strKey);
+  if (it != m_FontMap.end())
+    return it->second;
+  CFX_ByteString bsPsName = CFX_ByteString::FromUnicode(wsFontFamily);
+  FX_BOOL bBold = (dwFontStyles & FX_FONTSTYLE_Bold) == FX_FONTSTYLE_Bold;
+  FX_BOOL bItalic = (dwFontStyles & FX_FONTSTYLE_Italic) == FX_FONTSTYLE_Italic;
+  CFX_ByteString strFontName = PsNameToFontName(bsPsName, bBold, bItalic);
+  IFX_Font* pFont =
+      FindFont(strFontName, bBold, bItalic, pPDFFont, bStrictMatch);
+  if (pFont)
+    m_FontMap[strKey] = pFont;
+  return pFont;
+}
+CFX_ByteString CXFA_PDFFontMgr::PsNameToFontName(
+    const CFX_ByteString& strPsName,
+    FX_BOOL bBold,
+    FX_BOOL bItalic) {
+  int32_t nCount = sizeof(g_XFAPDFFontName) / sizeof(XFA_PDFFONTNAME);
+  for (int32_t i = 0; i < nCount; i++) {
+    if (strPsName == g_XFAPDFFontName[i].lpPsName) {
+      int32_t index = 1 + ((bItalic << 1) | bBold);
+      return *(&g_XFAPDFFontName[i].lpPsName + index);
+    }
+  }
+  return strPsName;
+}
+FX_BOOL CXFA_PDFFontMgr::PsNameMatchDRFontName(
+    const CFX_ByteStringC& bsPsName,
+    FX_BOOL bBold,
+    FX_BOOL bItalic,
+    const CFX_ByteString& bsDRFontName,
+    FX_BOOL bStrictMatch) {
+  CFX_ByteString bsDRName = bsDRFontName;
+  bsDRName.Remove('-');
+  int32_t iPsLen = bsPsName.GetLength();
+  int32_t nIndex = bsDRName.Find(bsPsName);
+  if (nIndex != -1 && !bStrictMatch) {
+    return TRUE;
+  }
+  if (nIndex != 0) {
+    return FALSE;
+  }
+  int32_t iDifferLength = bsDRName.GetLength() - iPsLen;
+  if (iDifferLength > 1 || (bBold || bItalic)) {
+    int32_t iBoldIndex = bsDRName.Find("Bold");
+    FX_BOOL bBoldFont = iBoldIndex > 0;
+    if (bBold ^ bBoldFont) {
+      return FALSE;
+    }
+    if (bBoldFont) {
+      iDifferLength =
+          std::min(iDifferLength - 4, bsDRName.GetLength() - iBoldIndex - 4);
+    }
+    FX_BOOL bItalicFont = TRUE;
+    if (bsDRName.Find("Italic") > 0) {
+      iDifferLength -= 6;
+    } else if (bsDRName.Find("It") > 0) {
+      iDifferLength -= 2;
+    } else if (bsDRName.Find("Oblique") > 0) {
+      iDifferLength -= 7;
+    } else {
+      bItalicFont = FALSE;
+    }
+    if (bItalic ^ bItalicFont) {
+      return FALSE;
+    }
+    if (iDifferLength > 1) {
+      CFX_ByteString bsDRTailer = bsDRName.Right(iDifferLength);
+      if (bsDRTailer.Equal("MT") || bsDRTailer.Equal("PSMT") ||
+          bsDRTailer.Equal("Regular") || bsDRTailer.Equal("Reg")) {
+        return TRUE;
+      }
+      if (bBoldFont || bItalicFont) {
+        return FALSE;
+      }
+      FX_BOOL bMatch = FALSE;
+      switch (bsPsName.GetAt(iPsLen - 1)) {
+        case 'L': {
+          if (bsDRName.Right(5).Equal("Light")) {
+            bMatch = TRUE;
+          }
+        } break;
+        case 'R': {
+          if (bsDRName.Right(7).Equal("Regular") ||
+              bsDRName.Right(3).Equal("Reg")) {
+            bMatch = TRUE;
+          }
+        } break;
+        case 'M': {
+          if (bsDRName.Right(5).Equal("Medium")) {
+            bMatch = TRUE;
+          }
+        } break;
+        default:
+          break;
+      }
+      return bMatch;
+    }
+  }
+  return TRUE;
+}
+FX_BOOL CXFA_PDFFontMgr::GetCharWidth(IFX_Font* pFont,
+                                      FX_WCHAR wUnicode,
+                                      int32_t& iWidth,
+                                      FX_BOOL bCharCode) {
+  if (wUnicode != 0x20 || bCharCode) {
+    return FALSE;
+  }
+  CPDF_Font* pPDFFont = (CPDF_Font*)m_FDE2PDFFont.GetValueAt(pFont);
+  if (!pPDFFont) {
+    return FALSE;
+  }
+  wUnicode = (FX_WCHAR)pPDFFont->CharCodeFromUnicode(wUnicode);
+  iWidth = pPDFFont->GetCharWidthF(wUnicode);
+  return TRUE;
+}
+CXFA_FontMgr::CXFA_FontMgr() : m_pDefFontMgr(NULL) {}
+CXFA_FontMgr::~CXFA_FontMgr() {
+  DelAllMgrMap();
+}
+IFX_Font* CXFA_FontMgr::GetFont(IXFA_Doc* hDoc,
+                                const CFX_WideStringC& wsFontFamily,
+                                FX_DWORD dwFontStyles,
+                                FX_WORD wCodePage) {
+  FX_DWORD dwHash = FX_HashCode_String_GetW(wsFontFamily.GetPtr(),
+                                            wsFontFamily.GetLength(), FALSE);
+  CFX_ByteString bsKey;
+  bsKey.Format("%u%u%u", dwHash, dwFontStyles, wCodePage);
+  auto it = m_FontMap.find(bsKey);
+  if (it != m_FontMap.end())
+    return it->second;
+  CFX_WideString wsEnglishName;
+  XFA_LocalFontNameToEnglishName(wsFontFamily, wsEnglishName);
+  CXFA_PDFFontMgr* pMgr = (CXFA_PDFFontMgr*)m_PDFFontMgrArray.GetValueAt(hDoc);
+  CPDF_Font* pPDFFont = NULL;
+  IFX_Font* pFont = NULL;
+  if (pMgr) {
+    pFont = pMgr->GetFont(wsEnglishName, dwFontStyles, &pPDFFont);
+    if (pFont)
+      return pFont;
+  }
+  if (!pFont && m_pDefFontMgr) {
+    pFont = m_pDefFontMgr->GetFont(hDoc, wsFontFamily, dwFontStyles, wCodePage);
+  }
+  if (!pFont && pMgr) {
+    pPDFFont = NULL;
+    pFont = pMgr->GetFont(wsEnglishName, dwFontStyles, &pPDFFont, FALSE);
+    if (pFont)
+      return pFont;
+  }
+  if (!pFont && m_pDefFontMgr) {
+    pFont = m_pDefFontMgr->GetDefaultFont(hDoc, wsFontFamily, dwFontStyles,
+                                          wCodePage);
+  }
+  if (pFont) {
+    if (pPDFFont) {
+      pMgr->m_FDE2PDFFont.SetAt(pFont, pPDFFont);
+      pFont->SetFontProvider(pMgr);
+    }
+    m_FontMap[bsKey] = pFont;
+  }
+  return pFont;
+}
+void CXFA_FontMgr::LoadDocFonts(IXFA_Doc* hDoc) {
+  if (!m_PDFFontMgrArray.GetValueAt(hDoc)) {
+    m_PDFFontMgrArray.SetAt(hDoc, new CXFA_PDFFontMgr((CXFA_FFDoc*)hDoc));
+  }
+}
+void CXFA_FontMgr::ReleaseDocFonts(IXFA_Doc* hDoc) {
+  CXFA_PDFFontMgr* pMgr = NULL;
+  if (m_PDFFontMgrArray.Lookup(hDoc, (void*&)pMgr)) {
+    delete pMgr;
+    m_PDFFontMgrArray.RemoveKey(hDoc);
+  }
+}
+void CXFA_FontMgr::DelAllMgrMap() {
+  FX_POSITION ps = m_PDFFontMgrArray.GetStartPosition();
+  while (ps) {
+    IXFA_Doc* hDoc = NULL;
+    CXFA_PDFFontMgr* pMgr = NULL;
+    m_PDFFontMgrArray.GetNextAssoc(ps, (void*&)hDoc, (void*&)pMgr);
+    delete pMgr;
+  }
+  m_PDFFontMgrArray.RemoveAll();
+  m_FontMap.clear();
+}
+void CXFA_FontMgr::SetDefFontMgr(IXFA_FontMgr* pFontMgr) {
+  m_pDefFontMgr = pFontMgr;
+}
diff --git a/xfa/fxfa/app/xfa_fontmgr.h b/xfa/fxfa/app/xfa_fontmgr.h
new file mode 100644
index 0000000..4436079
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fontmgr.h
@@ -0,0 +1,100 @@
+// 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_FXFA_APP_XFA_FONTMGR_H_
+#define XFA_FXFA_APP_XFA_FONTMGR_H_
+
+#include <map>
+
+#include "core/include/fxcrt/fx_ext.h"
+#include "core/include/fxcrt/fx_system.h"
+#include "xfa/fgas/font/fgas_font.h"
+#include "xfa/include/fxfa/fxfa.h"
+
+class CPDF_Font;
+
+struct XFA_FONTINFO {
+  FX_DWORD dwFontNameHash;
+  const FX_WCHAR* pPsName;
+  const FX_WCHAR* pReplaceFont;
+  FX_WORD dwStyles;
+  FX_WORD wCodePage;
+};
+
+class CXFA_DefFontMgr : public IXFA_FontMgr {
+ public:
+  CXFA_DefFontMgr() {}
+  ~CXFA_DefFontMgr() override;
+
+  // IXFA_FontMgr:
+  IFX_Font* GetFont(IXFA_Doc* hDoc,
+                    const CFX_WideStringC& wsFontFamily,
+                    FX_DWORD dwFontStyles,
+                    FX_WORD wCodePage = 0xFFFF) override;
+  IFX_Font* GetDefaultFont(IXFA_Doc* hDoc,
+                           const CFX_WideStringC& wsFontFamily,
+                           FX_DWORD dwFontStyles,
+                           FX_WORD wCodePage = 0xFFFF) override;
+
+ protected:
+  CFX_PtrArray m_CacheFonts;
+};
+
+class CXFA_PDFFontMgr : public IFX_FontProvider {
+ public:
+  CXFA_PDFFontMgr(CXFA_FFDoc* pDoc);
+  ~CXFA_PDFFontMgr();
+  IFX_Font* GetFont(const CFX_WideStringC& wsFontFamily,
+                    FX_DWORD dwFontStyles,
+                    CPDF_Font** pPDFFont,
+                    FX_BOOL bStrictMatch = TRUE);
+  FX_BOOL GetCharWidth(IFX_Font* pFont,
+                       FX_WCHAR wUnicode,
+                       int32_t& iWidth,
+                       FX_BOOL bCharCode);
+  CFX_MapPtrToPtr m_FDE2PDFFont;
+
+ protected:
+  IFX_Font* FindFont(CFX_ByteString strFamilyName,
+                     FX_BOOL bBold,
+                     FX_BOOL bItalic,
+                     CPDF_Font** pPDFFont,
+                     FX_BOOL bStrictMatch = TRUE);
+  CFX_ByteString PsNameToFontName(const CFX_ByteString& strPsName,
+                                  FX_BOOL bBold,
+                                  FX_BOOL bItalic);
+  FX_BOOL PsNameMatchDRFontName(const CFX_ByteStringC& bsPsName,
+                                FX_BOOL bBold,
+                                FX_BOOL bItalic,
+                                const CFX_ByteString& bsDRFontName,
+                                FX_BOOL bStrictMatch = TRUE);
+
+  CXFA_FFDoc* m_pDoc;
+  std::map<CFX_ByteString, IFX_Font*> m_FontMap;
+};
+
+class CXFA_FontMgr {
+ public:
+  CXFA_FontMgr();
+  ~CXFA_FontMgr();
+  IFX_Font* GetFont(IXFA_Doc* hDoc,
+                    const CFX_WideStringC& wsFontFamily,
+                    FX_DWORD dwFontStyles,
+                    FX_WORD wCodePage = 0xFFFF);
+  void LoadDocFonts(IXFA_Doc* hDoc);
+  void ReleaseDocFonts(IXFA_Doc* hDoc);
+
+  void SetDefFontMgr(IXFA_FontMgr* pFontMgr);
+
+ protected:
+  void DelAllMgrMap();
+
+  CFX_MapPtrToPtr m_PDFFontMgrArray;
+  IXFA_FontMgr* m_pDefFontMgr;
+  std::map<CFX_ByteString, IFX_Font*> m_FontMap;
+};
+
+#endif  //  XFA_FXFA_APP_XFA_FONTMGR_H_
diff --git a/xfa/fxfa/app/xfa_fwladapter.cpp b/xfa/fxfa/app/xfa_fwladapter.cpp
new file mode 100644
index 0000000..1e6010e
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fwladapter.cpp
@@ -0,0 +1,61 @@
+// 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/fxfa/app/xfa_fwladapter.h"
+
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_fffield.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+
+void FWL_PostMessageToMainRoop(CFWL_Message* pMessage) {}
+FX_BOOL FWL_ShowCaret(IFWL_Widget* pWidget,
+                      FX_BOOL bVisible,
+                      const CFX_RectF* pRtAnchor) {
+  CXFA_FFWidget* pXFAWidget = (CXFA_FFWidget*)pWidget->GetPrivateData(pWidget);
+  if (!pXFAWidget) {
+    return FALSE;
+  }
+  IXFA_DocProvider* pDocProvider = pXFAWidget->GetDoc()->GetDocProvider();
+  if (!pDocProvider) {
+    return FALSE;
+  }
+  if (bVisible) {
+    CFX_Matrix mt;
+    pXFAWidget->GetRotateMatrix(mt);
+    CFX_RectF rt(*pRtAnchor);
+    mt.TransformRect(rt);
+    pDocProvider->DisplayCaret(pXFAWidget, bVisible, &rt);
+    return TRUE;
+  }
+  pDocProvider->DisplayCaret(pXFAWidget, bVisible, pRtAnchor);
+  return TRUE;
+}
+
+FWL_ERR CXFA_FWLAdapterWidgetMgr::RepaintWidget(IFWL_Widget* pWidget,
+                                                const CFX_RectF* pRect) {
+  if (!pWidget)
+    return FWL_ERR_Indefinite;
+  CXFA_FFField* pField = (CXFA_FFField*)pWidget->GetPrivateData(pWidget);
+  if (!pField)
+    return FWL_ERR_Indefinite;
+  pField->AddInvalidateRect(nullptr);
+  return FWL_ERR_Succeeded;
+}
+
+FX_BOOL CXFA_FWLAdapterWidgetMgr::GetPopupPos(IFWL_Widget* pWidget,
+                                              FX_FLOAT fMinHeight,
+                                              FX_FLOAT fMaxHeight,
+                                              const CFX_RectF& rtAnchor,
+                                              CFX_RectF& rtPopup) {
+  CXFA_FFWidget* pFFWidget = (CXFA_FFWidget*)(pWidget->GetPrivateData(pWidget));
+  CFX_Matrix mt;
+  pFFWidget->GetRotateMatrix(mt);
+  CFX_RectF rtRotateAnchor(rtAnchor);
+  mt.TransformRect(rtRotateAnchor);
+  pFFWidget->GetDoc()->GetDocProvider()->GetPopupPos(
+      pFFWidget, fMinHeight, fMaxHeight, rtRotateAnchor, rtPopup);
+  return TRUE;
+}
diff --git a/xfa/fxfa/app/xfa_fwladapter.h b/xfa/fxfa/app/xfa_fwladapter.h
new file mode 100644
index 0000000..bf9a3d6
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fwladapter.h
@@ -0,0 +1,22 @@
+// 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_FXFA_APP_XFA_FWLADAPTER_H_
+#define XFA_FXFA_APP_XFA_FWLADAPTER_H_
+
+#include "xfa/include/fwl/adapter/fwl_sdadapterimp.h"
+
+class CXFA_FWLAdapterWidgetMgr : public CFWL_SDAdapterWidgetMgr {
+ public:
+  virtual FWL_ERR RepaintWidget(IFWL_Widget* pWidget, const CFX_RectF* pRect);
+  virtual FX_BOOL GetPopupPos(IFWL_Widget* pWidget,
+                              FX_FLOAT fMinHeight,
+                              FX_FLOAT fMaxHeight,
+                              const CFX_RectF& rtAnchor,
+                              CFX_RectF& rtPopup);
+};
+
+#endif  // XFA_FXFA_APP_XFA_FWLADAPTER_H_
diff --git a/xfa/fxfa/app/xfa_fwltheme.cpp b/xfa/fxfa/app/xfa_fwltheme.cpp
new file mode 100644
index 0000000..b0657ee
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fwltheme.cpp
@@ -0,0 +1,424 @@
+// 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/fxfa/app/xfa_fwltheme.h"
+
+#include "xfa/fde/tto/fde_textout.h"
+#include "xfa/fgas/crt/fgas_codepage.h"
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/include/fwl/basewidget/fwl_barcode.h"
+#include "xfa/include/fwl/basewidget/fwl_caret.h"
+#include "xfa/include/fwl/basewidget/fwl_checkbox.h"
+#include "xfa/include/fwl/basewidget/fwl_combobox.h"
+#include "xfa/include/fwl/basewidget/fwl_datetimepicker.h"
+#include "xfa/include/fwl/basewidget/fwl_edit.h"
+#include "xfa/include/fwl/basewidget/fwl_listbox.h"
+#include "xfa/include/fwl/basewidget/fwl_monthcalendar.h"
+#include "xfa/include/fwl/basewidget/fwl_picturebox.h"
+#include "xfa/include/fwl/basewidget/fwl_pushbutton.h"
+#include "xfa/include/fwl/basewidget/fwl_scrollbar.h"
+
+CXFA_FFWidget* XFA_ThemeGetOuterWidget(IFWL_Widget* pWidget) {
+  IFWL_Widget* pOuter = pWidget;
+  while (pOuter->GetOuter()) {
+    pOuter = pOuter->GetOuter();
+  }
+  if (pOuter) {
+    return (CXFA_FFWidget*)pOuter->GetPrivateData(pOuter);
+  }
+  return NULL;
+}
+CXFA_FWLTheme::CXFA_FWLTheme(CXFA_FFApp* pApp) : m_pApp(pApp) {
+  m_pTextOut = NULL;
+  m_dwCapacity = 0;
+  m_fCapacity = 0;
+  m_pCalendarFont = NULL;
+  m_Rect.Set(0, 0, 0, 0);
+  m_pCheckBoxTP = new CXFA_FWLCheckBoxTP;
+  m_pListBoxTP = new CFWL_ListBoxTP;
+  m_pPictureBoxTP = new CFWL_PictureBoxTP;
+  m_pSrollBarTP = new CFWL_ScrollBarTP;
+  m_pEditTP = new CXFA_FWLEditTP;
+  m_pComboBoxTP = new CFWL_ComboBoxTP;
+  m_pMonthCalendarTP = new CFWL_MonthCalendarTP;
+  m_pDateTimePickerTP = new CFWL_DateTimePickerTP;
+  m_pPushButtonTP = new CFWL_PushButtonTP;
+  m_pCaretTP = new CFWL_CaretTP;
+  m_pBarcodeTP = new CFWL_BarcodeTP;
+  Initialize();
+}
+CXFA_FWLTheme::~CXFA_FWLTheme() {
+  Finalize();
+  delete m_pCheckBoxTP;
+  delete m_pListBoxTP;
+  delete m_pPictureBoxTP;
+  delete m_pSrollBarTP;
+  delete m_pEditTP;
+  delete m_pComboBoxTP;
+  delete m_pMonthCalendarTP;
+  delete m_pDateTimePickerTP;
+  delete m_pPushButtonTP;
+  delete m_pCaretTP;
+  delete m_pBarcodeTP;
+}
+static const FX_WCHAR* g_FWLTheme_CalFonts[] = {
+    L"Arial", L"Courier New", L"DejaVu Sans",
+};
+FWL_ERR CXFA_FWLTheme::Initialize() {
+  m_pTextOut = IFDE_TextOut::Create();
+  for (size_t i = 0; !m_pCalendarFont && i < FX_ArraySize(g_FWLTheme_CalFonts);
+       ++i) {
+    m_pCalendarFont = IFX_Font::LoadFont(g_FWLTheme_CalFonts[i], 0, 0,
+                                         m_pApp->GetFDEFontMgr());
+  }
+  if (!m_pCalendarFont) {
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+    m_pCalendarFont = m_pApp->GetFDEFontMgr()->GetDefFontByCodePage(
+        FX_CODEPAGE_MSWin_WesternEuropean, 0, NULL);
+#else
+    m_pCalendarFont = m_pApp->GetFDEFontMgr()->GetFontByCodePage(
+        FX_CODEPAGE_MSWin_WesternEuropean, 0, NULL);
+#endif
+  }
+
+  FXSYS_assert(NULL != m_pCalendarFont);
+  FWLTHEME_Init();
+  return FWL_ERR_Succeeded;
+}
+FWL_ERR CXFA_FWLTheme::Finalize() {
+  if (m_pTextOut) {
+    m_pTextOut->Release();
+    m_pTextOut = NULL;
+  }
+  if (m_pCalendarFont) {
+    m_pCalendarFont->Release();
+    m_pCalendarFont = NULL;
+  }
+  FWLTHEME_Release();
+  return FWL_ERR_Succeeded;
+}
+FX_BOOL CXFA_FWLTheme::IsValidWidget(IFWL_Widget* pWidget) {
+  return TRUE;
+}
+FX_DWORD CXFA_FWLTheme::GetThemeID(IFWL_Widget* pWidget) {
+  return 0;
+}
+FX_DWORD CXFA_FWLTheme::SetThemeID(IFWL_Widget* pWidget,
+                                   FX_DWORD dwThemeID,
+                                   FX_BOOL bChildren) {
+  return 0;
+}
+FX_BOOL CXFA_FWLTheme::DrawBackground(CFWL_ThemeBackground* pParams) {
+  return GetTheme(pParams->m_pWidget)->DrawBackground(pParams);
+}
+FX_BOOL CXFA_FWLTheme::DrawText(CFWL_ThemeText* pParams) {
+  if (pParams->m_wsText.IsEmpty()) {
+    return FWL_ERR_Indefinite;
+  }
+  if (pParams->m_pWidget->GetClassID() == FWL_CLASSHASH_MonthCalendar) {
+    CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget);
+    if (!pWidget) {
+      return FWL_ERR_Indefinite;
+    }
+    m_pTextOut->SetStyles(pParams->m_dwTTOStyles);
+    m_pTextOut->SetAlignment(pParams->m_iTTOAlign);
+    m_pTextOut->SetFont(m_pCalendarFont);
+    m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize);
+    m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor);
+    if ((pParams->m_iPart == FWL_PART_MCD_DatesIn) &&
+        !(pParams->m_dwStates & FWL_ITEMSTATE_MCD_Flag) &&
+        (pParams->m_dwStates &
+         (FWL_PARTSTATE_MCD_Hovered | FWL_PARTSTATE_MCD_Selected))) {
+      m_pTextOut->SetTextColor(0xFFFFFFFF);
+    }
+    if (pParams->m_iPart == FWL_PART_MCD_Caption) {
+      if (m_pMonthCalendarTP->GetThemeID(pParams->m_pWidget) == 0) {
+        m_pTextOut->SetTextColor(ArgbEncode(0xff, 0, 153, 255));
+      } else {
+        m_pTextOut->SetTextColor(ArgbEncode(0xff, 128, 128, 0));
+      }
+    }
+    CFX_Graphics* pGraphics = pParams->m_pGraphics;
+    CFX_RenderDevice* pRenderDevice = pGraphics->GetRenderDevice();
+    if (!pRenderDevice)
+      return FALSE;
+    m_pTextOut->SetRenderDevice(pRenderDevice);
+    CFX_Matrix mtPart = pParams->m_matrix;
+    CFX_Matrix* pMatrix = pGraphics->GetMatrix();
+    if (pMatrix) {
+      mtPart.Concat(*pMatrix);
+    }
+    m_pTextOut->SetMatrix(mtPart);
+    m_pTextOut->DrawLogicText(pParams->m_wsText, pParams->m_wsText.GetLength(),
+                              pParams->m_rtPart);
+    return TRUE;
+  }
+  CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget);
+  if (!pWidget) {
+    return FWL_ERR_Indefinite;
+  }
+  CXFA_WidgetAcc* pAcc = pWidget->GetDataAcc();
+  CFX_Graphics* pGraphics = pParams->m_pGraphics;
+  CFX_RenderDevice* pRenderDevice = pGraphics->GetRenderDevice();
+  if (!pRenderDevice)
+    return FALSE;
+  m_pTextOut->SetRenderDevice(pRenderDevice);
+  m_pTextOut->SetStyles(pParams->m_dwTTOStyles);
+  m_pTextOut->SetAlignment(pParams->m_iTTOAlign);
+  m_pTextOut->SetFont(pAcc->GetFDEFont());
+  m_pTextOut->SetFontSize(pAcc->GetFontSize());
+  m_pTextOut->SetTextColor(pAcc->GetTextColor());
+  CFX_Matrix mtPart = pParams->m_matrix;
+  CFX_Matrix* pMatrix = pGraphics->GetMatrix();
+  if (pMatrix) {
+    mtPart.Concat(*pMatrix);
+  }
+  m_pTextOut->SetMatrix(mtPart);
+  m_pTextOut->DrawLogicText(pParams->m_wsText, pParams->m_wsText.GetLength(),
+                            pParams->m_rtPart);
+  return TRUE;
+}
+void* CXFA_FWLTheme::GetCapacity(CFWL_ThemePart* pThemePart,
+                                 FX_DWORD dwCapacity) {
+  switch (dwCapacity) {
+    case FWL_WGTCAPACITY_Font: {
+      if (CXFA_FFWidget* pWidget =
+              XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) {
+        return pWidget->GetDataAcc()->GetFDEFont();
+      }
+    } break;
+    case FWL_WGTCAPACITY_FontSize: {
+      if (CXFA_FFWidget* pWidget =
+              XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) {
+        m_fCapacity = pWidget->GetDataAcc()->GetFontSize();
+        return &m_fCapacity;
+      }
+    } break;
+    case FWL_WGTCAPACITY_TextColor: {
+      if (CXFA_FFWidget* pWidget =
+              XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) {
+        m_dwCapacity = pWidget->GetDataAcc()->GetTextColor();
+        return &m_dwCapacity;
+      }
+    } break;
+    case FWL_WGTCAPACITY_LineHeight: {
+      if (CXFA_FFWidget* pWidget =
+              XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) {
+        m_fCapacity = pWidget->GetDataAcc()->GetLineHeight();
+        return &m_fCapacity;
+      }
+    } break;
+    case FWL_WGTCAPACITY_ScrollBarWidth: {
+      m_fCapacity = 9;
+      return &m_fCapacity;
+    } break;
+    case FWL_WGTCAPACITY_UIMargin: {
+      CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget);
+      if (pWidget) {
+        CXFA_LayoutItem* pItem = pWidget;
+        CXFA_WidgetAcc* pWidgetAcc = pWidget->GetDataAcc();
+        pWidgetAcc->GetUIMargin(m_Rect);
+        if (CXFA_Para para = pWidgetAcc->GetPara()) {
+          m_Rect.left += para.GetMarginLeft();
+          if (pWidgetAcc->IsMultiLine()) {
+            m_Rect.width += para.GetMarginRight();
+          }
+        }
+        if (pItem->GetPrev() == NULL) {
+          if (pItem->GetNext()) {
+            m_Rect.height = 0;
+          }
+        } else if (pItem->GetNext() == NULL) {
+          m_Rect.top = 0;
+        } else {
+          m_Rect.top = 0;
+          m_Rect.height = 0;
+        }
+      }
+      return &m_Rect;
+    } break;
+    case FWL_WGTCAPACITY_SpaceAboveBelow: {
+      CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget);
+      if (pWidget) {
+        CXFA_WidgetAcc* pWidgetAcc = pWidget->GetDataAcc();
+        if (CXFA_Para para = pWidgetAcc->GetPara()) {
+          m_SizeAboveBelow.x = para.GetSpaceAbove();
+          m_SizeAboveBelow.y = para.GetSpaceBelow();
+        }
+      }
+      return &m_SizeAboveBelow;
+    } break;
+    default:
+      break;
+  }
+  if (pThemePart->m_pWidget->GetClassID() == FWL_CLASSHASH_MonthCalendar &&
+      dwCapacity >= FWL_MCCAPACITY_Sun && dwCapacity <= FWL_MCCAPACITY_Today) {
+    if (CXFA_FFWidget* pWidget =
+            XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) {
+      IXFA_AppProvider* pAppProvider = pWidget->GetAppProvider();
+      m_wsResource.Empty();
+      pAppProvider->LoadString(
+          XFA_IDS_StringWeekDay_Sun + dwCapacity - FWL_WGTCAPACITY_MAX - 5,
+          m_wsResource);
+      if (!m_wsResource.IsEmpty()) {
+        return &m_wsResource;
+      }
+    }
+  }
+  return GetTheme(pThemePart->m_pWidget)->GetCapacity(pThemePart, dwCapacity);
+}
+FX_BOOL CXFA_FWLTheme::IsCustomizedLayout(IFWL_Widget* pWidget) {
+  return GetTheme(pWidget)->IsCustomizedLayout(pWidget);
+}
+FWL_ERR CXFA_FWLTheme::GetPartRect(CFWL_ThemePart* pThemePart) {
+  CFX_RectF rect;
+  return GetTheme(pThemePart->m_pWidget)->GetPartRect(pThemePart, rect);
+}
+FX_BOOL CXFA_FWLTheme::IsInPart(CFWL_ThemePart* pThemePart,
+                                FX_FLOAT fx,
+                                FX_FLOAT fy) {
+  return GetTheme(pThemePart->m_pWidget)->IsInPart(pThemePart, fx, fy);
+}
+FX_BOOL CXFA_FWLTheme::CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect) {
+  if (pParams->m_pWidget->GetClassID() == FWL_CLASSHASH_MonthCalendar) {
+    CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget);
+    if (!pWidget) {
+      return FWL_ERR_Indefinite;
+    }
+    if (!pParams)
+      return FALSE;
+    if (!m_pTextOut)
+      return FALSE;
+    m_pTextOut->SetFont(m_pCalendarFont);
+    m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize);
+    m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor);
+    m_pTextOut->SetAlignment(pParams->m_iTTOAlign);
+    m_pTextOut->SetStyles(pParams->m_dwTTOStyles);
+    m_pTextOut->CalcLogicSize(pParams->m_wsText, pParams->m_wsText.GetLength(),
+                              rect);
+    return TRUE;
+  }
+  CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget);
+  if (!pWidget) {
+    return FWL_ERR_Indefinite;
+  }
+  CXFA_WidgetAcc* pAcc = pWidget->GetDataAcc();
+  m_pTextOut->SetFont(pAcc->GetFDEFont());
+  m_pTextOut->SetFontSize(pAcc->GetFontSize());
+  m_pTextOut->SetTextColor(pAcc->GetTextColor());
+  if (!pParams)
+    return FALSE;
+  if (!m_pTextOut)
+    return FALSE;
+  m_pTextOut->SetAlignment(pParams->m_iTTOAlign);
+  m_pTextOut->SetStyles(pParams->m_dwTTOStyles);
+  m_pTextOut->CalcLogicSize(pParams->m_wsText, pParams->m_wsText.GetLength(),
+                            rect);
+  return TRUE;
+}
+CFWL_WidgetTP* CXFA_FWLTheme::GetTheme(IFWL_Widget* pWidget) {
+  switch (pWidget->GetClassID()) {
+    case FWL_CLASSHASH_CheckBox:
+      return m_pCheckBoxTP;
+    case FWL_CLASSHASH_ListBox:
+      return m_pListBoxTP;
+    case FWL_CLASSHASH_PictureBox:
+      return m_pPictureBoxTP;
+    case FWL_CLASSHASH_ScrollBar:
+      return m_pSrollBarTP;
+    case FWL_CLASSHASH_Edit:
+      return m_pEditTP;
+    case FWL_CLASSHASH_ComboBox:
+      return m_pComboBoxTP;
+    case FWL_CLASSHASH_MonthCalendar:
+      return m_pMonthCalendarTP;
+    case FWL_CLASSHASH_DateTimePicker:
+      return m_pDateTimePickerTP;
+    case FWL_CLASSHASH_PushButton:
+      return m_pPushButtonTP;
+    case FWL_CLASSHASH_Caret:
+      return m_pCaretTP;
+    case FWL_CLASSHASH_Barcode:
+      return m_pBarcodeTP;
+    default:
+      break;
+  }
+  return NULL;
+}
+CXFA_FWLCheckBoxTP::CXFA_FWLCheckBoxTP() {}
+FX_BOOL CXFA_FWLCheckBoxTP::DrawBackground(CFWL_ThemeBackground* pParams) {
+  if (pParams->m_iPart != FWL_PART_CKB_CheckBox) {
+    return TRUE;
+  }
+  if (((pParams->m_dwStates & FWL_PARTSTATE_CKB_Mask2) ==
+       FWL_PARTSTATE_CKB_Checked) ||
+      ((pParams->m_dwStates & FWL_PARTSTATE_CKB_Mask2) ==
+       FWL_PARTSTATE_CKB_Neutral)) {
+    DrawCheckSign(pParams->m_pWidget, pParams->m_pGraphics, &pParams->m_rtPart,
+                  pParams->m_dwStates, &pParams->m_matrix);
+  }
+  return TRUE;
+}
+void CXFA_FWLCheckBoxTP::DrawCheckSign(IFWL_Widget* pWidget,
+                                       CFX_Graphics* pGraphics,
+                                       const CFX_RectF* pRtBox,
+                                       int32_t iState,
+                                       CFX_Matrix* pMatrix) {
+  CFX_RectF rtSign(*pRtBox);
+  FX_DWORD dwColor = 0xFF000000;
+  if ((iState & FWL_PARTSTATE_CKB_Mask2) == FWL_PARTSTATE_CKB_Neutral) {
+    dwColor = 0xFFA9A9A9;
+  }
+  {
+    FX_DWORD dwStyle = pWidget->GetStylesEx();
+    rtSign.Deflate(rtSign.width / 4, rtSign.height / 4);
+    switch (dwStyle & FWL_STYLEEXT_CKB_SignShapeMask) {
+      case FWL_STYLEEXT_CKB_SignShapeCheck:
+        DrawSignCheck(pGraphics, &rtSign, dwColor, pMatrix);
+        break;
+      case FWL_STYLEEXT_CKB_SignShapeCircle:
+        DrawSignCircle(pGraphics, &rtSign, dwColor, pMatrix);
+        break;
+      case FWL_STYLEEXT_CKB_SignShapeCross:
+        DrawSignCross(pGraphics, &rtSign, dwColor, pMatrix);
+        break;
+      case FWL_STYLEEXT_CKB_SignShapeDiamond:
+        DrawSignDiamond(pGraphics, &rtSign, dwColor, pMatrix);
+        break;
+      case FWL_STYLEEXT_CKB_SignShapeSquare:
+        DrawSignSquare(pGraphics, &rtSign, dwColor, pMatrix);
+        break;
+      case FWL_STYLEEXT_CKB_SignShapeStar:
+        DrawSignStar(pGraphics, &rtSign, dwColor, pMatrix);
+        break;
+      default:
+        break;
+    }
+  }
+}
+CXFA_FWLEditTP::CXFA_FWLEditTP() {}
+CXFA_FWLEditTP::~CXFA_FWLEditTP() {}
+FX_BOOL CXFA_FWLEditTP::DrawBackground(CFWL_ThemeBackground* pParams) {
+  if (FWL_PART_EDT_CombTextLine == pParams->m_iPart) {
+    CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget);
+    FX_ARGB cr = 0xFF000000;
+    FX_FLOAT fWidth = 1.0f;
+    if (CXFA_Border borderUI = pWidget->GetDataAcc()->GetUIBorder()) {
+      CXFA_Edge edge = borderUI.GetEdge(0);
+      if (edge) {
+        cr = edge.GetColor();
+        fWidth = edge.GetThickness();
+      }
+    }
+    CFX_Color crLine(cr);
+    pParams->m_pGraphics->SetStrokeColor(&crLine);
+    pParams->m_pGraphics->SetLineWidth(fWidth);
+    pParams->m_pGraphics->StrokePath(pParams->m_pPath, &pParams->m_matrix);
+    return TRUE;
+  }
+  return CFWL_EditTP::DrawBackground(pParams);
+}
diff --git a/xfa/fxfa/app/xfa_fwltheme.h b/xfa/fxfa/app/xfa_fwltheme.h
new file mode 100644
index 0000000..aab8099
--- /dev/null
+++ b/xfa/fxfa/app/xfa_fwltheme.h
@@ -0,0 +1,110 @@
+// 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_FXFA_APP_XFA_FWLTHEME_H_
+#define XFA_FXFA_APP_XFA_FWLTHEME_H_
+
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/include/fwl/core/fwl_target.h"
+#include "xfa/include/fwl/core/fwl_theme.h"
+#include "xfa/include/fwl/theme/barcodetp.h"
+#include "xfa/include/fwl/theme/carettp.h"
+#include "xfa/include/fwl/theme/checkboxtp.h"
+#include "xfa/include/fwl/theme/comboboxtp.h"
+#include "xfa/include/fwl/theme/datetimepickertp.h"
+#include "xfa/include/fwl/theme/edittp.h"
+#include "xfa/include/fwl/theme/listboxtp.h"
+#include "xfa/include/fwl/theme/monthcalendartp.h"
+#include "xfa/include/fwl/theme/pictureboxtp.h"
+#include "xfa/include/fwl/theme/pushbuttontp.h"
+#include "xfa/include/fwl/theme/scrollbartp.h"
+#include "xfa/include/fwl/theme/widgettp.h"
+
+class CXFA_FWLTheme : public IFWL_ThemeProvider {
+ public:
+  CXFA_FWLTheme(CXFA_FFApp* pApp);
+  virtual ~CXFA_FWLTheme();
+  virtual FWL_ERR Release() {
+    delete this;
+    return FWL_ERR_Succeeded;
+  }
+  virtual IFWL_Target* Retain() { return NULL; }
+  virtual FWL_ERR GetClassName(CFX_WideString& wsClass) const {
+    return FWL_ERR_Succeeded;
+  }
+  virtual FX_DWORD GetHashCode() const { return 0; }
+  virtual FWL_ERR Initialize();
+  virtual FWL_ERR Finalize();
+  virtual FX_BOOL IsValidWidget(IFWL_Widget* pWidget);
+  virtual FX_DWORD GetThemeID(IFWL_Widget* pWidget);
+  virtual FX_DWORD SetThemeID(IFWL_Widget* pWidget,
+                              FX_DWORD dwThemeID,
+                              FX_BOOL bChildren = TRUE);
+  virtual FX_BOOL DrawBackground(CFWL_ThemeBackground* pParams);
+  virtual FX_BOOL DrawText(CFWL_ThemeText* pParams);
+  virtual void* GetCapacity(CFWL_ThemePart* pThemePart, FX_DWORD dwCapacity);
+  virtual FX_BOOL IsCustomizedLayout(IFWL_Widget* pWidget);
+  virtual FWL_ERR GetPartRect(CFWL_ThemePart* pThemePart);
+  virtual FX_BOOL IsInPart(CFWL_ThemePart* pThemePart,
+                           FX_FLOAT fx,
+                           FX_FLOAT fy);
+
+  virtual FX_BOOL CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect);
+  virtual FWL_ERR GetThemeMatrix(IFWL_Widget* pWidget, CFX_Matrix& matrix) {
+    return FWL_ERR_Succeeded;
+  }
+  virtual FWL_ERR SetThemeMatrix(IFWL_Widget* pWidget,
+                                 const CFX_Matrix& matrix) {
+    return FWL_ERR_Succeeded;
+  }
+  virtual FWL_ERR GetPartRect(CFWL_ThemePart* pThemePart, CFX_RectF& rtPart) {
+    return FWL_ERR_Succeeded;
+  }
+
+ protected:
+  CFWL_WidgetTP* GetTheme(IFWL_Widget* pWidget);
+  CFWL_CheckBoxTP* m_pCheckBoxTP;
+  CFWL_ListBoxTP* m_pListBoxTP;
+  CFWL_PictureBoxTP* m_pPictureBoxTP;
+  CFWL_ScrollBarTP* m_pSrollBarTP;
+  CFWL_EditTP* m_pEditTP;
+  CFWL_ComboBoxTP* m_pComboBoxTP;
+  CFWL_MonthCalendarTP* m_pMonthCalendarTP;
+  CFWL_DateTimePickerTP* m_pDateTimePickerTP;
+  CFWL_PushButtonTP* m_pPushButtonTP;
+  CFWL_CaretTP* m_pCaretTP;
+  CFWL_BarcodeTP* m_pBarcodeTP;
+  IFDE_TextOut* m_pTextOut;
+  FX_FLOAT m_fCapacity;
+  FX_DWORD m_dwCapacity;
+  IFX_Font* m_pCalendarFont;
+  CFX_WideString m_wsResource;
+  CXFA_FFApp* m_pApp;
+  CFX_RectF m_Rect;
+  CFX_SizeF m_SizeAboveBelow;
+};
+class CXFA_FWLCheckBoxTP : public CFWL_CheckBoxTP {
+ public:
+  CXFA_FWLCheckBoxTP();
+  virtual FX_BOOL DrawBackground(CFWL_ThemeBackground* pParams);
+
+ protected:
+  void DrawCheckSign(IFWL_Widget* pWidget,
+                     CFX_Graphics* pGraphics,
+                     const CFX_RectF* pRtBox,
+                     int32_t iState,
+                     CFX_Matrix* pMatrix);
+};
+class CXFA_FWLEditTP : public CFWL_EditTP {
+ public:
+  CXFA_FWLEditTP();
+  virtual ~CXFA_FWLEditTP();
+
+ public:
+  virtual FX_BOOL DrawBackground(CFWL_ThemeBackground* pParams);
+};
+
+#endif  // XFA_FXFA_APP_XFA_FWLTHEME_H_
diff --git a/xfa/fxfa/app/xfa_rendercontext.cpp b/xfa/fxfa/app/xfa_rendercontext.cpp
new file mode 100644
index 0000000..5b5cf48
--- /dev/null
+++ b/xfa/fxfa/app/xfa_rendercontext.cpp
@@ -0,0 +1,77 @@
+// 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/fxfa/app/xfa_rendercontext.h"
+
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/include/fxgraphics/fx_graphics.h"
+
+#define XFA_RENDERCONTEXT_MaxCount 30
+
+IXFA_RenderContext* XFA_RenderContext_Create() {
+  return new CXFA_RenderContext;
+}
+CXFA_RenderContext::CXFA_RenderContext() {
+  m_pWidgetIterator = NULL;
+  m_pWidget = NULL;
+  m_pPageView = NULL;
+  m_pGS = NULL;
+  m_dwStatus = 0;
+  m_matrix.SetIdentity();
+  m_rtClipRect.Reset();
+}
+CXFA_RenderContext::~CXFA_RenderContext() {
+  StopRender();
+}
+int32_t CXFA_RenderContext::StartRender(IXFA_PageView* pPageView,
+                                        CFX_Graphics* pGS,
+                                        const CFX_Matrix& matrix,
+                                        const CXFA_RenderOptions& options) {
+  m_pPageView = pPageView;
+  m_pGS = pGS;
+  m_matrix = matrix;
+  m_options = options;
+  CFX_RectF rtPage;
+  pGS->GetClipRect(rtPage);
+  CFX_Matrix mtRes;
+  mtRes.SetReverse(matrix);
+  m_rtClipRect.Set(rtPage.left, rtPage.top, rtPage.width, rtPage.height);
+  mtRes.TransformRect(m_rtClipRect);
+  m_dwStatus = m_options.m_bHighlight ? XFA_WIDGETSTATUS_Highlight : 0;
+  FX_DWORD dwFilterType = XFA_WIDGETFILTER_Visible | XFA_WIDGETFILTER_AllType |
+                          (m_options.m_bPrint ? XFA_WIDGETSTATUS_Printable
+                                              : XFA_WIDGETSTATUS_Viewable);
+  m_pWidgetIterator =
+      m_pPageView->CreateWidgetIterator(XFA_TRAVERSEWAY_Form, dwFilterType);
+  m_pWidget = m_pWidgetIterator->MoveToNext();
+  return XFA_RENDERSTATUS_Ready;
+}
+int32_t CXFA_RenderContext::DoRender(IFX_Pause* pPause) {
+  int32_t iCount = 0;
+  while (m_pWidget) {
+    CXFA_FFWidget* pWidget = (CXFA_FFWidget*)m_pWidget;
+    CFX_RectF rtWidgetBox;
+    pWidget->GetBBox(rtWidgetBox, XFA_WIDGETSTATUS_Visible);
+    rtWidgetBox.width += 1;
+    rtWidgetBox.height += 1;
+    if (rtWidgetBox.IntersectWith(m_rtClipRect)) {
+      pWidget->RenderWidget(m_pGS, &m_matrix, m_dwStatus);
+    }
+    m_pWidget = m_pWidgetIterator->MoveToNext();
+    iCount++;
+    if (iCount > XFA_RENDERCONTEXT_MaxCount && pPause &&
+        pPause->NeedToPauseNow()) {
+      return XFA_RENDERSTATUS_ToBeContinued;
+    }
+  }
+  return XFA_RENDERSTATUS_Done;
+}
+void CXFA_RenderContext::StopRender() {
+  if (m_pWidgetIterator) {
+    m_pWidgetIterator->Release();
+    m_pWidgetIterator = NULL;
+  }
+}
diff --git a/xfa/fxfa/app/xfa_rendercontext.h b/xfa/fxfa/app/xfa_rendercontext.h
new file mode 100644
index 0000000..ef4b306
--- /dev/null
+++ b/xfa/fxfa/app/xfa_rendercontext.h
@@ -0,0 +1,35 @@
+// 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_FXFA_APP_XFA_RENDERCONTEXT_H_
+#define XFA_FXFA_APP_XFA_RENDERCONTEXT_H_
+
+#include "xfa/include/fxfa/fxfa.h"
+
+class CXFA_RenderContext : public IXFA_RenderContext {
+ public:
+  CXFA_RenderContext();
+  virtual ~CXFA_RenderContext();
+  virtual void Release() { delete this; }
+  virtual int32_t StartRender(IXFA_PageView* pPageView,
+                              CFX_Graphics* pGS,
+                              const CFX_Matrix& matrix,
+                              const CXFA_RenderOptions& options);
+  virtual int32_t DoRender(IFX_Pause* pPause = NULL);
+  virtual void StopRender();
+
+ protected:
+  IXFA_WidgetIterator* m_pWidgetIterator;
+  IXFA_Widget* m_pWidget;
+  IXFA_PageView* m_pPageView;
+  CFX_Graphics* m_pGS;
+  CFX_Matrix m_matrix;
+  CXFA_RenderOptions m_options;
+  FX_DWORD m_dwStatus;
+  CFX_RectF m_rtClipRect;
+};
+
+#endif  // XFA_FXFA_APP_XFA_RENDERCONTEXT_H_
diff --git a/xfa/fxfa/app/xfa_textlayout.cpp b/xfa/fxfa/app/xfa_textlayout.cpp
new file mode 100644
index 0000000..05316f8
--- /dev/null
+++ b/xfa/fxfa/app/xfa_textlayout.cpp
@@ -0,0 +1,2001 @@
+// 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/fxfa/app/xfa_textlayout.h"
+
+#include <algorithm>
+
+#include "core/include/fxcrt/fx_ext.h"
+#include "xfa/fde/fde_pen.h"
+#include "xfa/fgas/crt/fgas_algorithm.h"
+#include "xfa/fgas/crt/fgas_codepage.h"
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/app/xfa_fontmgr.h"
+
+CXFA_CSSTagProvider::~CXFA_CSSTagProvider() {
+  FX_POSITION pos = m_Attributes.GetStartPosition();
+  while (pos) {
+    CFX_WideString *pName = NULL, *pValue = NULL;
+    m_Attributes.GetNextAssoc(pos, (void*&)pName, (void*&)pValue);
+    delete pName;
+    delete pValue;
+  }
+}
+void CXFA_CSSTagProvider::GetNextAttribute(FX_POSITION& pos,
+                                           CFX_WideStringC& wsAttr,
+                                           CFX_WideStringC& wsValue) {
+  if (pos == NULL) {
+    return;
+  }
+  CFX_WideString* pName = NULL;
+  CFX_WideString* pValue = NULL;
+  m_Attributes.GetNextAssoc(pos, (void*&)pName, (void*&)pValue);
+  wsAttr = *pName;
+  wsValue = *pValue;
+}
+void CXFA_CSSTagProvider::SetAttribute(const CFX_WideString& wsAttr,
+                                       const CFX_WideString& wsValue) {
+  CFX_WideString* pName = new CFX_WideString();
+  CFX_WideString* pValue = new CFX_WideString();
+  *pName = wsAttr;
+  *pValue = wsValue;
+  m_Attributes.SetAt(pName, pValue);
+}
+void CXFA_TextParseContext::SetDecls(const IFDE_CSSDeclaration** ppDeclArray,
+                                     int32_t iDeclCount) {
+  if (iDeclCount <= 0 || ppDeclArray == NULL) {
+    return;
+  }
+  m_dwMatchedDecls = iDeclCount;
+  m_ppMatchedDecls = FX_Alloc(IFDE_CSSDeclaration*, iDeclCount);
+  FXSYS_memcpy(m_ppMatchedDecls, ppDeclArray,
+               iDeclCount * sizeof(IFDE_CSSDeclaration*));
+}
+CXFA_TextParser::~CXFA_TextParser() {
+  if (m_pUASheet)
+    m_pUASheet->Release();
+  if (m_pSelector)
+    m_pSelector->Release();
+  if (m_pAllocator)
+    m_pAllocator->Release();
+  FX_POSITION ps = m_mapXMLNodeToParseContext.GetStartPosition();
+  while (ps) {
+    IFDE_XMLNode* pXMLNode;
+    CXFA_TextParseContext* pParseContext;
+    m_mapXMLNodeToParseContext.GetNextAssoc(ps, pXMLNode, pParseContext);
+    if (pParseContext)
+      FXTARGET_DeleteWith(CXFA_TextParseContext, m_pAllocator, pParseContext);
+  }
+  m_mapXMLNodeToParseContext.RemoveAll();
+}
+void CXFA_TextParser::Reset() {
+  FX_POSITION ps = m_mapXMLNodeToParseContext.GetStartPosition();
+  while (ps) {
+    IFDE_XMLNode* pXMLNode;
+    CXFA_TextParseContext* pParseContext;
+    m_mapXMLNodeToParseContext.GetNextAssoc(ps, pXMLNode, pParseContext);
+    if (pParseContext)
+      FXTARGET_DeleteWith(CXFA_TextParseContext, m_pAllocator, pParseContext);
+  }
+  m_mapXMLNodeToParseContext.RemoveAll();
+  if (m_pAllocator) {
+    m_pAllocator->Release();
+    m_pAllocator = NULL;
+  }
+}
+void CXFA_TextParser::InitCSSData(IXFA_TextProvider* pTextProvider) {
+  if (pTextProvider == NULL) {
+    return;
+  }
+  if (m_pSelector == NULL) {
+    CXFA_FFDoc* pDoc = pTextProvider->GetDocNode();
+    IFX_FontMgr* pFontMgr = pDoc->GetApp()->GetFDEFontMgr();
+    FXSYS_assert(pFontMgr);
+    m_pSelector = IFDE_CSSStyleSelector::Create();
+    m_pSelector->SetFontMgr(pFontMgr);
+    FX_FLOAT fFontSize = 10;
+    CXFA_Font font = pTextProvider->GetFontNode();
+    if (font) {
+      fFontSize = font.GetFontSize();
+    }
+    m_pSelector->SetDefFontSize(fFontSize);
+  }
+  if (m_pUASheet == NULL) {
+    m_pUASheet = LoadDefaultSheetStyle();
+    m_pSelector->SetStyleSheet(FDE_CSSSTYLESHEETGROUP_UserAgent, m_pUASheet);
+    m_pSelector->UpdateStyleIndex(FDE_CSSMEDIATYPE_ALL);
+  }
+}
+IFDE_CSSStyleSheet* CXFA_TextParser::LoadDefaultSheetStyle() {
+  static const FX_WCHAR s_pStyle[] =
+      L"html,body,ol,p,ul{display:block}"
+      L"li{display:list-item}"
+      L"ol,ul{padding-left:33px}ol{list-style-type:decimal}ol,ul{margin-top:0;"
+      L"margin-bottom:0}ul,ol{margin:1.12em 0}"
+      L"a{color:#0000ff;text-decoration:underline}b{font-weight:bolder}i{font-"
+      L"style:italic}"
+      L"sup{vertical-align:+15em;font-size:.66em}sub{vertical-align:-15em;font-"
+      L"size:.66em}";
+  return IFDE_CSSStyleSheet::LoadFromBuffer(
+      CFX_WideString(), s_pStyle, FXSYS_wcslen(s_pStyle), FX_CODEPAGE_UTF8);
+}
+IFDE_CSSComputedStyle* CXFA_TextParser::CreateRootStyle(
+    IXFA_TextProvider* pTextProvider) {
+  CXFA_Font font = pTextProvider->GetFontNode();
+  CXFA_Para para = pTextProvider->GetParaNode();
+  IFDE_CSSComputedStyle* pStyle = m_pSelector->CreateComputedStyle(NULL);
+  IFDE_CSSFontStyle* pFontStyle = pStyle->GetFontStyles();
+  IFDE_CSSParagraphStyle* pParaStyle = pStyle->GetParagraphStyles();
+  FX_FLOAT fLineHeight = 0, fFontSize = 10;
+  if (para) {
+    fLineHeight = para.GetLineHeight();
+    FDE_CSSLENGTH indent;
+    indent.Set(FDE_CSSLENGTHUNIT_Point, para.GetTextIndent());
+    pParaStyle->SetTextIndent(indent);
+    FDE_CSSTEXTALIGN hAlgin = FDE_CSSTEXTALIGN_Left;
+    switch (para.GetHorizontalAlign()) {
+      case XFA_ATTRIBUTEENUM_Center:
+        hAlgin = FDE_CSSTEXTALIGN_Center;
+        break;
+      case XFA_ATTRIBUTEENUM_Right:
+        hAlgin = FDE_CSSTEXTALIGN_Right;
+        break;
+      case XFA_ATTRIBUTEENUM_Justify:
+        hAlgin = FDE_CSSTEXTALIGN_Justify;
+        break;
+      case XFA_ATTRIBUTEENUM_JustifyAll:
+        hAlgin = FDE_CSSTEXTALIGN_JustifyAll;
+        break;
+    }
+    pParaStyle->SetTextAlign(hAlgin);
+    FDE_CSSRECT rtMarginWidth;
+    rtMarginWidth.left.Set(FDE_CSSLENGTHUNIT_Point, para.GetMarginLeft());
+    rtMarginWidth.top.Set(FDE_CSSLENGTHUNIT_Point, para.GetSpaceAbove());
+    rtMarginWidth.right.Set(FDE_CSSLENGTHUNIT_Point, para.GetMarginRight());
+    rtMarginWidth.bottom.Set(FDE_CSSLENGTHUNIT_Point, para.GetSpaceBelow());
+    pStyle->GetBoundaryStyles()->SetMarginWidth(rtMarginWidth);
+  }
+  if (font) {
+    pFontStyle->SetColor(font.GetColor());
+    pFontStyle->SetFontStyle(font.IsItalic() ? FDE_CSSFONTSTYLE_Italic
+                                             : FDE_CSSFONTSTYLE_Normal);
+    pFontStyle->SetFontWeight(font.IsBold() ? FXFONT_FW_BOLD
+                                            : FXFONT_FW_NORMAL);
+    pParaStyle->SetNumberVerticalAlign(-font.GetBaselineShift());
+    fFontSize = font.GetFontSize();
+    FDE_CSSLENGTH letterSpacing;
+    letterSpacing.Set(FDE_CSSLENGTHUNIT_Point, font.GetLetterSpacing());
+    pParaStyle->SetLetterSpacing(letterSpacing);
+    FX_DWORD dwDecoration = 0;
+    if (font.GetLineThrough() > 0) {
+      dwDecoration |= FDE_CSSTEXTDECORATION_LineThrough;
+    }
+    if (font.GetUnderline() > 1) {
+      dwDecoration |= FDE_CSSTEXTDECORATION_Double;
+    } else if (font.GetUnderline() > 0) {
+      dwDecoration |= FDE_CSSTEXTDECORATION_Underline;
+    }
+    pParaStyle->SetTextDecoration(dwDecoration);
+  }
+  pParaStyle->SetLineHeight(fLineHeight);
+  pFontStyle->SetFontSize(fFontSize);
+  return pStyle;
+}
+IFDE_CSSComputedStyle* CXFA_TextParser::CreateStyle(
+    IFDE_CSSComputedStyle* pParentStyle) {
+  IFDE_CSSComputedStyle* pNewStyle =
+      m_pSelector->CreateComputedStyle(pParentStyle);
+  FXSYS_assert(pNewStyle);
+  if (pParentStyle) {
+    IFDE_CSSParagraphStyle* pParaStyle = pParentStyle->GetParagraphStyles();
+    FX_DWORD dwDecoration = pParaStyle->GetTextDecoration();
+    FX_FLOAT fBaseLine = 0;
+    if (pParaStyle->GetVerticalAlign() == FDE_CSSVERTICALALIGN_Number) {
+      fBaseLine = pParaStyle->GetNumberVerticalAlign();
+    }
+    pParaStyle = pNewStyle->GetParagraphStyles();
+    pParaStyle->SetTextDecoration(dwDecoration);
+    pParaStyle->SetNumberVerticalAlign(fBaseLine);
+    IFDE_CSSBoundaryStyle* pBoundarytyle = pParentStyle->GetBoundaryStyles();
+    const FDE_CSSRECT* pRect = pBoundarytyle->GetMarginWidth();
+    if (pRect) {
+      pBoundarytyle = pNewStyle->GetBoundaryStyles();
+      pBoundarytyle->SetMarginWidth(*pRect);
+    }
+  }
+  return pNewStyle;
+}
+IFDE_CSSComputedStyle* CXFA_TextParser::ComputeStyle(
+    IFDE_XMLNode* pXMLNode,
+    IFDE_CSSComputedStyle* pParentStyle) {
+  CXFA_TextParseContext* pContext = static_cast<CXFA_TextParseContext*>(
+      m_mapXMLNodeToParseContext.GetValueAt(pXMLNode));
+  if (!pContext)
+    return nullptr;
+  pContext->m_pParentStyle = pParentStyle;
+  pParentStyle->AddRef();
+  CXFA_CSSTagProvider tagProvider;
+  ParseTagInfo(pXMLNode, tagProvider);
+  if (tagProvider.m_bContent)
+    return nullptr;
+  IFDE_CSSComputedStyle* pStyle = CreateStyle(pParentStyle);
+  IFDE_CSSAccelerator* pCSSAccel = m_pSelector->InitAccelerator();
+  pCSSAccel->OnEnterTag(&tagProvider);
+  m_pSelector->ComputeStyle(&tagProvider, pContext->GetDecls(),
+                            pContext->CountDecls(), pStyle);
+  pCSSAccel->OnLeaveTag(&tagProvider);
+  return pStyle;
+}
+void CXFA_TextParser::DoParse(IFDE_XMLNode* pXMLContainer,
+                              IXFA_TextProvider* pTextProvider) {
+  if (pXMLContainer == NULL || pTextProvider == NULL || m_pAllocator) {
+    return;
+  }
+  m_pAllocator =
+      FX_CreateAllocator(FX_ALLOCTYPE_Fixed, 32, sizeof(CXFA_CSSTagProvider));
+  InitCSSData(pTextProvider);
+  IFDE_CSSComputedStyle* pRootStyle = CreateRootStyle(pTextProvider);
+  ParseRichText(pXMLContainer, pRootStyle);
+  pRootStyle->Release();
+}
+void CXFA_TextParser::ParseRichText(IFDE_XMLNode* pXMLNode,
+                                    IFDE_CSSComputedStyle* pParentStyle) {
+  if (pXMLNode == NULL) {
+    return;
+  }
+  CXFA_CSSTagProvider tagProvider;
+  ParseTagInfo(pXMLNode, tagProvider);
+  if (!tagProvider.m_bTagAviliable) {
+    return;
+  }
+  IFDE_CSSComputedStyle* pNewStyle = NULL;
+  if ((tagProvider.GetTagName() != FX_WSTRC(L"body")) ||
+      (tagProvider.GetTagName() != FX_WSTRC(L"html"))) {
+    CXFA_TextParseContext* pTextContext =
+        FXTARGET_NewWith(m_pAllocator) CXFA_TextParseContext;
+    FDE_CSSDISPLAY eDisplay = FDE_CSSDISPLAY_Inline;
+    if (!tagProvider.m_bContent) {
+      pNewStyle = CreateStyle(pParentStyle);
+      IFDE_CSSAccelerator* pCSSAccel = m_pSelector->InitAccelerator();
+      pCSSAccel->OnEnterTag(&tagProvider);
+      CFDE_CSSDeclarationArray DeclArray;
+      int32_t iMatchedDecls =
+          m_pSelector->MatchDeclarations(&tagProvider, DeclArray);
+      const IFDE_CSSDeclaration** ppMatchDecls =
+          (const IFDE_CSSDeclaration**)DeclArray.GetData();
+      m_pSelector->ComputeStyle(&tagProvider, ppMatchDecls, iMatchedDecls,
+                                pNewStyle);
+      pCSSAccel->OnLeaveTag(&tagProvider);
+      if (iMatchedDecls > 0) {
+        pTextContext->SetDecls(ppMatchDecls, iMatchedDecls);
+      }
+      eDisplay = pNewStyle->GetPositionStyles()->GetDisplay();
+    }
+    pTextContext->SetDisplay(eDisplay);
+    m_mapXMLNodeToParseContext.SetAt(pXMLNode, pTextContext);
+  }
+  for (IFDE_XMLNode* pXMLChild =
+           pXMLNode->GetNodeItem(IFDE_XMLNode::FirstChild);
+       pXMLChild;
+       pXMLChild = pXMLChild->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+    ParseRichText(pXMLChild, pNewStyle);
+  }
+  if (pNewStyle)
+    pNewStyle->Release();
+}
+void CXFA_TextParser::ParseTagInfo(IFDE_XMLNode* pXMLNode,
+                                   CXFA_CSSTagProvider& tagProvider) {
+  static const FX_DWORD s_XFATagName[] = {
+      0x61,       0x62,       0x69,       0x70,       0x0001f714,
+      0x00022a55, 0x000239bb, 0x00025881, 0x0bd37faa, 0x0bd37fb8,
+      0xa73e3af2, 0xb182eaae, 0xdb8ac455,
+  };
+  CFX_WideString wsName;
+  if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+    IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLNode;
+    pXMLElement->GetLocalTagName(wsName);
+    tagProvider.SetTagNameObj(wsName);
+    FX_DWORD dwHashCode =
+        FX_HashCode_String_GetW(wsName, wsName.GetLength(), TRUE);
+    static const int32_t s_iCount = sizeof(s_XFATagName) / sizeof(FX_DWORD);
+    CFX_DSPATemplate<FX_DWORD> lookup;
+    tagProvider.m_bTagAviliable =
+        lookup.Lookup(dwHashCode, s_XFATagName, s_iCount) > -1;
+    CFX_WideString wsValue;
+    pXMLElement->GetString(FX_WSTRC(L"style").GetPtr(), wsValue);
+    if (!wsValue.IsEmpty()) {
+      tagProvider.SetAttribute(FX_WSTRC(L"style"), wsValue);
+    }
+  } else if (pXMLNode->GetType() == FDE_XMLNODE_Text) {
+    tagProvider.m_bTagAviliable = TRUE;
+    tagProvider.m_bContent = TRUE;
+  }
+}
+int32_t CXFA_TextParser::GetVAlgin(IXFA_TextProvider* pTextProvider) const {
+  int32_t iAlign = XFA_ATTRIBUTEENUM_Top;
+  CXFA_Para para = pTextProvider->GetParaNode();
+  if (para) {
+    iAlign = para.GetVerticalAlign();
+  }
+  return iAlign;
+}
+FX_FLOAT CXFA_TextParser::GetTabInterval(IFDE_CSSComputedStyle* pStyle) const {
+  CFX_WideString wsValue;
+  if (pStyle && pStyle->GetCustomStyle(FX_WSTRC(L"tab-interval"), wsValue)) {
+    CXFA_Measurement ms(wsValue);
+    return ms.ToUnit(XFA_UNIT_Pt);
+  }
+  return 36;
+}
+int32_t CXFA_TextParser::CountTabs(IFDE_CSSComputedStyle* pStyle) const {
+  CFX_WideString wsValue;
+  if (pStyle && pStyle->GetCustomStyle(FX_WSTRC(L"xfa-tab-count"), wsValue)) {
+    return wsValue.GetInteger();
+  }
+  return 0;
+}
+FX_BOOL CXFA_TextParser::IsSpaceRun(IFDE_CSSComputedStyle* pStyle) const {
+  CFX_WideString wsValue;
+  if (pStyle && pStyle->GetCustomStyle(FX_WSTRC(L"xfa-spacerun"), wsValue)) {
+    wsValue.MakeLower();
+    return wsValue == FX_WSTRC(L"yes");
+  }
+  return FALSE;
+}
+IFX_Font* CXFA_TextParser::GetFont(IXFA_TextProvider* pTextProvider,
+                                   IFDE_CSSComputedStyle* pStyle) const {
+  CFX_WideStringC wsFamily = FX_WSTRC(L"Courier");
+  FX_DWORD dwStyle = 0;
+  CXFA_Font font = pTextProvider->GetFontNode();
+  if (font) {
+    font.GetTypeface(wsFamily);
+    if (font.IsBold()) {
+      dwStyle |= FX_FONTSTYLE_Bold;
+    }
+    if (font.IsItalic()) {
+      dwStyle |= FX_FONTSTYLE_Italic;
+    }
+  }
+  if (pStyle) {
+    IFDE_CSSFontStyle* pFontStyle = pStyle->GetFontStyles();
+    int32_t iCount = pFontStyle->CountFontFamilies();
+    if (iCount > 0) {
+      wsFamily = pFontStyle->GetFontFamily(iCount - 1);
+    }
+    dwStyle = 0;
+    if (pFontStyle->GetFontWeight() > FXFONT_FW_NORMAL) {
+      dwStyle |= FX_FONTSTYLE_Bold;
+    }
+    if (pFontStyle->GetFontStyle() == FDE_CSSFONTSTYLE_Italic) {
+      dwStyle |= FX_FONTSTYLE_Italic;
+    }
+  }
+  CXFA_FFDoc* pDoc = pTextProvider->GetDocNode();
+  CXFA_FontMgr* pFontMgr = pDoc->GetApp()->GetXFAFontMgr();
+  return pFontMgr->GetFont(pDoc, wsFamily, dwStyle);
+}
+FX_FLOAT CXFA_TextParser::GetFontSize(IXFA_TextProvider* pTextProvider,
+                                      IFDE_CSSComputedStyle* pStyle) const {
+  if (pStyle)
+    return pStyle->GetFontStyles()->GetFontSize();
+
+  CXFA_Font font = pTextProvider->GetFontNode();
+  if (font) {
+    return font.GetFontSize();
+  }
+  return 10;
+}
+int32_t CXFA_TextParser::GetHorScale(IXFA_TextProvider* pTextProvider,
+                                     IFDE_CSSComputedStyle* pStyle,
+                                     IFDE_XMLNode* pXMLNode) const {
+  if (pStyle) {
+    CFX_WideString wsValue;
+    if (pStyle->GetCustomStyle(FX_WSTRC(L"xfa-font-horizontal-scale"),
+                               wsValue)) {
+      return wsValue.GetInteger();
+    }
+    while (pXMLNode) {
+      CXFA_TextParseContext* pContext = static_cast<CXFA_TextParseContext*>(
+          m_mapXMLNodeToParseContext.GetValueAt(pXMLNode));
+      if (pContext && pContext->m_pParentStyle &&
+          pContext->m_pParentStyle->GetCustomStyle(
+              FX_WSTRC(L"xfa-font-horizontal-scale"), wsValue)) {
+        return wsValue.GetInteger();
+      }
+      pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::Parent);
+    }
+  }
+  if (CXFA_Font font = pTextProvider->GetFontNode()) {
+    return static_cast<int32_t>(font.GetHorizontalScale());
+  }
+  return 100;
+}
+int32_t CXFA_TextParser::GetVerScale(IXFA_TextProvider* pTextProvider,
+                                     IFDE_CSSComputedStyle* pStyle) const {
+  if (pStyle) {
+    CFX_WideString wsValue;
+    if (pStyle->GetCustomStyle(FX_WSTRC(L"xfa-font-vertical-scale"), wsValue)) {
+      return wsValue.GetInteger();
+    }
+  }
+  if (CXFA_Font font = pTextProvider->GetFontNode()) {
+    return (int32_t)font.GetVerticalScale();
+  }
+  return 100;
+}
+void CXFA_TextParser::GetUnderline(IXFA_TextProvider* pTextProvider,
+                                   IFDE_CSSComputedStyle* pStyle,
+                                   int32_t& iUnderline,
+                                   int32_t& iPeriod) const {
+  iUnderline = 0;
+  iPeriod = XFA_ATTRIBUTEENUM_All;
+  if (pStyle) {
+    FX_DWORD dwDecoration = pStyle->GetParagraphStyles()->GetTextDecoration();
+    if (dwDecoration & FDE_CSSTEXTDECORATION_Double) {
+      iUnderline = 2;
+    } else if (dwDecoration & FDE_CSSTEXTDECORATION_Underline) {
+      iUnderline = 1;
+    }
+    CFX_WideString wsValue;
+    if (pStyle->GetCustomStyle(FX_WSTRC(L"underlinePeriod"), wsValue)) {
+      if (wsValue == FX_WSTRC(L"word")) {
+        iPeriod = XFA_ATTRIBUTEENUM_Word;
+      }
+    } else if (CXFA_Font font = pTextProvider->GetFontNode()) {
+      iPeriod = font.GetUnderlinePeriod();
+    }
+  } else {
+    CXFA_Font font = pTextProvider->GetFontNode();
+    if (font) {
+      iUnderline = font.GetUnderline();
+      iPeriod = font.GetUnderlinePeriod();
+    }
+  }
+}
+void CXFA_TextParser::GetLinethrough(IXFA_TextProvider* pTextProvider,
+                                     IFDE_CSSComputedStyle* pStyle,
+                                     int32_t& iLinethrough) const {
+  if (pStyle) {
+    FX_DWORD dwDecoration = pStyle->GetParagraphStyles()->GetTextDecoration();
+    iLinethrough = (dwDecoration & FDE_CSSTEXTDECORATION_LineThrough) ? 1 : 0;
+  } else {
+    CXFA_Font font = pTextProvider->GetFontNode();
+    if (font) {
+      iLinethrough = font.GetLineThrough();
+    }
+  }
+}
+FX_ARGB CXFA_TextParser::GetColor(IXFA_TextProvider* pTextProvider,
+                                  IFDE_CSSComputedStyle* pStyle) const {
+  if (pStyle)
+    return pStyle->GetFontStyles()->GetColor();
+
+  if (CXFA_Font font = pTextProvider->GetFontNode())
+    return font.GetColor();
+
+  return 0xFF000000;
+}
+FX_FLOAT CXFA_TextParser::GetBaseline(IXFA_TextProvider* pTextProvider,
+                                      IFDE_CSSComputedStyle* pStyle) const {
+  if (pStyle) {
+    IFDE_CSSParagraphStyle* pParaStyle = pStyle->GetParagraphStyles();
+    if (pParaStyle->GetVerticalAlign() == FDE_CSSVERTICALALIGN_Number) {
+      return pParaStyle->GetNumberVerticalAlign();
+    }
+  } else if (CXFA_Font font = pTextProvider->GetFontNode()) {
+    return font.GetBaselineShift();
+  }
+  return 0;
+}
+FX_FLOAT CXFA_TextParser::GetLineHeight(IXFA_TextProvider* pTextProvider,
+                                        IFDE_CSSComputedStyle* pStyle,
+                                        FX_BOOL bFirst,
+                                        FX_FLOAT fVerScale) const {
+  FX_FLOAT fLineHeight = 0;
+  if (pStyle) {
+    fLineHeight = pStyle->GetParagraphStyles()->GetLineHeight();
+  } else if (CXFA_Para para = pTextProvider->GetParaNode()) {
+    fLineHeight = para.GetLineHeight();
+  }
+  if (bFirst) {
+    FX_FLOAT fFontSize = GetFontSize(pTextProvider, pStyle);
+    if (fLineHeight < 0.1f) {
+      fLineHeight = fFontSize;
+    } else {
+      fLineHeight = std::min(fLineHeight, fFontSize);
+    }
+  } else if (fLineHeight < 0.1f) {
+    fLineHeight = GetFontSize(pTextProvider, pStyle) * 1.2f;
+  }
+  fLineHeight *= fVerScale;
+  return fLineHeight;
+}
+FX_BOOL CXFA_TextParser::GetEmbbedObj(IXFA_TextProvider* pTextProvider,
+                                      IFDE_XMLNode* pXMLNode,
+                                      CFX_WideString& wsValue) {
+  wsValue.Empty();
+  if (pXMLNode == NULL) {
+    return FALSE;
+  }
+  FX_BOOL bRet = FALSE;
+  if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+    IFDE_XMLElement* pElement = (IFDE_XMLElement*)pXMLNode;
+    CFX_WideString wsAttr;
+    pElement->GetString(FX_WSTRC(L"xfa:embed").GetPtr(), wsAttr);
+    if (wsAttr.IsEmpty()) {
+      return FALSE;
+    }
+    if (wsAttr.GetAt(0) == L'#') {
+      wsAttr.Delete(0);
+    }
+    CFX_WideString ws;
+    pElement->GetString(FX_WSTRC(L"xfa:embedType").GetPtr(), ws);
+    if (ws.IsEmpty()) {
+      ws = L"som";
+    } else {
+      ws.MakeLower();
+    }
+    FX_BOOL bURI = (ws == FX_WSTRC(L"uri"));
+    if (!bURI && ws != FX_WSTRC(L"som")) {
+      return FALSE;
+    }
+    ws.Empty();
+    pElement->GetString(FX_WSTRC(L"xfa:embedMode").GetPtr(), ws);
+    if (ws.IsEmpty()) {
+      ws = L"formatted";
+    } else {
+      ws.MakeLower();
+    }
+    FX_BOOL bRaw = (ws == FX_WSTRC(L"raw"));
+    if (!bRaw && ws != FX_WSTRC(L"formatted")) {
+      return FALSE;
+    }
+    bRet = pTextProvider->GetEmbbedObj(bURI, bRaw, wsAttr, wsValue);
+  }
+  return bRet;
+}
+CXFA_TextParseContext* CXFA_TextParser::GetParseContextFromMap(
+    IFDE_XMLNode* pXMLNode) {
+  return (CXFA_TextParseContext*)m_mapXMLNodeToParseContext.GetValueAt(
+      pXMLNode);
+}
+enum XFA_TABSTOPSSTATUS {
+  XFA_TABSTOPSSTATUS_Error,
+  XFA_TABSTOPSSTATUS_EOS,
+  XFA_TABSTOPSSTATUS_None,
+  XFA_TABSTOPSSTATUS_Alignment,
+  XFA_TABSTOPSSTATUS_StartLeader,
+  XFA_TABSTOPSSTATUS_Leader,
+  XFA_TABSTOPSSTATUS_Location,
+};
+FX_BOOL CXFA_TextParser::GetTabstops(
+    IFDE_CSSComputedStyle* pStyle,
+    CXFA_TextTabstopsContext* pTabstopContext) {
+  if (pStyle == NULL || pTabstopContext == NULL) {
+    return FALSE;
+  }
+  CFX_WideString wsValue;
+  if (!pStyle->GetCustomStyle(FX_WSTRC(L"xfa-tab-stops"), wsValue) &&
+      !pStyle->GetCustomStyle(FX_WSTRC(L"tab-stops"), wsValue)) {
+    return FALSE;
+  }
+  int32_t iLength = wsValue.GetLength();
+  const FX_WCHAR* pTabStops = wsValue;
+  int32_t iCur = 0;
+  int32_t iLast = 0;
+  CFX_WideString wsAlign;
+  XFA_TABSTOPSSTATUS eStatus = XFA_TABSTOPSSTATUS_None;
+  FX_WCHAR ch;
+  while (iCur < iLength) {
+    ch = pTabStops[iCur];
+    switch (eStatus) {
+      case XFA_TABSTOPSSTATUS_None:
+        if (ch <= ' ') {
+          iCur++;
+        } else {
+          eStatus = XFA_TABSTOPSSTATUS_Alignment;
+          iLast = iCur;
+        }
+        break;
+      case XFA_TABSTOPSSTATUS_Alignment:
+        if (ch == ' ') {
+          wsAlign = CFX_WideStringC(pTabStops + iLast, iCur - iLast);
+          eStatus = XFA_TABSTOPSSTATUS_StartLeader;
+          iCur++;
+          while (iCur < iLength && pTabStops[iCur] <= ' ') {
+            iCur++;
+          }
+          iLast = iCur;
+        } else {
+          iCur++;
+        }
+        break;
+      case XFA_TABSTOPSSTATUS_StartLeader:
+        if (ch != 'l') {
+          eStatus = XFA_TABSTOPSSTATUS_Location;
+        } else {
+          int32_t iCount = 0;
+          while (iCur < iLength) {
+            ch = pTabStops[iCur];
+            iCur++;
+            if (ch == '(') {
+              iCount++;
+            } else if (ch == ')') {
+              iCount--;
+              if (iCount == 0) {
+                break;
+              }
+            }
+          }
+          while (iCur < iLength && pTabStops[iCur] <= ' ') {
+            iCur++;
+          }
+          iLast = iCur;
+          eStatus = XFA_TABSTOPSSTATUS_Location;
+        }
+        break;
+      case XFA_TABSTOPSSTATUS_Location:
+        if (ch == ' ') {
+          FX_DWORD dwHashCode =
+              FX_HashCode_String_GetW(wsAlign, wsAlign.GetLength(), TRUE);
+          CXFA_Measurement ms(CFX_WideStringC(pTabStops + iLast, iCur - iLast));
+          FX_FLOAT fPos = ms.ToUnit(XFA_UNIT_Pt);
+          pTabstopContext->Append(dwHashCode, fPos);
+          wsAlign.Empty();
+          eStatus = XFA_TABSTOPSSTATUS_None;
+        }
+        iCur++;
+        break;
+      default:
+        break;
+    }
+  }
+  if (!wsAlign.IsEmpty()) {
+    FX_DWORD dwHashCode =
+        FX_HashCode_String_GetW(wsAlign, wsAlign.GetLength(), TRUE);
+    CXFA_Measurement ms(CFX_WideStringC(pTabStops + iLast, iCur - iLast));
+    FX_FLOAT fPos = ms.ToUnit(XFA_UNIT_Pt);
+    pTabstopContext->Append(dwHashCode, fPos);
+  }
+  return TRUE;
+}
+CXFA_TextLayout::CXFA_TextLayout(IXFA_TextProvider* pTextProvider)
+    : m_bHasBlock(FALSE),
+      m_pTextProvider(pTextProvider),
+      m_pTextDataNode(nullptr),
+      m_bRichText(FALSE),
+      m_pAllocator(nullptr),
+      m_pBreak(nullptr),
+      m_pLoader(nullptr),
+      m_iLines(0),
+      m_fMaxWidth(0),
+      m_pTabstopContext(nullptr),
+      m_bBlockContinue(TRUE) {
+  FXSYS_assert(m_pTextProvider);
+}
+CXFA_TextLayout::~CXFA_TextLayout() {
+  m_textParser.Reset();
+  delete m_pLoader;
+  delete m_pTabstopContext;
+  Unload();
+}
+void CXFA_TextLayout::Unload() {
+  int32_t iCount = m_pieceLines.GetSize();
+  for (int32_t i = 0; i < iCount; i++) {
+    CXFA_PieceLine* pLine = m_pieceLines.GetAt(i);
+    FXTARGET_DeleteWith(CXFA_PieceLine, m_pAllocator, pLine);
+  }
+  m_pieceLines.RemoveAll();
+  if (m_pBreak) {
+    m_pBreak->Release();
+    m_pBreak = NULL;
+  }
+  if (m_pAllocator) {
+    m_pAllocator->Release();
+    m_pAllocator = NULL;
+  }
+}
+const CXFA_PieceLineArray* CXFA_TextLayout::GetPieceLines() {
+  return &m_pieceLines;
+}
+void CXFA_TextLayout::GetTextDataNode() {
+  if (m_pTextProvider == NULL) {
+    return;
+  }
+  CXFA_Node* pNode = m_pTextProvider->GetTextNode(m_bRichText);
+  if (pNode && m_bRichText) {
+    m_textParser.Reset();
+  }
+  m_pTextDataNode = pNode;
+}
+IFDE_XMLNode* CXFA_TextLayout::GetXMLContainerNode() {
+  IFDE_XMLNode* pXMLContainer = NULL;
+  if (m_bRichText) {
+    IFDE_XMLNode* pXMLRoot = m_pTextDataNode->GetXMLMappingNode();
+    if (!pXMLRoot) {
+      return pXMLContainer;
+    }
+    for (IFDE_XMLNode* pXMLChild =
+             pXMLRoot->GetNodeItem(IFDE_XMLNode::FirstChild);
+         pXMLChild;
+         pXMLChild = pXMLChild->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+      if (pXMLChild->GetType() == FDE_XMLNODE_Element) {
+        IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLChild;
+        CFX_WideString wsTag;
+        pXMLElement->GetLocalTagName(wsTag);
+        if (wsTag.Equal(FX_WSTRC(L"body")) || wsTag.Equal(FX_WSTRC(L"html"))) {
+          pXMLContainer = pXMLChild;
+          break;
+        }
+      }
+    }
+  }
+  return pXMLContainer;
+}
+IFX_RTFBreak* CXFA_TextLayout::CreateBreak(FX_BOOL bDefault) {
+  FX_DWORD dwStyle = FX_RTFLAYOUTSTYLE_ExpandTab;
+  if (!bDefault) {
+    dwStyle |= FX_RTFLAYOUTSTYLE_Pagination;
+  }
+  IFX_RTFBreak* pBreak = IFX_RTFBreak::Create(0);
+  pBreak->SetLayoutStyles(dwStyle);
+  pBreak->SetLineBreakChar(L'\n');
+  pBreak->SetLineBreakTolerance(1);
+  pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, NULL));
+  pBreak->SetFontSize(m_textParser.GetFontSize(m_pTextProvider, NULL));
+  return pBreak;
+}
+void CXFA_TextLayout::InitBreak(FX_FLOAT fLineWidth) {
+  CXFA_Font font = m_pTextProvider->GetFontNode();
+  CXFA_Para para = m_pTextProvider->GetParaNode();
+  FX_FLOAT fStart = 0;
+  FX_FLOAT fStartPos = 0;
+  if (para) {
+    int32_t iAlign = FX_RTFLINEALIGNMENT_Left;
+    switch (para.GetHorizontalAlign()) {
+      case XFA_ATTRIBUTEENUM_Center:
+        iAlign = FX_RTFLINEALIGNMENT_Center;
+        break;
+      case XFA_ATTRIBUTEENUM_Right:
+        iAlign = FX_RTFLINEALIGNMENT_Right;
+        break;
+      case XFA_ATTRIBUTEENUM_Justify:
+        iAlign = FX_RTFLINEALIGNMENT_Justified;
+        break;
+      case XFA_ATTRIBUTEENUM_JustifyAll:
+        iAlign = FX_RTFLINEALIGNMENT_Distributed;
+        break;
+    }
+    m_pBreak->SetAlignment(iAlign);
+    fStart = para.GetMarginLeft();
+    if (m_pTextProvider->IsCheckButtonAndAutoWidth()) {
+      if (iAlign != FX_RTFLINEALIGNMENT_Left) {
+        fLineWidth -= para.GetMarginRight();
+      }
+    } else {
+      fLineWidth -= para.GetMarginRight();
+    }
+    if (fLineWidth < 0) {
+      fLineWidth = fStart;
+    }
+    fStartPos = fStart;
+    FX_FLOAT fIndent = para.GetTextIndent();
+    if (fIndent > 0) {
+      fStartPos += fIndent;
+    }
+  }
+  m_pBreak->SetLineBoundary(fStart, fLineWidth);
+  m_pBreak->SetLineStartPos(fStartPos);
+  if (font) {
+    m_pBreak->SetHorizontalScale((int32_t)font.GetHorizontalScale());
+    m_pBreak->SetVerticalScale((int32_t)font.GetVerticalScale());
+    m_pBreak->SetCharSpace(font.GetLetterSpacing());
+  }
+  FX_FLOAT fFontSize = m_textParser.GetFontSize(m_pTextProvider, NULL);
+  m_pBreak->SetFontSize(fFontSize);
+  m_pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, NULL));
+  m_pBreak->SetLineBreakTolerance(fFontSize * 0.2f);
+}
+void CXFA_TextLayout::InitBreak(IFDE_CSSComputedStyle* pStyle,
+                                FDE_CSSDISPLAY eDisplay,
+                                FX_FLOAT fLineWidth,
+                                IFDE_XMLNode* pXMLNode,
+                                IFDE_CSSComputedStyle* pParentStyle) {
+  if (pStyle == NULL) {
+    InitBreak(fLineWidth);
+    return;
+  }
+  IFDE_CSSParagraphStyle* pParaStyle = pStyle->GetParagraphStyles();
+  if (eDisplay == FDE_CSSDISPLAY_Block || eDisplay == FDE_CSSDISPLAY_ListItem) {
+    int32_t iAlign = FX_RTFLINEALIGNMENT_Left;
+    switch (pParaStyle->GetTextAlign()) {
+      case FDE_CSSTEXTALIGN_Right:
+        iAlign = FX_RTFLINEALIGNMENT_Right;
+        break;
+      case FDE_CSSTEXTALIGN_Center:
+        iAlign = FX_RTFLINEALIGNMENT_Center;
+        break;
+      case FDE_CSSTEXTALIGN_Justify:
+        iAlign = FX_RTFLINEALIGNMENT_Justified;
+        break;
+      case FDE_CSSTEXTALIGN_JustifyAll:
+        iAlign = FX_RTFLINEALIGNMENT_Distributed;
+        break;
+      default:
+        break;
+    }
+    m_pBreak->SetAlignment(iAlign);
+    FX_FLOAT fStart = 0;
+    const FDE_CSSRECT* pRect = pStyle->GetBoundaryStyles()->GetMarginWidth();
+    const FDE_CSSRECT* pPaddingRect =
+        pStyle->GetBoundaryStyles()->GetPaddingWidth();
+    if (pRect) {
+      fStart = pRect->left.GetValue();
+      fLineWidth -= pRect->right.GetValue();
+      if (pPaddingRect) {
+        fStart += pPaddingRect->left.GetValue();
+        fLineWidth -= pPaddingRect->right.GetValue();
+      }
+      if (eDisplay == FDE_CSSDISPLAY_ListItem) {
+        const FDE_CSSRECT* pParRect =
+            pParentStyle->GetBoundaryStyles()->GetMarginWidth();
+        const FDE_CSSRECT* pParPaddingRect =
+            pParentStyle->GetBoundaryStyles()->GetPaddingWidth();
+        if (pParRect) {
+          fStart += pParRect->left.GetValue();
+          fLineWidth -= pParRect->right.GetValue();
+          if (pParPaddingRect) {
+            fStart += pParPaddingRect->left.GetValue();
+            fLineWidth -= pParPaddingRect->right.GetValue();
+          }
+        }
+        FDE_CSSRECT pNewRect;
+        pNewRect.left.Set(FDE_CSSLENGTHUNIT_Point, fStart);
+        pNewRect.right.Set(FDE_CSSLENGTHUNIT_Point, pRect->right.GetValue());
+        pNewRect.top.Set(FDE_CSSLENGTHUNIT_Point, pRect->top.GetValue());
+        pNewRect.bottom.Set(FDE_CSSLENGTHUNIT_Point, pRect->bottom.GetValue());
+        pStyle->GetBoundaryStyles()->SetMarginWidth(pNewRect);
+      }
+    }
+    m_pBreak->SetLineBoundary(fStart, fLineWidth);
+    FX_FLOAT fIndent = pParaStyle->GetTextIndent().GetValue();
+    if (fIndent > 0) {
+      fStart += fIndent;
+    }
+    m_pBreak->SetLineStartPos(fStart);
+    m_pBreak->SetTabWidth(m_textParser.GetTabInterval(pStyle));
+    if (m_pTabstopContext == NULL) {
+      m_pTabstopContext = new CXFA_TextTabstopsContext;
+    }
+    m_textParser.GetTabstops(pStyle, m_pTabstopContext);
+    for (int32_t i = 0; i < m_pTabstopContext->m_iTabCount; i++) {
+      XFA_TABSTOPS* pTab = m_pTabstopContext->m_tabstops.GetDataPtr(i);
+      m_pBreak->AddPositionedTab(pTab->fTabstops);
+    }
+  }
+  FX_FLOAT fFontSize = m_textParser.GetFontSize(m_pTextProvider, pStyle);
+  m_pBreak->SetFontSize(fFontSize);
+  m_pBreak->SetLineBreakTolerance(fFontSize * 0.2f);
+  m_pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, pStyle));
+  m_pBreak->SetHorizontalScale(
+      m_textParser.GetHorScale(m_pTextProvider, pStyle, pXMLNode));
+  m_pBreak->SetVerticalScale(m_textParser.GetVerScale(m_pTextProvider, pStyle));
+  m_pBreak->SetCharSpace(pParaStyle->GetLetterSpacing().GetValue());
+}
+int32_t CXFA_TextLayout::GetText(CFX_WideString& wsText) {
+  GetTextDataNode();
+  wsText.Empty();
+  if (m_bRichText) {
+  } else {
+    wsText = m_pTextDataNode->GetContent();
+  }
+  return wsText.GetLength();
+}
+FX_FLOAT CXFA_TextLayout::GetLayoutHeight() {
+  if (m_pLoader == NULL) {
+    return 0;
+  }
+  int32_t iCount = m_pLoader->m_lineHeights.GetSize();
+  if (iCount == 0 && m_pLoader->m_fWidth > 0) {
+    CFX_SizeF szMax(m_pLoader->m_fWidth, m_pLoader->m_fHeight);
+    CFX_SizeF szDef;
+    m_pLoader->m_bSaveLineHeight = TRUE;
+    m_pLoader->m_fLastPos = 0;
+    CalcSize(szMax, szMax, szDef);
+    m_pLoader->m_bSaveLineHeight = FALSE;
+    return szDef.y;
+  }
+  FX_FLOAT fHeight = m_pLoader->m_fHeight;
+  if (fHeight < 0.1f) {
+    fHeight = 0;
+    for (int32_t i = 0; i < iCount; i++) {
+      fHeight += m_pLoader->m_lineHeights.ElementAt(i);
+    }
+  }
+  return fHeight;
+}
+FX_FLOAT CXFA_TextLayout::StartLayout(FX_FLOAT fWidth) {
+  if (m_pLoader == NULL) {
+    m_pLoader = new CXFA_LoaderContext;
+  }
+  if (fWidth < 0 || (m_pLoader->m_fWidth > -1 &&
+                     FXSYS_fabs(fWidth - m_pLoader->m_fWidth) > 0)) {
+    m_pLoader->m_lineHeights.RemoveAll();
+    m_Blocks.RemoveAll();
+    Unload();
+    m_pLoader->m_fStartLineOffset = 0;
+  }
+  m_pLoader->m_fWidth = fWidth;
+  if (fWidth < 0) {
+    CFX_SizeF szMax;
+    CFX_SizeF szDef;
+    m_pLoader->m_bSaveLineHeight = TRUE;
+    m_pLoader->m_fLastPos = 0;
+    CalcSize(szMax, szMax, szDef);
+    m_pLoader->m_bSaveLineHeight = FALSE;
+    fWidth = szDef.x;
+  }
+  return fWidth;
+}
+FX_BOOL CXFA_TextLayout::DoLayout(int32_t iBlockIndex,
+                                  FX_FLOAT& fCalcHeight,
+                                  FX_FLOAT fContentAreaHeight,
+                                  FX_FLOAT fTextHeight) {
+  if (m_pLoader == NULL) {
+    return FALSE;
+  }
+  int32_t iBlockCount = m_Blocks.GetSize();
+  FX_FLOAT fHeight = fTextHeight;
+  if (fHeight < 0) {
+    fHeight = GetLayoutHeight();
+  }
+  m_pLoader->m_fHeight = fHeight;
+  if (fContentAreaHeight < 0) {
+    return FALSE;
+  }
+  m_bHasBlock = TRUE;
+  if (iBlockCount == 0 && fHeight > 0) {
+    fHeight = fTextHeight - GetLayoutHeight();
+    if (fHeight > 0) {
+      int32_t iAlign = m_textParser.GetVAlgin(m_pTextProvider);
+      if (iAlign == XFA_ATTRIBUTEENUM_Middle) {
+        fHeight /= 2.0f;
+      } else if (iAlign != XFA_ATTRIBUTEENUM_Bottom) {
+        fHeight = 0;
+      }
+      m_pLoader->m_fStartLineOffset = fHeight;
+    }
+  }
+  FX_FLOAT fLinePos = m_pLoader->m_fStartLineOffset;
+  int32_t iLineIndex = 0;
+  if (iBlockCount > 1) {
+    if (iBlockCount >= (iBlockIndex + 1) * 2) {
+      iLineIndex = m_Blocks.ElementAt(iBlockIndex * 2);
+    } else {
+      iLineIndex = m_Blocks.ElementAt(iBlockCount - 1) +
+                   m_Blocks.ElementAt(iBlockCount - 2);
+    }
+    if (m_pLoader->m_BlocksHeight.GetSize() > 0) {
+      for (int32_t i = 0; i < iBlockIndex; i++) {
+        fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1);
+      }
+    }
+  }
+  int32_t iCount = m_pLoader->m_lineHeights.GetSize();
+  int32_t i = 0;
+  for (i = iLineIndex; i < iCount; i++) {
+    FX_FLOAT fLineHeight = m_pLoader->m_lineHeights.ElementAt(i);
+    if ((i == iLineIndex) && (fLineHeight - fContentAreaHeight > 0.001)) {
+      fCalcHeight = 0;
+      return TRUE;
+    }
+    if (fLinePos + fLineHeight - fContentAreaHeight > 0.001) {
+      if (iBlockCount >= (iBlockIndex + 1) * 2) {
+        m_Blocks.SetAt(iBlockIndex * 2, iLineIndex);
+        m_Blocks.SetAt(iBlockIndex * 2 + 1, i - iLineIndex);
+      } else {
+        m_Blocks.Add(iLineIndex);
+        m_Blocks.Add(i - iLineIndex);
+      }
+      if (i == iLineIndex) {
+        if (fCalcHeight <= fLinePos) {
+          if (m_pLoader->m_BlocksHeight.GetSize() > iBlockIndex * 2 &&
+              (m_pLoader->m_BlocksHeight.GetAt(iBlockIndex * 2) ==
+               iBlockIndex)) {
+            m_pLoader->m_BlocksHeight.SetAt(iBlockIndex * 2 + 1, fCalcHeight);
+          } else {
+            m_pLoader->m_BlocksHeight.Add((FX_FLOAT)iBlockIndex);
+            m_pLoader->m_BlocksHeight.Add(fCalcHeight);
+          }
+        }
+        return TRUE;
+      }
+      fCalcHeight = fLinePos;
+      return TRUE;
+    }
+    fLinePos += fLineHeight;
+  }
+  return FALSE;
+}
+int32_t CXFA_TextLayout::CountBlocks() const {
+  int32_t iCount = m_Blocks.GetSize() / 2;
+  return iCount > 0 ? iCount : 1;
+}
+FX_BOOL CXFA_TextLayout::CalcSize(const CFX_SizeF& minSize,
+                                  const CFX_SizeF& maxSize,
+                                  CFX_SizeF& defaultSize) {
+  defaultSize.x = maxSize.x;
+  if (defaultSize.x < 1) {
+    defaultSize.x = 0xFFFF;
+  }
+  if (m_pBreak)
+    m_pBreak->Release();
+
+  m_pBreak = CreateBreak(FALSE);
+  FX_FLOAT fLinePos = 0;
+  m_iLines = 0;
+  m_fMaxWidth = 0;
+  Loader(defaultSize, fLinePos, FALSE);
+  if (fLinePos < 0.1f) {
+    fLinePos = m_textParser.GetFontSize(m_pTextProvider, NULL);
+  }
+  if (m_pTabstopContext) {
+    delete m_pTabstopContext;
+    m_pTabstopContext = NULL;
+  }
+  defaultSize = CFX_SizeF(m_fMaxWidth, fLinePos);
+  return TRUE;
+}
+FX_BOOL CXFA_TextLayout::Layout(const CFX_SizeF& size, FX_FLOAT* fHeight) {
+  if (size.x < 1) {
+    return FALSE;
+  }
+  Unload();
+  m_pBreak = CreateBreak(TRUE);
+  if (m_pLoader) {
+    m_pLoader->m_iTotalLines = -1;
+    m_pLoader->m_iChar = 0;
+  }
+  m_iLines = 0;
+  FX_FLOAT fLinePos = 0;
+  Loader(size, fLinePos, TRUE);
+  UpdateAlign(size.y, fLinePos);
+  if (m_pTabstopContext) {
+    delete m_pTabstopContext;
+    m_pTabstopContext = NULL;
+  }
+  if (fHeight) {
+    *fHeight = fLinePos;
+  }
+  return TRUE;
+}
+FX_BOOL CXFA_TextLayout::Layout(int32_t iBlock) {
+  if (m_pLoader == NULL || iBlock < 0 || iBlock >= CountBlocks()) {
+    return FALSE;
+  }
+  if (m_pLoader->m_fWidth < 1) {
+    return FALSE;
+  }
+  m_pLoader->m_iTotalLines = -1;
+  m_iLines = 0;
+  FX_FLOAT fLinePos = 0;
+  CXFA_Node* pNode = NULL;
+  CFX_SizeF szText(m_pLoader->m_fWidth, m_pLoader->m_fHeight);
+  int32_t iCount = m_Blocks.GetSize();
+  int32_t iBlocksHeightCount = m_pLoader->m_BlocksHeight.GetSize();
+  iBlocksHeightCount /= 2;
+  if (iBlock < iBlocksHeightCount) {
+    return TRUE;
+  }
+  if (iBlock == iBlocksHeightCount) {
+    Unload();
+    m_pBreak = CreateBreak(TRUE);
+    fLinePos = m_pLoader->m_fStartLineOffset;
+    for (int32_t i = 0; i < iBlocksHeightCount; i++) {
+      fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1);
+    }
+    m_pLoader->m_iChar = 0;
+    if (iCount > 1) {
+      m_pLoader->m_iTotalLines = m_Blocks.ElementAt(iBlock * 2 + 1);
+    }
+    Loader(szText, fLinePos, TRUE);
+    if (iCount == 0 && m_pLoader->m_fStartLineOffset < 0.1f) {
+      UpdateAlign(szText.y, fLinePos);
+    }
+  } else if (m_pTextDataNode) {
+    iBlock *= 2;
+    if (iBlock < iCount - 2) {
+      m_pLoader->m_iTotalLines = m_Blocks.ElementAt(iBlock + 1);
+    }
+    m_pBreak->Reset();
+    if (m_bRichText) {
+      IFDE_XMLNode* pContainerNode = GetXMLContainerNode();
+      if (!pContainerNode) {
+        return TRUE;
+      }
+      IFDE_XMLNode* pXMLNode = m_pLoader->m_pXMLNode;
+      if (pXMLNode == NULL) {
+        return TRUE;
+      }
+      IFDE_XMLNode* pSaveXMLNode = m_pLoader->m_pXMLNode;
+      for (; pXMLNode;
+           pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+        FX_BOOL bFlag = LoadRichText(pXMLNode, szText, fLinePos,
+                                     m_pLoader->m_pParentStyle, TRUE);
+        if (!bFlag) {
+          break;
+        }
+      }
+      while (pXMLNode == NULL) {
+        pXMLNode = pSaveXMLNode->GetNodeItem(IFDE_XMLNode::Parent);
+        if (pXMLNode == pContainerNode) {
+          break;
+        }
+        FX_BOOL bFlag =
+            LoadRichText(pXMLNode, szText, fLinePos, m_pLoader->m_pParentStyle,
+                         TRUE, NULL, FALSE);
+        if (!bFlag) {
+          break;
+        }
+        pSaveXMLNode = pXMLNode;
+        pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling);
+        if (!pXMLNode) {
+          continue;
+        }
+        for (; pXMLNode;
+             pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+          FX_BOOL bFlag = LoadRichText(pXMLNode, szText, fLinePos,
+                                       m_pLoader->m_pParentStyle, TRUE);
+          if (!bFlag) {
+            break;
+          }
+        }
+      }
+    } else {
+      pNode = m_pLoader->m_pNode;
+      if (pNode == NULL) {
+        return TRUE;
+      }
+      LoadText(pNode, szText, fLinePos, TRUE);
+    }
+  }
+  if (iBlock == iCount) {
+    delete m_pTabstopContext;
+    m_pTabstopContext = nullptr;
+    delete m_pLoader;
+    m_pLoader = nullptr;
+  }
+  return TRUE;
+}
+void CXFA_TextLayout::ItemBlocks(const CFX_RectF& rtText, int32_t iBlockIndex) {
+  if (!m_pLoader) {
+    return;
+  }
+  int32_t iCountHeight = m_pLoader->m_lineHeights.GetSize();
+  if (iCountHeight == 0) {
+    return;
+  }
+  FX_BOOL bEndItem = TRUE;
+  int32_t iBlockCount = m_Blocks.GetSize();
+  FX_FLOAT fLinePos = m_pLoader->m_fStartLineOffset;
+  int32_t iLineIndex = 0;
+  if (iBlockIndex > 0) {
+    int32_t iBlockHeightCount = m_pLoader->m_BlocksHeight.GetSize();
+    iBlockHeightCount /= 2;
+    if (iBlockHeightCount >= iBlockIndex) {
+      for (int32_t i = 0; i < iBlockIndex; i++) {
+        fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1);
+      }
+    } else {
+      fLinePos = 0;
+    }
+    iLineIndex = m_Blocks.ElementAt(iBlockCount - 1) +
+                 m_Blocks.ElementAt(iBlockCount - 2);
+  }
+  int32_t i = 0;
+  for (i = iLineIndex; i < iCountHeight; i++) {
+    FX_FLOAT fLineHeight = m_pLoader->m_lineHeights.ElementAt(i);
+    if (fLinePos + fLineHeight - rtText.height > 0.001) {
+      m_Blocks.Add(iLineIndex);
+      m_Blocks.Add(i - iLineIndex);
+      bEndItem = FALSE;
+      break;
+    }
+    fLinePos += fLineHeight;
+  }
+  if (iCountHeight > 0 && (i - iLineIndex) > 0 && bEndItem) {
+    m_Blocks.Add(iLineIndex);
+    m_Blocks.Add(i - iLineIndex);
+  }
+}
+FX_BOOL CXFA_TextLayout::DrawString(CFX_RenderDevice* pFxDevice,
+                                    const CFX_Matrix& tmDoc2Device,
+                                    const CFX_RectF& rtClip,
+                                    int32_t iBlock) {
+  IFDE_RenderDevice* pDevice = IFDE_RenderDevice::Create(pFxDevice);
+  if (pDevice == NULL) {
+    return FALSE;
+  }
+  FDE_HDEVICESTATE state = pDevice->SaveState();
+  pDevice->SetClipRect(rtClip);
+  IFDE_SolidBrush* pSolidBrush =
+      (IFDE_SolidBrush*)IFDE_Brush::Create(FDE_BRUSHTYPE_Solid);
+  IFDE_Pen* pPen = IFDE_Pen::Create();
+  FXSYS_assert(pDevice);
+  FXSYS_assert(pSolidBrush);
+  FXSYS_assert(pPen);
+  if (m_pieceLines.GetSize() == 0) {
+    int32_t iBlockCount = CountBlocks();
+    for (int32_t i = 0; i < iBlockCount; i++) {
+      Layout(i);
+    }
+  }
+  FXTEXT_CHARPOS* pCharPos = NULL;
+  int32_t iCharCount = 0;
+  int32_t iLineStart = 0;
+  int32_t iPieceLines = m_pieceLines.GetSize();
+  int32_t iCount = m_Blocks.GetSize();
+  if (iCount > 0) {
+    iBlock *= 2;
+    if (iBlock < iCount) {
+      iLineStart = m_Blocks.ElementAt(iBlock);
+      iPieceLines = m_Blocks.ElementAt(iBlock + 1);
+    } else {
+      iPieceLines = 0;
+    }
+  }
+  for (int32_t i = 0; i < iPieceLines; i++) {
+    if (i + iLineStart >= m_pieceLines.GetSize()) {
+      break;
+    }
+    CXFA_PieceLine* pPieceLine = m_pieceLines.GetAt(i + iLineStart);
+    int32_t iPieces = pPieceLine->m_textPieces.GetSize();
+    int32_t j = 0;
+    for (j = 0; j < iPieces; j++) {
+      const XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(j);
+      int32_t iChars = pPiece->iChars;
+      if (iCharCount < iChars) {
+        FX_Free(pCharPos);
+        pCharPos = FX_Alloc(FXTEXT_CHARPOS, iChars);
+        iCharCount = iChars;
+      }
+      FXSYS_memset(pCharPos, 0, iCharCount * sizeof(FXTEXT_CHARPOS));
+      RenderString(pDevice, pSolidBrush, pPieceLine, j, pCharPos, tmDoc2Device);
+    }
+    for (j = 0; j < iPieces; j++) {
+      RenderPath(pDevice, pPen, pPieceLine, j, pCharPos, tmDoc2Device);
+    }
+  }
+  pDevice->RestoreState(state);
+  FX_Free(pCharPos);
+  pSolidBrush->Release();
+  pPen->Release();
+  pDevice->Release();
+  return iPieceLines;
+}
+void CXFA_TextLayout::UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom) {
+  fHeight -= fBottom;
+  if (fHeight < 0.1f) {
+    return;
+  }
+  switch (m_textParser.GetVAlgin(m_pTextProvider)) {
+    case XFA_ATTRIBUTEENUM_Middle:
+      fHeight /= 2.0f;
+      break;
+    case XFA_ATTRIBUTEENUM_Bottom:
+      break;
+    default:
+      return;
+  }
+  int32_t iCount = m_pieceLines.GetSize();
+  for (int32_t i = 0; i < iCount; i++) {
+    CXFA_PieceLine* pPieceLine = m_pieceLines.GetAt(i);
+    int32_t iPieces = pPieceLine->m_textPieces.GetSize();
+    for (int32_t j = 0; j < iPieces; j++) {
+      XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(j);
+      CFX_RectF& rect = pPiece->rtPiece;
+      rect.top += fHeight;
+    }
+  }
+}
+FX_BOOL CXFA_TextLayout::Loader(const CFX_SizeF& szText,
+                                FX_FLOAT& fLinePos,
+                                FX_BOOL bSavePieces) {
+  if (m_pAllocator == NULL) {
+    m_pAllocator = FX_CreateAllocator(FX_ALLOCTYPE_Static, 256, 0);
+  }
+  GetTextDataNode();
+  if (m_pTextDataNode == NULL) {
+    return TRUE;
+  }
+  if (m_bRichText) {
+    IFDE_XMLNode* pXMLContainer = GetXMLContainerNode();
+    if (pXMLContainer) {
+      if (!m_textParser.IsParsed()) {
+        m_textParser.DoParse(pXMLContainer, m_pTextProvider);
+      }
+      IFDE_CSSComputedStyle* pRootStyle =
+          m_textParser.CreateRootStyle(m_pTextProvider);
+      LoadRichText(pXMLContainer, szText, fLinePos, pRootStyle, bSavePieces);
+      pRootStyle->Release();
+    }
+  } else {
+    LoadText(m_pTextDataNode, szText, fLinePos, bSavePieces);
+  }
+  return TRUE;
+}
+void CXFA_TextLayout::LoadText(CXFA_Node* pNode,
+                               const CFX_SizeF& szText,
+                               FX_FLOAT& fLinePos,
+                               FX_BOOL bSavePieces) {
+  InitBreak(szText.x);
+  CXFA_Para para = m_pTextProvider->GetParaNode();
+  FX_FLOAT fSpaceAbove = 0;
+  if (para) {
+    fSpaceAbove = para.GetSpaceAbove();
+    if (fSpaceAbove < 0.1f) {
+      fSpaceAbove = 0;
+    }
+    int32_t verAlign = para.GetVerticalAlign();
+    switch (verAlign) {
+      case XFA_ATTRIBUTEENUM_Top:
+      case XFA_ATTRIBUTEENUM_Middle:
+      case XFA_ATTRIBUTEENUM_Bottom: {
+        fLinePos += fSpaceAbove;
+        break;
+      }
+    }
+  }
+  CFX_WideString wsText = pNode->GetContent();
+  wsText.TrimRight(L" ");
+  FX_BOOL bRet = AppendChar(wsText, fLinePos, fSpaceAbove, bSavePieces);
+  if (bRet && m_pLoader) {
+    m_pLoader->m_pNode = pNode;
+  } else {
+    EndBreak(FX_RTFBREAK_ParagraphBreak, fLinePos, bSavePieces);
+  }
+}
+FX_BOOL CXFA_TextLayout::LoadRichText(IFDE_XMLNode* pXMLNode,
+                                      const CFX_SizeF& szText,
+                                      FX_FLOAT& fLinePos,
+                                      IFDE_CSSComputedStyle* pParentStyle,
+                                      FX_BOOL bSavePieces,
+                                      CXFA_LinkUserData* pLinkData,
+                                      FX_BOOL bEndBreak,
+                                      FX_BOOL bIsOl,
+                                      int32_t iLiCount) {
+  if (pXMLNode == NULL) {
+    return FALSE;
+  }
+  CXFA_TextParseContext* pContext =
+      m_textParser.GetParseContextFromMap(pXMLNode);
+  FDE_CSSDISPLAY eDisplay = FDE_CSSDISPLAY_None;
+  FX_BOOL bContentNode = FALSE;
+  FX_FLOAT fSpaceBelow = 0;
+  IFDE_CSSComputedStyle* pStyle = NULL;
+  CFX_WideString wsName;
+  if (bEndBreak) {
+    FX_BOOL bCurOl = FALSE;
+    FX_BOOL bCurLi = FALSE;
+    IFDE_XMLElement* pElement = NULL;
+    if (pContext) {
+      if (m_bBlockContinue ||
+          (m_pLoader && pXMLNode == m_pLoader->m_pXMLNode)) {
+        m_bBlockContinue = TRUE;
+      }
+      if (pXMLNode->GetType() == FDE_XMLNODE_Text) {
+        bContentNode = TRUE;
+      } else if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+        pElement = (IFDE_XMLElement*)pXMLNode;
+        pElement->GetLocalTagName(wsName);
+      }
+      if (wsName == FX_WSTRC(L"ol")) {
+        bIsOl = TRUE;
+        bCurOl = TRUE;
+      }
+      if (m_bBlockContinue || bContentNode == FALSE) {
+        eDisplay = pContext->GetDisplay();
+        if (eDisplay != FDE_CSSDISPLAY_Block &&
+            eDisplay != FDE_CSSDISPLAY_Inline &&
+            eDisplay != FDE_CSSDISPLAY_ListItem) {
+          return TRUE;
+        }
+        pStyle = m_textParser.ComputeStyle(pXMLNode, pParentStyle);
+        InitBreak(bContentNode ? pParentStyle : pStyle, eDisplay, szText.x,
+                  pXMLNode, pParentStyle);
+        if ((eDisplay == FDE_CSSDISPLAY_Block ||
+             eDisplay == FDE_CSSDISPLAY_ListItem) &&
+            pStyle &&
+            (wsName.IsEmpty() ||
+             (wsName != FX_WSTRC(L"body") && wsName != FX_WSTRC(L"html") &&
+              wsName != FX_WSTRC(L"ol") && wsName != FX_WSTRC(L"ul")))) {
+          const FDE_CSSRECT* pRect =
+              pStyle->GetBoundaryStyles()->GetMarginWidth();
+          if (pRect) {
+            fLinePos += pRect->top.GetValue();
+            fSpaceBelow = pRect->bottom.GetValue();
+          }
+        }
+        if (wsName == FX_WSTRC(L"a")) {
+          CFX_WideString wsLinkContent;
+          FXSYS_assert(pElement);
+          pElement->GetString(FX_WSTRC(L"href").GetPtr(), wsLinkContent);
+          if (!wsLinkContent.IsEmpty()) {
+            pLinkData = FXTARGET_NewWith(m_pAllocator) CXFA_LinkUserData(
+                m_pAllocator,
+                wsLinkContent.GetBuffer(wsLinkContent.GetLength()));
+            wsLinkContent.ReleaseBuffer(wsLinkContent.GetLength());
+          }
+        }
+        int32_t iTabCount =
+            m_textParser.CountTabs(bContentNode ? pParentStyle : pStyle);
+        FX_BOOL bSpaceRun =
+            m_textParser.IsSpaceRun(bContentNode ? pParentStyle : pStyle);
+        CFX_WideString wsText;
+        if (bContentNode && iTabCount == 0) {
+          ((IFDE_XMLText*)pXMLNode)->GetText(wsText);
+        } else if (wsName == FX_WSTRC(L"br")) {
+          wsText = L'\n';
+        } else if (wsName == FX_WSTRC(L"li")) {
+          bCurLi = TRUE;
+          if (bIsOl) {
+            wsText.Format(L"%d.  ", iLiCount);
+          } else {
+            wsText = 0x00B7 + FX_WSTRC(L"  ");
+          }
+        } else if (!bContentNode) {
+          if (iTabCount > 0) {
+            while (iTabCount-- > 0)
+              wsText += L'\t';
+          } else {
+            m_textParser.GetEmbbedObj(m_pTextProvider, pXMLNode, wsText);
+          }
+        }
+        int32_t iLength = wsText.GetLength();
+        if (iLength > 0 && bContentNode && !bSpaceRun) {
+          ProcessText(wsText);
+        }
+        if (m_pLoader) {
+          if (wsText.GetLength() > 0 &&
+              (m_pLoader->m_dwFlags & XFA_LOADERCNTXTFLG_FILTERSPACE)) {
+            wsText.TrimLeft(0x20);
+          }
+          if (FDE_CSSDISPLAY_Block == eDisplay) {
+            m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE;
+          } else if (FDE_CSSDISPLAY_Inline == eDisplay &&
+                     (m_pLoader->m_dwFlags & XFA_LOADERCNTXTFLG_FILTERSPACE)) {
+            m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE;
+          } else if (wsText.GetLength() > 0 &&
+                     (0x20 == wsText.GetAt(wsText.GetLength() - 1))) {
+            m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE;
+          } else if (wsText.GetLength() != 0) {
+            m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE;
+          }
+        }
+        if (wsText.GetLength() > 0) {
+          if (m_pLoader == NULL || m_pLoader->m_iChar == 0) {
+            if (pLinkData) {
+              pLinkData->AddRef();
+            }
+            CXFA_TextUserData* pUserData = FXTARGET_NewWith(m_pAllocator)
+                CXFA_TextUserData(m_pAllocator,
+                                  bContentNode ? pParentStyle : pStyle,
+                                  pLinkData);
+            m_pBreak->SetUserData(pUserData);
+          }
+          if (AppendChar(wsText, fLinePos, 0, bSavePieces)) {
+            if (m_pLoader) {
+              m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE;
+            }
+            if (IsEnd(bSavePieces)) {
+              if (m_pLoader && m_pLoader->m_iTotalLines > -1) {
+                m_pLoader->m_pXMLNode = pXMLNode;
+                m_pLoader->m_pParentStyle = pParentStyle;
+              }
+              if (pStyle)
+                pStyle->Release();
+              return FALSE;
+            }
+            return TRUE;
+          }
+        }
+      }
+    }
+    FX_BOOL ret = TRUE;
+    for (IFDE_XMLNode* pChildNode =
+             pXMLNode->GetNodeItem(IFDE_XMLNode::FirstChild);
+         pChildNode;
+         pChildNode = pChildNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+      if (bCurOl) {
+        iLiCount++;
+      }
+      ret = LoadRichText(pChildNode, szText, fLinePos,
+                         pContext ? pStyle : pParentStyle, bSavePieces,
+                         pLinkData, TRUE, bIsOl, iLiCount);
+      if (ret == FALSE) {
+        return FALSE;
+      }
+    }
+    if (m_pLoader) {
+      if (FDE_CSSDISPLAY_Block == eDisplay) {
+        m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE;
+      }
+    }
+    if (bCurLi) {
+      EndBreak(FX_RTFBREAK_LineBreak, fLinePos, bSavePieces);
+    }
+  } else {
+    if (pContext) {
+      eDisplay = pContext->GetDisplay();
+    }
+  }
+  if (m_bBlockContinue) {
+    if (pContext && !bContentNode) {
+      FX_DWORD dwStatus = (eDisplay == FDE_CSSDISPLAY_Block)
+                              ? FX_RTFBREAK_ParagraphBreak
+                              : FX_RTFBREAK_PieceBreak;
+      EndBreak(dwStatus, fLinePos, bSavePieces);
+      if (eDisplay == FDE_CSSDISPLAY_Block) {
+        fLinePos += fSpaceBelow;
+        if (m_pTabstopContext) {
+          m_pTabstopContext->RemoveAll();
+        }
+      }
+      if (wsName == FX_WSTRC(L"a")) {
+        if (pLinkData) {
+          pLinkData->Release();
+          pLinkData = nullptr;
+        }
+      }
+      if (IsEnd(bSavePieces)) {
+        if (pStyle) {
+          pStyle->Release();
+        }
+        if (m_pLoader && m_pLoader->m_iTotalLines > -1) {
+          m_pLoader->m_pXMLNode =
+              pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling);
+          m_pLoader->m_pParentStyle = pParentStyle;
+        }
+        return FALSE;
+      }
+    }
+  }
+  if (pStyle)
+    pStyle->Release();
+  return TRUE;
+}
+FX_BOOL CXFA_TextLayout::AppendChar(const CFX_WideString& wsText,
+                                    FX_FLOAT& fLinePos,
+                                    FX_FLOAT fSpaceAbove,
+                                    FX_BOOL bSavePieces) {
+  FX_DWORD dwStatus = 0;
+  int32_t iChar = 0;
+  if (m_pLoader) {
+    iChar = m_pLoader->m_iChar;
+  }
+  int32_t iLength = wsText.GetLength();
+  for (int32_t i = iChar; i < iLength; i++) {
+    FX_WCHAR wch = wsText.GetAt(i);
+    if (wch == 0xA0) {
+      wch = 0x20;
+    }
+    if ((dwStatus = m_pBreak->AppendChar(wch)) > FX_RTFBREAK_PieceBreak) {
+      AppendTextLine(dwStatus, fLinePos, bSavePieces);
+      if (IsEnd(bSavePieces)) {
+        if (m_pLoader)
+          m_pLoader->m_iChar = i;
+        return TRUE;
+      }
+      if (dwStatus == FX_RTFBREAK_ParagraphBreak && m_bRichText) {
+        fLinePos += fSpaceAbove;
+      }
+    }
+  }
+  if (m_pLoader) {
+    m_pLoader->m_iChar = 0;
+  }
+  return FALSE;
+}
+FX_BOOL CXFA_TextLayout::IsEnd(FX_BOOL bSavePieces) {
+  if (!bSavePieces) {
+    return FALSE;
+  }
+  if (m_pLoader && m_pLoader->m_iTotalLines > 0) {
+    return m_iLines >= m_pLoader->m_iTotalLines;
+  }
+  return FALSE;
+}
+void CXFA_TextLayout::ProcessText(CFX_WideString& wsText) {
+  int32_t iLen = wsText.GetLength();
+  if (iLen == 0) {
+    return;
+  }
+  FX_WCHAR* psz = wsText.GetBuffer(iLen);
+  int32_t iTrimLeft = 0;
+  FX_WCHAR wch = 0, wPrev = 0;
+  for (int32_t i = 0; i < iLen; i++) {
+    wch = psz[i];
+    if (wch < 0x20) {
+      wch = 0x20;
+    }
+    if (wch == 0x20 && wPrev == 0x20) {
+      continue;
+    }
+    wPrev = wch;
+    psz[iTrimLeft++] = wch;
+  }
+  wsText.ReleaseBuffer(iLen);
+  wsText = wsText.Left(iTrimLeft);
+}
+void CXFA_TextLayout::EndBreak(FX_DWORD dwStatus,
+                               FX_FLOAT& fLinePos,
+                               FX_BOOL bSavePieces) {
+  dwStatus = m_pBreak->EndBreak(dwStatus);
+  if (dwStatus > FX_RTFBREAK_PieceBreak) {
+    AppendTextLine(dwStatus, fLinePos, bSavePieces, TRUE);
+  }
+}
+void CXFA_TextLayout::DoTabstops(IFDE_CSSComputedStyle* pStyle,
+                                 CXFA_PieceLine* pPieceLine) {
+  if (m_pTabstopContext == NULL || m_pTabstopContext->m_iTabCount == 0) {
+    return;
+  }
+  if (pStyle == NULL || pPieceLine == NULL) {
+    return;
+  }
+  int32_t iPieces = pPieceLine->m_textPieces.GetSize();
+  if (iPieces == 0) {
+    return;
+  }
+  XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(iPieces - 1);
+  int32_t& iTabstopsIndex = m_pTabstopContext->m_iTabIndex;
+  int32_t iCount = m_textParser.CountTabs(pStyle);
+  if (iTabstopsIndex > m_pTabstopContext->m_iTabCount - 1) {
+    return;
+  }
+  if (iCount > 0) {
+    iTabstopsIndex++;
+    m_pTabstopContext->m_bTabstops = TRUE;
+    FX_FLOAT fRight = 0;
+    if (iPieces > 1) {
+      XFA_TextPiece* p = pPieceLine->m_textPieces.GetAt(iPieces - 2);
+      fRight = p->rtPiece.right();
+    }
+    m_pTabstopContext->m_fTabWidth =
+        pPiece->rtPiece.width + pPiece->rtPiece.left - fRight;
+  } else if (iTabstopsIndex > -1) {
+    FX_FLOAT fLeft = 0;
+    if (m_pTabstopContext->m_bTabstops) {
+      XFA_TABSTOPS* pTabstops =
+          m_pTabstopContext->m_tabstops.GetDataPtr(iTabstopsIndex);
+      FX_DWORD dwAlgin = pTabstops->dwAlign;
+      if (dwAlgin == FX_HashCode_String_GetW(L"center", 6)) {
+        fLeft = pPiece->rtPiece.width / 2.0f;
+      } else if (dwAlgin == FX_HashCode_String_GetW(L"right", 5) ||
+                 dwAlgin == FX_HashCode_String_GetW(L"before", 6)) {
+        fLeft = pPiece->rtPiece.width;
+      } else if (dwAlgin == FX_HashCode_String_GetW(L"decimal", 7)) {
+        int32_t iChars = pPiece->iChars;
+        for (int32_t i = 0; i < iChars; i++) {
+          if (pPiece->pszText[i] == L'.') {
+            break;
+          }
+          fLeft += pPiece->pWidths[i] / 20000.0f;
+        }
+      }
+      m_pTabstopContext->m_fLeft =
+          std::min(fLeft, m_pTabstopContext->m_fTabWidth);
+      m_pTabstopContext->m_bTabstops = FALSE;
+      m_pTabstopContext->m_fTabWidth = 0;
+    }
+    pPiece->rtPiece.left -= m_pTabstopContext->m_fLeft;
+  }
+}
+void CXFA_TextLayout::AppendTextLine(FX_DWORD dwStatus,
+                                     FX_FLOAT& fLinePos,
+                                     FX_BOOL bSavePieces,
+                                     FX_BOOL bEndBreak) {
+  int32_t iPieces = m_pBreak->CountBreakPieces();
+  if (iPieces < 1) {
+    return;
+  }
+  IFDE_CSSComputedStyle* pStyle = NULL;
+  if (bSavePieces) {
+    CXFA_PieceLine* pPieceLine = FXTARGET_NewWith(m_pAllocator) CXFA_PieceLine;
+    m_pieceLines.Add(pPieceLine);
+    if (m_pTabstopContext) {
+      m_pTabstopContext->Reset();
+    }
+    FX_FLOAT fLineStep = 0, fBaseLine = 0;
+    int32_t i = 0;
+    for (i = 0; i < iPieces; i++) {
+      const CFX_RTFPiece* pPiece = m_pBreak->GetBreakPiece(i);
+      CXFA_TextUserData* pUserData = (CXFA_TextUserData*)pPiece->m_pUserData;
+      if (pUserData)
+        pStyle = pUserData->m_pStyle;
+      FX_FLOAT fVerScale = pPiece->m_iVerticalScale / 100.0f;
+      XFA_TextPiece* pTP = FXTARGET_NewWith(m_pAllocator) XFA_TextPiece();
+      pTP->pszText =
+          (FX_WCHAR*)m_pAllocator->Alloc(pPiece->m_iChars * sizeof(FX_WCHAR));
+      pTP->pWidths =
+          (int32_t*)m_pAllocator->Alloc(pPiece->m_iChars * sizeof(int32_t));
+      pTP->iChars = pPiece->m_iChars;
+      pPiece->GetString(pTP->pszText);
+      pPiece->GetWidths(pTP->pWidths);
+      pTP->iBidiLevel = pPiece->m_iBidiLevel;
+      pTP->iHorScale = pPiece->m_iHorizontalScale;
+      pTP->iVerScale = pPiece->m_iVerticalScale;
+      m_textParser.GetUnderline(m_pTextProvider, pStyle, pTP->iUnderline,
+                                pTP->iPeriod);
+      m_textParser.GetLinethrough(m_pTextProvider, pStyle, pTP->iLineThrough);
+      pTP->dwColor = m_textParser.GetColor(m_pTextProvider, pStyle);
+      pTP->pFont = m_textParser.GetFont(m_pTextProvider, pStyle);
+      pTP->fFontSize = m_textParser.GetFontSize(m_pTextProvider, pStyle);
+      pTP->rtPiece.left = pPiece->m_iStartPos / 20000.0f;
+      pTP->rtPiece.width = pPiece->m_iWidth / 20000.0f;
+      pTP->rtPiece.height = (FX_FLOAT)pPiece->m_iFontSize * fVerScale / 20.0f;
+      FX_FLOAT fBaseLineTemp =
+          m_textParser.GetBaseline(m_pTextProvider, pStyle);
+      pTP->rtPiece.top = fBaseLineTemp;
+      pPieceLine->m_textPieces.Add(pTP);
+      FX_FLOAT fLineHeight = m_textParser.GetLineHeight(
+          m_pTextProvider, pStyle, m_iLines == 0, fVerScale);
+      if (fBaseLineTemp > 0) {
+        FX_FLOAT fLineHeightTmp = fBaseLineTemp + pTP->rtPiece.height;
+        if (fLineHeight < fLineHeightTmp) {
+          fLineHeight = fLineHeightTmp;
+        } else {
+          fBaseLineTemp = 0;
+        }
+      } else if (fBaseLine < -fBaseLineTemp) {
+        fBaseLine = -fBaseLineTemp;
+      }
+      fLineStep = std::max(fLineStep, fLineHeight);
+      if (pUserData && pUserData->m_pLinkData) {
+        pUserData->m_pLinkData->AddRef();
+        pTP->pLinkData = pUserData->m_pLinkData;
+      } else {
+        pTP->pLinkData = NULL;
+      }
+      DoTabstops(pStyle, pPieceLine);
+    }
+    for (i = 0; i < iPieces; i++) {
+      XFA_TextPiece* pTP = pPieceLine->m_textPieces.GetAt(i);
+      FX_FLOAT& fTop = pTP->rtPiece.top;
+      FX_FLOAT fBaseLineTemp = fTop;
+      fTop = fLinePos + fLineStep - pTP->rtPiece.height - fBaseLineTemp;
+      fTop = std::max(0.0f, fTop);
+    }
+    fLinePos += fLineStep + fBaseLine;
+  } else {
+    FX_FLOAT fLineStep = 0;
+    FX_FLOAT fLineWidth = 0;
+    for (int32_t i = 0; i < iPieces; i++) {
+      const CFX_RTFPiece* pPiece = m_pBreak->GetBreakPiece(i);
+      CXFA_TextUserData* pUserData = (CXFA_TextUserData*)pPiece->m_pUserData;
+      if (pUserData)
+        pStyle = pUserData->m_pStyle;
+      FX_FLOAT fVerScale = pPiece->m_iVerticalScale / 100.0f;
+      FX_FLOAT fBaseLine = m_textParser.GetBaseline(m_pTextProvider, pStyle);
+      FX_FLOAT fLineHeight = m_textParser.GetLineHeight(
+          m_pTextProvider, pStyle, m_iLines == 0, fVerScale);
+      if (fBaseLine > 0) {
+        FX_FLOAT fLineHeightTmp =
+            fBaseLine + (FX_FLOAT)pPiece->m_iFontSize * fVerScale / 20.0f;
+        if (fLineHeight < fLineHeightTmp) {
+          fLineHeight = fLineHeightTmp;
+        }
+      }
+      fLineStep = std::max(fLineStep, fLineHeight);
+      fLineWidth += pPiece->m_iWidth / 20000.0f;
+    }
+    fLinePos += fLineStep;
+    m_fMaxWidth = std::max(m_fMaxWidth, fLineWidth);
+    if (m_pLoader && m_pLoader->m_bSaveLineHeight) {
+      FX_FLOAT fHeight = fLinePos - m_pLoader->m_fLastPos;
+      m_pLoader->m_fLastPos = fLinePos;
+      m_pLoader->m_lineHeights.Add(fHeight);
+    }
+  }
+  if (pStyle) {
+    pStyle->AddRef();
+  }
+  m_pBreak->ClearBreakPieces();
+  if (dwStatus == FX_RTFBREAK_ParagraphBreak) {
+    m_pBreak->Reset();
+    if (!pStyle && bEndBreak) {
+      CXFA_Para para = m_pTextProvider->GetParaNode();
+      if (para) {
+        FX_FLOAT fStartPos = para.GetMarginLeft();
+        FX_FLOAT fIndent = para.GetTextIndent();
+        if (fIndent > 0) {
+          fStartPos += fIndent;
+        }
+        FX_FLOAT fSpaceBelow = para.GetSpaceBelow();
+        if (fSpaceBelow < 0.1f) {
+          fSpaceBelow = 0;
+        }
+        m_pBreak->SetLineStartPos(fStartPos);
+        fLinePos += fSpaceBelow;
+      }
+    }
+  }
+  if (pStyle) {
+    FX_FLOAT fStart = 0;
+    const FDE_CSSRECT* pRect = pStyle->GetBoundaryStyles()->GetMarginWidth();
+    if (pRect) {
+      fStart = pRect->left.GetValue();
+    }
+    FX_FLOAT fTextIndent =
+        pStyle->GetParagraphStyles()->GetTextIndent().GetValue();
+    if (fTextIndent < 0) {
+      fStart -= fTextIndent;
+    }
+    m_pBreak->SetLineStartPos(fStart);
+    pStyle->Release();
+  }
+  m_iLines++;
+}
+void CXFA_TextLayout::RenderString(IFDE_RenderDevice* pDevice,
+                                   IFDE_SolidBrush* pBrush,
+                                   CXFA_PieceLine* pPieceLine,
+                                   int32_t iPiece,
+                                   FXTEXT_CHARPOS* pCharPos,
+                                   const CFX_Matrix& tmDoc2Device) {
+  const XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(iPiece);
+  int32_t iCount = GetDisplayPos(pPiece, pCharPos);
+  if (iCount > 0) {
+    pBrush->SetColor(pPiece->dwColor);
+    pDevice->DrawString(pBrush, pPiece->pFont, pCharPos, iCount,
+                        pPiece->fFontSize, &tmDoc2Device);
+  }
+  pPieceLine->m_charCounts.Add(iCount);
+}
+void CXFA_TextLayout::RenderPath(IFDE_RenderDevice* pDevice,
+                                 IFDE_Pen* pPen,
+                                 CXFA_PieceLine* pPieceLine,
+                                 int32_t iPiece,
+                                 FXTEXT_CHARPOS* pCharPos,
+                                 const CFX_Matrix& tmDoc2Device) {
+  XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(iPiece);
+  FX_BOOL bNoUnderline = pPiece->iUnderline < 1 || pPiece->iUnderline > 2;
+  FX_BOOL bNoLineThrough = pPiece->iLineThrough < 1 || pPiece->iLineThrough > 2;
+  if (bNoUnderline && bNoLineThrough) {
+    return;
+  }
+  pPen->SetColor(pPiece->dwColor);
+  IFDE_Path* pPath = IFDE_Path::Create();
+  int32_t iChars = GetDisplayPos(pPiece, pCharPos);
+  if (iChars > 0) {
+    CFX_PointF pt1, pt2;
+    FX_FLOAT fEndY = pCharPos[0].m_OriginY + 1.05f;
+    int32_t i = 0;
+    if (pPiece->iPeriod == XFA_ATTRIBUTEENUM_Word) {
+      for (int32_t i = 0; i < pPiece->iUnderline; i++) {
+        for (int32_t j = 0; j < iChars; j++) {
+          pt1.x = pCharPos[j].m_OriginX;
+          pt2.x =
+              pt1.x + pCharPos[j].m_FontCharWidth * pPiece->fFontSize / 1000.0f;
+          pt1.y = pt2.y = fEndY;
+          pPath->AddLine(pt1, pt2);
+        }
+        fEndY += 2.0f;
+      }
+    } else {
+      pt1.x = pCharPos[0].m_OriginX;
+      pt2.x =
+          pCharPos[iChars - 1].m_OriginX +
+          pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f;
+      for (int32_t i = 0; i < pPiece->iUnderline; i++) {
+        pt1.y = pt2.y = fEndY;
+        pPath->AddLine(pt1, pt2);
+        fEndY += 2.0f;
+      }
+    }
+    fEndY = pCharPos[0].m_OriginY - pPiece->rtPiece.height * 0.25f;
+    pt1.x = pCharPos[0].m_OriginX;
+    pt2.x = pCharPos[iChars - 1].m_OriginX +
+            pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f;
+    for (i = 0; i < pPiece->iLineThrough; i++) {
+      pt1.y = pt2.y = fEndY;
+      pPath->AddLine(pt1, pt2);
+      fEndY += 2.0f;
+    }
+  } else {
+    if (bNoLineThrough &&
+        (bNoUnderline || pPiece->iPeriod != XFA_ATTRIBUTEENUM_All)) {
+      goto XFA_RenderPathRet;
+    }
+    int32_t iCharsTmp = 0;
+    int32_t iPiecePrev = iPiece, iPieceNext = iPiece;
+    while (iPiecePrev > 0) {
+      iPiecePrev--;
+      iCharsTmp = pPieceLine->m_charCounts.GetAt(iPiecePrev);
+      if (iCharsTmp > 0) {
+        break;
+      }
+    }
+    if (iCharsTmp == 0) {
+      goto XFA_RenderPathRet;
+    }
+    iCharsTmp = 0;
+    int32_t iPieces = pPieceLine->m_textPieces.GetSize();
+    while (iPieceNext < iPieces - 1) {
+      iPieceNext++;
+      iCharsTmp = pPieceLine->m_charCounts.GetAt(iPieceNext);
+      if (iCharsTmp > 0) {
+        break;
+      }
+    }
+    if (iCharsTmp == 0) {
+      goto XFA_RenderPathRet;
+    }
+    FX_FLOAT fOrgX = 0.0f, fEndX = 0.0f;
+    pPiece = pPieceLine->m_textPieces.GetAt(iPiecePrev);
+    iChars = GetDisplayPos(pPiece, pCharPos);
+    if (iChars < 1) {
+      goto XFA_RenderPathRet;
+    }
+    fOrgX = pCharPos[iChars - 1].m_OriginX +
+            pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f;
+    pPiece = pPieceLine->m_textPieces.GetAt(iPieceNext);
+    iChars = GetDisplayPos(pPiece, pCharPos);
+    if (iChars < 1) {
+      goto XFA_RenderPathRet;
+    }
+    fEndX = pCharPos[0].m_OriginX;
+    CFX_PointF pt1, pt2;
+    pt1.x = fOrgX, pt2.x = fEndX;
+    FX_FLOAT fEndY = pCharPos[0].m_OriginY + 1.05f;
+    int32_t i = 0;
+    for (i = 0; i < pPiece->iUnderline; i++) {
+      pt1.y = pt2.y = fEndY;
+      pPath->AddLine(pt1, pt2);
+      fEndY += 2.0f;
+    }
+    fEndY = pCharPos[0].m_OriginY - pPiece->rtPiece.height * 0.25f;
+    for (i = 0; i < pPiece->iLineThrough; i++) {
+      pt1.y = pt2.y = fEndY;
+      pPath->AddLine(pt1, pt2);
+      fEndY += 2.0f;
+    }
+  }
+  pDevice->DrawPath(pPen, 1, pPath, &tmDoc2Device);
+XFA_RenderPathRet:
+  pPath->Release();
+}
+int32_t CXFA_TextLayout::GetDisplayPos(const XFA_TextPiece* pPiece,
+                                       FXTEXT_CHARPOS* pCharPos,
+                                       FX_BOOL bCharCode) {
+  if (pPiece == NULL) {
+    return 0;
+  }
+  FX_RTFTEXTOBJ tr;
+  if (!ToRun(pPiece, tr)) {
+    return 0;
+  }
+  return m_pBreak->GetDisplayPos(&tr, pCharPos, bCharCode);
+}
+FX_BOOL CXFA_TextLayout::ToRun(const XFA_TextPiece* pPiece, FX_RTFTEXTOBJ& tr) {
+  int32_t iLength = pPiece->iChars;
+  if (iLength < 1) {
+    return FALSE;
+  }
+  tr.pStr = pPiece->pszText;
+  tr.pFont = pPiece->pFont;
+  tr.pRect = &pPiece->rtPiece;
+  tr.pWidths = pPiece->pWidths;
+  tr.iLength = iLength;
+  tr.fFontSize = pPiece->fFontSize;
+  tr.iBidiLevel = pPiece->iBidiLevel;
+  tr.iCharRotation = 0;
+  tr.wLineBreakChar = L'\n';
+  tr.iVerticalScale = pPiece->iVerScale;
+  tr.dwLayoutStyles = FX_RTFLAYOUTSTYLE_ExpandTab;
+  tr.iHorizontalScale = pPiece->iHorScale;
+  return TRUE;
+}
diff --git a/xfa/fxfa/app/xfa_textlayout.h b/xfa/fxfa/app/xfa_textlayout.h
new file mode 100644
index 0000000..9cc1e29
--- /dev/null
+++ b/xfa/fxfa/app/xfa_textlayout.h
@@ -0,0 +1,425 @@
+// 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_FXFA_APP_XFA_TEXTLAYOUT_H_
+#define XFA_FXFA_APP_XFA_TEXTLAYOUT_H_
+
+#include "xfa/fde/css/fde_css.h"
+#include "xfa/fde/fde_brush.h"
+#include "xfa/fde/fde_renderdevice.h"
+#include "xfa/fgas/layout/fgas_rtfbreak.h"
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+#include "xfa/fxfa/parser/xfa_object.h"
+
+#define XFA_LOADERCNTXTFLG_FILTERSPACE 0x001
+
+class CXFA_Para;
+class CXFA_Font;
+class CXFA_TextTabstopsContext;
+
+class IXFA_TextProvider {
+ public:
+  virtual ~IXFA_TextProvider() {}
+  virtual CXFA_Node* GetTextNode(FX_BOOL& bRichText) = 0;
+  virtual CXFA_Para GetParaNode() = 0;
+  virtual CXFA_Font GetFontNode() = 0;
+  virtual FX_BOOL IsCheckButtonAndAutoWidth() = 0;
+  virtual CXFA_FFDoc* GetDocNode() = 0;
+  virtual FX_BOOL GetEmbbedObj(FX_BOOL bURI,
+                               FX_BOOL bRaw,
+                               const CFX_WideString& wsAttr,
+                               CFX_WideString& wsValue) = 0;
+};
+
+class CXFA_CSSTagProvider : public IFDE_CSSTagProvider {
+ public:
+  CXFA_CSSTagProvider() : m_bTagAviliable(FALSE), m_bContent(FALSE) {}
+  virtual ~CXFA_CSSTagProvider();
+  virtual CFX_WideStringC GetTagName() { return m_wsTagName; }
+  virtual FX_POSITION GetFirstAttribute() {
+    return m_Attributes.GetStartPosition();
+  }
+  virtual void GetNextAttribute(FX_POSITION& pos,
+                                CFX_WideStringC& wsAttr,
+                                CFX_WideStringC& wsValue);
+  void SetTagNameObj(const CFX_WideString& wsName) { m_wsTagName = wsName; }
+  void SetAttribute(const CFX_WideString& wsAttr,
+                    const CFX_WideString& wsValue);
+  FX_BOOL m_bTagAviliable;
+  FX_BOOL m_bContent;
+
+ protected:
+  CFX_WideString m_wsTagName;
+  CFX_MapPtrToPtr m_Attributes;
+};
+
+class CXFA_TextParseContext : public CFX_Target {
+ public:
+  CXFA_TextParseContext()
+      : m_pParentStyle(nullptr),
+        m_ppMatchedDecls(nullptr),
+        m_dwMatchedDecls(0),
+        m_eDisplay(FDE_CSSDISPLAY_None) {}
+  ~CXFA_TextParseContext() {
+    if (m_pParentStyle)
+      m_pParentStyle->Release();
+    FX_Free(m_ppMatchedDecls);
+  }
+  void SetDisplay(FDE_CSSDISPLAY eDisplay) { m_eDisplay = eDisplay; }
+  FDE_CSSDISPLAY GetDisplay() const { return m_eDisplay; }
+  void SetDecls(const IFDE_CSSDeclaration** ppDeclArray, int32_t iDeclCount);
+  const IFDE_CSSDeclaration** GetDecls() {
+    return (const IFDE_CSSDeclaration**)m_ppMatchedDecls;
+  }
+  FX_DWORD CountDecls() const { return m_dwMatchedDecls; }
+  IFDE_CSSComputedStyle* m_pParentStyle;
+
+ protected:
+  IFDE_CSSDeclaration** m_ppMatchedDecls;
+  FX_DWORD m_dwMatchedDecls;
+  FDE_CSSDISPLAY m_eDisplay;
+};
+
+class CXFA_TextParser {
+ public:
+  CXFA_TextParser() : m_pAllocator(NULL), m_pSelector(NULL), m_pUASheet(NULL) {}
+  virtual ~CXFA_TextParser();
+  void Reset();
+  void DoParse(IFDE_XMLNode* pXMLContainer, IXFA_TextProvider* pTextProvider);
+  IFDE_CSSComputedStyle* CreateRootStyle(IXFA_TextProvider* pTextProvider);
+  IFDE_CSSComputedStyle* ComputeStyle(IFDE_XMLNode* pXMLNode,
+                                      IFDE_CSSComputedStyle* pParentStyle);
+  FX_BOOL IsParsed() const { return m_pAllocator != NULL; }
+
+  int32_t GetVAlgin(IXFA_TextProvider* pTextProvider) const;
+  FX_FLOAT GetTabInterval(IFDE_CSSComputedStyle* pStyle) const;
+  int32_t CountTabs(IFDE_CSSComputedStyle* pStyle) const;
+  FX_BOOL IsSpaceRun(IFDE_CSSComputedStyle* pStyle) const;
+  FX_BOOL GetTabstops(IFDE_CSSComputedStyle* pStyle,
+                      CXFA_TextTabstopsContext* pTabstopContext);
+  IFX_Font* GetFont(IXFA_TextProvider* pTextProvider,
+                    IFDE_CSSComputedStyle* pStyle) const;
+  FX_FLOAT GetFontSize(IXFA_TextProvider* pTextProvider,
+                       IFDE_CSSComputedStyle* pStyle) const;
+  int32_t GetHorScale(IXFA_TextProvider* pTextProvider,
+                      IFDE_CSSComputedStyle* pStyle,
+                      IFDE_XMLNode* pXMLNode) const;
+  int32_t GetVerScale(IXFA_TextProvider* pTextProvider,
+                      IFDE_CSSComputedStyle* pStyle) const;
+  void GetUnderline(IXFA_TextProvider* pTextProvider,
+                    IFDE_CSSComputedStyle* pStyle,
+                    int32_t& iUnderline,
+                    int32_t& iPeriod) const;
+  void GetLinethrough(IXFA_TextProvider* pTextProvider,
+                      IFDE_CSSComputedStyle* pStyle,
+                      int32_t& iLinethrough) const;
+  FX_ARGB GetColor(IXFA_TextProvider* pTextProvider,
+                   IFDE_CSSComputedStyle* pStyle) const;
+  FX_FLOAT GetBaseline(IXFA_TextProvider* pTextProvider,
+                       IFDE_CSSComputedStyle* pStyle) const;
+  FX_FLOAT GetLineHeight(IXFA_TextProvider* pTextProvider,
+                         IFDE_CSSComputedStyle* pStyle,
+                         FX_BOOL bFirst,
+                         FX_FLOAT fVerScale) const;
+  FX_BOOL GetEmbbedObj(IXFA_TextProvider* pTextProvider,
+                       IFDE_XMLNode* pXMLNode,
+                       CFX_WideString& wsValue);
+  CXFA_TextParseContext* GetParseContextFromMap(IFDE_XMLNode* pXMLNode);
+
+ private:
+  void InitCSSData(IXFA_TextProvider* pTextProvider);
+  void ParseRichText(IFDE_XMLNode* pXMLNode,
+                     IFDE_CSSComputedStyle* pParentStyle);
+  void ParseTagInfo(IFDE_XMLNode* pXMLNode, CXFA_CSSTagProvider& tagProvider);
+  IFDE_CSSStyleSheet* LoadDefaultSheetStyle();
+  IFDE_CSSComputedStyle* CreateStyle(IFDE_CSSComputedStyle* pParentStyle);
+  IFX_MEMAllocator* m_pAllocator;
+  IFDE_CSSStyleSelector* m_pSelector;
+  IFDE_CSSStyleSheet* m_pUASheet;
+  CFX_MapPtrTemplate<IFDE_XMLNode*, CXFA_TextParseContext*>
+      m_mapXMLNodeToParseContext;
+};
+
+class CXFA_LoaderContext {
+ public:
+  CXFA_LoaderContext()
+      : m_bSaveLineHeight(FALSE),
+        m_fWidth(0),
+        m_fHeight(0),
+        m_fLastPos(0),
+        m_fStartLineOffset(0),
+        m_iChar(0),
+        m_iTotalLines(-1),
+        m_pXMLNode(NULL),
+        m_pNode(NULL),
+        m_pParentStyle(NULL),
+        m_dwFlags(0) {}
+  FX_BOOL m_bSaveLineHeight;
+  FX_FLOAT m_fWidth;
+  FX_FLOAT m_fHeight;
+  FX_FLOAT m_fLastPos;
+  FX_FLOAT m_fStartLineOffset;
+  int32_t m_iChar;
+  int32_t m_iLines;
+  int32_t m_iTotalLines;
+  IFDE_XMLNode* m_pXMLNode;
+  CXFA_Node* m_pNode;
+  IFDE_CSSComputedStyle* m_pParentStyle;
+  CFX_ArrayTemplate<FX_FLOAT> m_lineHeights;
+  FX_DWORD m_dwFlags;
+  CFX_FloatArray m_BlocksHeight;
+};
+
+class CXFA_LinkUserData : public IFX_Unknown, public CFX_Target {
+ public:
+  CXFA_LinkUserData(IFX_MEMAllocator* pAllocator, FX_WCHAR* pszText)
+      : m_pAllocator(pAllocator), m_dwRefCount(1) {
+    m_pszURLContent = pszText;
+  }
+  ~CXFA_LinkUserData() {}
+  virtual FX_DWORD Release() {
+    FX_DWORD dwRefCount = --m_dwRefCount;
+    if (dwRefCount <= 0) {
+      FXTARGET_DeleteWith(CXFA_LinkUserData, m_pAllocator, this);
+    }
+    return dwRefCount;
+  }
+  virtual FX_DWORD AddRef() { return ++m_dwRefCount; }
+
+ public:
+  const FX_WCHAR* GetLinkURL() { return m_pszURLContent; }
+
+ protected:
+  IFX_MEMAllocator* m_pAllocator;
+  FX_DWORD m_dwRefCount;
+  CFX_WideString m_pszURLContent;
+};
+
+class CXFA_TextUserData : public IFX_Unknown, public CFX_Target {
+ public:
+  CXFA_TextUserData(IFX_MEMAllocator* pAllocator, IFDE_CSSComputedStyle* pStyle)
+      : m_pStyle(pStyle),
+        m_pLinkData(nullptr),
+        m_pAllocator(pAllocator),
+        m_dwRefCount(0) {
+    FXSYS_assert(m_pAllocator);
+    if (m_pStyle)
+      m_pStyle->AddRef();
+  }
+  CXFA_TextUserData(IFX_MEMAllocator* pAllocator,
+                    IFDE_CSSComputedStyle* pStyle,
+                    CXFA_LinkUserData* pLinkData)
+      : m_pStyle(pStyle),
+        m_pLinkData(pLinkData),
+        m_pAllocator(pAllocator),
+        m_dwRefCount(0) {
+    FXSYS_assert(m_pAllocator);
+    if (m_pStyle)
+      m_pStyle->AddRef();
+  }
+  ~CXFA_TextUserData() {
+    if (m_pStyle)
+      m_pStyle->Release();
+    if (m_pLinkData)
+      m_pLinkData->Release();
+  }
+  virtual FX_DWORD Release() {
+    FX_DWORD dwRefCount = --m_dwRefCount;
+    if (dwRefCount == 0) {
+      FXTARGET_DeleteWith(CXFA_TextUserData, m_pAllocator, this);
+    }
+    return dwRefCount;
+  }
+  virtual FX_DWORD AddRef() { return ++m_dwRefCount; }
+
+  IFDE_CSSComputedStyle* m_pStyle;
+  CXFA_LinkUserData* m_pLinkData;
+
+ protected:
+  IFX_MEMAllocator* m_pAllocator;
+  FX_DWORD m_dwRefCount;
+};
+
+class XFA_TextPiece : public CFX_Target {
+ public:
+  XFA_TextPiece() : pszText(nullptr), pFont(nullptr), pLinkData(nullptr) {}
+  ~XFA_TextPiece() {
+    if (pLinkData)
+      pLinkData->Release();
+  }
+
+  FX_WCHAR* pszText;
+  int32_t iChars;
+  int32_t* pWidths;
+  int32_t iHorScale;
+  int32_t iVerScale;
+  int32_t iBidiLevel;
+  int32_t iUnderline;
+  int32_t iPeriod;
+  int32_t iLineThrough;
+  IFX_Font* pFont;
+  FX_ARGB dwColor;
+  FX_FLOAT fFontSize;
+  CFX_RectF rtPiece;
+  CXFA_LinkUserData* pLinkData;
+};
+typedef CFX_ArrayTemplate<XFA_TextPiece*> CXFA_PieceArray;
+
+class CXFA_PieceLine : public CFX_Target {
+ public:
+  CXFA_PieceLine() {}
+  CXFA_PieceArray m_textPieces;
+  CFX_Int32Array m_charCounts;
+};
+typedef CFX_ArrayTemplate<CXFA_PieceLine*> CXFA_PieceLineArray;
+
+struct XFA_TABSTOPS {
+  FX_DWORD dwAlign;
+  FX_FLOAT fTabstops;
+};
+
+class CXFA_TextTabstopsContext {
+ public:
+  CXFA_TextTabstopsContext()
+      : m_iTabCount(0),
+        m_iTabIndex(-1),
+        m_bTabstops(FALSE),
+        m_fTabWidth(0),
+        m_fLeft(0) {}
+  void Append(FX_DWORD dwAlign, FX_FLOAT fTabstops) {
+    int32_t i = 0;
+    for (i = 0; i < m_iTabCount; i++) {
+      XFA_TABSTOPS* pTabstop = m_tabstops.GetDataPtr(i);
+      if (fTabstops < pTabstop->fTabstops) {
+        break;
+      }
+    }
+    m_tabstops.InsertSpaceAt(i, 1);
+    XFA_TABSTOPS tabstop;
+    tabstop.dwAlign = dwAlign;
+    tabstop.fTabstops = fTabstops;
+    m_tabstops.SetAt(i, tabstop);
+    m_iTabCount++;
+  }
+  void RemoveAll() {
+    m_tabstops.RemoveAll();
+    m_iTabCount = 0;
+  }
+  void Reset() {
+    m_iTabIndex = -1;
+    m_bTabstops = FALSE;
+    m_fTabWidth = 0;
+    m_fLeft = 0;
+  }
+  CFX_ArrayTemplate<XFA_TABSTOPS> m_tabstops;
+  int32_t m_iTabCount;
+  int32_t m_iTabIndex;
+  FX_BOOL m_bTabstops;
+  FX_FLOAT m_fTabWidth;
+  FX_FLOAT m_fLeft;
+};
+
+class CXFA_TextLayout {
+ public:
+  CXFA_TextLayout(IXFA_TextProvider* pTextProvider);
+  virtual ~CXFA_TextLayout();
+  int32_t GetText(CFX_WideString& wsText);
+  FX_FLOAT GetLayoutHeight();
+  FX_FLOAT StartLayout(FX_FLOAT fWidth = -1);
+  FX_BOOL DoLayout(int32_t iBlockIndex,
+                   FX_FLOAT& fCalcHeight,
+                   FX_FLOAT fContentAreaHeight = -1,
+                   FX_FLOAT fTextHeight = -1);
+
+  FX_BOOL CalcSize(const CFX_SizeF& minSize,
+                   const CFX_SizeF& maxSize,
+                   CFX_SizeF& defaultSize);
+  FX_BOOL Layout(const CFX_SizeF& size, FX_FLOAT* fHeight = NULL);
+  void ItemBlocks(const CFX_RectF& rtText, int32_t iBlockIndex);
+  FX_BOOL DrawString(CFX_RenderDevice* pFxDevice,
+                     const CFX_Matrix& tmDoc2Device,
+                     const CFX_RectF& rtClip,
+                     int32_t iBlock = 0);
+  FX_BOOL IsLoaded() const { return m_pieceLines.GetSize() > 0; }
+  void Unload();
+  const CXFA_PieceLineArray* GetPieceLines();
+
+  FX_BOOL m_bHasBlock;
+  CFX_Int32Array m_Blocks;
+
+ private:
+  void GetTextDataNode();
+  IFDE_XMLNode* GetXMLContainerNode();
+  IFX_RTFBreak* CreateBreak(FX_BOOL bDefault);
+  void InitBreak(FX_FLOAT fLineWidth);
+  void InitBreak(IFDE_CSSComputedStyle* pStyle,
+                 FDE_CSSDISPLAY eDisplay,
+                 FX_FLOAT fLineWidth,
+                 IFDE_XMLNode* pXMLNode,
+                 IFDE_CSSComputedStyle* pParentStyle = NULL);
+  FX_BOOL Loader(const CFX_SizeF& szText,
+                 FX_FLOAT& fLinePos,
+                 FX_BOOL bSavePieces = TRUE);
+  void LoadText(CXFA_Node* pNode,
+                const CFX_SizeF& szText,
+                FX_FLOAT& fLinePos,
+                FX_BOOL bSavePieces);
+  FX_BOOL LoadRichText(IFDE_XMLNode* pXMLNode,
+                       const CFX_SizeF& szText,
+                       FX_FLOAT& fLinePos,
+                       IFDE_CSSComputedStyle* pParentStyle,
+                       FX_BOOL bSavePieces,
+                       CXFA_LinkUserData* pLinkData = NULL,
+                       FX_BOOL bEndBreak = TRUE,
+                       FX_BOOL bIsOl = FALSE,
+                       int32_t iLiCount = 0);
+  FX_BOOL AppendChar(const CFX_WideString& wsText,
+                     FX_FLOAT& fLinePos,
+                     FX_FLOAT fSpaceAbove,
+                     FX_BOOL bSavePieces);
+  void AppendTextLine(FX_DWORD dwStatus,
+                      FX_FLOAT& fLinePos,
+                      FX_BOOL bSavePieces,
+                      FX_BOOL bEndBreak = FALSE);
+  void EndBreak(FX_DWORD dwStatus, FX_FLOAT& fLinePos, FX_BOOL bDefault);
+  FX_BOOL IsEnd(FX_BOOL bSavePieces);
+  void ProcessText(CFX_WideString& wsText);
+  void UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom);
+  void RenderString(IFDE_RenderDevice* pDevice,
+                    IFDE_SolidBrush* pBrush,
+                    CXFA_PieceLine* pPieceLine,
+                    int32_t iPiece,
+                    FXTEXT_CHARPOS* pCharPos,
+                    const CFX_Matrix& tmDoc2Device);
+  void RenderPath(IFDE_RenderDevice* pDevice,
+                  IFDE_Pen* pPen,
+                  CXFA_PieceLine* pPieceLine,
+                  int32_t iPiece,
+                  FXTEXT_CHARPOS* pCharPos,
+                  const CFX_Matrix& tmDoc2Device);
+  int32_t GetDisplayPos(const XFA_TextPiece* pPiece,
+                        FXTEXT_CHARPOS* pCharPos,
+                        FX_BOOL bCharCode = FALSE);
+  FX_BOOL ToRun(const XFA_TextPiece* pPiece, FX_RTFTEXTOBJ& tr);
+  void DoTabstops(IFDE_CSSComputedStyle* pStyle, CXFA_PieceLine* pPieceLine);
+  FX_BOOL Layout(int32_t iBlock);
+  int32_t CountBlocks() const;
+
+  IXFA_TextProvider* m_pTextProvider;
+  CXFA_Node* m_pTextDataNode;
+  FX_BOOL m_bRichText;
+  IFX_MEMAllocator* m_pAllocator;
+  IFX_RTFBreak* m_pBreak;
+  CXFA_LoaderContext* m_pLoader;
+  int32_t m_iLines;
+  FX_FLOAT m_fMaxWidth;
+  CXFA_TextParser m_textParser;
+  CXFA_PieceLineArray m_pieceLines;
+  CXFA_TextTabstopsContext* m_pTabstopContext;
+  FX_BOOL m_bBlockContinue;
+};
+
+#endif  // XFA_FXFA_APP_XFA_TEXTLAYOUT_H_