summaryrefslogtreecommitdiff
path: root/xfa/src/fgas/src
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/src/fgas/src')
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu1250.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu1251.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu1252.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu1253.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu1254.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu1255.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu1256.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu1257.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu1258.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu874.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu932.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu936.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu949.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpcu950.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi1250.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi1251.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi1252.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi1253.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi1254.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi1255.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi1256.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi1257.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi1258.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi874.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi932.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi936.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi949.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cphi950.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc1250.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc1251.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc1252.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc1253.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc1254.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc1255.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc1256.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc1257.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc1258.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc874.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc932.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc936.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc949.cpp6
-rw-r--r--xfa/src/fgas/src/crt/codepage/cpuc950.cpp6
-rw-r--r--xfa/src/fgas/src/crt/fx_algorithm.cpp315
-rw-r--r--xfa/src/fgas/src/crt/fx_codepage.cpp373
-rw-r--r--xfa/src/fgas/src/crt/fx_codepage.h9
-rw-r--r--xfa/src/fgas/src/crt/fx_cpmgr.cpp65
-rw-r--r--xfa/src/fgas/src/crt/fx_encode.cpp189
-rw-r--r--xfa/src/fgas/src/crt/fx_memory.cpp334
-rw-r--r--xfa/src/fgas/src/crt/fx_memory.h199
-rw-r--r--xfa/src/fgas/src/crt/fx_stream.cpp1613
-rw-r--r--xfa/src/fgas/src/crt/fx_stream.h405
-rw-r--r--xfa/src/fgas/src/crt/fx_system.cpp236
-rw-r--r--xfa/src/fgas/src/crt/fx_utils.cpp456
-rw-r--r--xfa/src/fgas/src/crt/fx_utils.h32
-rw-r--r--xfa/src/fgas/src/fgas_base.h12
-rw-r--r--xfa/src/fgas/src/font/fx_fontutils.cpp236
-rw-r--r--xfa/src/fgas/src/font/fx_fontutils.h19
-rw-r--r--xfa/src/fgas/src/font/fx_gdifont.cpp532
-rw-r--r--xfa/src/fgas/src/font/fx_gdifont.h89
-rw-r--r--xfa/src/fgas/src/font/fx_gefont.cpp595
-rw-r--r--xfa/src/fgas/src/font/fx_gefont.h81
-rw-r--r--xfa/src/fgas/src/font/fx_stdfontmgr.cpp1490
-rw-r--r--xfa/src/fgas/src/font/fx_stdfontmgr.h175
-rw-r--r--xfa/src/fgas/src/layout/fx_linebreak.cpp121
-rw-r--r--xfa/src/fgas/src/layout/fx_rtfbreak.cpp1522
-rw-r--r--xfa/src/fgas/src/layout/fx_rtfbreak.h180
-rw-r--r--xfa/src/fgas/src/layout/fx_textbreak.cpp1653
-rw-r--r--xfa/src/fgas/src/layout/fx_textbreak.h171
-rw-r--r--xfa/src/fgas/src/layout/fx_unicode.cpp146
-rw-r--r--xfa/src/fgas/src/layout/fx_unicode.h15
-rw-r--r--xfa/src/fgas/src/localization/fx_datetime.cpp548
-rw-r--r--xfa/src/fgas/src/localization/fx_locale.cpp4954
-rw-r--r--xfa/src/fgas/src/localization/fx_localeimp.h74
-rw-r--r--xfa/src/fgas/src/localization/fx_localemgr.cpp100
-rw-r--r--xfa/src/fgas/src/localization/fx_localemgr.h27
-rw-r--r--xfa/src/fgas/src/xml/fx_sax_imp.cpp720
-rw-r--r--xfa/src/fgas/src/xml/fx_sax_imp.h140
77 files changed, 18078 insertions, 0 deletions
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu1250.cpp b/xfa/src/fgas/src/crt/codepage/cpcu1250.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu1250.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu1251.cpp b/xfa/src/fgas/src/crt/codepage/cpcu1251.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu1251.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu1252.cpp b/xfa/src/fgas/src/crt/codepage/cpcu1252.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu1252.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu1253.cpp b/xfa/src/fgas/src/crt/codepage/cpcu1253.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu1253.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu1254.cpp b/xfa/src/fgas/src/crt/codepage/cpcu1254.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu1254.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu1255.cpp b/xfa/src/fgas/src/crt/codepage/cpcu1255.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu1255.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu1256.cpp b/xfa/src/fgas/src/crt/codepage/cpcu1256.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu1256.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu1257.cpp b/xfa/src/fgas/src/crt/codepage/cpcu1257.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu1257.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu1258.cpp b/xfa/src/fgas/src/crt/codepage/cpcu1258.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu1258.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu874.cpp b/xfa/src/fgas/src/crt/codepage/cpcu874.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu874.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu932.cpp b/xfa/src/fgas/src/crt/codepage/cpcu932.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu932.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu936.cpp b/xfa/src/fgas/src/crt/codepage/cpcu936.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu936.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu949.cpp b/xfa/src/fgas/src/crt/codepage/cpcu949.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu949.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpcu950.cpp b/xfa/src/fgas/src/crt/codepage/cpcu950.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpcu950.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi1250.cpp b/xfa/src/fgas/src/crt/codepage/cphi1250.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi1250.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi1251.cpp b/xfa/src/fgas/src/crt/codepage/cphi1251.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi1251.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi1252.cpp b/xfa/src/fgas/src/crt/codepage/cphi1252.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi1252.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi1253.cpp b/xfa/src/fgas/src/crt/codepage/cphi1253.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi1253.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi1254.cpp b/xfa/src/fgas/src/crt/codepage/cphi1254.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi1254.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi1255.cpp b/xfa/src/fgas/src/crt/codepage/cphi1255.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi1255.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi1256.cpp b/xfa/src/fgas/src/crt/codepage/cphi1256.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi1256.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi1257.cpp b/xfa/src/fgas/src/crt/codepage/cphi1257.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi1257.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi1258.cpp b/xfa/src/fgas/src/crt/codepage/cphi1258.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi1258.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi874.cpp b/xfa/src/fgas/src/crt/codepage/cphi874.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi874.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi932.cpp b/xfa/src/fgas/src/crt/codepage/cphi932.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi932.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi936.cpp b/xfa/src/fgas/src/crt/codepage/cphi936.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi936.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi949.cpp b/xfa/src/fgas/src/crt/codepage/cphi949.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi949.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cphi950.cpp b/xfa/src/fgas/src/crt/codepage/cphi950.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cphi950.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc1250.cpp b/xfa/src/fgas/src/crt/codepage/cpuc1250.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc1250.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc1251.cpp b/xfa/src/fgas/src/crt/codepage/cpuc1251.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc1251.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc1252.cpp b/xfa/src/fgas/src/crt/codepage/cpuc1252.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc1252.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc1253.cpp b/xfa/src/fgas/src/crt/codepage/cpuc1253.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc1253.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc1254.cpp b/xfa/src/fgas/src/crt/codepage/cpuc1254.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc1254.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc1255.cpp b/xfa/src/fgas/src/crt/codepage/cpuc1255.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc1255.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc1256.cpp b/xfa/src/fgas/src/crt/codepage/cpuc1256.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc1256.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc1257.cpp b/xfa/src/fgas/src/crt/codepage/cpuc1257.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc1257.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc1258.cpp b/xfa/src/fgas/src/crt/codepage/cpuc1258.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc1258.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc874.cpp b/xfa/src/fgas/src/crt/codepage/cpuc874.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc874.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc932.cpp b/xfa/src/fgas/src/crt/codepage/cpuc932.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc932.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc936.cpp b/xfa/src/fgas/src/crt/codepage/cpuc936.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc936.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc949.cpp b/xfa/src/fgas/src/crt/codepage/cpuc949.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc949.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/codepage/cpuc950.cpp b/xfa/src/fgas/src/crt/codepage/cpuc950.cpp
new file mode 100644
index 0000000000..6cd252bcf4
--- /dev/null
+++ b/xfa/src/fgas/src/crt/codepage/cpuc950.cpp
@@ -0,0 +1,6 @@
+// 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
+
diff --git a/xfa/src/fgas/src/crt/fx_algorithm.cpp b/xfa/src/fgas/src/crt/fx_algorithm.cpp
new file mode 100644
index 0000000000..e2d77d1a0e
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_algorithm.cpp
@@ -0,0 +1,315 @@
+// 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 "../fgas_base.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+const static FX_CHAR g_FXBase64EncoderMap[64] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/',
+};
+typedef struct _FX_BASE64DATA {
+
+ FX_DWORD data1 : 2;
+ FX_DWORD data2 : 6;
+ FX_DWORD data3 : 4;
+ FX_DWORD data4 : 4;
+ FX_DWORD data5 : 6;
+ FX_DWORD data6 : 2;
+ FX_DWORD data7 : 8;
+} FX_BASE64DATA, * FX_LPBASE64ENCODEDATA;
+typedef FX_BASE64DATA const * FX_LPCBASE64DATA;
+static void FX_Base64EncodePiece(const FX_BASE64DATA &src, FX_INT32 iBytes, FX_CHAR dst[4])
+{
+ dst[0] = g_FXBase64EncoderMap[src.data2];
+ FX_DWORD b = src.data1 << 4;
+ if (iBytes > 1) {
+ b |= src.data4;
+ }
+ dst[1] = g_FXBase64EncoderMap[b];
+ if (iBytes > 1) {
+ b = src.data3 << 2;
+ if (iBytes > 2) {
+ b |= src.data6;
+ }
+ dst[2] = g_FXBase64EncoderMap[b];
+ if (iBytes > 2) {
+ dst[3] = g_FXBase64EncoderMap[src.data5];
+ } else {
+ dst[3] = '=';
+ }
+ } else {
+ dst[2] = dst[3] = '=';
+ }
+}
+FX_INT32 FX_Base64EncodeA(FX_LPCBYTE pSrc, FX_INT32 iSrcLen, FX_LPSTR pDst)
+{
+ FXSYS_assert(pSrc != NULL);
+ if (iSrcLen < 1) {
+ return 0;
+ }
+ if (pDst == NULL) {
+ FX_INT32 iDstLen = iSrcLen / 3 * 4;
+ if ((iSrcLen % 3) != 0) {
+ iDstLen += 4;
+ }
+ return iDstLen;
+ }
+ FX_BASE64DATA srcData;
+ FX_INT32 iBytes = 3;
+ FX_LPSTR pDstEnd = pDst;
+ while (iSrcLen > 0) {
+ if (iSrcLen > 2) {
+ ((FX_LPBYTE)&srcData)[0] = *pSrc ++;
+ ((FX_LPBYTE)&srcData)[1] = *pSrc ++;
+ ((FX_LPBYTE)&srcData)[2] = *pSrc ++;
+ iSrcLen -= 3;
+ } else {
+ *((FX_LPDWORD)&srcData) = 0;
+ ((FX_LPBYTE)&srcData)[0] = *pSrc ++;
+ if (iSrcLen > 1) {
+ ((FX_LPBYTE)&srcData)[1] = *pSrc ++;
+ }
+ iBytes = iSrcLen;
+ iSrcLen = 0;
+ }
+ FX_Base64EncodePiece(srcData, iBytes, pDstEnd);
+ pDstEnd += 4;
+ }
+ return pDstEnd - pDst;
+}
+const static FX_BYTE g_FXBase64DecoderMap[256] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
+ 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+static void FX_Base64DecodePiece(const FX_CHAR src[4], FX_INT32 iChars, FX_BASE64DATA &dst, FX_INT32 &iBytes)
+{
+ FXSYS_assert(iChars > 0 && iChars < 5);
+ iBytes = 1;
+ dst.data2 = g_FXBase64DecoderMap[(FX_BYTE)src[0]];
+ if (iChars > 1) {
+ FX_BYTE b = g_FXBase64DecoderMap[(FX_BYTE)src[1]];
+ dst.data1 = b >> 4;
+ dst.data4 = b;
+ if (iChars > 2) {
+ iBytes = 2;
+ b = g_FXBase64DecoderMap[(FX_BYTE)src[2]];
+ dst.data3 = b >> 2;
+ dst.data6 = b;
+ if (iChars > 3) {
+ iBytes = 3;
+ dst.data5 = g_FXBase64DecoderMap[(FX_BYTE)src[3]];
+ } else {
+ dst.data5 = 0;
+ }
+ } else {
+ dst.data3 = 0;
+ }
+ } else {
+ dst.data1 = 0;
+ }
+}
+FX_INT32 FX_Base64DecodeA(FX_LPCSTR pSrc, FX_INT32 iSrcLen, FX_LPBYTE pDst)
+{
+ FXSYS_assert(pSrc != NULL);
+ if (iSrcLen < 1) {
+ return 0;
+ }
+ while (iSrcLen > 0 && pSrc[iSrcLen - 1] == '=') {
+ iSrcLen --;
+ }
+ if (iSrcLen < 1) {
+ return 0;
+ }
+ if (pDst == NULL) {
+ FX_INT32 iDstLen = iSrcLen / 4 * 3;
+ iSrcLen %= 4;
+ if (iSrcLen == 1) {
+ iDstLen += 1;
+ } else if (iSrcLen == 2) {
+ iDstLen += 1;
+ } else if (iSrcLen == 3) {
+ iDstLen += 2;
+ }
+ return iDstLen;
+ }
+ FX_CHAR srcData[4];
+ FX_BASE64DATA dstData;
+ FX_INT32 iChars = 4, iBytes;
+ FX_LPBYTE pDstEnd = pDst;
+ while (iSrcLen > 0) {
+ if (iSrcLen > 3) {
+ *((FX_DWORD*)srcData) = *((FX_DWORD*)pSrc);
+ pSrc += 4;
+ iSrcLen -= 4;
+ } else {
+ *((FX_LPDWORD)&dstData) = 0;
+ *((FX_DWORD*)srcData) = 0;
+ srcData[0] = *pSrc ++;
+ if (iSrcLen > 1) {
+ srcData[1] = *pSrc ++;
+ }
+ if (iSrcLen > 2) {
+ srcData[2] = *pSrc ++;
+ }
+ iChars = iSrcLen;
+ iSrcLen = 0;
+ }
+ FX_Base64DecodePiece(srcData, iChars, dstData, iBytes);
+ *pDstEnd ++ = ((FX_LPBYTE)&dstData)[0];
+ if (iBytes > 1) {
+ *pDstEnd ++ = ((FX_LPBYTE)&dstData)[1];
+ }
+ if (iBytes > 2) {
+ *pDstEnd ++ = ((FX_LPBYTE)&dstData)[2];
+ }
+ }
+ return pDstEnd - pDst;
+}
+FX_INT32 FX_Base64DecodeW(FX_LPCWSTR pSrc, FX_INT32 iSrcLen, FX_LPBYTE pDst)
+{
+ FXSYS_assert(pSrc != NULL);
+ if (iSrcLen < 1) {
+ return 0;
+ }
+ while (iSrcLen > 0 && pSrc[iSrcLen - 1] == '=') {
+ iSrcLen --;
+ }
+ if (iSrcLen < 1) {
+ return 0;
+ }
+ if (pDst == NULL) {
+ FX_INT32 iDstLen = iSrcLen / 4 * 3;
+ iSrcLen %= 4;
+ if (iSrcLen == 1) {
+ iDstLen += 1;
+ } else if (iSrcLen == 2) {
+ iDstLen += 1;
+ } else if (iSrcLen == 3) {
+ iDstLen += 2;
+ }
+ return iDstLen;
+ }
+ FX_CHAR srcData[4];
+ FX_BASE64DATA dstData;
+ FX_INT32 iChars = 4, iBytes;
+ FX_LPBYTE pDstEnd = pDst;
+ while (iSrcLen > 0) {
+ if (iSrcLen > 3) {
+ srcData[0] = (FX_CHAR) * pSrc ++;
+ srcData[1] = (FX_CHAR) * pSrc ++;
+ srcData[2] = (FX_CHAR) * pSrc ++;
+ srcData[3] = (FX_CHAR) * pSrc ++;
+ iSrcLen -= 4;
+ } else {
+ *((FX_LPDWORD)&dstData) = 0;
+ *((FX_DWORD*)srcData) = 0;
+ srcData[0] = (FX_CHAR) * pSrc ++;
+ if (iSrcLen > 1) {
+ srcData[1] = (FX_CHAR) * pSrc ++;
+ }
+ if (iSrcLen > 2) {
+ srcData[2] = (FX_CHAR) * pSrc ++;
+ }
+ iChars = iSrcLen;
+ iSrcLen = 0;
+ }
+ FX_Base64DecodePiece(srcData, iChars, dstData, iBytes);
+ *pDstEnd ++ = ((FX_LPBYTE)&dstData)[0];
+ if (iBytes > 1) {
+ *pDstEnd ++ = ((FX_LPBYTE)&dstData)[1];
+ }
+ if (iBytes > 2) {
+ *pDstEnd ++ = ((FX_LPBYTE)&dstData)[2];
+ }
+ }
+ return pDstEnd - pDst;
+}
+const static FX_BYTE g_FXHex2DecMap[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+FX_BYTE FX_Hex2Dec(FX_BYTE hexHigh, FX_BYTE hexLow)
+{
+ return (g_FXHex2DecMap[hexHigh] << 4) + g_FXHex2DecMap[hexLow];
+}
+FX_INT32 FX_SeparateStringW(FX_LPCWSTR pStr, FX_INT32 iStrLen, FX_WCHAR delimiter, CFX_WideStringArray &pieces)
+{
+ if (pStr == NULL) {
+ return 0;
+ }
+ if (iStrLen < 0) {
+ iStrLen = FXSYS_wcslen(pStr);
+ }
+ FX_LPCWSTR pToken = pStr;
+ FX_LPCWSTR pEnd = pStr + iStrLen;
+ while (TRUE) {
+ if (pStr >= pEnd || delimiter == *pStr) {
+ CFX_WideString sub(pToken, pStr - pToken);
+ pieces.Add(sub);
+ pToken = pStr + 1;
+ if (pStr >= pEnd) {
+ break;
+ }
+ }
+ pStr ++;
+ }
+ return pieces.GetSize();
+}
+#ifdef __cplusplus
+};
+#endif
diff --git a/xfa/src/fgas/src/crt/fx_codepage.cpp b/xfa/src/fgas/src/crt/fx_codepage.cpp
new file mode 100644
index 0000000000..798edc9776
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_codepage.cpp
@@ -0,0 +1,373 @@
+// 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 "../fgas_base.h"
+#include "fx_codepage.h"
+static const FX_CHARSET_MAP g_FXCharset2CodePageTable[] = {
+ { 0, 1252 },
+ { 1, 0 },
+ { 2, 42 },
+ { 77, 10000 },
+ { 78, 10001 },
+ { 79, 10003 },
+ { 80, 10008 },
+ { 81, 10002 },
+ { 83, 10005 },
+ { 84, 10004 },
+ { 85, 10006 },
+ { 86, 10081 },
+ { 87, 10021 },
+ { 88, 10029 },
+ { 89, 10007 },
+ { 128, 932 },
+ { 129, 949 },
+ { 130, 1361 },
+ { 134, 936 },
+ { 136, 950 },
+ { 161, 1253 },
+ { 162, 1254 },
+ { 163, 1258 },
+ { 177, 1255 },
+ { 178, 1256 },
+ { 186, 1257 },
+ { 204, 1251 },
+ { 222, 874 },
+ { 238, 1250 },
+ { 254, 437 },
+ { 255, 850 },
+};
+FX_WORD FX_GetCodePageFromCharset(FX_BYTE charset)
+{
+ FX_INT32 iEnd = sizeof(g_FXCharset2CodePageTable) / sizeof(FX_CHARSET_MAP) - 1;
+ FXSYS_assert(iEnd >= 0);
+ FX_INT32 iStart = 0, iMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const FX_CHARSET_MAP & cp = g_FXCharset2CodePageTable[iMid];
+ if (charset == cp.charset) {
+ return cp.codepage;
+ } else if (charset < cp.charset) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return 0xFFFF;
+}
+static const FX_CHARSET_MAP g_FXCodepage2CharsetTable[] = {
+ { 1, 0 },
+ { 2, 42 },
+ { 254, 437 },
+ { 255, 850 },
+ { 222, 874 },
+ { 128, 932 },
+ { 134, 936 },
+ { 129, 949 },
+ { 136, 950 },
+ { 238, 1250 },
+ { 204, 1251 },
+ { 0, 1252 },
+ { 161, 1253 },
+ { 162, 1254 },
+ { 177, 1255 },
+ { 178, 1256 },
+ { 186, 1257 },
+ { 163, 1258 },
+ { 130, 1361 },
+ { 77, 10000 },
+ { 78, 10001 },
+ { 79, 10003 },
+ { 80, 10008 },
+ { 81, 10002 },
+ { 83, 10005 },
+ { 84, 10004 },
+ { 85, 10006 },
+ { 86, 10081 },
+ { 87, 10021 },
+ { 88, 10029 },
+ { 89, 10007 },
+};
+FX_WORD FX_GetCharsetFromCodePage(FX_WORD codepage)
+{
+ FX_INT32 iEnd = sizeof(g_FXCodepage2CharsetTable) / sizeof(FX_CHARSET_MAP) - 1;
+ FXSYS_assert(iEnd >= 0);
+ FX_INT32 iStart = 0, iMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const FX_CHARSET_MAP & cp = g_FXCodepage2CharsetTable[iMid];
+ if (codepage == cp.codepage) {
+ return cp.charset;
+ } else if (codepage < cp.codepage) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return 0xFFFF;
+}
+const FX_LANG2CPMAP g_FXLang2CodepageTable[] = {
+ {FX_LANG_Arabic_SaudiArabia , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_Bulgarian_Bulgaria , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Catalan_Catalan , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Chinese_Taiwan , FX_CODEPAGE_ChineseTraditional },
+ {FX_LANG_CzechRepublic , FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Danish_Denmark , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_German_Germany , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Greek_Greece , FX_CODEPAGE_MSWin_Greek },
+ {FX_LANG_English_UnitedStates , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_TraditionalSort , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Finnish_Finland , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_France , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Hebrew_Israel , FX_CODEPAGE_MSWin_Hebrew },
+ {FX_LANG_Hungarian_Hungary , FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Icelandic_Iceland , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Italian_Italy , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Japanese_Japan , FX_CODEPAGE_ShiftJIS },
+ {FX_LANG_Korean_Korea , FX_CODEPAGE_Korean },
+ {FX_LANG_Dutch_Netherlands , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Norwegian_Bokmal , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Polish_Poland , FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Portuguese_Brazil , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Romanian_Romania , FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Russian_Russia , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Croatian_Croatia , FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Slovak_Slovakia , FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Albanian_Albania , FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Swedish_Sweden , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Thai_Thailand , FX_CODEPAGE_MSDOS_Thai },
+ {FX_LANG_Turkish_Turkey , FX_CODEPAGE_MSWin_Turkish },
+ {FX_LANG_Urdu_Pakistan , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_Indonesian_Indonesia , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Ukrainian_Ukraine , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Belarusian_Belarus , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Slovenian_Slovenia , FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Estonian_Estonia , FX_CODEPAGE_MSWin_Baltic },
+ {FX_LANG_Latvian_Latvia , FX_CODEPAGE_MSWin_Baltic },
+ {FX_LANG_Lithuanian_Lithuania , FX_CODEPAGE_MSWin_Baltic },
+ {FX_LANG_Persian , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_Vietnamese_Vietnam , FX_CODEPAGE_MSWin_Vietnamese },
+ {FX_LANG_Armenian_Armenia , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Azerbaijan_Latin , FX_CODEPAGE_MSWin_Turkish },
+ {FX_LANG_Basque_Basque , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Macedonian , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Afrikaans_SouthAfrica , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Georgian_Georgia , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Faroese_FaroeIslands , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Hindi_India , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Malay_Malaysia , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Kazakh_Kazakhstan , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Kyrgyz_Kyrgyzstan , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Kiswahili_Kenya , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Uzbek_LatinUzbekistan , FX_CODEPAGE_MSWin_Turkish },
+ {FX_LANG_Tatar_Russia , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Punjabi_India , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Gujarati_India , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Tamil_India , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Telugu_India , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Kannada_India , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Marathi_India , FX_CODEPAGE_DefANSI },
+ {FX_LANG_SanskritIndia , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Mongolian_CyrillicMongolia, FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Galician_Galician , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Konkani_India , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Syriac_Syria , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Divehi_Maldives , FX_CODEPAGE_DefANSI },
+ {FX_LANG_Arabic_Iraq , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_Chinese_PRC , FX_CODEPAGE_ChineseSimplified },
+ {FX_LANG_German_Switzerland , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_English_UnitedKingdom , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Mexico , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_Belgium , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Italian_Switzerland , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Dutch_Belgium , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Norwegian_Nynorsk , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Portuguese_Portugal , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_SerbianLatin_Serbia , FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Swedish_Finland , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Azerbaijan_Cyrillic , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Malay_BruneiDarussalam , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Uzbek_CyrillicUzbekistan , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Arabic_Egypt , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_Chinese_HongKong , FX_CODEPAGE_ChineseTraditional },
+ {FX_LANG_German_Austria , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_English_Australia , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_InternationalSort, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_Canada , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_SerbianCyrillic_Serbia , FX_CODEPAGE_MSWin_Cyrillic },
+ {FX_LANG_Arabic_Libya , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_Chinese_Singapore , FX_CODEPAGE_ChineseSimplified },
+ {FX_LANG_German_Luxembourg , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_English_Canada , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Guatemala , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_Switzerland , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Algeria , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_Chinese_Macao , FX_CODEPAGE_ChineseTraditional },
+ {FX_LANG_German_Liechtenstein , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_English_NewZealand , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_CostaRica , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_Luxembourg , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Morocco , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_English_Ireland , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Panama , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_Monaco , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Tunisia , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_English_SouthAfrica , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_DominicanRepublic, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Oman , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_English_Jamaica , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Venezuela , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Yemen , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_English_Caribbean , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Colombia , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Syria , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_English_Belize , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Peru , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Jordan , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_English_TrinidadTobago , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Argentina , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Lebanon , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_English_Zimbabwe , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Ecuador , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Kuwait , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_English_Philippines , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Chile , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_UAE , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_Spanish_Uruguay , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Bahrain , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_Spanish_Paraguay , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Qatar , FX_CODEPAGE_MSWin_Arabic },
+ {FX_LANG_Spanish_Bolivia , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_ElSalvador , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Honduras , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Nicaragua , FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_PuertoRico , FX_CODEPAGE_MSWin_WesternEuropean},
+};
+FX_WORD FX_GetDefCodePageByLanguage(FX_WORD wLanguage)
+{
+ FX_INT32 iEnd = sizeof(g_FXLang2CodepageTable) / sizeof(FX_LANG2CPMAP) - 1;
+ FXSYS_assert(iEnd >= 0);
+ FX_INT32 iStart = 0, iMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const FX_LANG2CPMAP &cp = g_FXLang2CodepageTable[iMid];
+ if (wLanguage == cp.wLanguage) {
+ return cp.wCodepage;
+ } else if (wLanguage < cp.wLanguage) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return 0xFFFF;
+}
+static const FX_STR2CPHASH g_FXCPHashTable[] = {
+ { 0xd45, 0x6faf }, { 0xd46, 0x6fb0 }, { 0xd47, 0x6fb1 }, { 0xd48, 0x6fb2 },
+ { 0xd49, 0x4e6 }, { 0xd4d, 0x6fbd }, { 0xe9e, 0x4e4 }, { 0xc998, 0x1b5 },
+ { 0x18ef0, 0x3a8 }, { 0x19f85, 0x5182 }, { 0x2e2335, 0x3b6 }, { 0x325153, 0x5182 },
+ { 0x145bded, 0x2716 }, { 0x3c9a5f2, 0xc6f3 }, { 0x4c45f2d, 0x3a4 }, { 0x4c45f4e, 0xc431 },
+ { 0x58caf51, 0x4e4 }, { 0x5a5cd7d, 0x3a8 }, { 0x5a6c6a7, 0x4e4 }, { 0x5a6ca0b, 0x1b5 },
+ { 0x5a6cd68, 0x307 }, { 0x5a6d8d3, 0x4e4 }, { 0x5a6d948, 0x354 }, { 0x5a6d96b, 0x362 },
+ { 0x5a6d984, 0x366 }, { 0x5a90e35, 0x1b5 }, { 0x5e0cf00, 0x6fb5 }, { 0x609c324, 0x551 },
+ { 0x617d97f, 0x5182 }, { 0x6a6fd91, 0xfde8 }, { 0x6a6fd92, 0xfde9 }, { 0x6b102de, 0xcadc },
+ { 0x6b10f48, 0x4e89 }, { 0x1020805f, 0x4e4 }, { 0x10f0524c, 0x6fb5 }, { 0x11d558fe, 0x6fb0 },
+ { 0x13898d19, 0xc42d }, { 0x13898d3a, 0xc431 }, { 0x138a319e, 0x6fb1 }, { 0x14679c09, 0x96c6 },
+ { 0x153f0a3d, 0x6fb2 }, { 0x1576eeb3, 0x4e20 }, { 0x169a0ce6, 0xc6f9 }, { 0x16f3e2dc, 0x6fb3 },
+ { 0x18a8bb7a, 0x6fb4 }, { 0x1a5d9419, 0x6fb5 }, { 0x1a847b48, 0x3a8 }, { 0x1b762419, 0xcec8 },
+ { 0x1b9d7847, 0x475 }, { 0x1c126cb9, 0x6fb6 }, { 0x1ccdbc7d, 0x4f42 }, { 0x1d330f5f, 0x2714 },
+ { 0x1dc74559, 0x4e6 }, { 0x1edd80da, 0x4e4 }, { 0x23e4b03d, 0xfde8 }, { 0x24f28a16, 0x4f3d },
+ { 0x286e7a32, 0x2715 }, { 0x2c7c18ed, 0x3a8 }, { 0x2e2103b7, 0x2713 }, { 0x304bf479, 0x6fb4 },
+ { 0x304bf47d, 0x6fb5 }, { 0x309bb869, 0xfde8 }, { 0x309bb86a, 0xfde9 }, { 0x33664357, 0x3b6 },
+ { 0x352d6b49, 0x3a4 }, { 0x36f5661c, 0x1b5 }, { 0x392e8f48, 0xcadc }, { 0x3dc7c64c, 0x47c },
+ { 0x3ed2e8e1, 0x4e4 }, { 0x3f0c2fea, 0xcaed }, { 0x3f0fef8f, 0xc6f2 }, { 0x3f5e130f, 0x5182 },
+ { 0x47174d1f, 0x3a8 }, { 0x49686b7b, 0x6fb4 }, { 0x4b80b0d9, 0x3a4 }, { 0x4dcda97a, 0x4e4 },
+ { 0x4dcda9b6, 0x4e4 }, { 0x4e881e6a, 0x5221 }, { 0x4ffdf5a1, 0x36a }, { 0x4ffdf5a5, 0x6fbd },
+ { 0x5241ce16, 0x4e8b }, { 0x546bab9d, 0x4e4 }, { 0x54a3d64e, 0x6fb6 }, { 0x562179bd, 0x5161 },
+ { 0x57c1df15, 0xc6f7 }, { 0x61ff6e62, 0x4f36 }, { 0x6359c7d8, 0x4f35 }, { 0x63f3c335, 0x3a8 },
+ { 0x645a0f78, 0x477 }, { 0x691ac2fd, 0x275f }, { 0x6dc2eab0, 0x2d0 }, { 0x6dc2eeef, 0x35e },
+ { 0x6dc2ef10, 0x36a }, { 0x7103138a, 0x47d }, { 0x710dfbd0, 0xc6f5 }, { 0x7319f6cb, 0x36a },
+ { 0x745096ad, 0x3a8 }, { 0x74866229, 0x4e8c }, { 0x77185fa5, 0x3a8 }, { 0x7953f002, 0x6faf },
+ { 0x7953f003, 0x6fb0 }, { 0x7953f004, 0x6fb1 }, { 0x7953f005, 0x6fb2 }, { 0x7953f006, 0x6fb7 },
+ { 0x7953f00a, 0x6fbd }, { 0x7c577571, 0x2761 }, { 0x7e8c8ff1, 0x479 }, { 0x8031f47f, 0x3b5 },
+ { 0x8031f481, 0x3b5 }, { 0x80c4a710, 0x5187 }, { 0x857c7e14, 0xfde8 }, { 0x857c7e15, 0xfde9 },
+ { 0x86b59c90, 0x4e4 }, { 0x86b59c91, 0x6fb0 }, { 0x86b59c92, 0x6fb1 }, { 0x86b59c93, 0x6fb2 },
+ { 0x86b59c94, 0x6fb3 }, { 0x86b59c95, 0x6fb4 }, { 0x86b59c96, 0x6fb5 }, { 0x86b59c97, 0x4e7 },
+ { 0x86b59c98, 0x4e6 }, { 0x8b4b24ec, 0x5190 }, { 0x8face362, 0x4e4 }, { 0x8ff9ec2a, 0xfde9 },
+ { 0x919d3989, 0xcadc }, { 0x9967e5ad, 0x4e22 }, { 0x99f8b933, 0x6fbd }, { 0x9bd2a380, 0x4fc7 },
+ { 0x9befad23, 0x4f38 }, { 0x9c7ac649, 0x4f3c }, { 0xa02468db, 0xdeae }, { 0xa02468ec, 0xdeab },
+ { 0xa024692a, 0xdeaa }, { 0xa0246997, 0xdeb2 }, { 0xa02469ff, 0xdeb0 }, { 0xa0246a3d, 0xdeb1 },
+ { 0xa0246a8c, 0xdeaf }, { 0xa0246a9a, 0xdeb3 }, { 0xa0246b16, 0xdeac }, { 0xa0246b1a, 0xdead },
+ { 0xa071addc, 0x4b1 }, { 0xa38b62dc, 0x474 }, { 0xa4c09fed, 0x3a8 }, { 0xa51e86e5, 0x4e7 },
+ { 0xa67ab13e, 0x3a4 }, { 0xa7414244, 0x51a9 }, { 0xa9ddbead, 0xc6fb }, { 0xab24ffab, 0x4e8a },
+ { 0xabef8ac4, 0x2710 }, { 0xabfa20ac, 0x6fb4 }, { 0xad36895e, 0x4e2 }, { 0xad36895f, 0x4e3 },
+ { 0xaf310e90, 0x402 }, { 0xaf31166f, 0x4e8 }, { 0xaf7277a5, 0x3b6 }, { 0xafc0d8b3, 0x96c6 },
+ { 0xb0fd5dba, 0xcae0 }, { 0xb0fd5e95, 0xcadc }, { 0xb1052893, 0x7149 }, { 0xb1e98745, 0x36a },
+ { 0xb277e91c, 0x5166 }, { 0xb2f7eac5, 0xcae0 }, { 0xb2f7eba0, 0xcadc }, { 0xb2f7ebc1, 0x3b5 },
+ { 0xb53fa77d, 0x3a8 }, { 0xb6391138, 0x6fb5 }, { 0xb7358b7f, 0x6fb6 }, { 0xb8c42b40, 0x4e4 },
+ { 0xb8c42ea4, 0x1b5 }, { 0xb8c439e7, 0x2e1 }, { 0xb8c43a61, 0x307 }, { 0xb8c43d6c, 0x4e4 },
+ { 0xb8c43ddf, 0x352 }, { 0xb8c43de1, 0x354 }, { 0xb8c43de6, 0x359 }, { 0xb8c43dff, 0x35d },
+ { 0xb8c43e04, 0x362 }, { 0xb8c43e07, 0x365 }, { 0xbcd29a7f, 0x3a8 }, { 0xbce34e78, 0x5182 },
+ { 0xbce34e7b, 0x556a }, { 0xbce81504, 0x3b5 }, { 0xbd8a4c95, 0x272d }, { 0xbdd89dad, 0x4e4 },
+ { 0xbdd89dae, 0x6fb0 }, { 0xbdd89daf, 0x6fb1 }, { 0xbdd89db0, 0x6fb2 }, { 0xbdd89db1, 0x4e6 },
+ { 0xbdd89db5, 0x6fbd }, { 0xc1756e9f, 0x36b }, { 0xc7482444, 0x47a }, { 0xc9281c18, 0x4e4 },
+ { 0xc9ef95df, 0x47b }, { 0xccc9db0d, 0x4e4 }, { 0xccc9db0e, 0x6fb0 }, { 0xcd73425f, 0x3b6 },
+ { 0xce38b40b, 0x4b0 }, { 0xce99e549, 0x25 }, { 0xcf598740, 0x4e7 }, { 0xcf6d6f78, 0x4e4 },
+ { 0xcf758df6, 0x3a4 }, { 0xd1266e51, 0x6fb5 }, { 0xd2910213, 0x2718 }, { 0xd29196bb, 0x2712 },
+ { 0xd3eb2fc2, 0x476 }, { 0xd442dc2c, 0x4fc4 }, { 0xd9da4da4, 0x2711 }, { 0xdbad2f42, 0x4e4 },
+ { 0xdbad2f43, 0x6fb0 }, { 0xdbad2f44, 0x6fb1 }, { 0xdbad2f45, 0x6fb2 }, { 0xdbad2f46, 0x6fb3 },
+ { 0xdbad2f47, 0x6fb4 }, { 0xdbad2f48, 0x6fb5 }, { 0xdbad2f49, 0x6fb6 }, { 0xdbad2f4a, 0x4e6 },
+ { 0xdc438033, 0x4f31 }, { 0xdccb439b, 0x477 }, { 0xdccdc626, 0x3b5 }, { 0xdd80a595, 0x4e4 },
+ { 0xdd80a596, 0x6fb0 }, { 0xdd80a59e, 0x6fb1 }, { 0xdd80a5b4, 0x6fb2 }, { 0xdd80a5d9, 0x6fb5 },
+ { 0xdd80a5da, 0x6fb4 }, { 0xdd80a5fa, 0x6fb6 }, { 0xdd80a615, 0x6fb3 }, { 0xdd80a619, 0x4e6 },
+ { 0xdd80a61a, 0x3b5 }, { 0xdd80c0f8, 0x4e9f }, { 0xdf7e46ff, 0x4fc8 }, { 0xdf8680fd, 0x556a },
+ { 0xdfb0bd6e, 0xc42d }, { 0xdff05486, 0x2c4 }, { 0xe3323399, 0x3a4 }, { 0xe60412dd, 0x3b5 },
+ { 0xeee47add, 0x4b0 }, { 0xf021a186, 0x4e2 }, { 0xf021a187, 0x4e3 }, { 0xf021a188, 0x4e4 },
+ { 0xf021a189, 0x4e5 }, { 0xf021a18a, 0x4e6 }, { 0xf021a18b, 0x4e7 }, { 0xf021a18c, 0x4e8 },
+ { 0xf021a18d, 0x4e9 }, { 0xf021a18e, 0x4ea }, { 0xf0700456, 0x6fb3 }, { 0xf274f175, 0x3b5 },
+ { 0xf2a9730b, 0x3a8 }, { 0xf3d463c2, 0x3a4 }, { 0xf52a70a3, 0xc42e }, { 0xf5693147, 0x6fb3 },
+ { 0xf637e157, 0x478 }, { 0xfc213f3a, 0x2717 }, { 0xff654d14, 0x3b5 },
+};
+FX_WORD FX_GetCodePageFromStringA(FX_LPCSTR pStr, FX_INT32 iLength)
+{
+ FXSYS_assert(pStr != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_strlen(pStr);
+ }
+ if (iLength == 0) {
+ return 0xFFFF;
+ }
+ FX_UINT32 uHash = FX_HashCode_String_GetA(pStr, iLength, TRUE);
+ FX_INT32 iStart = 0, iMid;
+ FX_INT32 iEnd = sizeof(g_FXCPHashTable) / sizeof(FX_STR2CPHASH) - 1;
+ FXSYS_assert(iEnd >= 0);
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const FX_STR2CPHASH & cp = g_FXCPHashTable[iMid];
+ if (uHash == cp.uHash) {
+ return (FX_WORD)cp.uCodePage;
+ } else if (uHash < cp.uHash) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return 0xFFFF;
+}
+FX_WORD FX_GetCodePageFormStringW(FX_LPCWSTR pStr, FX_INT32 iLength)
+{
+ if (iLength < 0) {
+ iLength = FXSYS_wcslen(pStr);
+ }
+ if (iLength == 0) {
+ return 0xFFFF;
+ }
+ CFX_ByteString csStr;
+ FX_LPSTR pBuf = csStr.GetBuffer(iLength + 1);
+ for (FX_INT32 i = 0; i < iLength; ++i) {
+ *pBuf ++ = (FX_CHAR) * pStr ++;
+ }
+ csStr.ReleaseBuffer(iLength);
+ return FX_GetCodePageFromStringA(csStr, iLength);
+}
diff --git a/xfa/src/fgas/src/crt/fx_codepage.h b/xfa/src/fgas/src/crt/fx_codepage.h
new file mode 100644
index 0000000000..031f4642cb
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_codepage.h
@@ -0,0 +1,9 @@
+// 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 _FX_CODEPAGE_IMP
+#define _FX_CODEPAGE_IMP
+#endif
diff --git a/xfa/src/fgas/src/crt/fx_cpmgr.cpp b/xfa/src/fgas/src/crt/fx_cpmgr.cpp
new file mode 100644
index 0000000000..7bb2aa4a8d
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_cpmgr.cpp
@@ -0,0 +1,65 @@
+// 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 "../fgas_base.h"
+#include "fx_codepage.h"
+#ifdef _FXCP
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+extern const FX_CODEPAGE_HEADER g_CP936_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP932_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP949_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP950_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP874_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP1250_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP1251_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP1252_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP1253_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP1254_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP1255_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP1256_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP1257_MapHeader;
+extern const FX_CODEPAGE_HEADER g_CP1258_MapHeader;
+extern const FX_CPCU_MAPINFO g_CP936_CUMap;
+extern const FX_CPCU_MAPINFO g_CP932_CUMap;
+extern const FX_CPCU_MAPINFO g_CP949_CUMap;
+extern const FX_CPCU_MAPINFO g_CP950_CUMap;
+extern const FX_CPCU_MAPINFO g_CP874_CUMap;
+extern const FX_CPCU_MAPINFO g_CP1250_CUMap;
+extern const FX_CPCU_MAPINFO g_CP1251_CUMap;
+extern const FX_CPCU_MAPINFO g_CP1252_CUMap;
+extern const FX_CPCU_MAPINFO g_CP1253_CUMap;
+extern const FX_CPCU_MAPINFO g_CP1254_CUMap;
+extern const FX_CPCU_MAPINFO g_CP1255_CUMap;
+extern const FX_CPCU_MAPINFO g_CP1256_CUMap;
+extern const FX_CPCU_MAPINFO g_CP1257_CUMap;
+extern const FX_CPCU_MAPINFO g_CP1258_CUMap;
+FX_LPCCODEPAGE FX_GetCodePage(FX_WORD wCodePage)
+{
+ FX_INT32 iEnd = sizeof(g_FXCodePageMgr) / sizeof(FX_CODEPAGE) - 1;
+ FXSYS_assert(iEnd >= 0);
+ FX_INT32 iStart = 0, iMid;
+ FX_UINT16 uCPID;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const FX_CODEPAGE &cp = g_FXCodePageMgr[iMid];
+ uCPID = cp.pCPHeader->uCPID;
+ if (wCodePage == uCPID) {
+ return g_FXCodePageMgr + iMid;
+ } else if (wCodePage < uCPID) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return NULL;
+}
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/xfa/src/fgas/src/crt/fx_encode.cpp b/xfa/src/fgas/src/crt/fx_encode.cpp
new file mode 100644
index 0000000000..892b5a9059
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_encode.cpp
@@ -0,0 +1,189 @@
+// 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 "../fgas_base.h"
+#include "fx_codepage.h"
+void FX_SwapByteOrder(FX_LPWSTR pStr, FX_INT32 iLength)
+{
+ FXSYS_assert(pStr != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_wcslen(pStr);
+ }
+ FX_WORD wch;
+ if (sizeof(FX_WCHAR) > 2) {
+ while (iLength -- > 0) {
+ wch = (FX_WORD) * pStr;
+ wch = (wch >> 8) | (wch << 8);
+ wch &= 0x00FF;
+ *pStr ++ = wch;
+ }
+ } else {
+ while (iLength -- > 0) {
+ wch = (FX_WORD) * pStr;
+ wch = (wch >> 8) | (wch << 8);
+ *pStr ++ = wch;
+ }
+ }
+}
+void FX_SwapByteOrderCopy(FX_LPCWSTR pSrc, FX_LPWSTR pDst, FX_INT32 iLength)
+{
+ FXSYS_assert(pSrc != NULL && pDst != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_wcslen(pSrc);
+ }
+ FX_WORD wch;
+ if (sizeof(FX_WCHAR) > 2) {
+ while (iLength -- > 0) {
+ wch = (FX_WORD) * pSrc ++;
+ wch = (wch >> 8) | (wch << 8);
+ wch &= 0x00FF;
+ *pDst ++ = wch;
+ }
+ } else {
+ while (iLength -- > 0) {
+ wch = (FX_WORD) * pSrc ++;
+ wch = (wch >> 8) | (wch << 8);
+ *pDst ++ = wch;
+ }
+ }
+}
+void FX_UTF16ToWChar(FX_LPVOID pBuffer, FX_INT32 iLength)
+{
+ FXSYS_assert(pBuffer != NULL && iLength > 0);
+ if (sizeof(FX_WCHAR) == 2) {
+ return;
+ }
+ FX_WORD *pSrc = (FX_WORD*)pBuffer;
+ FX_LPWSTR pDst = (FX_LPWSTR)pBuffer;
+ while (--iLength >= 0) {
+ pDst[iLength] = (FX_WCHAR)pSrc[iLength];
+ }
+}
+void FX_UTF16ToWCharCopy(const FX_WORD *pUTF16, FX_LPWSTR pWChar, FX_INT32 iLength)
+{
+ FXSYS_assert(pUTF16 != NULL && pWChar != NULL && iLength > 0);
+ if (sizeof(FX_WCHAR) == 2) {
+ FXSYS_memcpy(pWChar, pUTF16, iLength * sizeof(FX_WCHAR));
+ } else {
+ while (--iLength >= 0) {
+ pWChar[iLength] = (FX_WCHAR)pUTF16[iLength];
+ }
+ }
+}
+void FX_WCharToUTF16(FX_LPVOID pBuffer, FX_INT32 iLength)
+{
+ FXSYS_assert(pBuffer != NULL && iLength > 0);
+ if (sizeof(FX_WCHAR) == 2) {
+ return;
+ }
+ FX_LPCWSTR pSrc = (FX_LPCWSTR)pBuffer;
+ FX_WORD *pDst = (FX_WORD*)pBuffer;
+ while (--iLength >= 0) {
+ *pDst++ = (FX_WORD) * pSrc++;
+ }
+}
+void FX_WCharToUTF16Copy(FX_LPCWSTR pWChar, FX_WORD *pUTF16, FX_INT32 iLength)
+{
+ FXSYS_assert(pWChar != NULL && pUTF16 != NULL && iLength > 0);
+ if (sizeof(FX_WCHAR) == 2) {
+ FXSYS_memcpy(pUTF16, pWChar, iLength * sizeof(FX_WCHAR));
+ } else {
+ while (--iLength >= 0) {
+ *pUTF16++ = (FX_WORD) * pWChar++;
+ }
+ }
+}
+inline FX_DWORD FX_DWordFromBytes(FX_LPCBYTE pStr)
+{
+ return FXBSTR_ID(pStr[3], pStr[2], pStr[1], pStr[0]);
+}
+inline FX_WORD FX_WordFromBytes(FX_LPCBYTE pStr)
+{
+ return (pStr[1] << 8 | pStr[0]);
+}
+FX_INT32 FX_DecodeString(FX_WORD wCodePage, FX_LPCSTR pSrc, FX_INT32 *pSrcLen, FX_LPWSTR pDst, FX_INT32 *pDstLen, FX_BOOL bErrBreak)
+{
+ if (wCodePage == FX_CODEPAGE_UTF8) {
+ return FX_UTF8Decode(pSrc, pSrcLen, pDst, pDstLen);
+ }
+ return -1;
+}
+FX_INT32 FX_UTF8Decode(FX_LPCSTR pSrc, FX_INT32 *pSrcLen, FX_LPWSTR pDst, FX_INT32 *pDstLen)
+{
+ if (pSrcLen == NULL || pDstLen == NULL) {
+ return -1;
+ }
+ FX_INT32 iSrcLen = *pSrcLen;
+ if (iSrcLen < 1) {
+ *pSrcLen = *pDstLen = 0;
+ return 1;
+ }
+ FX_INT32 iDstLen = *pDstLen;
+ FX_BOOL bValidDst = (pDst != NULL && iDstLen > 0);
+ FX_DWORD dwCode = 0;
+ FX_INT32 iPending = 0;
+ FX_INT32 iSrcNum = 0, iDstNum = 0;
+ FX_INT32 k = 0;
+ FX_INT32 iIndex = 0;
+ k = 1;
+ while (iIndex < iSrcLen) {
+ FX_BYTE byte = (FX_BYTE) * (pSrc + iIndex);
+ if (byte < 0x80) {
+ iPending = 0;
+ k = 1;
+ iDstNum ++;
+ iSrcNum += k;
+ if (bValidDst) {
+ *pDst ++ = byte;
+ if (iDstNum >= iDstLen) {
+ break;
+ }
+ }
+ } else if (byte < 0xc0) {
+ if (iPending < 1) {
+ break;
+ }
+ iPending--;
+ dwCode |= (byte & 0x3f) << (iPending * 6);
+ if (iPending == 0) {
+ iDstNum ++;
+ iSrcNum += k;
+ if (bValidDst) {
+ *pDst ++ = dwCode;
+ if (iDstNum >= iDstLen) {
+ break;
+ }
+ }
+ }
+ } else if (byte < 0xe0) {
+ iPending = 1;
+ k = 2;
+ dwCode = (byte & 0x1f) << 6;
+ } else if (byte < 0xf0) {
+ iPending = 2;
+ k = 3;
+ dwCode = (byte & 0x0f) << 12;
+ } else if (byte < 0xf8) {
+ iPending = 3;
+ k = 4;
+ dwCode = (byte & 0x07) << 18;
+ } else if (byte < 0xfc) {
+ iPending = 4;
+ k = 5;
+ dwCode = (byte & 0x03) << 24;
+ } else if (byte < 0xfe) {
+ iPending = 5;
+ k = 6;
+ dwCode = (byte & 0x01) << 30;
+ } else {
+ break;
+ }
+ iIndex++;
+ }
+ *pSrcLen = iSrcNum;
+ *pDstLen = iDstNum;
+ return 1;
+}
diff --git a/xfa/src/fgas/src/crt/fx_memory.cpp b/xfa/src/fgas/src/crt/fx_memory.cpp
new file mode 100644
index 0000000000..12d081a645
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_memory.cpp
@@ -0,0 +1,334 @@
+// 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 "../fgas_base.h"
+#include "fx_memory.h"
+#define FX_4BYTEALIGN(size) (((size) + 3) / 4 * 4)
+IFX_MEMAllocator* FX_CreateAllocator(FX_ALLOCTYPE eType, size_t chunkSize, size_t blockSize)
+{
+ switch (eType) {
+#ifndef _FXEMB
+ case FX_ALLOCTYPE_Dynamic:
+ return FXTARGET_New CFX_DynamicStore(chunkSize);
+#endif
+ case FX_ALLOCTYPE_Default:
+ return FXTARGET_New CFX_DefStore();
+ case FX_ALLOCTYPE_Static:
+ return FXTARGET_New CFX_StaticStore(chunkSize);
+ case FX_ALLOCTYPE_Fixed:
+ return FXTARGET_New CFX_FixedStore(blockSize, chunkSize);
+ default:
+ return NULL;
+ }
+}
+CFX_StaticStore::CFX_StaticStore(size_t iDefChunkSize)
+ : m_iAllocatedSize(0)
+ , m_iDefChunkSize(iDefChunkSize)
+ , m_pChunk(NULL)
+ , m_pLastChunk(NULL)
+{
+ FXSYS_assert(m_iDefChunkSize != 0);
+}
+CFX_StaticStore::~CFX_StaticStore()
+{
+ register FX_LPSTATICSTORECHUNK pChunk, pNext;
+ pChunk = m_pChunk;
+ while (pChunk != NULL) {
+ pNext = pChunk->pNextChunk;
+ FX_Free(pChunk);
+ pChunk = pNext;
+ }
+}
+FX_LPSTATICSTORECHUNK CFX_StaticStore::AllocChunk(size_t size)
+{
+ FXSYS_assert(size != 0);
+ register FX_LPSTATICSTORECHUNK pChunk = (FX_LPSTATICSTORECHUNK)FX_Alloc(FX_BYTE, sizeof(FX_STATICSTORECHUNK) + size);
+ if (pChunk == NULL) {
+ return NULL;
+ }
+ pChunk->iChunkSize = size;
+ pChunk->iFreeSize = size;
+ pChunk->pNextChunk = NULL;
+ if (m_pLastChunk == NULL) {
+ m_pChunk = pChunk;
+ } else {
+ m_pLastChunk->pNextChunk = pChunk;
+ }
+ m_pLastChunk = pChunk;
+ return pChunk;
+}
+FX_LPSTATICSTORECHUNK CFX_StaticStore::FindChunk(size_t size)
+{
+ FXSYS_assert(size != 0);
+ if (m_pLastChunk == NULL || m_pLastChunk->iFreeSize < size) {
+ return AllocChunk(FX_MAX(m_iDefChunkSize, size));
+ }
+ return m_pLastChunk;
+}
+void* CFX_StaticStore::Alloc(size_t size)
+{
+ size = FX_4BYTEALIGN(size);
+ FXSYS_assert(size != 0);
+ register FX_LPSTATICSTORECHUNK pChunk = FindChunk(size);
+ FXSYS_assert(pChunk != NULL && pChunk->iFreeSize >= size);
+ register FX_LPBYTE p = (FX_LPBYTE)pChunk;
+ p += sizeof(FX_STATICSTORECHUNK) + pChunk->iChunkSize - pChunk->iFreeSize;
+ pChunk->iFreeSize -= size;
+ m_iAllocatedSize += size;
+ return p;
+}
+size_t CFX_StaticStore::SetDefChunkSize(size_t size)
+{
+ FXSYS_assert(size != 0);
+ size_t v = m_iDefChunkSize;
+ m_iDefChunkSize = size;
+ return v;
+}
+CFX_FixedStore::CFX_FixedStore(size_t iBlockSize, size_t iBlockNumsInChunk)
+ : m_iBlockSize(FX_4BYTEALIGN(iBlockSize))
+ , m_iDefChunkSize(FX_4BYTEALIGN(iBlockNumsInChunk))
+ , m_pChunk(NULL)
+{
+ FXSYS_assert(m_iBlockSize != 0 && m_iDefChunkSize != 0);
+}
+CFX_FixedStore::~CFX_FixedStore()
+{
+ register FX_LPFIXEDSTORECHUNK pChunk, pNext;
+ pChunk = m_pChunk;
+ while (pChunk != NULL) {
+ pNext = pChunk->pNextChunk;
+ FX_Free(pChunk);
+ pChunk = pNext;
+ }
+}
+FX_LPFIXEDSTORECHUNK CFX_FixedStore::AllocChunk()
+{
+ FX_INT32 iTotalSize = sizeof(FX_FIXEDSTORECHUNK) + m_iDefChunkSize + m_iBlockSize * m_iDefChunkSize;
+ register FX_LPFIXEDSTORECHUNK pChunk = (FX_LPFIXEDSTORECHUNK)FX_Alloc(FX_BYTE, iTotalSize);
+ if (pChunk == NULL) {
+ return NULL;
+ }
+ FXSYS_memset(pChunk->FirstFlag(), 0, m_iDefChunkSize);
+ pChunk->pNextChunk = m_pChunk;
+ pChunk->iChunkSize = m_iDefChunkSize;
+ pChunk->iFreeNum = m_iDefChunkSize;
+ m_pChunk = pChunk;
+ return pChunk;
+}
+void* CFX_FixedStore::Alloc(size_t size)
+{
+ if (size > m_iBlockSize) {
+ return NULL;
+ }
+ register FX_LPFIXEDSTORECHUNK pChunk = m_pChunk;
+ while (pChunk != NULL) {
+ if (pChunk->iFreeNum > 0) {
+ break;
+ }
+ pChunk = pChunk->pNextChunk;
+ }
+ if (pChunk == NULL) {
+ pChunk = AllocChunk();
+ }
+ FXSYS_assert(pChunk != NULL);
+ register FX_LPBYTE pFlags = pChunk->FirstFlag();
+ register size_t i = 0;
+ for (; i < pChunk->iChunkSize; i ++)
+ if (pFlags[i] == 0) {
+ break;
+ }
+ FXSYS_assert(i < pChunk->iChunkSize);
+ pFlags[i] = 1;
+ pChunk->iFreeNum --;
+ return pChunk->FirstBlock() + i * m_iBlockSize;
+}
+void CFX_FixedStore::Free(void* pBlock)
+{
+ FXSYS_assert(pBlock != NULL);
+ register FX_LPFIXEDSTORECHUNK pPrior, pChunk;
+ pPrior = NULL, pChunk = m_pChunk;
+ register FX_LPBYTE pStart = NULL, pEnd;
+ while (pChunk != NULL) {
+ pStart = pChunk->FirstBlock();
+ if (pBlock >= pStart) {
+ pEnd = pStart + m_iBlockSize * pChunk->iChunkSize;
+ if (pBlock < pEnd) {
+ break;
+ }
+ }
+ pPrior = pChunk, pChunk = pChunk->pNextChunk;
+ }
+ FXSYS_assert(pChunk != NULL);
+ register size_t iPos = ((FX_LPBYTE)pBlock - pStart) / m_iBlockSize;
+ FXSYS_assert(iPos < pChunk->iChunkSize);
+ register FX_LPBYTE pFlags = pChunk->FirstFlag();
+ if (pFlags[iPos] == 0) {
+ return;
+ }
+ pFlags[iPos] = 0;
+ pChunk->iFreeNum ++;
+ if (pChunk->iFreeNum == pChunk->iChunkSize) {
+ if (pPrior == NULL) {
+ m_pChunk = pChunk->pNextChunk;
+ } else {
+ pPrior->pNextChunk = pChunk->pNextChunk;
+ }
+ FX_Free(pChunk);
+ }
+}
+size_t CFX_FixedStore::SetDefChunkSize(size_t iChunkSize)
+{
+ FXSYS_assert(iChunkSize != 0);
+ size_t v = m_iDefChunkSize;
+ m_iDefChunkSize = FX_4BYTEALIGN(iChunkSize);
+ return v;
+}
+#ifndef _FXEMB
+CFX_DynamicStore::CFX_DynamicStore(size_t iDefChunkSize)
+ : m_iDefChunkSize(iDefChunkSize)
+ , m_pChunk(NULL)
+{
+ FXSYS_assert(m_iDefChunkSize != 0);
+}
+CFX_DynamicStore::~CFX_DynamicStore()
+{
+ register FX_LPDYNAMICSTORECHUNK pChunk, pNext;
+ pChunk = m_pChunk;
+ while (pChunk != NULL) {
+ pNext = pChunk->pNextChunk;
+ FX_Free(pChunk);
+ pChunk = pNext;
+ }
+}
+FX_LPDYNAMICSTORECHUNK CFX_DynamicStore::AllocChunk(size_t size)
+{
+ FXSYS_assert(size != 0);
+ register FX_LPDYNAMICSTORECHUNK pChunk = (FX_LPDYNAMICSTORECHUNK)FX_Alloc(FX_BYTE, sizeof(FX_DYNAMICSTORECHUNK) + sizeof(FX_DYNAMICSTOREBLOCK) * 2 + size);
+ if (pChunk == NULL) {
+ return NULL;
+ }
+ pChunk->iChunkSize = size;
+ pChunk->iFreeSize = size;
+ register FX_LPDYNAMICSTOREBLOCK pBlock = pChunk->FirstBlock();
+ pBlock->iBlockSize = size;
+ pBlock->bUsed = FALSE;
+ pBlock = pBlock->NextBlock();
+ pBlock->iBlockSize = 0;
+ pBlock->bUsed = TRUE;
+ if (m_pChunk != NULL && size >= m_iDefChunkSize) {
+ FX_LPDYNAMICSTORECHUNK pLast = m_pChunk;
+ while (pLast->pNextChunk != NULL) {
+ pLast = pLast->pNextChunk;
+ }
+ pLast->pNextChunk = pChunk;
+ pChunk->pNextChunk = NULL;
+ } else {
+ pChunk->pNextChunk = m_pChunk;
+ m_pChunk = pChunk;
+ }
+ return pChunk;
+}
+void* CFX_DynamicStore::Alloc(size_t size)
+{
+ size = FX_4BYTEALIGN(size);
+ FXSYS_assert(size != 0);
+ register FX_LPDYNAMICSTORECHUNK pChunk = m_pChunk;
+ register FX_LPDYNAMICSTOREBLOCK pBlock = NULL;
+ while (pChunk != NULL) {
+ if (pChunk->iFreeSize >= size) {
+ pBlock = pChunk->FirstBlock();
+ register FX_BOOL bFind = FALSE;
+ while(pBlock->iBlockSize != 0) {
+ if (!pBlock->bUsed && pBlock->iBlockSize >= size) {
+ bFind = TRUE;
+ break;
+ }
+ pBlock = pBlock->NextBlock();
+ }
+ if (bFind) {
+ break;
+ }
+ }
+ pChunk = pChunk->pNextChunk;
+ }
+ if (pChunk == NULL) {
+ pChunk = AllocChunk(FX_MAX(m_iDefChunkSize, size));
+ pBlock = pChunk->FirstBlock();
+ }
+ FXSYS_assert(pChunk != NULL && pBlock != NULL);
+ register size_t m = size + sizeof(FX_DYNAMICSTOREBLOCK);
+ pBlock->bUsed = TRUE;
+ if (pBlock->iBlockSize > m) {
+ register size_t n = pBlock->iBlockSize;
+ pBlock->iBlockSize = size;
+ register FX_LPDYNAMICSTOREBLOCK pNextBlock = pBlock->NextBlock();
+ pNextBlock->bUsed = FALSE;
+ pNextBlock->iBlockSize = n - size - sizeof(FX_DYNAMICSTOREBLOCK);
+ pChunk->iFreeSize -= size + sizeof(FX_DYNAMICSTOREBLOCK);
+ } else {
+ pChunk->iFreeSize -= pBlock->iBlockSize;
+ }
+ return pBlock->Data();
+}
+void CFX_DynamicStore::Free(void* pBlock)
+{
+ FXSYS_assert(pBlock != NULL);
+ register FX_LPDYNAMICSTORECHUNK pPriorChunk, pChunk;
+ pPriorChunk = NULL, pChunk = m_pChunk;
+ while (pChunk != NULL) {
+ if (pBlock > pChunk && pBlock <= ((FX_LPBYTE)pChunk + sizeof(FX_DYNAMICSTORECHUNK) + pChunk->iChunkSize)) {
+ break;
+ }
+ pPriorChunk = pChunk, pChunk = pChunk->pNextChunk;
+ }
+ FXSYS_assert(pChunk != NULL);
+ register FX_LPDYNAMICSTOREBLOCK pPriorBlock, pFindBlock;
+ pPriorBlock = NULL, pFindBlock = pChunk->FirstBlock();
+ while(pFindBlock->iBlockSize != 0) {
+ if (pBlock == (void*)pFindBlock->Data()) {
+ break;
+ }
+ pPriorBlock = pFindBlock;
+ pFindBlock = pFindBlock->NextBlock();
+ }
+ FXSYS_assert(pFindBlock->iBlockSize != 0 && pFindBlock->bUsed && pBlock == (void*)pFindBlock->Data());
+ pFindBlock->bUsed = FALSE;
+ pChunk->iFreeSize += pFindBlock->iBlockSize;
+ if (pPriorBlock == NULL) {
+ pPriorBlock = pChunk->FirstBlock();
+ } else if (pPriorBlock->bUsed) {
+ pPriorBlock = pFindBlock;
+ }
+ pFindBlock = pPriorBlock;
+ register size_t sizeFree = 0;
+ register size_t sizeBlock = 0;
+ while (pFindBlock->iBlockSize != 0 && !pFindBlock->bUsed) {
+ if (pFindBlock != pPriorBlock) {
+ sizeFree += sizeof(FX_DYNAMICSTOREBLOCK);
+ sizeBlock += sizeof(FX_DYNAMICSTOREBLOCK);
+ }
+ sizeBlock += pFindBlock->iBlockSize;
+ pFindBlock = pFindBlock->NextBlock();
+ }
+ pPriorBlock->iBlockSize = sizeBlock;
+ pChunk->iFreeSize += sizeFree;
+ if (pChunk->iFreeSize == pChunk->iChunkSize) {
+ if (pPriorChunk == NULL) {
+ m_pChunk = pChunk->pNextChunk;
+ } else {
+ pPriorChunk->pNextChunk = pChunk->pNextChunk;
+ }
+ FX_Free(pChunk);
+ }
+}
+size_t CFX_DynamicStore::SetDefChunkSize(size_t size)
+{
+ FXSYS_assert(size != 0);
+ size_t v = m_iDefChunkSize;
+ m_iDefChunkSize = size;
+ return v;
+}
+#endif
diff --git a/xfa/src/fgas/src/crt/fx_memory.h b/xfa/src/fgas/src/crt/fx_memory.h
new file mode 100644
index 0000000000..9121c32c0f
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_memory.h
@@ -0,0 +1,199 @@
+// 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 _FX_MEMORY_IMP
+#define _FX_MEMORY_IMP
+class CFX_DefStore;
+class CFX_StaticStore;
+class CFX_FixedStore;
+class CFX_DynamicStore;
+class CFX_DefStore : public IFX_MEMAllocator, public CFX_Target
+{
+public:
+ CFX_DefStore() {}
+ ~CFX_DefStore() {}
+ virtual void Release()
+ {
+ FXTARGET_Delete this;
+ }
+ virtual void* Alloc(size_t size)
+ {
+ return FX_Alloc(FX_BYTE, size);
+ }
+ virtual void Free(void *pBlock)
+ {
+ FX_Free(pBlock);
+ }
+ virtual size_t GetBlockSize() const
+ {
+ return 0;
+ }
+ virtual size_t GetDefChunkSize() const
+ {
+ return 0;
+ }
+ virtual size_t SetDefChunkSize(size_t size)
+ {
+ return 0;
+ }
+ virtual size_t GetCurrentDataSize() const
+ {
+ return 0;
+ }
+};
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(push, 1)
+#endif
+typedef struct _FX_STATICSTORECHUNK {
+ _FX_STATICSTORECHUNK* pNextChunk;
+ size_t iChunkSize;
+ size_t iFreeSize;
+} FX_STATICSTORECHUNK, * FX_LPSTATICSTORECHUNK;
+typedef FX_STATICSTORECHUNK const * FX_LPCSTATICSTORECHUNK;
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(pop)
+#endif
+class CFX_StaticStore : public IFX_MEMAllocator, public CFX_Target
+{
+public:
+ CFX_StaticStore(size_t iDefChunkSize = 4096);
+ ~CFX_StaticStore();
+ virtual void Release()
+ {
+ FXTARGET_Delete this;
+ }
+ virtual void* Alloc(size_t size);
+ virtual void Free(FX_LPVOID pBlock) {}
+ virtual size_t GetBlockSize() const
+ {
+ return 0;
+ }
+ virtual size_t GetDefChunkSize() const
+ {
+ return m_iDefChunkSize;
+ }
+ virtual size_t SetDefChunkSize(size_t size);
+ virtual size_t GetCurrentDataSize() const
+ {
+ return m_iAllocatedSize;
+ }
+protected:
+ size_t m_iAllocatedSize;
+ size_t m_iDefChunkSize;
+ FX_LPSTATICSTORECHUNK m_pChunk;
+ FX_LPSTATICSTORECHUNK m_pLastChunk;
+ FX_LPSTATICSTORECHUNK AllocChunk(size_t size);
+ FX_LPSTATICSTORECHUNK FindChunk(size_t size);
+};
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(push, 1)
+#endif
+typedef struct _FX_FIXEDSTORECHUNK {
+ FX_LPBYTE FirstFlag() const
+ {
+ return (FX_LPBYTE)this + sizeof(_FX_FIXEDSTORECHUNK);
+ }
+ FX_LPBYTE FirstBlock() const
+ {
+ return FirstFlag() + iChunkSize;
+ }
+ _FX_FIXEDSTORECHUNK* pNextChunk;
+ size_t iChunkSize;
+ size_t iFreeNum;
+} FX_FIXEDSTORECHUNK, * FX_LPFIXEDSTORECHUNK;
+typedef FX_FIXEDSTORECHUNK const * FX_LPCFIXEDSTORECHUNK;
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(pop)
+#endif
+class CFX_FixedStore : public IFX_MEMAllocator, public CFX_Target
+{
+public:
+ CFX_FixedStore(size_t iBlockSize, size_t iBlockNumsInChunk);
+ virtual ~CFX_FixedStore();
+ virtual void Release()
+ {
+ FXTARGET_Delete this;
+ }
+ virtual void* Alloc(size_t size);
+ virtual void Free(FX_LPVOID pBlock);
+ virtual size_t GetBlockSize() const
+ {
+ return m_iBlockSize;
+ }
+ virtual size_t GetDefChunkSize() const
+ {
+ return m_iDefChunkSize;
+ }
+ virtual size_t SetDefChunkSize(size_t iChunkSize);
+ virtual size_t GetCurrentDataSize() const
+ {
+ return 0;
+ }
+protected:
+ size_t m_iBlockSize;
+ size_t m_iDefChunkSize;
+ FX_LPFIXEDSTORECHUNK m_pChunk;
+ FX_LPFIXEDSTORECHUNK AllocChunk();
+};
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(push, 1)
+#endif
+typedef struct _FX_DYNAMICSTOREBLOCK {
+ _FX_DYNAMICSTOREBLOCK* NextBlock() const
+ {
+ return (_FX_DYNAMICSTOREBLOCK*)(Data() + iBlockSize);
+ }
+ FX_LPBYTE Data() const
+ {
+ return (FX_LPBYTE)this + sizeof(_FX_DYNAMICSTOREBLOCK);
+ }
+ size_t iBlockSize;
+ FX_BOOL bUsed;
+} FX_DYNAMICSTOREBLOCK, * FX_LPDYNAMICSTOREBLOCK;
+typedef FX_DYNAMICSTOREBLOCK const * FX_LPCDYNAMICSTOREBLOCK;
+typedef struct _FX_DYNAMICSTORECHUNK {
+ FX_LPDYNAMICSTOREBLOCK FirstBlock() const
+ {
+ return (FX_LPDYNAMICSTOREBLOCK)((FX_LPBYTE)this + sizeof(_FX_DYNAMICSTORECHUNK));
+ }
+ _FX_DYNAMICSTORECHUNK* pNextChunk;
+ size_t iChunkSize;
+ size_t iFreeSize;
+} FX_DYNAMICSTORECHUNK, * FX_LPDYNAMICSTORECHUNK;
+typedef FX_DYNAMICSTORECHUNK const * FX_LPCDYNAMICSTORECHUNK;
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(pop)
+#endif
+class CFX_DynamicStore : public IFX_MEMAllocator, public CFX_Target
+{
+public:
+ CFX_DynamicStore(size_t iDefChunkSize = 4096);
+ virtual ~CFX_DynamicStore();
+ virtual void Release()
+ {
+ FXTARGET_Delete this;
+ }
+ virtual void* Alloc(size_t size);
+ virtual void Free(FX_LPVOID pBlock);
+ virtual size_t GetBlockSize() const
+ {
+ return 0;
+ }
+ virtual size_t GetDefChunkSize() const
+ {
+ return m_iDefChunkSize;
+ }
+ virtual size_t SetDefChunkSize(size_t size);
+ virtual size_t GetCurrentDataSize() const
+ {
+ return 0;
+ }
+protected:
+ size_t m_iDefChunkSize;
+ FX_LPDYNAMICSTORECHUNK m_pChunk;
+ FX_LPDYNAMICSTORECHUNK AllocChunk(size_t size);
+};
+#endif
diff --git a/xfa/src/fgas/src/crt/fx_stream.cpp b/xfa/src/fgas/src/crt/fx_stream.cpp
new file mode 100644
index 0000000000..fff3fe1e86
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_stream.cpp
@@ -0,0 +1,1613 @@
+// 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 "../fgas_base.h"
+#include "fx_stream.h"
+IFX_Stream* IFX_Stream::CreateStream(IFX_BufferRead *pBufferRead, FX_DWORD dwAccess, FX_INT32 iFileSize, FX_BOOL bReleaseBufferRead )
+{
+ CFX_Stream *pSR = FX_NEW CFX_Stream;
+ if (!pSR) {
+ return NULL;
+ }
+ if (!pSR->LoadBufferRead(pBufferRead, iFileSize, dwAccess, bReleaseBufferRead)) {
+ pSR->Release();
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ IFX_Stream *pTR = FX_NEW CFX_TextStream(pSR, TRUE);
+ if (!pTR) {
+ pTR->Release();
+ pTR = NULL;
+ }
+ return pTR;
+ }
+ return pSR;
+}
+IFX_Stream* IFX_Stream::CreateStream(IFX_FileRead *pFileRead, FX_DWORD dwAccess)
+{
+ CFX_Stream *pSR = FX_NEW CFX_Stream;
+ if (pSR == NULL) {
+ return NULL;
+ }
+ if (!pSR->LoadFileRead(pFileRead, dwAccess)) {
+ pSR->Release();
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ IFX_Stream *pTR = FX_NEW CFX_TextStream(pSR, TRUE);
+ if (pTR == NULL) {
+ pSR->Release();
+ return NULL;
+ }
+ return pTR;
+ }
+ return pSR;
+}
+IFX_Stream* IFX_Stream::CreateStream(IFX_FileWrite *pFileWrite, FX_DWORD dwAccess)
+{
+ CFX_Stream *pSR = FX_NEW CFX_Stream;
+ if (pSR == NULL) {
+ return NULL;
+ }
+ if (!pSR->LoadFileWrite(pFileWrite, dwAccess)) {
+ pSR->Release();
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ IFX_Stream *pTR = FX_NEW CFX_TextStream(pSR, TRUE);
+ if (pTR == NULL) {
+ pSR->Release();
+ return NULL;
+ }
+ return pTR;
+ }
+ return pSR;
+}
+IFX_Stream* IFX_Stream::CreateStream(FX_LPCWSTR pszFileName, FX_DWORD dwAccess)
+{
+ CFX_Stream *pSR = FX_NEW CFX_Stream;
+ if (pSR == NULL) {
+ return NULL;
+ }
+ if (!pSR->LoadFile(pszFileName, dwAccess)) {
+ pSR->Release();
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ IFX_Stream *pTR = FX_NEW CFX_TextStream(pSR, TRUE);
+ if (pTR == NULL) {
+ pSR->Release();
+ return NULL;
+ }
+ return pTR;
+ }
+ return pSR;
+}
+IFX_Stream* IFX_Stream::CreateStream(FX_LPBYTE pData, FX_INT32 length, FX_DWORD dwAccess)
+{
+ CFX_Stream *pSR = FX_NEW CFX_Stream;
+ if (pSR == NULL) {
+ return NULL;
+ }
+ if (!pSR->LoadBuffer(pData, length, dwAccess)) {
+ pSR->Release();
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ IFX_Stream *pTR = FX_NEW CFX_TextStream(pSR, TRUE);
+ if (pTR == NULL) {
+ pSR->Release();
+ return NULL;
+ }
+ return pTR;
+ }
+ return pSR;
+}
+CFX_StreamImp::CFX_StreamImp()
+ : CFX_ThreadLock()
+ , m_dwAccess(0)
+{
+}
+CFX_FileStreamImp::CFX_FileStreamImp()
+ : CFX_StreamImp()
+ , m_hFile(NULL)
+ , m_iLength(0)
+{
+}
+CFX_FileStreamImp::~CFX_FileStreamImp()
+{
+ if (m_hFile != NULL) {
+ FXSYS_fclose(m_hFile);
+ }
+}
+FX_BOOL CFX_FileStreamImp::LoadFile(FX_LPCWSTR pszSrcFileName, FX_DWORD dwAccess)
+{
+ FXSYS_assert(m_hFile == NULL);
+ FXSYS_assert(pszSrcFileName != NULL && FXSYS_wcslen(pszSrcFileName) > 0);
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || _FX_OS_ == _FX_WIN64_
+ CFX_WideString wsMode;
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ if (dwAccess & FX_STREAMACCESS_Append) {
+ wsMode = L"a+b";
+ } else if (dwAccess & FX_STREAMACCESS_Truncate) {
+ wsMode = L"w+b";
+ } else {
+ wsMode = L"r+b";
+ }
+ } else {
+ wsMode = L"rb";
+ }
+#ifdef _FX_WINAPI_PARTITION_APP_
+ CFX_WideString wsSrcFileName(pszSrcFileName);
+ _wfopen_s(&m_hFile, wsSrcFileName, wsMode);
+#else
+ m_hFile = FXSYS_wfopen(pszSrcFileName, wsMode);
+#endif
+ if (m_hFile == NULL) {
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ if (dwAccess & FX_STREAMACCESS_Create) {
+#ifdef _FX_WINAPI_PARTITION_APP_
+ CFX_WideString wsSrcFileName(pszSrcFileName);
+ _wfopen_s(&m_hFile, wsSrcFileName, L"w+b");
+#else
+ m_hFile = FXSYS_wfopen(pszSrcFileName, L"w+b");
+#endif
+ }
+ if (m_hFile == NULL) {
+#ifdef _FX_WINAPI_PARTITION_APP_
+ CFX_WideString wsSrcFileName(pszSrcFileName);
+ _wfopen_s(&m_hFile, wsSrcFileName, L"r+b");
+#else
+ m_hFile = FXSYS_wfopen(pszSrcFileName, L"r+b");
+#endif
+ if (m_hFile == NULL) {
+ return FALSE;
+ }
+ if (dwAccess & FX_STREAMACCESS_Truncate) {
+ FX_fsetsize(m_hFile, 0);
+ }
+ }
+ } else {
+ return FALSE;
+ }
+ }
+#else
+ CFX_ByteString wsMode;
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ if (dwAccess & FX_STREAMACCESS_Append) {
+ wsMode = "a+b";
+ } else if (dwAccess & FX_STREAMACCESS_Truncate) {
+ wsMode = "w+b";
+ } else {
+ wsMode = "r+b";
+ }
+ } else {
+ wsMode = "rb";
+ }
+ CFX_ByteString szFileName = CFX_ByteString::FromUnicode(pszSrcFileName);
+ m_hFile = FXSYS_fopen(szFileName, wsMode);
+ if (m_hFile == NULL) {
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ if (dwAccess & FX_STREAMACCESS_Create) {
+ m_hFile = FXSYS_fopen(szFileName, "w+b");
+ }
+ if (m_hFile == NULL) {
+ m_hFile = FXSYS_fopen(szFileName, "r+b");
+ if (m_hFile == NULL) {
+ return FALSE;
+ }
+ if (dwAccess & FX_STREAMACCESS_Truncate) {
+ FX_fsetsize(m_hFile, 0);
+ }
+ }
+ } else {
+ return FALSE;
+ }
+ }
+#endif
+ m_dwAccess = dwAccess;
+ if ((dwAccess & (FX_STREAMACCESS_Write | FX_STREAMACCESS_Truncate)) == (FX_STREAMACCESS_Write | FX_STREAMACCESS_Truncate)) {
+ m_iLength = 0;
+ } else {
+ m_iLength = FX_filelength(m_hFile);
+ }
+ return TRUE;
+}
+FX_INT32 CFX_FileStreamImp::GetLength() const
+{
+ FXSYS_assert(m_hFile != NULL);
+ return m_iLength;
+}
+FX_INT32 CFX_FileStreamImp::Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset)
+{
+ FXSYS_assert(m_hFile != NULL);
+ FXSYS_fseek(m_hFile, iOffset, eSeek);
+ return FXSYS_ftell(m_hFile);
+}
+FX_INT32 CFX_FileStreamImp::GetPosition()
+{
+ FXSYS_assert(m_hFile != NULL);
+ return FXSYS_ftell(m_hFile);
+}
+FX_BOOL CFX_FileStreamImp::IsEOF() const
+{
+ FXSYS_assert(m_hFile != NULL);
+ return FXSYS_ftell(m_hFile) >= m_iLength;
+}
+FX_INT32 CFX_FileStreamImp::ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ FXSYS_assert(m_hFile != NULL);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ return FXSYS_fread(pBuffer, 1, iBufferSize, m_hFile);
+}
+FX_INT32 CFX_FileStreamImp::ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS)
+{
+ FXSYS_assert(m_hFile != NULL);
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ if (m_iLength <= 0) {
+ return 0;
+ }
+ FX_INT32 iPosition = FXSYS_ftell(m_hFile);
+ FX_INT32 iLen = FX_MIN((m_iLength - iPosition) / 2, iMaxLength);
+ if (iLen <= 0) {
+ return 0;
+ }
+ iLen = FXSYS_fread(pStr, 2, iLen, m_hFile);
+ FX_INT32 iCount = 0;
+ while (*pStr != L'\0' && iCount < iLen) {
+ pStr ++, iCount ++;
+ }
+ iPosition += iCount * 2;
+ if (FXSYS_ftell(m_hFile) != iPosition) {
+ FXSYS_fseek(m_hFile, iPosition, 0);
+ }
+ bEOS = (iPosition >= m_iLength);
+ return iCount;
+}
+FX_INT32 CFX_FileStreamImp::WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ FX_INT32 iRet = FXSYS_fwrite(pBuffer, 1, iBufferSize, m_hFile);
+ if (iRet != 0) {
+ FX_INT32 iPos = FXSYS_ftell(m_hFile);
+ if (iPos > m_iLength) {
+ m_iLength = iPos;
+ }
+ }
+ return iRet;
+}
+FX_INT32 CFX_FileStreamImp::WriteString(FX_LPCWSTR pStr, FX_INT32 iLength)
+{
+ FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FXSYS_assert(pStr != NULL && iLength > 0);
+ FX_INT32 iRet = FXSYS_fwrite(pStr, 2, iLength, m_hFile);
+ if (iRet != 0) {
+ FX_INT32 iPos = FXSYS_ftell(m_hFile);
+ if (iPos > m_iLength) {
+ m_iLength = iPos;
+ }
+ }
+ return iRet;
+}
+void CFX_FileStreamImp::Flush()
+{
+ FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FXSYS_fflush(m_hFile);
+}
+FX_BOOL CFX_FileStreamImp::SetLength(FX_INT32 iLength)
+{
+ FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FX_BOOL bRet = FX_fsetsize(m_hFile, iLength);
+ m_iLength = FX_filelength(m_hFile);
+ return bRet;
+}
+CFX_FileReadStreamImp::CFX_FileReadStreamImp()
+ : m_pFileRead(NULL)
+ , m_iPosition(0)
+ , m_iLength(0)
+{
+}
+FX_BOOL CFX_FileReadStreamImp::LoadFileRead(IFX_FileRead *pFileRead, FX_DWORD dwAccess)
+{
+ FXSYS_assert(m_pFileRead == NULL && pFileRead != NULL);
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ return FALSE;
+ }
+ m_pFileRead = pFileRead;
+ m_iLength = m_pFileRead->GetSize();
+ return TRUE;
+}
+FX_INT32 CFX_FileReadStreamImp::GetLength() const
+{
+ return m_iLength;
+}
+FX_INT32 CFX_FileReadStreamImp::Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset)
+{
+ switch (eSeek) {
+ case FX_STREAMSEEK_Begin:
+ m_iPosition = iOffset;
+ break;
+ case FX_STREAMSEEK_Current:
+ m_iPosition += iOffset;
+ break;
+ case FX_STREAMSEEK_End:
+ m_iPosition = m_iLength + iOffset;
+ break;
+ }
+ if (m_iPosition < 0) {
+ m_iPosition = 0;
+ } else if (m_iPosition >= m_iLength) {
+ m_iPosition = m_iLength;
+ }
+ return m_iPosition;
+}
+FX_BOOL CFX_FileReadStreamImp::IsEOF() const
+{
+ return m_iPosition >= m_iLength;
+}
+FX_INT32 CFX_FileReadStreamImp::ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ FXSYS_assert(m_pFileRead != NULL);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ if (iBufferSize > m_iLength - m_iPosition) {
+ iBufferSize = m_iLength - m_iPosition;
+ }
+ if (m_pFileRead->ReadBlock(pBuffer, m_iPosition, iBufferSize)) {
+ m_iPosition += iBufferSize;
+ return iBufferSize;
+ }
+ return 0;
+}
+FX_INT32 CFX_FileReadStreamImp::ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS)
+{
+ FXSYS_assert(m_pFileRead != NULL);
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ iMaxLength = ReadData((FX_LPBYTE)pStr, iMaxLength * 2) / 2;
+ if (iMaxLength <= 0) {
+ return 0;
+ }
+ FX_INT32 i = 0;
+ while (i < iMaxLength && pStr[i] != L'\0') {
+ ++i;
+ }
+ bEOS = (m_iPosition >= m_iLength) || pStr[i] == L'\0';
+ return i;
+}
+CFX_BufferReadStreamImp::CFX_BufferReadStreamImp()
+ : m_pBufferRead(NULL)
+ , m_bReleaseBufferRead(FALSE)
+ , m_iPosition(0)
+ , m_iBufferSize(0)
+{
+}
+CFX_BufferReadStreamImp::~CFX_BufferReadStreamImp()
+{
+ if (m_bReleaseBufferRead && m_pBufferRead != NULL) {
+ m_pBufferRead->Release();
+ }
+}
+FX_BOOL CFX_BufferReadStreamImp::LoadBufferRead(IFX_BufferRead *pBufferRead, FX_INT32 iFileSize, FX_DWORD dwAccess, FX_BOOL bReleaseBufferRead)
+{
+ FXSYS_assert(m_pBufferRead == NULL && pBufferRead != NULL);
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ return FALSE;
+ }
+ m_bReleaseBufferRead = bReleaseBufferRead;
+ m_pBufferRead = pBufferRead;
+ m_iBufferSize = iFileSize;
+ if (m_iBufferSize >= 0) {
+ return TRUE;
+ }
+ if (!m_pBufferRead->ReadNextBlock(TRUE)) {
+ return FALSE;
+ }
+ m_iBufferSize = m_pBufferRead->GetBlockSize();
+ while (!m_pBufferRead->IsEOF()) {
+ m_pBufferRead->ReadNextBlock(FALSE);
+ m_iBufferSize += m_pBufferRead->GetBlockSize();
+ }
+ return TRUE;
+}
+FX_INT32 CFX_BufferReadStreamImp::GetLength() const
+{
+ return m_iBufferSize;
+}
+FX_INT32 CFX_BufferReadStreamImp::Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset)
+{
+ FX_INT32 iLength = GetLength();
+ switch (eSeek) {
+ case FX_STREAMSEEK_Begin:
+ m_iPosition = iOffset;
+ break;
+ case FX_STREAMSEEK_Current:
+ m_iPosition += iOffset;
+ break;
+ case FX_STREAMSEEK_End:
+ m_iPosition = iLength + iOffset;
+ break;
+ }
+ if (m_iPosition < 0) {
+ m_iPosition = 0;
+ } else if (m_iPosition >= iLength) {
+ m_iPosition = iLength;
+ }
+ return m_iPosition;
+}
+FX_BOOL CFX_BufferReadStreamImp::IsEOF() const
+{
+ return m_pBufferRead ? m_pBufferRead->IsEOF() : TRUE;
+}
+FX_INT32 CFX_BufferReadStreamImp::ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ FXSYS_assert(m_pBufferRead != NULL);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ FX_INT32 iLength = GetLength();
+ if (m_iPosition >= iLength) {
+ return 0;
+ }
+ if (iBufferSize > iLength - m_iPosition) {
+ iBufferSize = iLength - m_iPosition;
+ }
+ FX_DWORD dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ FX_DWORD dwBlockSize = m_pBufferRead->GetBlockSize();
+ if (m_iPosition < (FX_INT32)dwBlockOffset) {
+ if (!m_pBufferRead->ReadNextBlock(TRUE)) {
+ return 0;
+ }
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ }
+ while (m_iPosition < (FX_INT32)dwBlockOffset || m_iPosition >= (FX_INT32)(dwBlockOffset + dwBlockSize)) {
+ if (m_pBufferRead->IsEOF() || !m_pBufferRead->ReadNextBlock(FALSE)) {
+ break;
+ }
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ }
+ if (m_iPosition < (FX_INT32)dwBlockOffset || m_iPosition >= (FX_INT32)(dwBlockOffset + dwBlockSize)) {
+ return 0;
+ }
+ FX_LPCBYTE pBufferTmp = m_pBufferRead->GetBlockBuffer();
+ FX_DWORD dwOffsetTmp = m_iPosition - dwBlockOffset;
+ FX_DWORD dwCopySize = FX_MIN(iBufferSize, (FX_INT32)(dwBlockSize - dwOffsetTmp));
+ FXSYS_memcpy(pBuffer, pBufferTmp + dwOffsetTmp, dwCopySize);
+ dwOffsetTmp = dwCopySize;
+ iBufferSize -= dwCopySize;
+ while (iBufferSize > 0) {
+ if (!m_pBufferRead->ReadNextBlock(FALSE)) {
+ break;
+ }
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ pBufferTmp = m_pBufferRead->GetBlockBuffer();
+ dwCopySize = FX_MIN((FX_DWORD)iBufferSize, dwBlockSize);
+ FXSYS_memcpy(pBuffer + dwOffsetTmp, pBufferTmp, dwCopySize);
+ dwOffsetTmp += dwCopySize;
+ iBufferSize -= dwCopySize;
+ }
+ m_iPosition += dwOffsetTmp;
+ return dwOffsetTmp;
+}
+FX_INT32 CFX_BufferReadStreamImp::ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS)
+{
+ FXSYS_assert(m_pBufferRead != NULL);
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ iMaxLength = ReadData((FX_LPBYTE)pStr, iMaxLength * 2) / 2;
+ if (iMaxLength <= 0) {
+ return 0;
+ }
+ FX_INT32 i = 0;
+ while (i < iMaxLength && pStr[i] != L'\0') {
+ ++i;
+ }
+ bEOS = (m_iPosition >= GetLength()) || pStr[i] == L'\0';
+ return i;
+}
+CFX_FileWriteStreamImp::CFX_FileWriteStreamImp()
+ : m_pFileWrite(NULL)
+ , m_iPosition(0)
+{
+}
+FX_BOOL CFX_FileWriteStreamImp::LoadFileWrite(IFX_FileWrite *pFileWrite, FX_DWORD dwAccess)
+{
+ FXSYS_assert(m_pFileWrite == NULL && pFileWrite != NULL);
+ if (dwAccess & FX_STREAMACCESS_Read) {
+ return FALSE;
+ }
+ if (dwAccess & FX_STREAMACCESS_Append) {
+ m_iPosition = pFileWrite->GetSize();
+ }
+ m_pFileWrite = pFileWrite;
+ return TRUE;
+}
+FX_INT32 CFX_FileWriteStreamImp::GetLength() const
+{
+ if (!m_pFileWrite) {
+ return 0;
+ }
+ return (FX_INT32)m_pFileWrite->GetSize();
+}
+FX_INT32 CFX_FileWriteStreamImp::Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset)
+{
+ FX_INT32 iLength = GetLength();
+ switch (eSeek) {
+ case FX_STREAMSEEK_Begin:
+ m_iPosition = iOffset;
+ break;
+ case FX_STREAMSEEK_Current:
+ m_iPosition += iOffset;
+ break;
+ case FX_STREAMSEEK_End:
+ m_iPosition = iLength + iOffset;
+ break;
+ }
+ if (m_iPosition < 0) {
+ m_iPosition = 0;
+ } else if (m_iPosition >= iLength) {
+ m_iPosition = iLength;
+ }
+ return m_iPosition;
+}
+FX_BOOL CFX_FileWriteStreamImp::IsEOF() const
+{
+ return m_iPosition >= GetLength();
+}
+FX_INT32 CFX_FileWriteStreamImp::WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ if (!m_pFileWrite) {
+ return 0;
+ }
+ if (m_pFileWrite->WriteBlock(pBuffer, m_iPosition, iBufferSize)) {
+ m_iPosition += iBufferSize;
+ }
+ return iBufferSize;
+}
+FX_INT32 CFX_FileWriteStreamImp::WriteString(FX_LPCWSTR pStr, FX_INT32 iLength)
+{
+ return WriteData((FX_LPCBYTE)pStr, iLength * sizeof(FX_WCHAR));
+}
+void CFX_FileWriteStreamImp::Flush()
+{
+ if (m_pFileWrite) {
+ m_pFileWrite->Flush();
+ }
+}
+CFX_BufferStreamImp::CFX_BufferStreamImp()
+ : CFX_StreamImp()
+ , m_pData(NULL)
+ , m_iTotalSize(0)
+ , m_iPosition(0)
+ , m_iLength(0)
+{
+}
+FX_BOOL CFX_BufferStreamImp::LoadBuffer(FX_LPBYTE pData, FX_INT32 iTotalSize, FX_DWORD dwAccess)
+{
+ FXSYS_assert(m_pData == NULL);
+ FXSYS_assert(pData != NULL && iTotalSize > 0);
+ m_dwAccess = dwAccess;
+ m_pData = pData;
+ m_iTotalSize = iTotalSize;
+ m_iPosition = 0;
+ m_iLength = (dwAccess & FX_STREAMACCESS_Write) != 0 ? 0 : iTotalSize;
+ return TRUE;
+}
+FX_INT32 CFX_BufferStreamImp::GetLength() const
+{
+ FXSYS_assert(m_pData != NULL);
+ return m_iLength;
+}
+FX_INT32 CFX_BufferStreamImp::Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset)
+{
+ FXSYS_assert(m_pData != NULL);
+ if (eSeek == FX_STREAMSEEK_Begin) {
+ m_iPosition = iOffset;
+ } else if (eSeek == FX_STREAMSEEK_Current) {
+ m_iPosition += iOffset;
+ } else if (eSeek == FX_STREAMSEEK_End) {
+ m_iPosition = m_iLength + iOffset;
+ }
+ if (m_iPosition > m_iLength) {
+ m_iPosition = m_iLength;
+ }
+ if (m_iPosition < 0) {
+ m_iPosition = 0;
+ }
+ return m_iPosition;
+}
+FX_INT32 CFX_BufferStreamImp::GetPosition()
+{
+ FXSYS_assert(m_pData != NULL);
+ return m_iPosition;
+}
+FX_BOOL CFX_BufferStreamImp::IsEOF() const
+{
+ FXSYS_assert(m_pData != NULL);
+ return m_iPosition >= m_iLength;
+}
+FX_INT32 CFX_BufferStreamImp::ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ FXSYS_assert(m_pData != NULL);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ FX_INT32 iLen = FX_MIN(m_iLength - m_iPosition, iBufferSize);
+ if (iLen <= 0) {
+ return 0;
+ }
+ FXSYS_memcpy(pBuffer, m_pData + m_iPosition, iLen);
+ m_iPosition += iLen;
+ return iLen;
+}
+FX_INT32 CFX_BufferStreamImp::ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS)
+{
+ FXSYS_assert(m_pData != NULL);
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ FX_INT32 iLen = FX_MIN((m_iLength - m_iPosition) / 2, iMaxLength);
+ if (iLen <= 0) {
+ return 0;
+ }
+ FX_LPCWSTR pSrc = (FX_LPCWSTR)(FX_LPSTR)(m_pData + m_iPosition);
+ FX_INT32 iCount = 0;
+ while (*pSrc != L'\0' && iCount < iLen) {
+ *pStr ++ = *pSrc ++, iCount ++;
+ }
+ m_iPosition += iCount * 2;
+ bEOS = (*pSrc == L'\0') || (m_iPosition >= m_iLength);
+ return iCount;
+}
+FX_INT32 CFX_BufferStreamImp::WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ FXSYS_assert(m_pData != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ FX_INT32 iLen = FX_MIN(m_iTotalSize - m_iPosition, iBufferSize);
+ if (iLen <= 0) {
+ return 0;
+ }
+ FXSYS_memcpy(m_pData + m_iPosition, pBuffer, iLen);
+ m_iPosition += iLen;
+ if (m_iPosition > m_iLength) {
+ m_iLength = m_iPosition;
+ }
+ return iLen;
+}
+FX_INT32 CFX_BufferStreamImp::WriteString(FX_LPCWSTR pStr, FX_INT32 iLength)
+{
+ FXSYS_assert(m_pData != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FXSYS_assert(pStr != NULL && iLength > 0);
+ FX_INT32 iLen = FX_MIN((m_iTotalSize - m_iPosition) / 2, iLength);
+ if (iLen <= 0) {
+ return 0;
+ }
+ FXSYS_memcpy(m_pData + m_iPosition, pStr, iLen * 2);
+ m_iPosition += iLen * 2;
+ if (m_iPosition > m_iLength) {
+ m_iLength = m_iPosition;
+ }
+ return iLen;
+}
+IFX_Stream* IFX_Stream::CreateTextStream(IFX_Stream *pBaseStream, FX_BOOL bDeleteOnRelease)
+{
+ FXSYS_assert(pBaseStream != NULL);
+ return FX_NEW CFX_TextStream(pBaseStream, bDeleteOnRelease);
+}
+CFX_TextStream::CFX_TextStream(IFX_Stream *pStream, FX_BOOL bDelStream)
+ : m_wCodePage(FX_CODEPAGE_DefANSI)
+ , m_wBOMLength(0)
+ , m_dwBOM(0)
+ , m_pBuf(NULL)
+ , m_iBufSize(0)
+ , m_bDelStream(bDelStream)
+ , m_pStreamImp(pStream)
+ , m_iRefCount(1)
+{
+ FXSYS_assert(m_pStreamImp != NULL);
+ m_pStreamImp->Retain();
+ InitStream();
+}
+CFX_TextStream::~CFX_TextStream()
+{
+ m_pStreamImp->Release();
+ if (m_bDelStream) {
+ m_pStreamImp->Release();
+ }
+ if (m_pBuf != NULL) {
+ FX_Free(m_pBuf);
+ }
+}
+void CFX_TextStream::InitStream()
+{
+ FX_INT32 iPosition = m_pStreamImp->GetPosition();
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, 0);
+ m_pStreamImp->ReadData((FX_LPBYTE)&m_dwBOM, 3);
+#if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
+ m_dwBOM &= 0x00FFFFFF;
+ if (m_dwBOM == 0x00BFBBEF) {
+ m_wBOMLength = 3;
+ m_wCodePage = FX_CODEPAGE_UTF8;
+ } else {
+ m_dwBOM &= 0x0000FFFF;
+ if (m_dwBOM == 0x0000FFFE) {
+ m_wBOMLength = 2;
+ m_wCodePage = FX_CODEPAGE_UTF16BE;
+ } else if (m_dwBOM == 0x0000FEFF) {
+ m_wBOMLength = 2;
+ m_wCodePage = FX_CODEPAGE_UTF16LE;
+ } else {
+ m_wBOMLength = 0;
+ m_dwBOM = 0;
+ m_wCodePage = FXSYS_GetACP();
+ }
+ }
+#else
+ m_dwBOM &= 0xFFFFFF00;
+ if (m_dwBOM == 0xEFBBBF00) {
+ m_wBOMLength = 3;
+ m_wCodePage = FX_CODEPAGE_UTF8;
+ } else {
+ m_dwBOM &= 0xFFFF0000;
+ if (m_dwBOM == 0xFEFF0000) {
+ m_wBOMLength = 2;
+ m_wCodePage = FX_CODEPAGE_UTF16BE;
+ } else if (m_dwBOM == 0xFFFE0000) {
+ m_wBOMLength = 2;
+ m_wCodePage = FX_CODEPAGE_UTF16LE;
+ } else {
+ m_wBOMLength = 0;
+ m_dwBOM = 0;
+ m_wCodePage = FXSYS_GetACP();
+ }
+ }
+#endif
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, FX_MAX(m_wBOMLength, iPosition));
+}
+void CFX_TextStream::Release()
+{
+ if (--m_iRefCount < 1) {
+ delete this;
+ }
+}
+IFX_Stream* CFX_TextStream::Retain()
+{
+ m_iRefCount++;
+ return this;
+}
+FX_DWORD CFX_TextStream::GetAccessModes() const
+{
+ return m_pStreamImp->GetAccessModes() | FX_STREAMACCESS_Text;
+}
+FX_INT32 CFX_TextStream::GetLength() const
+{
+ return m_pStreamImp->GetLength();
+}
+FX_INT32 CFX_TextStream::Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset)
+{
+ return m_pStreamImp->Seek(eSeek, iOffset);
+}
+FX_INT32 CFX_TextStream::GetPosition()
+{
+ return m_pStreamImp->GetPosition();
+}
+FX_BOOL CFX_TextStream::IsEOF() const
+{
+ return m_pStreamImp->IsEOF();
+}
+FX_INT32 CFX_TextStream::ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ return m_pStreamImp->ReadData(pBuffer, iBufferSize);
+}
+FX_INT32 CFX_TextStream::WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ return m_pStreamImp->WriteData(pBuffer, iBufferSize);
+}
+void CFX_TextStream::Flush()
+{
+ m_pStreamImp->Flush();
+}
+FX_BOOL CFX_TextStream::SetLength(FX_INT32 iLength)
+{
+ return m_pStreamImp->SetLength(iLength);
+}
+FX_WORD CFX_TextStream::GetCodePage() const
+{
+ return m_wCodePage;
+}
+IFX_Stream* CFX_TextStream::CreateSharedStream(FX_DWORD dwAccess, FX_INT32 iOffset, FX_INT32 iLength)
+{
+ IFX_Stream *pSR = m_pStreamImp->CreateSharedStream(dwAccess, iOffset, iLength);
+ if (pSR == NULL) {
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ IFX_Stream *pTR = FX_NEW CFX_TextStream(pSR, TRUE);
+ if (pTR == NULL) {
+ pSR->Release();
+ return NULL;
+ }
+ return pTR;
+ }
+ return pSR;
+}
+FX_INT32 CFX_TextStream::GetBOM(FX_BYTE bom[4]) const
+{
+ if (m_wBOMLength < 1) {
+ return 0;
+ }
+ *(FX_DWORD*)bom = m_dwBOM;
+ return (FX_INT32)m_wBOMLength;
+}
+FX_WORD CFX_TextStream::SetCodePage(FX_WORD wCodePage)
+{
+ if (m_wBOMLength > 0) {
+ return m_wCodePage;
+ }
+ FX_WORD v = m_wCodePage;
+ m_wCodePage = wCodePage;
+ return v;
+}
+FX_INT32 CFX_TextStream::ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS, FX_INT32 const *pByteSize)
+{
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ FX_INT32 iLen;
+ if (m_wCodePage == FX_CODEPAGE_UTF16LE || m_wCodePage == FX_CODEPAGE_UTF16BE) {
+ FX_INT32 iBytes = pByteSize == NULL ? iMaxLength * 2 : *pByteSize;
+ m_pStreamImp->Lock();
+ iLen = m_pStreamImp->ReadData((FX_LPBYTE)pStr, iBytes);
+ m_pStreamImp->Unlock();
+ iMaxLength = iLen / 2;
+ if (sizeof(FX_WCHAR) > 2) {
+ FX_UTF16ToWChar(pStr, iMaxLength);
+ }
+#if _FX_ENDIAN_ == _FX_BIG_ENDIAN_
+ if (m_wCodePage == FX_CODEPAGE_UTF16LE) {
+ FX_SwapByteOrder(pStr, iMaxLength);
+ }
+#else
+ if (m_wCodePage == FX_CODEPAGE_UTF16BE) {
+ FX_SwapByteOrder(pStr, iMaxLength);
+ }
+#endif
+ } else {
+ FX_INT32 pos = m_pStreamImp->GetPosition();
+ FX_INT32 iBytes = pByteSize == NULL ? iMaxLength : *pByteSize;
+ iBytes = FX_MIN(iBytes, m_pStreamImp->GetLength() - pos);
+ if (iBytes > 0) {
+ if (m_pBuf == NULL) {
+ m_pBuf = (FX_LPBYTE)FX_Alloc(FX_BYTE, iBytes);
+ m_iBufSize = iBytes;
+ } else if (iBytes > m_iBufSize) {
+ m_pBuf = (FX_LPBYTE)FX_Realloc(FX_BYTE, m_pBuf, iBytes);
+ m_iBufSize = iBytes;
+ }
+ m_pStreamImp->Lock();
+ iLen = m_pStreamImp->ReadData(m_pBuf, iBytes);
+ FX_INT32 iSrc = iLen;
+ FX_INT32 iDecode = FX_DecodeString(m_wCodePage, (FX_LPCSTR)m_pBuf, &iSrc, pStr, &iMaxLength, TRUE);
+ m_pStreamImp->Seek(FX_STREAMSEEK_Current, iSrc - iLen);
+ m_pStreamImp->Unlock();
+ if (iDecode < 1) {
+ return -1;
+ }
+ } else {
+ iMaxLength = 0;
+ }
+ }
+ bEOS = m_pStreamImp->IsEOF();
+ return iMaxLength;
+}
+FX_INT32 CFX_TextStream::WriteString(FX_LPCWSTR pStr, FX_INT32 iLength)
+{
+ FXSYS_assert(pStr != NULL && iLength > 0);
+ if ((m_pStreamImp->GetAccessModes() & FX_STREAMACCESS_Write) == 0) {
+ return -1;
+ }
+ if (m_wCodePage == FX_CODEPAGE_UTF8) {
+ FX_INT32 len = iLength;
+ CFX_UTF8Encoder encoder;
+ while (len -- > 0) {
+ encoder.Input(*pStr ++);
+ }
+ CFX_ByteStringC bsResult = encoder.GetResult();
+ m_pStreamImp->Lock();
+ m_pStreamImp->WriteData((FX_LPCBYTE)bsResult.GetCStr(), bsResult.GetLength());
+ m_pStreamImp->Unlock();
+ }
+ return iLength;
+}
+CFX_Stream::CFX_Stream()
+ : m_eStreamType(FX_SREAMTYPE_Unknown)
+ , m_pStreamImp(NULL)
+ , m_dwAccess(0)
+ , m_iTotalSize(0)
+ , m_iPosition(0)
+ , m_iStart(0)
+ , m_iLength(0)
+ , m_iRefCount(1)
+{
+}
+CFX_Stream::~CFX_Stream()
+{
+ if (m_eStreamType != FX_STREAMTYPE_Stream && m_pStreamImp != NULL) {
+ m_pStreamImp->Release();
+ }
+}
+FX_BOOL CFX_Stream::LoadFile(FX_LPCWSTR pszSrcFileName, FX_DWORD dwAccess)
+{
+ if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
+ return FALSE;
+ }
+ if (pszSrcFileName == NULL || FXSYS_wcslen(pszSrcFileName) < 1) {
+ return FALSE;
+ }
+ m_pStreamImp = FX_NEW CFX_FileStreamImp();
+ if (m_pStreamImp == NULL) {
+ return FALSE;
+ }
+ FX_BOOL bRet = ((CFX_FileStreamImp*)m_pStreamImp)->LoadFile(pszSrcFileName, dwAccess);
+ if (!bRet) {
+ m_pStreamImp->Release();
+ m_pStreamImp = NULL;
+ } else {
+ m_eStreamType = FX_STREAMTYPE_File;
+ m_dwAccess = dwAccess;
+ m_iLength = m_pStreamImp->GetLength();
+ }
+ return bRet;
+}
+FX_BOOL CFX_Stream::LoadFileRead(IFX_FileRead *pFileRead, FX_DWORD dwAccess)
+{
+ if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
+ return FALSE;
+ }
+ if (pFileRead == NULL) {
+ return FALSE;
+ }
+ m_pStreamImp = FX_NEW CFX_FileReadStreamImp();
+ if (m_pStreamImp == NULL) {
+ return FALSE;
+ }
+ FX_BOOL bRet = ((CFX_FileReadStreamImp*)m_pStreamImp)->LoadFileRead(pFileRead, dwAccess);
+ if (!bRet) {
+ m_pStreamImp->Release();
+ m_pStreamImp = NULL;
+ } else {
+ m_eStreamType = FX_STREAMTYPE_File;
+ m_dwAccess = dwAccess;
+ m_iLength = m_pStreamImp->GetLength();
+ }
+ return bRet;
+}
+FX_BOOL CFX_Stream::LoadFileWrite(IFX_FileWrite *pFileWrite, FX_DWORD dwAccess)
+{
+ if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
+ return FALSE;
+ }
+ if (pFileWrite == NULL) {
+ return FALSE;
+ }
+ m_pStreamImp = FX_NEW CFX_FileWriteStreamImp();
+ if (m_pStreamImp == NULL) {
+ return FALSE;
+ }
+ FX_BOOL bRet = ((CFX_FileWriteStreamImp*)m_pStreamImp)->LoadFileWrite(pFileWrite, dwAccess);
+ if (!bRet) {
+ m_pStreamImp->Release();
+ m_pStreamImp = NULL;
+ } else {
+ m_eStreamType = FX_STREAMTYPE_File;
+ m_dwAccess = dwAccess;
+ m_iLength = m_pStreamImp->GetLength();
+ }
+ return bRet;
+}
+FX_BOOL CFX_Stream::LoadBuffer(FX_LPBYTE pData, FX_INT32 iTotalSize, FX_DWORD dwAccess)
+{
+ if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
+ return FALSE;
+ }
+ if (pData == NULL || iTotalSize < 1) {
+ return FALSE;
+ }
+ m_pStreamImp = FX_NEW CFX_BufferStreamImp();
+ if (m_pStreamImp == NULL) {
+ return FALSE;
+ }
+ FX_BOOL bRet = ((CFX_BufferStreamImp*)m_pStreamImp)->LoadBuffer(pData, iTotalSize, dwAccess);
+ if (!bRet) {
+ m_pStreamImp->Release();
+ m_pStreamImp = NULL;
+ } else {
+ m_eStreamType = FX_STREAMTYPE_Buffer;
+ m_dwAccess = dwAccess;
+ m_iLength = m_pStreamImp->GetLength();
+ }
+ return bRet;
+}
+FX_BOOL CFX_Stream::LoadBufferRead(IFX_BufferRead *pBufferRead, FX_INT32 iFileSize, FX_DWORD dwAccess, FX_BOOL bReleaseBufferRead)
+{
+ if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
+ return FALSE;
+ }
+ if (!pBufferRead) {
+ return FALSE;
+ }
+ m_pStreamImp = FX_NEW CFX_BufferReadStreamImp;
+ if (m_pStreamImp == NULL) {
+ return FALSE;
+ }
+ FX_BOOL bRet = ((CFX_BufferReadStreamImp*)m_pStreamImp)->LoadBufferRead(pBufferRead, iFileSize, dwAccess, bReleaseBufferRead);
+ if (!bRet) {
+ m_pStreamImp->Release();
+ m_pStreamImp = NULL;
+ } else {
+ m_eStreamType = FX_STREAMTYPE_BufferRead;
+ m_dwAccess = dwAccess;
+ m_iLength = m_pStreamImp->GetLength();
+ }
+ return bRet;
+}
+void CFX_Stream::Release()
+{
+ if (--m_iRefCount < 1) {
+ delete this;
+ }
+}
+IFX_Stream* CFX_Stream::Retain()
+{
+ m_iRefCount++;
+ return this;
+}
+FX_INT32 CFX_Stream::GetLength() const
+{
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ if (m_eStreamType == FX_STREAMTYPE_File || m_eStreamType == FX_STREAMTYPE_Buffer) {
+ return m_pStreamImp->GetLength();
+ }
+ return m_iLength;
+}
+FX_INT32 CFX_Stream::Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset)
+{
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ if (m_eStreamType == FX_STREAMTYPE_File || m_eStreamType == FX_STREAMTYPE_Buffer) {
+ return m_iPosition = m_pStreamImp->Seek(eSeek, iOffset);
+ }
+ FX_INT32 iEnd = m_iStart + m_iLength;
+ FX_INT32 iPosition = m_iStart + iOffset;
+ if (eSeek == FX_STREAMSEEK_Begin) {
+ m_iPosition = iPosition;
+ } else if (eSeek == FX_STREAMSEEK_Current) {
+ m_iPosition += iOffset;
+ } else if (eSeek == FX_STREAMSEEK_End) {
+ m_iPosition = iEnd + iOffset;
+ }
+ if (m_iPosition > iEnd) {
+ m_iPosition = iEnd;
+ }
+ if (m_iPosition < m_iStart) {
+ m_iPosition = m_iStart;
+ }
+ return m_iPosition - m_iStart;
+}
+FX_INT32 CFX_Stream::GetPosition()
+{
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ if (m_eStreamType == FX_STREAMTYPE_File || m_eStreamType == FX_STREAMTYPE_Buffer) {
+ return m_iPosition = m_pStreamImp->GetPosition();
+ }
+ return m_iPosition - m_iStart;
+}
+FX_BOOL CFX_Stream::IsEOF() const
+{
+ if (m_pStreamImp == NULL) {
+ return TRUE;
+ }
+ if (m_eStreamType == FX_STREAMTYPE_File || m_eStreamType == FX_STREAMTYPE_Buffer) {
+ return m_pStreamImp->IsEOF();
+ }
+ return m_iPosition >= m_iStart + m_iLength;
+}
+FX_INT32 CFX_Stream::ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ FX_INT32 iLen = FX_MIN(m_iStart + m_iLength - m_iPosition, iBufferSize);
+ if (iLen <= 0) {
+ return 0;
+ }
+ m_pStreamImp->Lock();
+ if (m_pStreamImp->GetPosition() != m_iPosition) {
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
+ }
+ iLen = m_pStreamImp->ReadData(pBuffer, iLen);
+ m_iPosition = m_pStreamImp->GetPosition();
+ m_pStreamImp->Unlock();
+ return iLen;
+}
+FX_INT32 CFX_Stream::ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS, FX_INT32 const *pByteSize)
+{
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ FX_INT32 iEnd = m_iStart + m_iLength;
+ FX_INT32 iLen = iEnd - m_iPosition;
+ if (pByteSize != NULL) {
+ iLen = FX_MIN(iLen, *pByteSize);
+ }
+ iLen = FX_MIN(iEnd / 2, iMaxLength);
+ if (iLen <= 0) {
+ return 0;
+ }
+ m_pStreamImp->Lock();
+ if (m_pStreamImp->GetPosition() != m_iPosition) {
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
+ }
+ iLen = m_pStreamImp->ReadString(pStr, iLen, bEOS);
+ m_iPosition = m_pStreamImp->GetPosition();
+ if (iLen > 0 && m_iPosition >= iEnd) {
+ bEOS = TRUE;
+ }
+ m_pStreamImp->Unlock();
+ return iLen;
+}
+FX_INT32 CFX_Stream::WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize)
+{
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
+ return -1;
+ }
+ FX_INT32 iLen = iBufferSize;
+ if (m_eStreamType == FX_STREAMTYPE_Stream) {
+ iLen = FX_MIN(m_iStart + m_iTotalSize - m_iPosition, iBufferSize);
+ if (iLen <= 0) {
+ return 0;
+ }
+ }
+ m_pStreamImp->Lock();
+ FX_INT32 iEnd = m_iStart + m_iLength;
+ if (m_pStreamImp->GetPosition() != m_iPosition) {
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
+ }
+ iLen = m_pStreamImp->WriteData(pBuffer, iLen);
+ m_iPosition = m_pStreamImp->GetPosition();
+ if (m_iPosition > iEnd) {
+ m_iLength = m_iPosition - m_iStart;
+ }
+ m_pStreamImp->Unlock();
+ return iLen;
+}
+FX_INT32 CFX_Stream::WriteString(FX_LPCWSTR pStr, FX_INT32 iLength)
+{
+ FXSYS_assert(pStr != NULL && iLength > 0);
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
+ return -1;
+ }
+ FX_INT32 iLen = iLength;
+ if (m_eStreamType == FX_STREAMTYPE_Stream) {
+ iLen = FX_MIN((m_iStart + m_iTotalSize - m_iPosition) / 2, iLength);
+ if (iLen <= 0) {
+ return 0;
+ }
+ }
+ m_pStreamImp->Lock();
+ FX_INT32 iEnd = m_iStart + m_iLength;
+ if (m_pStreamImp->GetPosition() != m_iPosition) {
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
+ }
+ iLen = m_pStreamImp->WriteString(pStr, iLen);
+ m_iPosition = m_pStreamImp->GetPosition();
+ if (m_iPosition > iEnd) {
+ m_iLength = m_iPosition - m_iStart;
+ }
+ m_pStreamImp->Unlock();
+ return iLen;
+}
+void CFX_Stream::Flush()
+{
+ if (m_pStreamImp == NULL) {
+ return;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
+ return;
+ }
+ m_pStreamImp->Flush();
+}
+FX_BOOL CFX_Stream::SetLength(FX_INT32 iLength)
+{
+ if (m_pStreamImp == NULL) {
+ return FALSE;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
+ return FALSE;
+ }
+ return m_pStreamImp->SetLength(iLength);
+}
+FX_INT32 CFX_Stream::GetBOM(FX_BYTE bom[4]) const
+{
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ return 0;
+}
+FX_WORD CFX_Stream::GetCodePage() const
+{
+#if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
+ return FX_CODEPAGE_UTF16LE;
+#else
+ return FX_CODEPAGE_UTF16BE;
+#endif
+}
+FX_WORD CFX_Stream::SetCodePage(FX_WORD wCodePage)
+{
+#if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
+ return FX_CODEPAGE_UTF16LE;
+#else
+ return FX_CODEPAGE_UTF16BE;
+#endif
+}
+IFX_Stream* CFX_Stream::CreateSharedStream(FX_DWORD dwAccess, FX_INT32 iOffset, FX_INT32 iLength)
+{
+ FXSYS_assert( iLength > 0);
+ if (m_pStreamImp == NULL) {
+ return NULL;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Text) != 0 && (dwAccess & FX_STREAMACCESS_Text) == 0) {
+ return NULL;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Write) == 0 && (dwAccess & FX_STREAMACCESS_Write) != 0) {
+ return NULL;
+ }
+ register FX_INT32 iStart = m_iStart + iOffset;
+ register FX_INT32 iTotal = m_iStart + m_iLength;
+ if (iStart < m_iStart || iStart >= iTotal) {
+ return NULL;
+ }
+ register FX_INT32 iEnd = iStart + iLength;
+ if (iEnd < iStart || iEnd > iTotal) {
+ return NULL;
+ }
+ CFX_Stream *pShared = FX_NEW CFX_Stream;
+ if (pShared == NULL) {
+ return NULL;
+ }
+ pShared->m_eStreamType = FX_STREAMTYPE_Stream;
+ pShared->m_pStreamImp = m_pStreamImp;
+ pShared->m_dwAccess = dwAccess;
+ pShared->m_iTotalSize = iLength;
+ pShared->m_iPosition = iStart;
+ pShared->m_iStart = iStart;
+ pShared->m_iLength = (dwAccess & FX_STREAMACCESS_Write) != 0 ? 0 : iLength;
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ return IFX_Stream::CreateTextStream(pShared, TRUE);
+ }
+ return pShared;
+}
+IFX_FileRead* FX_CreateFileRead(IFX_Stream *pBaseStream, FX_BOOL bReleaseStream)
+{
+ FXSYS_assert(pBaseStream != NULL);
+ return FX_NEW CFGAS_FileRead(pBaseStream, bReleaseStream);
+}
+#ifdef FX_FILESIZE
+CFGAS_FileRead::CFGAS_FileRead(IFX_Stream *pStream, FX_BOOL bReleaseStream)
+ : m_bReleaseStream(bReleaseStream)
+ , m_pStream(pStream)
+{
+ FXSYS_assert(m_pStream != NULL);
+}
+CFGAS_FileRead::~CFGAS_FileRead()
+{
+ if (m_bReleaseStream) {
+ m_pStream->Release();
+ }
+}
+FX_FILESIZE CFGAS_FileRead::GetSize()
+{
+ return (FX_FILESIZE)m_pStream->GetLength();
+}
+FX_BOOL CFGAS_FileRead::ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
+{
+ m_pStream->Lock();
+ m_pStream->Seek(FX_STREAMSEEK_Begin, (FX_INT32)offset);
+ FX_INT32 iLen = m_pStream->ReadData((FX_LPBYTE)buffer, (FX_INT32)size);
+ m_pStream->Unlock();
+ return iLen == (FX_INT32)size;
+}
+#else
+CFGAS_FileRead::CFGAS_FileRead(IFX_Stream *pStream, FX_BOOL bReleaseStream)
+ : m_bReleaseStream(bReleaseStream)
+ , m_pStream(pStream)
+{
+ FXSYS_assert(m_pStream != NULL);
+}
+CFGAS_FileRead::~CFGAS_FileRead()
+{
+ if (m_bReleaseStream) {
+ m_pStream->Release();
+ }
+}
+FX_DWORD CFGAS_FileRead::GetSize()
+{
+ return (FX_DWORD)m_pStream->GetLength();
+}
+FX_BOOL CFGAS_FileRead::ReadBlock(void* buffer, FX_DWORD offset, FX_DWORD size)
+{
+ m_pStream->Lock();
+ m_pStream->Seek(FX_STREAMSEEK_Begin, (FX_INT32)offset);
+ FX_INT32 iLen = m_pStream->ReadData((FX_LPBYTE)buffer, (FX_INT32)size);
+ m_pStream->Unlock();
+ return iLen == (FX_INT32)size;
+}
+#endif
+#ifdef FX_FILESIZE
+IFX_FileRead* FX_CreateFileRead(IFX_BufferRead *pBufferRead, FX_FILESIZE iFileSize, FX_BOOL bReleaseStream)
+{
+ if (!pBufferRead) {
+ return NULL;
+ }
+ return FX_NEW CFX_BufferAccImp(pBufferRead, iFileSize, bReleaseStream);
+}
+CFX_BufferAccImp::CFX_BufferAccImp(IFX_BufferRead *pBufferRead, FX_FILESIZE iFileSize, FX_BOOL bReleaseStream)
+ : m_pBufferRead(pBufferRead)
+ , m_bReleaseStream(bReleaseStream)
+ , m_iBufSize(iFileSize)
+{
+ FXSYS_assert(m_pBufferRead);
+}
+CFX_BufferAccImp::~CFX_BufferAccImp()
+{
+ if (m_bReleaseStream && m_pBufferRead) {
+ m_pBufferRead->Release();
+ }
+}
+FX_FILESIZE CFX_BufferAccImp::GetSize()
+{
+ if (!m_pBufferRead) {
+ return 0;
+ }
+ if (m_iBufSize >= 0) {
+ return m_iBufSize;
+ }
+ if (!m_pBufferRead->ReadNextBlock(TRUE)) {
+ return 0;
+ }
+ m_iBufSize = (FX_FILESIZE)m_pBufferRead->GetBlockSize();
+ while (!m_pBufferRead->IsEOF()) {
+ m_pBufferRead->ReadNextBlock(FALSE);
+ m_iBufSize += (FX_FILESIZE)m_pBufferRead->GetBlockSize();
+ }
+ return m_iBufSize;
+}
+FX_BOOL CFX_BufferAccImp::ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
+{
+ if (!m_pBufferRead) {
+ return FALSE;
+ }
+ if (!buffer || !size) {
+ return TRUE;
+ }
+ FX_FILESIZE dwBufSize = GetSize();
+ if (offset >= dwBufSize) {
+ return FALSE;
+ }
+ size_t dwBlockSize = m_pBufferRead->GetBlockSize();
+ FX_FILESIZE dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ if (offset < dwBlockOffset) {
+ if (!m_pBufferRead->ReadNextBlock(TRUE)) {
+ return FALSE;
+ }
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ }
+ while (offset < dwBlockOffset || offset >= (FX_FILESIZE)(dwBlockOffset + dwBlockSize)) {
+ if (m_pBufferRead->IsEOF() || !m_pBufferRead->ReadNextBlock(FALSE)) {
+ break;
+ }
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ }
+ if (offset < dwBlockOffset || offset >= (FX_FILESIZE)(dwBlockOffset + dwBlockSize)) {
+ return FALSE;
+ }
+ FX_LPCBYTE pBuffer = m_pBufferRead->GetBlockBuffer();
+ FX_FILESIZE dwOffset = offset - dwBlockOffset;
+ size_t dwCopySize = FX_MIN(size, dwBlockSize - dwOffset);
+ FXSYS_memcpy(buffer, pBuffer + dwOffset, dwCopySize);
+ offset = dwCopySize;
+ size -= dwCopySize;
+ while (size) {
+ if (!m_pBufferRead->ReadNextBlock(FALSE)) {
+ break;
+ }
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ pBuffer = m_pBufferRead->GetBlockBuffer();
+ dwCopySize = FX_MIN(size, dwBlockSize);
+ FXSYS_memcpy(((FX_LPBYTE)buffer) + offset, pBuffer, dwCopySize);
+ offset += dwCopySize;
+ size -= dwCopySize;
+ }
+ return TRUE;
+}
+#else
+IFX_FileRead* FX_CreateFileRead(IFX_BufferRead *pBufferRead, FX_INT32 iFileSize, FX_BOOL bReleaseStream)
+{
+ if (!pBufferRead) {
+ return NULL;
+ }
+ return FX_NEW CFX_BufferAccImp(pBufferRead, iFileSize, bReleaseStream);
+}
+CFX_BufferAccImp::CFX_BufferAccImp(IFX_BufferRead *pBufferRead, FX_INT32 iFileSize, FX_BOOL bReleaseStream)
+ : m_pBufferRead(pBufferRead)
+ , m_bReleaseStream(bReleaseStream)
+ , m_iBufSize(iFileSize)
+{
+ FXSYS_assert(m_pBufferRead);
+}
+CFX_BufferAccImp::~CFX_BufferAccImp()
+{
+ if (m_bReleaseStream && m_pBufferRead) {
+ m_pBufferRead->Release();
+ }
+}
+FX_DWORD CFX_BufferAccImp::GetSize()
+{
+ if (!m_pBufferRead) {
+ return 0;
+ }
+ if (m_iBufSize >= 0) {
+ return m_iBufSize;
+ }
+ if (!m_pBufferRead->ReadNextBlock(TRUE)) {
+ return 0;
+ }
+ m_iBufSize = (FX_DWORD)m_pBufferRead->GetBlockSize();
+ while (!m_pBufferRead->IsEOF()) {
+ m_pBufferRead->ReadNextBlock(FALSE);
+ m_iBufSize += (FX_DWORD)m_pBufferRead->GetBlockSize();
+ }
+ return m_iBufSize;
+}
+FX_BOOL CFX_BufferAccImp::ReadBlock(void* buffer, FX_DWORD offset, FX_DWORD size)
+{
+ if (!m_pBufferRead) {
+ return FALSE;
+ }
+ if (!buffer || !size) {
+ return TRUE;
+ }
+ FX_DWORD dwBufSize = GetSize();
+ if (offset >= dwBufSize) {
+ return FALSE;
+ }
+ size_t dwBlockSize = m_pBufferRead->GetBlockSize();
+ FX_DWORD dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ if (offset < dwBlockOffset) {
+ if (!m_pBufferRead->ReadNextBlock(TRUE)) {
+ return FALSE;
+ }
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ }
+ while (offset < dwBlockOffset || offset >= (FX_DWORD)(dwBlockOffset + dwBlockSize)) {
+ if (m_pBufferRead->IsEOF() || !m_pBufferRead->ReadNextBlock(FALSE)) {
+ break;
+ }
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ }
+ if (offset < dwBlockOffset || offset >= (FX_DWORD)(dwBlockOffset + dwBlockSize)) {
+ return FALSE;
+ }
+ FX_LPCBYTE pBuffer = m_pBufferRead->GetBlockBuffer();
+ FX_DWORD dwOffset = offset - dwBlockOffset;
+ FX_DWORD dwCopySize = FX_MIN(size, dwBlockSize - dwOffset);
+ FXSYS_memcpy(buffer, pBuffer + dwOffset, dwCopySize);
+ offset = dwCopySize;
+ size -= dwCopySize;
+ while (size) {
+ if (!m_pBufferRead->ReadNextBlock(FALSE)) {
+ break;
+ }
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ pBuffer = m_pBufferRead->GetBlockBuffer();
+ dwCopySize = FX_MIN(size, dwBlockSize);
+ FXSYS_memcpy(((FX_LPBYTE)buffer) + offset, pBuffer, dwCopySize);
+ offset += dwCopySize;
+ size -= dwCopySize;
+ }
+ return TRUE;
+}
+#endif
+IFX_FileWrite* FX_CreateFileWrite(IFX_Stream *pBaseStream, FX_BOOL bReleaseStream)
+{
+ FXSYS_assert(pBaseStream != NULL);
+ return FX_NEW CFGAS_FileWrite(pBaseStream, bReleaseStream);
+}
+#ifdef FX_FILESIZE
+CFGAS_FileWrite::CFGAS_FileWrite(IFX_Stream *pStream, FX_BOOL bReleaseStream)
+ : m_pStream(pStream)
+ , m_bReleaseStream(bReleaseStream)
+{
+ FXSYS_assert(m_pStream != NULL);
+}
+CFGAS_FileWrite::~CFGAS_FileWrite()
+{
+ if (m_bReleaseStream) {
+ m_pStream->Release();
+ }
+}
+FX_FILESIZE CFGAS_FileWrite::GetSize()
+{
+ return m_pStream->GetLength();
+}
+FX_BOOL CFGAS_FileWrite::Flush()
+{
+ m_pStream->Flush();
+ return TRUE;
+}
+FX_BOOL CFGAS_FileWrite::WriteBlock(const void* pData, size_t size)
+{
+ return m_pStream->WriteData((FX_LPCBYTE)pData, (FX_INT32)size) == (FX_INT32)size;
+}
+FX_BOOL CFGAS_FileWrite::WriteBlock(const void* pData, FX_FILESIZE offset, size_t size)
+{
+ m_pStream->Lock();
+ m_pStream->Seek(FX_STREAMSEEK_Begin, offset);
+ FX_INT32 iLen = m_pStream->WriteData((FX_LPBYTE)pData, (FX_INT32)size);
+ m_pStream->Unlock();
+ return iLen == (FX_INT32)size;
+}
+#else
+CFGAS_FileWrite::CFGAS_FileWrite(IFX_Stream *pStream, FX_BOOL bReleaseStream)
+ : m_pStream(pStream)
+ , m_bReleaseStream(bReleaseStream)
+{
+ FXSYS_assert(m_pStream != NULL);
+}
+CFGAS_FileWrite::~CFGAS_FileWrite()
+{
+ if (m_bReleaseStream) {
+ m_pStream->Release();
+ }
+}
+FX_DWORD CFGAS_FileWrite::GetSize()
+{
+ return m_pStream->GetLength();
+}
+FX_DWORD CFGAS_FileWrite::Flush()
+{
+ m_pStream->Flush();
+ return 0;
+}
+FX_BOOL CFGAS_FileWrite::WriteBlock(const void* pData, FX_DWORD size)
+{
+ return m_pStream->WriteData((FX_LPCBYTE)pData, (FX_INT32)size) == (FX_INT32)size;
+}
+FX_BOOL CFGAS_FileWrite::WriteBlock(const void* pData, FX_DWORD offset, FX_DWORD size)
+{
+ m_pStream->Lock();
+ m_pStream->Seek(FX_STREAMSEEK_Begin, offset);
+ FX_INT32 iLen = m_pStream->WriteData((FX_LPBYTE)pData, (FX_INT32)size);
+ m_pStream->Unlock();
+ return iLen == (FX_INT32)size;
+}
+#endif
diff --git a/xfa/src/fgas/src/crt/fx_stream.h b/xfa/src/fgas/src/crt/fx_stream.h
new file mode 100644
index 0000000000..630a0fb77f
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_stream.h
@@ -0,0 +1,405 @@
+// 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 _FX_STREAM_IMP
+#define _FX_STREAM_IMP
+class CFX_StreamImp;
+class CFX_FileStreamImp;
+class CFX_BufferStreamImp;
+class CFX_FileReadStreamImp;
+class CFX_BufferReadStreamImp;
+class CFX_FileWriteStreamImp;
+class CFX_Stream;
+class CFX_TextStream;
+class CFX_FileRead;
+class CFX_FileWrite;
+class CFX_BufferAccImp;
+class CFX_StreamImp : public CFX_ThreadLock, public CFX_Object
+{
+public:
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual FX_DWORD GetAccessModes() const
+ {
+ return m_dwAccess;
+ }
+ virtual FX_INT32 GetLength() const = 0;
+ virtual FX_INT32 Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset) = 0;
+ virtual FX_INT32 GetPosition() = 0;
+ virtual FX_BOOL IsEOF() const = 0;
+ virtual FX_INT32 ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize) = 0;
+ virtual FX_INT32 ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS) = 0;
+ virtual FX_INT32 WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize) = 0;
+ virtual FX_INT32 WriteString(FX_LPCWSTR pStr, FX_INT32 iLength) = 0;
+ virtual void Flush() = 0;
+ virtual FX_BOOL SetLength(FX_INT32 iLength) = 0;
+protected:
+ CFX_StreamImp();
+ virtual ~CFX_StreamImp() {}
+ FX_DWORD m_dwAccess;
+};
+class CFX_FileStreamImp : public CFX_StreamImp
+{
+public:
+ CFX_FileStreamImp();
+ virtual ~CFX_FileStreamImp();
+ FX_BOOL LoadFile(FX_LPCWSTR pszSrcFileName, FX_DWORD dwAccess);
+ virtual FX_INT32 GetLength() const;
+ virtual FX_INT32 Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset);
+ virtual FX_INT32 GetPosition();
+ virtual FX_BOOL IsEOF() const;
+ virtual FX_INT32 ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS);
+ virtual FX_INT32 WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 WriteString(FX_LPCWSTR pStr, FX_INT32 iLength);
+ virtual void Flush();
+ virtual FX_BOOL SetLength(FX_INT32 iLength);
+protected:
+ FXSYS_FILE *m_hFile;
+ FX_INT32 m_iLength;
+};
+class CFX_BufferStreamImp : public CFX_StreamImp
+{
+public:
+ CFX_BufferStreamImp();
+ virtual ~CFX_BufferStreamImp() {}
+ FX_BOOL LoadBuffer(FX_LPBYTE pData, FX_INT32 iTotalSize, FX_DWORD dwAccess);
+ virtual FX_INT32 GetLength() const;
+ virtual FX_INT32 Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset);
+ virtual FX_INT32 GetPosition();
+ virtual FX_BOOL IsEOF() const;
+ virtual FX_INT32 ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS);
+ virtual FX_INT32 WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 WriteString(FX_LPCWSTR pStr, FX_INT32 iLength);
+ virtual void Flush() {}
+ virtual FX_BOOL SetLength(FX_INT32 iLength)
+ {
+ return FALSE;
+ }
+protected:
+ FX_LPBYTE m_pData;
+ FX_INT32 m_iTotalSize;
+ FX_INT32 m_iPosition;
+ FX_INT32 m_iLength;
+};
+class CFX_FileReadStreamImp : public CFX_StreamImp
+{
+public:
+ CFX_FileReadStreamImp();
+ virtual ~CFX_FileReadStreamImp() {}
+ FX_BOOL LoadFileRead(IFX_FileRead *pFileRead, FX_DWORD dwAccess);
+ virtual FX_INT32 GetLength() const;
+ virtual FX_INT32 Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset);
+ virtual FX_INT32 GetPosition()
+ {
+ return m_iPosition;
+ }
+ virtual FX_BOOL IsEOF() const;
+
+ virtual FX_INT32 ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS);
+ virtual FX_INT32 WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize)
+ {
+ return 0;
+ }
+ virtual FX_INT32 WriteString(FX_LPCWSTR pStr, FX_INT32 iLength)
+ {
+ return 0;
+ }
+ virtual void Flush() {}
+ virtual FX_BOOL SetLength(FX_INT32 iLength)
+ {
+ return FALSE;
+ }
+protected:
+ IFX_FileRead *m_pFileRead;
+ FX_INT32 m_iPosition;
+ FX_INT32 m_iLength;
+};
+class CFX_BufferReadStreamImp : public CFX_StreamImp
+{
+public:
+ CFX_BufferReadStreamImp();
+ ~CFX_BufferReadStreamImp();
+ FX_BOOL LoadBufferRead(IFX_BufferRead *pBufferRead, FX_INT32 iFileSize, FX_DWORD dwAccess, FX_BOOL bReleaseBufferRead);
+
+ virtual FX_INT32 GetLength() const;
+ virtual FX_INT32 Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset);
+ virtual FX_INT32 GetPosition()
+ {
+ return m_iPosition;
+ }
+ virtual FX_BOOL IsEOF() const;
+
+ virtual FX_INT32 ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS);
+ virtual FX_INT32 WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize)
+ {
+ return 0;
+ }
+ virtual FX_INT32 WriteString(FX_LPCWSTR pStr, FX_INT32 iLength)
+ {
+ return 0;
+ }
+ virtual void Flush() {}
+ virtual FX_BOOL SetLength(FX_INT32 iLength)
+ {
+ return FALSE;
+ }
+private:
+ IFX_BufferRead *m_pBufferRead;
+ FX_BOOL m_bReleaseBufferRead;
+ FX_INT32 m_iPosition;
+ FX_INT32 m_iBufferSize;
+};
+class CFX_FileWriteStreamImp : public CFX_StreamImp
+{
+public:
+ CFX_FileWriteStreamImp();
+ virtual ~CFX_FileWriteStreamImp() {}
+ FX_BOOL LoadFileWrite(IFX_FileWrite *pFileWrite, FX_DWORD dwAccess);
+ virtual FX_INT32 GetLength() const;
+ virtual FX_INT32 Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset);
+ virtual FX_INT32 GetPosition()
+ {
+ return m_iPosition;
+ }
+ virtual FX_BOOL IsEOF() const;
+ virtual FX_INT32 ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize)
+ {
+ return 0;
+ }
+ virtual FX_INT32 ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS)
+ {
+ return 0;
+ }
+ virtual FX_INT32 WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 WriteString(FX_LPCWSTR pStr, FX_INT32 iLength);
+ virtual void Flush();
+ virtual FX_BOOL SetLength(FX_INT32 iLength)
+ {
+ return FALSE;
+ }
+protected:
+ IFX_FileWrite *m_pFileWrite;
+ FX_INT32 m_iPosition;
+};
+enum FX_STREAMTYPE {
+ FX_SREAMTYPE_Unknown = 0,
+ FX_STREAMTYPE_File ,
+ FX_STREAMTYPE_Buffer ,
+ FX_STREAMTYPE_Stream ,
+ FX_STREAMTYPE_BufferRead ,
+};
+class CFX_Stream : public IFX_Stream, public CFX_ThreadLock, public CFX_Object
+{
+public:
+ CFX_Stream();
+ ~CFX_Stream();
+ FX_BOOL LoadFile(FX_LPCWSTR pszSrcFileName, FX_DWORD dwAccess);
+ FX_BOOL LoadBuffer(FX_LPBYTE pData, FX_INT32 iTotalSize, FX_DWORD dwAccess);
+ FX_BOOL LoadFileRead(IFX_FileRead *pFileRead, FX_DWORD dwAccess);
+ FX_BOOL LoadFileWrite(IFX_FileWrite *pFileWrite, FX_DWORD dwAccess);
+ FX_BOOL LoadBufferRead(IFX_BufferRead *pBufferRead, FX_INT32 iFileSize, FX_DWORD dwAccess, FX_BOOL bReleaseBufferRead);
+ virtual void Release();
+ virtual IFX_Stream* Retain();
+ virtual FX_DWORD GetAccessModes() const
+ {
+ return m_dwAccess;
+ }
+ virtual FX_INT32 GetLength() const;
+ virtual FX_INT32 Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset);
+ virtual FX_INT32 GetPosition();
+ virtual FX_BOOL IsEOF() const;
+ virtual FX_INT32 ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS, FX_INT32 const *pByteSize = NULL);
+ virtual FX_INT32 WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 WriteString(FX_LPCWSTR pStr, FX_INT32 iLength);
+ virtual void Flush();
+ virtual FX_BOOL SetLength(FX_INT32 iLength);
+ virtual FX_INT32 GetBOM(FX_BYTE bom[4]) const;
+ virtual FX_WORD GetCodePage() const;
+ virtual FX_WORD SetCodePage(FX_WORD wCodePage);
+ virtual void Lock()
+ {
+ CFX_ThreadLock::Lock();
+ }
+ virtual void Unlock()
+ {
+ CFX_ThreadLock::Unlock();
+ }
+ virtual IFX_Stream* CreateSharedStream(FX_DWORD dwAccess, FX_INT32 iOffset, FX_INT32 iLength);
+protected:
+ FX_STREAMTYPE m_eStreamType;
+ CFX_StreamImp *m_pStreamImp;
+ FX_DWORD m_dwAccess;
+ FX_INT32 m_iTotalSize;
+ FX_INT32 m_iPosition;
+ FX_INT32 m_iStart;
+ FX_INT32 m_iLength;
+ FX_INT32 m_iRefCount;
+};
+class CFX_TextStream : public IFX_Stream, public CFX_ThreadLock, public CFX_Object
+{
+public:
+ CFX_TextStream(IFX_Stream *pStream, FX_BOOL bDelStream);
+ ~CFX_TextStream();
+ virtual void Release();
+ virtual IFX_Stream* Retain();
+
+ virtual FX_DWORD GetAccessModes() const;
+ virtual FX_INT32 GetLength() const;
+ virtual FX_INT32 Seek(FX_STREAMSEEK eSeek, FX_INT32 iOffset);
+ virtual FX_INT32 GetPosition();
+ virtual FX_BOOL IsEOF() const;
+
+ virtual FX_INT32 ReadData(FX_LPBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 ReadString(FX_LPWSTR pStr, FX_INT32 iMaxLength, FX_BOOL &bEOS, FX_INT32 const *pByteSize = NULL);
+ virtual FX_INT32 WriteData(FX_LPCBYTE pBuffer, FX_INT32 iBufferSize);
+ virtual FX_INT32 WriteString(FX_LPCWSTR pStr, FX_INT32 iLength);
+ virtual void Flush();
+ virtual FX_BOOL SetLength(FX_INT32 iLength);
+
+ virtual FX_INT32 GetBOM(FX_BYTE bom[4]) const;
+ virtual FX_WORD GetCodePage() const;
+ virtual FX_WORD SetCodePage(FX_WORD wCodePage);
+
+ virtual void Lock()
+ {
+ CFX_ThreadLock::Lock();
+ }
+ virtual void Unlock()
+ {
+ CFX_ThreadLock::Unlock();
+ }
+
+ virtual IFX_Stream* CreateSharedStream(FX_DWORD dwAccess, FX_INT32 iOffset, FX_INT32 iLength);
+protected:
+ FX_WORD m_wCodePage;
+ FX_WORD m_wBOMLength;
+ FX_DWORD m_dwBOM;
+ FX_LPBYTE m_pBuf;
+ FX_INT32 m_iBufSize;
+ FX_BOOL m_bDelStream;
+ IFX_Stream *m_pStreamImp;
+ FX_INT32 m_iRefCount;
+ void InitStream();
+};
+#ifdef FX_FILESIZE
+class CFGAS_FileRead : public IFX_FileRead, public CFX_Object
+{
+public:
+ CFGAS_FileRead(IFX_Stream *pStream, FX_BOOL bReleaseStream);
+ virtual ~CFGAS_FileRead();
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual FX_FILESIZE GetSize();
+ virtual FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size);
+protected:
+ FX_BOOL m_bReleaseStream;
+ IFX_Stream *m_pStream;
+};
+#else
+class CFGAS_FileRead : public IFX_FileRead, public CFX_Object
+{
+public:
+ CFGAS_FileRead(IFX_Stream *pStream, FX_BOOL bReleaseStream);
+ virtual ~CFGAS_FileRead();
+
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual FX_DWORD GetSize();
+ virtual FX_BOOL ReadBlock(void* buffer, FX_DWORD offset, FX_DWORD size);
+
+protected:
+ FX_BOOL m_bReleaseStream;
+ IFX_Stream *m_pStream;
+};
+#endif
+#ifdef FX_FILESIZE
+class CFX_BufferAccImp : public IFX_FileRead, public CFX_Object
+{
+public:
+ CFX_BufferAccImp(IFX_BufferRead *pBufferRead, FX_FILESIZE iFileSize, FX_BOOL bReleaseStream);
+ virtual ~CFX_BufferAccImp();
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual FX_FILESIZE GetSize();
+ virtual FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size);
+protected:
+ IFX_BufferRead *m_pBufferRead;
+ FX_BOOL m_bReleaseStream;
+ FX_FILESIZE m_iBufSize;
+};
+#else
+class CFX_BufferAccImp : public IFX_FileRead, public CFX_Object
+{
+public:
+ CFX_BufferAccImp(IFX_BufferRead *pBufferRead, FX_INT32 iFileSize, FX_BOOL bReleaseStream);
+ virtual ~CFX_BufferAccImp();
+
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual FX_DWORD GetSize();
+ virtual FX_BOOL ReadBlock(void* buffer, FX_DWORD offset, FX_DWORD size);
+
+protected:
+ IFX_BufferRead *m_pBufferRead;
+ FX_BOOL m_bReleaseStream;
+ FX_INT32 m_iBufSize;
+};
+#endif
+#ifdef FX_FILESIZE
+class CFGAS_FileWrite : public IFX_FileWrite, public CFX_Object
+{
+public:
+ CFGAS_FileWrite(IFX_Stream *pStream, FX_BOOL bReleaseStream);
+ virtual ~CFGAS_FileWrite();
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual FX_FILESIZE GetSize();
+ virtual FX_BOOL Flush();
+ virtual FX_BOOL WriteBlock(const void* pData, size_t size);
+ virtual FX_BOOL WriteBlock(const void* pData, FX_FILESIZE offset, size_t size);
+protected:
+ IFX_Stream *m_pStream;
+ FX_BOOL m_bReleaseStream;
+};
+#else
+class CFGAS_FileWrite : public IFX_FileWrite, public CFX_Object
+{
+public:
+ CFGAS_FileWrite(IFX_Stream *pStream, FX_BOOL bReleaseStream);
+ virtual ~CFGAS_FileWrite();
+
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual FX_DWORD GetSize();
+ virtual FX_DWORD Flush();
+ virtual FX_BOOL WriteBlock(const void* pData, FX_DWORD size);
+ virtual FX_BOOL WriteBlock(const void* pData, FX_DWORD offset, FX_DWORD size);
+
+protected:
+ IFX_Stream *m_pStream;
+ FX_BOOL m_bReleaseStream;
+};
+#endif
+#endif
diff --git a/xfa/src/fgas/src/crt/fx_system.cpp b/xfa/src/fgas/src/crt/fx_system.cpp
new file mode 100644
index 0000000000..c8e4407a79
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_system.cpp
@@ -0,0 +1,236 @@
+// 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 "../fgas_base.h"
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || _FX_OS_ == _FX_WIN64_
+#include <io.h>
+#elif _FX_OS_ == _FX_LINUX_DESKTOP_ || _FX_OS_ == _FX_LINUX_Mini_
+#include <sys/times.h>
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+FX_FLOAT FX_tan(FX_FLOAT a)
+{
+ return (FX_FLOAT)tan(a);
+}
+FX_FLOAT FX_log(FX_FLOAT b, FX_FLOAT x)
+{
+ return FXSYS_log(x) / FXSYS_log(b);
+}
+FX_LPWSTR FX_wcsncpy(FX_LPWSTR dstStr, FX_LPCWSTR srcStr, size_t count)
+{
+ FXSYS_assert(dstStr != NULL && srcStr != NULL && count > 0);
+ for (size_t i = 0; i < count; ++i)
+ if ((dstStr[i] = srcStr[i]) == L'\0') {
+ break;
+ }
+ return dstStr;
+}
+FX_INT32 FX_wcsnicmp(FX_LPCWSTR s1, FX_LPCWSTR s2, size_t count)
+{
+ FXSYS_assert(s1 != NULL && s2 != NULL && count > 0);
+ FX_WCHAR wch1 = 0, wch2 = 0;
+ while (count-- > 0) {
+ wch1 = (FX_WCHAR)FX_tolower(*s1++);
+ wch2 = (FX_WCHAR)FX_tolower(*s2++);
+ if (wch1 != wch2) {
+ break;
+ }
+ }
+ return wch1 - wch2;
+}
+FX_INT32 FX_strnicmp(FX_LPCSTR s1, FX_LPCSTR s2, size_t count)
+{
+ FXSYS_assert(s1 != NULL && s2 != NULL && count > 0);
+ FX_CHAR ch1 = 0, ch2 = 0;
+ while (count-- > 0) {
+ ch1 = (FX_CHAR)FX_tolower(*s1++);
+ ch2 = (FX_CHAR)FX_tolower(*s2++);
+ if (ch1 != ch2) {
+ break;
+ }
+ }
+ return ch1 - ch2;
+}
+FX_INT32 FX_filelength(FXSYS_FILE *file)
+{
+ FXSYS_assert(file != NULL);
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_
+ return _filelength(_fileno(file));
+#else
+ FX_INT32 iPos = FXSYS_ftell(file);
+ FXSYS_fseek(file, 0, FXSYS_SEEK_END);
+ FX_INT32 iLen = FXSYS_ftell(file);
+ FXSYS_fseek(file, iPos, FXSYS_SEEK_SET);
+ return iLen;
+#endif
+}
+FX_BOOL FX_fsetsize(FXSYS_FILE *file, FX_INT32 size)
+{
+ FXSYS_assert(file != NULL);
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_
+ return _chsize(_fileno(file), size) == 0;
+#elif _FX_OS_ == _FX_WIN32_MOBILE_
+ HANDLE hFile = _fileno(file);
+ FX_DWORD dwPos = ::SetFilePointer(hFile, 0, 0, FILE_CURRENT);
+ ::SetFilePointer(hFile, size, 0, FILE_BEGIN);
+ FX_BOOL bRet = ::SetEndOfFile(hFile);
+ ::SetFilePointer(hFile, (FX_INT32)dwPos, 0, FILE_BEGIN);
+ return bRet;
+#else
+ return FALSE;
+#endif
+}
+FX_FLOAT FX_strtof(FX_LPCSTR pcsStr, FX_INT32 iLength , FX_INT32 *pUsedLen )
+{
+ FXSYS_assert(pcsStr != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_strlen(pcsStr);
+ }
+ return FX_wcstof(CFX_WideString::FromLocal(pcsStr, iLength), iLength, pUsedLen);
+}
+FX_FLOAT FX_wcstof(FX_LPCWSTR pwsStr, FX_INT32 iLength , FX_INT32 *pUsedLen )
+{
+ FXSYS_assert(pwsStr != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_wcslen(pwsStr);
+ }
+ if (iLength == 0) {
+ return 0.0f;
+ }
+ FX_INT32 iUsedLen = 0;
+ FX_BOOL bNegtive = FALSE;
+ switch (pwsStr[iUsedLen]) {
+ case '-':
+ bNegtive = TRUE;
+ case '+':
+ iUsedLen++;
+ break;
+ }
+ FX_FLOAT fValue = 0.0f;
+ while (iUsedLen < iLength) {
+ FX_WCHAR wch = pwsStr[iUsedLen];
+ if (wch >= L'0' && wch <= L'9') {
+ fValue = fValue * 10.0f + (wch - L'0');
+ } else {
+ break;
+ }
+ iUsedLen++;
+ }
+ if (iUsedLen < iLength && pwsStr[iUsedLen] == L'.') {
+ FX_FLOAT fPrecise = 0.1f;
+ while (++iUsedLen < iLength) {
+ FX_WCHAR wch = pwsStr[iUsedLen];
+ if (wch >= L'0' && wch <= L'9') {
+ fValue += (wch - L'0') * fPrecise;
+ fPrecise *= 0.1f;
+ } else {
+ break;
+ }
+ }
+ }
+ if (pUsedLen) {
+ *pUsedLen = iUsedLen;
+ }
+ return bNegtive ? -fValue : fValue;
+}
+void FX_memset(FX_LPVOID pBuf, FX_INT32 iValue, size_t size)
+{
+ FXSYS_assert(pBuf != NULL && size > 0 && (size & 0x03) == 0);
+ FXSYS_assert((((size_t)pBuf) & 0x03) == 0);
+ FX_DWORD *pStart = (FX_DWORD*)pBuf;
+ FX_DWORD *pEnd = pStart + (size >> 2);
+ while (pStart < pEnd) {
+ *pStart ++ = iValue;
+ }
+}
+void FX_memcpy(FX_LPVOID pDst, FX_LPCVOID pSrc, size_t size)
+{
+ FXSYS_assert(pDst != NULL && pSrc != NULL && size > 0 && (size & 0x03) == 0);
+ FXSYS_assert((((size_t)pDst) & 0x03) == 0 && (((size_t)pSrc) & 0x03) == 0);
+ FX_DWORD *pStart = (FX_DWORD*)pDst;
+ FX_DWORD *pEnd = pStart + (size >> 2);
+ FX_DWORD *pValue = (FX_DWORD*)pSrc;
+ while (pStart < pEnd) {
+ *pStart ++ = *pValue ++;
+ }
+}
+FX_BOOL FX_IsRelativePath(const CFX_WideStringC &wsUrl)
+{
+ FX_INT32 iUrlLen = wsUrl.GetLength();
+ if (iUrlLen == 0) {
+ return TRUE;
+ }
+ for (FX_INT32 i = FX_MIN(5, iUrlLen) - 1; i >= 0; --i)
+ if (wsUrl.GetAt(i) == ':') {
+ return FALSE;
+ }
+ return TRUE;
+}
+FX_BOOL FX_JoinPath(const CFX_WideStringC &wsBasePath, const CFX_WideStringC &wsRelativePath, CFX_WideString &wsAbsolutePath)
+{
+ if (!FX_IsRelativePath(wsRelativePath)) {
+ wsAbsolutePath = wsRelativePath;
+ return TRUE;
+ }
+ FX_LPCWSTR pRelStart = wsRelativePath.GetPtr();
+ FX_LPCWSTR pRelEnd = pRelStart + wsRelativePath.GetLength();
+ if (pRelStart < pRelEnd) {
+ switch (*pRelStart) {
+ case '#':
+ wsAbsolutePath = CFX_WideString(wsBasePath, wsRelativePath);
+ return wsAbsolutePath.GetLength() > 0;
+ case '/':
+ case '\\':
+ wsAbsolutePath = wsRelativePath;
+ return wsAbsolutePath.GetLength() > 0;
+ }
+ }
+ FX_INT32 nBackCount = 0;
+ for(;;) {
+ if (pRelStart >= pRelEnd) {
+ wsAbsolutePath = wsBasePath;
+ return TRUE;
+ }
+ if (*pRelStart != '.') {
+ break;
+ }
+ if (pRelStart + 1 < pRelEnd &&
+ (pRelStart[1] == '/' || pRelStart[1] == '\\')) {
+ pRelStart += 2;
+ } else if (pRelStart + 2 < pRelEnd
+ && pRelStart[1] == '.'
+ && (pRelStart[2] == '/' || pRelStart[2] == '\\')) {
+ pRelStart += 3;
+ nBackCount++;
+ } else {
+ return FALSE;
+ }
+ }
+ FX_LPCWSTR pBaseStart = wsBasePath.GetPtr();
+ FX_LPCWSTR pBaseEnd = pBaseStart + wsBasePath.GetLength();
+ while(pBaseStart < (--pBaseEnd) && *pBaseEnd != '/' && *pBaseEnd != '\\')
+ ;
+ if (pBaseStart == pBaseEnd) {
+ wsAbsolutePath = CFX_WideStringC(pRelStart, pRelEnd - pRelStart);
+ return wsAbsolutePath.GetLength() > 0;
+ }
+ while (nBackCount > 0) {
+ if (pBaseStart >= (--pBaseEnd)) {
+ return FALSE;
+ } else if (*pBaseEnd == '/' || *pBaseEnd == '\\')
+ if ((--nBackCount) <= 0) {
+ break;
+ }
+ }
+ wsAbsolutePath = CFX_WideString(CFX_WideStringC(pBaseStart, pBaseEnd - pBaseStart + 1),
+ CFX_WideStringC(pRelStart, pRelEnd - pRelStart));
+ return wsAbsolutePath.GetLength() > 0;
+}
+#ifdef __cplusplus
+};
+#endif
diff --git a/xfa/src/fgas/src/crt/fx_utils.cpp b/xfa/src/fgas/src/crt/fx_utils.cpp
new file mode 100644
index 0000000000..f13af23216
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_utils.cpp
@@ -0,0 +1,456 @@
+// 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 "../fgas_base.h"
+#include "fx_utils.h"
+CFX_ThreadLock::CFX_ThreadLock()
+ : m_pData(NULL)
+{
+}
+CFX_ThreadLock::~CFX_ThreadLock()
+{
+}
+void CFX_ThreadLock::Lock()
+{
+}
+void CFX_ThreadLock::Unlock()
+{
+}
+typedef struct _FX_BASEARRAYDATA : public CFX_Target {
+ FX_INT32 iGrowSize;
+ FX_INT32 iBlockSize;
+ FX_INT32 iTotalCount;
+ FX_INT32 iBlockCount;
+ FX_LPBYTE pBuffer;
+} FX_BASEARRAYDATA, * FX_LPBASEARRAYDATA;
+typedef FX_BASEARRAYDATA const * FX_LPCBASEARRAYDATA;
+CFX_BaseArray::CFX_BaseArray(FX_INT32 iGrowSize, FX_INT32 iBlockSize)
+{
+ FXSYS_assert(iGrowSize > 0 && iBlockSize > 0);
+ m_pData = FXTARGET_New FX_BASEARRAYDATA;
+ FX_memset(m_pData, 0, sizeof(FX_BASEARRAYDATA));
+ ((FX_LPBASEARRAYDATA)m_pData)->iGrowSize = iGrowSize;
+ ((FX_LPBASEARRAYDATA)m_pData)->iBlockSize = iBlockSize;
+}
+CFX_BaseArray::~CFX_BaseArray()
+{
+ FX_LPBASEARRAYDATA pData = (FX_LPBASEARRAYDATA)m_pData;
+ if (pData->pBuffer != NULL) {
+ FX_Free(pData->pBuffer);
+ }
+ FXTARGET_Delete pData;
+}
+FX_INT32 CFX_BaseArray::GetSize() const
+{
+ return ((FX_LPBASEARRAYDATA)m_pData)->iBlockCount;
+}
+FX_INT32 CFX_BaseArray::GetBlockSize() const
+{
+ return ((FX_LPBASEARRAYDATA)m_pData)->iBlockSize;
+}
+FX_LPBYTE CFX_BaseArray::AddSpaceTo(FX_INT32 index)
+{
+ FXSYS_assert(index > -1);
+ FX_LPBYTE &pBuffer = ((FX_LPBASEARRAYDATA)m_pData)->pBuffer;
+ FX_INT32 &iTotalCount = ((FX_LPBASEARRAYDATA)m_pData)->iTotalCount;
+ FX_INT32 iBlockSize = ((FX_LPBASEARRAYDATA)m_pData)->iBlockSize;
+ if (index >= iTotalCount) {
+ FX_INT32 iGrowSize = ((FX_LPBASEARRAYDATA)m_pData)->iGrowSize;
+ iTotalCount = (index / iGrowSize + 1) * iGrowSize;
+ FX_INT32 iNewSize = iTotalCount * iBlockSize;
+ if (pBuffer == NULL) {
+ pBuffer = (FX_LPBYTE)FX_Alloc(FX_BYTE, iNewSize);
+ } else {
+ pBuffer = (FX_LPBYTE)FX_Realloc(FX_BYTE, pBuffer, iNewSize);
+ }
+ }
+ FXSYS_assert(pBuffer != NULL);
+ FX_INT32 &iBlockCount = ((FX_LPBASEARRAYDATA)m_pData)->iBlockCount;
+ if (index >= iBlockCount) {
+ iBlockCount = index + 1;
+ }
+ return pBuffer + index * iBlockSize;
+}
+FX_LPBYTE CFX_BaseArray::GetAt(FX_INT32 index) const
+{
+ FXSYS_assert(index > -1 && index < ((FX_LPBASEARRAYDATA)m_pData)->iBlockCount);
+ return ((FX_LPBASEARRAYDATA)m_pData)->pBuffer + index * ((FX_LPBASEARRAYDATA)m_pData)->iBlockSize;
+}
+FX_LPBYTE CFX_BaseArray::GetBuffer() const
+{
+ return ((FX_LPBASEARRAYDATA)m_pData)->pBuffer;
+}
+FX_INT32 CFX_BaseArray::Append(const CFX_BaseArray &src, FX_INT32 iStart, FX_INT32 iCount)
+{
+ FX_INT32 iBlockSize = ((FX_LPBASEARRAYDATA)m_pData)->iBlockSize;
+ FXSYS_assert(iBlockSize == ((FX_LPBASEARRAYDATA)src.m_pData)->iBlockSize);
+ FX_INT32 &iBlockCount = ((FX_LPBASEARRAYDATA)m_pData)->iBlockCount;
+ FX_INT32 iAdded = src.GetSize();
+ FXSYS_assert(iStart > -1 && iStart < iAdded);
+ if (iCount < 0) {
+ iCount = iAdded;
+ }
+ if (iStart + iCount > iAdded) {
+ iCount = iAdded - iStart;
+ }
+ if (iCount < 1) {
+ return 0;
+ }
+ FX_LPBYTE pDst = ((FX_LPBASEARRAYDATA)m_pData)->pBuffer + iBlockCount * iBlockSize;
+ AddSpaceTo(iBlockCount + iCount - 1);
+ FX_memcpy(pDst, ((FX_LPBASEARRAYDATA)src.m_pData)->pBuffer + iStart * iBlockSize, iCount * iBlockSize);
+ return iCount;
+}
+FX_INT32 CFX_BaseArray::Copy(const CFX_BaseArray &src, FX_INT32 iStart, FX_INT32 iCount)
+{
+ FX_INT32 iBlockSize = ((FX_LPBASEARRAYDATA)m_pData)->iBlockSize;
+ FXSYS_assert(iBlockSize == ((FX_LPBASEARRAYDATA)src.m_pData)->iBlockSize);
+ FX_INT32 iCopied = src.GetSize();
+ FXSYS_assert(iStart > -1 && iStart < iCopied);
+ if (iCount < 0) {
+ iCount = iCopied;
+ }
+ if (iStart + iCount > iCopied) {
+ iCount = iCopied - iStart;
+ }
+ if (iCount < 1) {
+ return 0;
+ }
+ RemoveAll(TRUE);
+ AddSpaceTo(iCount - 1);
+ FX_memcpy(((FX_LPBASEARRAYDATA)m_pData)->pBuffer, ((FX_LPBASEARRAYDATA)src.m_pData)->pBuffer + iStart * iBlockSize, iCount * iBlockSize);
+ return iCount;
+}
+FX_INT32 CFX_BaseArray::RemoveLast(FX_INT32 iCount)
+{
+ FX_INT32 &iBlockCount = ((FX_LPBASEARRAYDATA)m_pData)->iBlockCount;
+ if (iCount < 0 || iCount > iBlockCount) {
+ iCount = iBlockCount;
+ iBlockCount = 0;
+ } else {
+ iBlockCount -= iCount;
+ }
+ return iCount;
+}
+void CFX_BaseArray::RemoveAll(FX_BOOL bLeaveMemory)
+{
+ if (!bLeaveMemory) {
+ FX_LPBYTE &pBuffer = ((FX_LPBASEARRAYDATA)m_pData)->pBuffer;
+ if (pBuffer != NULL) {
+ FX_Free(pBuffer);
+ pBuffer = NULL;
+ }
+ ((FX_LPBASEARRAYDATA)m_pData)->iTotalCount = 0;
+ }
+ ((FX_LPBASEARRAYDATA)m_pData)->iBlockCount = 0;
+}
+CFX_BaseMassArrayImp::CFX_BaseMassArrayImp(FX_INT32 iChunkSize, FX_INT32 iBlockSize)
+ : m_iChunkSize(iChunkSize)
+ , m_iBlockSize(iBlockSize)
+ , m_iChunkCount(0)
+ , m_iBlockCount(0)
+{
+ FXSYS_assert(m_iChunkSize > 0 && m_iBlockSize > 0);
+ m_pData = FX_NEW CFX_PtrArray;
+ m_pData->SetSize(16);
+}
+CFX_BaseMassArrayImp::~CFX_BaseMassArrayImp()
+{
+ RemoveAll();
+ delete m_pData;
+}
+FX_LPBYTE CFX_BaseMassArrayImp::AddSpaceTo(FX_INT32 index)
+{
+ FXSYS_assert(index > -1);
+ FX_LPBYTE pChunk;
+ if (index < m_iBlockCount) {
+ pChunk = (FX_LPBYTE)m_pData->GetAt(index / m_iChunkSize);
+ } else {
+ FX_INT32 iMemSize = m_iChunkSize * m_iBlockSize;
+ while (TRUE) {
+ if (index < m_iChunkCount * m_iChunkSize) {
+ pChunk = (FX_LPBYTE)m_pData->GetAt(index / m_iChunkSize);
+ break;
+ } else {
+ pChunk = (FX_LPBYTE)FX_Alloc(FX_BYTE, iMemSize);
+ if (m_iChunkCount < m_pData->GetSize()) {
+ m_pData->SetAt(m_iChunkCount, pChunk);
+ } else {
+ m_pData->Add(pChunk);
+ }
+ m_iChunkCount ++;
+ }
+ }
+ }
+ FXSYS_assert(pChunk != NULL);
+ m_iBlockCount = index + 1;
+ return pChunk + (index % m_iChunkSize) * m_iBlockSize;
+}
+FX_LPBYTE CFX_BaseMassArrayImp::GetAt(FX_INT32 index) const
+{
+ FXSYS_assert(index > -1 && index < m_iBlockCount);
+ FX_LPBYTE pChunk = (FX_LPBYTE)m_pData->GetAt(index / m_iChunkSize);
+ FXSYS_assert(pChunk != NULL);
+ return pChunk + (index % m_iChunkSize) * m_iBlockSize;
+}
+FX_INT32 CFX_BaseMassArrayImp::Append(const CFX_BaseMassArrayImp &src, FX_INT32 iStart, FX_INT32 iCount)
+{
+ FXSYS_assert(m_iBlockSize == src.m_iBlockSize);
+ FX_INT32 iAdded = src.m_iBlockCount;
+ FXSYS_assert(iStart > -1 && iStart < iAdded);
+ if (iCount < 0) {
+ iCount = iAdded;
+ }
+ if (iStart + iCount > iAdded) {
+ iCount = iAdded - iStart;
+ }
+ if (iCount < 1) {
+ return m_iBlockCount;
+ }
+ FX_INT32 iBlockCount = m_iBlockCount;
+ FX_INT32 iTotal = m_iBlockCount + iCount;
+ AddSpaceTo(iTotal - 1);
+ Append(iBlockCount, src, iStart, iCount);
+ return m_iBlockCount;
+}
+FX_INT32 CFX_BaseMassArrayImp::Copy(const CFX_BaseMassArrayImp &src, FX_INT32 iStart, FX_INT32 iCount)
+{
+ FXSYS_assert(m_iBlockSize == src.m_iBlockSize);
+ FX_INT32 iCopied = src.m_iBlockCount;
+ FXSYS_assert(iStart > -1);
+ if (iStart >= iCopied) {
+ return 0;
+ }
+ RemoveAll(TRUE);
+ if (iCount < 0) {
+ iCount = iCopied;
+ }
+ if (iStart + iCount > iCopied) {
+ iCount = iCopied - iStart;
+ }
+ if (iCount < 1) {
+ return 0;
+ }
+ if (m_iBlockCount < iCount) {
+ AddSpaceTo(iCount - 1);
+ }
+ Append(0, src, iStart, iCount);
+ return m_iBlockCount;
+}
+void CFX_BaseMassArrayImp::Append(FX_INT32 iDstStart, const CFX_BaseMassArrayImp &src, FX_INT32 iSrcStart, FX_INT32 iSrcCount)
+{
+ FXSYS_assert(iDstStart > -1 && m_iBlockSize == src.m_iBlockSize);
+ FX_INT32 iSrcTotal = src.m_iBlockCount;
+ FXSYS_assert(iSrcTotal > 0 && m_iBlockCount >= iDstStart + iSrcCount);
+ FXSYS_assert(iSrcStart > -1 && iSrcStart < iSrcTotal && iSrcCount > 0 && iSrcStart + iSrcCount <= iSrcTotal);
+ FX_INT32 iDstChunkIndex = iDstStart / m_iChunkSize;
+ FX_INT32 iSrcChunkIndex = iSrcStart / src.m_iChunkSize;
+ FX_LPBYTE pDstChunk = (FX_LPBYTE)GetAt(iDstStart);
+ FX_LPBYTE pSrcChunk = (FX_LPBYTE)src.GetAt(iSrcStart);
+ FX_INT32 iDstChunkSize = m_iChunkSize - (iDstStart % m_iChunkSize);
+ FX_INT32 iSrcChunkSize = src.m_iChunkSize - (iSrcStart % src.m_iChunkSize);
+ FX_INT32 iCopySize = FX_MIN(iSrcCount, FX_MIN(iSrcChunkSize, iDstChunkSize));
+ FX_INT32 iCopyBytes = iCopySize * m_iBlockSize;
+ while (iSrcCount > 0) {
+ FXSYS_assert(pDstChunk != NULL && pSrcChunk != NULL);
+ FXSYS_memcpy(pDstChunk, pSrcChunk, iCopyBytes);
+ iSrcCount -= iCopySize;
+ iSrcChunkSize -= iCopySize;
+ if (iSrcChunkSize < 1) {
+ iSrcChunkSize = src.m_iChunkSize;
+ iSrcChunkIndex ++;
+ pSrcChunk = (FX_LPBYTE)src.m_pData->GetAt(iSrcChunkIndex);
+ } else {
+ pSrcChunk += iCopyBytes;
+ }
+ iDstChunkSize -= iCopySize;
+ if (iDstChunkSize < 1) {
+ iDstChunkSize = m_iChunkSize;
+ iDstChunkIndex ++;
+ pDstChunk = (FX_LPBYTE)m_pData->GetAt(iDstChunkIndex);
+ } else {
+ pDstChunk += iCopyBytes;
+ }
+ iCopySize = FX_MIN(iSrcCount, FX_MIN(iSrcChunkSize, iDstChunkSize));
+ iCopyBytes = iCopySize * m_iBlockSize;
+ }
+}
+FX_INT32 CFX_BaseMassArrayImp::RemoveLast(FX_INT32 iCount)
+{
+ if (iCount < 0 || iCount >= m_iBlockCount) {
+ m_iBlockCount = 0;
+ } else {
+ m_iBlockCount -= iCount;
+ }
+ return m_iBlockCount;
+}
+void CFX_BaseMassArrayImp::RemoveAll(FX_BOOL bLeaveMemory)
+{
+ if (bLeaveMemory) {
+ m_iBlockCount = 0;
+ return;
+ }
+ for (FX_INT32 i = 0; i < m_iChunkCount; i ++) {
+ FX_LPVOID p = m_pData->GetAt(i);
+ if (p == NULL) {
+ continue;
+ }
+ FX_Free(p);
+ }
+ m_pData->RemoveAll();
+ m_iChunkCount = 0;
+ m_iBlockCount = 0;
+}
+CFX_BaseMassArray::CFX_BaseMassArray(FX_INT32 iChunkSize, FX_INT32 iBlockSize)
+{
+ m_pData = FXTARGET_New CFX_BaseMassArrayImp(iChunkSize, iBlockSize);
+}
+CFX_BaseMassArray::~CFX_BaseMassArray()
+{
+ FXTARGET_Delete (CFX_BaseMassArrayImp*)m_pData;
+}
+FX_INT32 CFX_BaseMassArray::GetSize() const
+{
+ return ((CFX_BaseMassArrayImp*)m_pData)->m_iBlockCount;
+}
+FX_LPBYTE CFX_BaseMassArray::AddSpaceTo(FX_INT32 index)
+{
+ return ((CFX_BaseMassArrayImp*)m_pData)->AddSpaceTo(index);
+}
+FX_LPBYTE CFX_BaseMassArray::GetAt(FX_INT32 index) const
+{
+ return ((CFX_BaseMassArrayImp*)m_pData)->GetAt(index);
+}
+FX_INT32 CFX_BaseMassArray::Append(const CFX_BaseMassArray &src, FX_INT32 iStart, FX_INT32 iCount)
+{
+ return ((CFX_BaseMassArrayImp*)m_pData)->Append(*(CFX_BaseMassArrayImp*)src.m_pData, iStart, iCount);
+}
+FX_INT32 CFX_BaseMassArray::Copy(const CFX_BaseMassArray &src, FX_INT32 iStart, FX_INT32 iCount)
+{
+ return ((CFX_BaseMassArrayImp*)m_pData)->Copy(*(CFX_BaseMassArrayImp*)src.m_pData, iStart, iCount);
+}
+FX_INT32 CFX_BaseMassArray::RemoveLast(FX_INT32 iCount)
+{
+ return ((CFX_BaseMassArrayImp*)m_pData)->RemoveLast(iCount);
+}
+void CFX_BaseMassArray::RemoveAll(FX_BOOL bLeaveMemory)
+{
+ ((CFX_BaseMassArrayImp*)m_pData)->RemoveAll(bLeaveMemory);
+}
+typedef struct _FX_BASEDISCRETEARRAYDATA : public CFX_Object {
+ FX_INT32 iBlockSize;
+ FX_INT32 iChunkSize;
+ FX_INT32 iChunkCount;
+ CFX_PtrArray ChunkBuffer;
+} FX_BASEDISCRETEARRAYDATA, * FX_LPBASEDISCRETEARRAYDATA;
+typedef FX_BASEDISCRETEARRAYDATA const * FX_LPCBASEDISCRETEARRAYDATA;
+CFX_BaseDiscreteArray::CFX_BaseDiscreteArray(FX_INT32 iChunkSize, FX_INT32 iBlockSize)
+{
+ FXSYS_assert(iChunkSize > 0 && iBlockSize > 0);
+ FX_LPBASEDISCRETEARRAYDATA pData;
+ m_pData = pData = FX_NEW FX_BASEDISCRETEARRAYDATA;
+ pData->ChunkBuffer.SetSize(16);
+ pData->iChunkCount = 0;
+ pData->iChunkSize = iChunkSize;
+ pData->iBlockSize = iBlockSize;
+}
+CFX_BaseDiscreteArray::~CFX_BaseDiscreteArray()
+{
+ RemoveAll();
+ delete (FX_LPBASEDISCRETEARRAYDATA)m_pData;
+}
+FX_LPBYTE CFX_BaseDiscreteArray::AddSpaceTo(FX_INT32 index)
+{
+ FXSYS_assert(index > -1);
+ FX_LPBASEDISCRETEARRAYDATA pData = (FX_LPBASEDISCRETEARRAYDATA)m_pData;
+ FX_INT32 &iChunkCount = pData->iChunkCount;
+ FX_INT32 iChunkSize = pData->iChunkSize;
+ FX_LPBYTE pChunk = NULL;
+ FX_INT32 iChunk = index / iChunkSize;
+ if (iChunk < iChunkCount) {
+ pChunk = (FX_LPBYTE)pData->ChunkBuffer.GetAt(iChunk);
+ }
+ if (pChunk == NULL) {
+ FX_INT32 iMemSize = iChunkSize * pData->iBlockSize;
+ pChunk = (FX_LPBYTE)FX_Alloc(FX_BYTE, iMemSize);
+ FXSYS_memset(pChunk, 0, iMemSize);
+ pData->ChunkBuffer.SetAtGrow(iChunk, pChunk);
+ if (iChunkCount <= iChunk) {
+ iChunkCount = iChunk + 1;
+ }
+ }
+ return pChunk + (index % iChunkSize) * pData->iBlockSize;
+}
+FX_LPBYTE CFX_BaseDiscreteArray::GetAt(FX_INT32 index) const
+{
+ FXSYS_assert(index > -1);
+ FX_LPBASEDISCRETEARRAYDATA pData = (FX_LPBASEDISCRETEARRAYDATA)m_pData;
+ FX_INT32 iChunkSize = pData->iChunkSize;
+ FX_INT32 iChunk = index / iChunkSize;
+ if (iChunk >= pData->iChunkCount) {
+ return NULL;
+ }
+ FX_LPBYTE pChunk = (FX_LPBYTE)pData->ChunkBuffer.GetAt(iChunk);
+ if (pChunk == NULL) {
+ return NULL;
+ }
+ return pChunk + (index % iChunkSize) * pData->iBlockSize;
+}
+void CFX_BaseDiscreteArray::RemoveAll()
+{
+ FX_LPBASEDISCRETEARRAYDATA pData = (FX_LPBASEDISCRETEARRAYDATA)m_pData;
+ CFX_PtrArray &ChunkBuffer = pData->ChunkBuffer;
+ FX_INT32 &iChunkCount = pData->iChunkCount;
+ for (FX_INT32 i = 0; i < iChunkCount; i++) {
+ FX_LPVOID p = ChunkBuffer.GetAt(i);
+ if (p == NULL) {
+ continue;
+ }
+ FX_Free(p);
+ }
+ ChunkBuffer.RemoveAll();
+ iChunkCount = 0;
+}
+CFX_BaseStack::CFX_BaseStack(FX_INT32 iChunkSize, FX_INT32 iBlockSize)
+{
+ m_pData = FXTARGET_New CFX_BaseMassArrayImp(iChunkSize, iBlockSize);
+}
+CFX_BaseStack::~CFX_BaseStack()
+{
+ FXTARGET_Delete (CFX_BaseMassArrayImp*)m_pData;
+}
+FX_LPBYTE CFX_BaseStack::Push()
+{
+ return ((CFX_BaseMassArrayImp*)m_pData)->AddSpace();
+}
+void CFX_BaseStack::Pop()
+{
+ FX_INT32 &iBlockCount = ((CFX_BaseMassArrayImp*)m_pData)->m_iBlockCount;
+ if (iBlockCount < 1) {
+ return;
+ }
+ iBlockCount --;
+}
+FX_LPBYTE CFX_BaseStack::GetTopElement() const
+{
+ FX_INT32 iSize = ((CFX_BaseMassArrayImp*)m_pData)->m_iBlockCount;
+ if (iSize < 1) {
+ return NULL;
+ }
+ return ((CFX_BaseMassArrayImp*)m_pData)->GetAt(iSize - 1);
+}
+FX_INT32 CFX_BaseStack::GetSize() const
+{
+ return ((CFX_BaseMassArrayImp*)m_pData)->m_iBlockCount;
+}
+FX_LPBYTE CFX_BaseStack::GetAt(FX_INT32 index) const
+{
+ return ((CFX_BaseMassArrayImp*)m_pData)->GetAt(index);
+}
+void CFX_BaseStack::RemoveAll(FX_BOOL bLeaveMemory )
+{
+ ((CFX_BaseMassArrayImp*)m_pData)->RemoveAll(bLeaveMemory);
+}
diff --git a/xfa/src/fgas/src/crt/fx_utils.h b/xfa/src/fgas/src/crt/fx_utils.h
new file mode 100644
index 0000000000..a073b80e57
--- /dev/null
+++ b/xfa/src/fgas/src/crt/fx_utils.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 _FX_UTILS_IMP
+#define _FX_UTILS_IMP
+class CFX_BaseMassArrayImp : public CFX_Target
+{
+public:
+ CFX_BaseMassArrayImp(FX_INT32 iChunkSize, FX_INT32 iBlockSize);
+ ~CFX_BaseMassArrayImp();
+ FX_LPBYTE AddSpace()
+ {
+ return AddSpaceTo(m_iBlockCount);
+ }
+ FX_LPBYTE AddSpaceTo(FX_INT32 index);
+ FX_LPBYTE GetAt(FX_INT32 index) const;
+ FX_INT32 Append(const CFX_BaseMassArrayImp &src, FX_INT32 iStart = 0, FX_INT32 iCount = -1);
+ FX_INT32 Copy(const CFX_BaseMassArrayImp &src, FX_INT32 iStart = 0, FX_INT32 iCount = -1);
+ FX_INT32 RemoveLast(FX_INT32 iCount = -1);
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE);
+ FX_INT32 m_iChunkSize;
+ FX_INT32 m_iBlockSize;
+ FX_INT32 m_iChunkCount;
+ FX_INT32 m_iBlockCount;
+ CFX_PtrArray *m_pData;
+protected:
+ void Append(FX_INT32 iDstStart, const CFX_BaseMassArrayImp &src, FX_INT32 iSrcStart = 0, FX_INT32 iSrcCount = -1);
+};
+#endif
diff --git a/xfa/src/fgas/src/fgas_base.h b/xfa/src/fgas/src/fgas_base.h
new file mode 100644
index 0000000000..d860ec3c9b
--- /dev/null
+++ b/xfa/src/fgas/src/fgas_base.h
@@ -0,0 +1,12 @@
+// 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 _FXMATH_BASE_
+#define _FXMATH_BASE_
+#include "../../foxitlib.h"
+#include "../../../../core/include/fxge/fx_freetype.h"
+#include "../include/fgas.h"
+#endif
diff --git a/xfa/src/fgas/src/font/fx_fontutils.cpp b/xfa/src/fgas/src/font/fx_fontutils.cpp
new file mode 100644
index 0000000000..b2a7028fb8
--- /dev/null
+++ b/xfa/src/fgas/src/font/fx_fontutils.cpp
@@ -0,0 +1,236 @@
+// 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 "../fgas_base.h"
+#include "fx_fontutils.h"
+FX_DWORD FGAS_GetFontHashCode(FX_WORD wCodePage, FX_DWORD dwFontStyles)
+{
+ FX_DWORD dwHash = wCodePage;
+ if (dwFontStyles & FX_FONTSTYLE_FixedPitch) {
+ dwHash |= 0x00010000;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Serif) {
+ dwHash |= 0x00020000;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Symbolic) {
+ dwHash |= 0x00040000;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Script) {
+ dwHash |= 0x00080000;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Italic) {
+ dwHash |= 0x00100000;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Bold) {
+ dwHash |= 0x00200000;
+ }
+ return dwHash;
+}
+FX_DWORD FGAS_GetFontFamilyHash(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage)
+{
+ CFX_WideString wsFont(pszFontFamily);
+ if (dwFontStyles & FX_FONTSTYLE_Bold) {
+ wsFont += L"Bold";
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Italic) {
+ wsFont += L"Italic";
+ }
+ wsFont += wCodePage;
+ return FX_HashCode_String_GetW((FX_LPCWSTR)wsFont, wsFont.GetLength());
+}
+static const FGAS_FONTUSB g_FXGdiFontUSBTable[] = {
+ {0x0000 , 0x007F , 0 , 1252 },
+ {0x0080 , 0x00FF , 1 , 1252 },
+ {0x0100 , 0x017F , 2 , 1250 },
+ {0x0180 , 0x024F , 3 , 1250 },
+ {0x0250 , 0x02AF , 4 , 0xFFFF},
+ {0x02B0 , 0x02FF , 5 , 0xFFFF},
+ {0x0300 , 0x036F , 6 , 0xFFFF},
+ {0x0370 , 0x03FF , 7 , 1253 },
+ {0x0400 , 0x04FF , 9 , 1251 },
+ {0x0500 , 0x052F , 9 , 0xFFFF},
+ {0x0530 , 0x058F , 10 , 0xFFFF},
+ {0x0590 , 0x05FF , 11 , 1255 },
+ {0x0600 , 0x06FF , 13 , 1256 },
+ {0x0700 , 0x074F , 71 , 0xFFFF},
+ {0x0750 , 0x077F , 13 , 0xFFFF},
+ {0x0780 , 0x07BF , 72 , 0xFFFF},
+ {0x07C0 , 0x07FF , 14 , 0xFFFF},
+ {0x0800 , 0x08FF , 999, 0xFFFF},
+ {0x0900 , 0x097F , 15 , 0xFFFF},
+ {0x0980 , 0x09FF , 16 , 0xFFFF},
+ {0x0A00 , 0x0A7F , 17 , 0xFFFF},
+ {0x0A80 , 0x0AFF , 18 , 0xFFFF},
+ {0x0B00 , 0x0B7F , 19 , 0xFFFF},
+ {0x0B80 , 0x0BFF , 20 , 0xFFFF},
+ {0x0C00 , 0x0C7F , 21 , 0xFFFF},
+ {0x0C80 , 0x0CFF , 22 , 0xFFFF},
+ {0x0D00 , 0x0D7F , 23 , 0xFFFF},
+ {0x0D80 , 0x0DFF , 73 , 0xFFFF},
+ {0x0E00 , 0x0E7F , 24 , 874 },
+ {0x0E80 , 0x0EFF , 25 , 0xFFFF},
+ {0x0F00 , 0x0FFF , 70 , 0xFFFF},
+ {0x1000 , 0x109F , 74 , 0xFFFF},
+ {0x10A0 , 0x10FF , 26 , 0xFFFF},
+ {0x1100 , 0x11FF , 28 , 0xFFFF},
+ {0x1200 , 0x137F , 75 , 0xFFFF},
+ {0x1380 , 0x139F , 75 , 0xFFFF},
+ {0x13A0 , 0x13FF , 76 , 0xFFFF},
+ {0x1400 , 0x167F , 77 , 0xFFFF},
+ {0x1680 , 0x169F , 78 , 0xFFFF},
+ {0x16A0 , 0x16FF , 79 , 0xFFFF},
+ {0x1700 , 0x171F , 84 , 0xFFFF},
+ {0x1720 , 0x173F , 84 , 0xFFFF},
+ {0x1740 , 0x175F , 84 , 0xFFFF},
+ {0x1760 , 0x177F , 84 , 0xFFFF},
+ {0x1780 , 0x17FF , 80 , 0xFFFF},
+ {0x1800 , 0x18AF , 81 , 0xFFFF},
+ {0x18B0 , 0x18FF , 999, 0xFFFF},
+ {0x1900 , 0x194F , 93 , 0xFFFF},
+ {0x1950 , 0x197F , 94 , 0xFFFF},
+ {0x1980 , 0x19DF , 95 , 0xFFFF},
+ {0x19E0 , 0x19FF , 80 , 0xFFFF},
+ {0x1A00 , 0x1A1F , 96 , 0xFFFF},
+ {0x1A20 , 0x1AFF , 999, 0xFFFF},
+ {0x1B00 , 0x1B7F , 27 , 0xFFFF},
+ {0x1B80 , 0x1BBF , 112, 0xFFFF},
+ {0x1BC0 , 0x1BFF , 999, 0xFFFF},
+ {0x1C00 , 0x1C4F , 113, 0xFFFF},
+ {0x1C50 , 0x1C7F , 114, 0xFFFF},
+ {0x1C80 , 0x1CFF , 999, 0xFFFF},
+ {0x1D00 , 0x1D7F , 4 , 0xFFFF},
+ {0x1D80 , 0x1DBF , 4 , 0xFFFF},
+ {0x1DC0 , 0x1DFF , 6 , 0xFFFF},
+ {0x1E00 , 0x1EFF , 29 , 0xFFFF},
+ {0x1F00 , 0x1FFF , 30 , 0xFFFF},
+ {0x2000 , 0x206F , 31 , 0xFFFF},
+ {0x2070 , 0x209F , 32 , 0xFFFF},
+ {0x20A0 , 0x20CF , 33 , 0xFFFF},
+ {0x20D0 , 0x20FF , 34 , 0xFFFF},
+ {0x2100 , 0x214F , 35 , 0xFFFF},
+ {0x2150 , 0x215F , 36 , 0xFFFF},
+ {0x2160 , 0x216B , 36 , 936 },
+ {0x216C , 0x216F , 36 , 0xFFFF},
+ {0x2170 , 0x2179 , 36 , 936 },
+ {0x217A , 0x218F , 36 , 0xFFFF},
+ {0x2190 , 0x2199 , 37 , 949 },
+ {0x219A , 0x21FF , 37 , 0xFFFF},
+ {0x2200 , 0x22FF , 38 , 0xFFFF},
+ {0x2300 , 0x23FF , 39 , 0xFFFF},
+ {0x2400 , 0x243F , 40 , 0xFFFF},
+ {0x2440 , 0x245F , 41 , 0xFFFF},
+ {0x2460 , 0x2473 , 42 , 932 },
+ {0x2474 , 0x249B , 42 , 936 },
+ {0x249C , 0x24E9 , 42 , 949 },
+ {0x24EA , 0x24FF , 42 , 0xFFFF},
+ {0x2500 , 0x2573 , 43 , 936 },
+ {0x2574 , 0x257F , 43 , 0xFFFF},
+ {0x2580 , 0x2580 , 44 , 0xFFFF},
+ {0x2581 , 0x258F , 44 , 936 },
+ {0x2590 , 0x259F , 44 , 0xFFFF},
+ {0x25A0 , 0x25FF , 45 , 0xFFFF},
+ {0x2600 , 0x26FF , 46 , 0xFFFF},
+ {0x2700 , 0x27BF , 47 , 0xFFFF},
+ {0x27C0 , 0x27EF , 38 , 0xFFFF},
+ {0x27F0 , 0x27FF , 37 , 0xFFFF},
+ {0x2800 , 0x28FF , 82 , 0xFFFF},
+ {0x2900 , 0x297F , 37 , 0xFFFF},
+ {0x2980 , 0x29FF , 38 , 0xFFFF},
+ {0x2A00 , 0x2AFF , 38 , 0xFFFF},
+ {0x2B00 , 0x2BFF , 37 , 0xFFFF},
+ {0x2C00 , 0x2C5F , 97 , 0xFFFF},
+ {0x2C60 , 0x2C7F , 29 , 0xFFFF},
+ {0x2C80 , 0x2CFF , 8 , 0xFFFF},
+ {0x2D00 , 0x2D2F , 26 , 0xFFFF},
+ {0x2D30 , 0x2D7F , 98 , 0xFFFF},
+ {0x2D80 , 0x2DDF , 75 , 0xFFFF},
+ {0x2DE0 , 0x2DFF , 9 , 0xFFFF},
+ {0x2E00 , 0x2E7F , 31 , 0xFFFF},
+ {0x2E80 , 0x2EFF , 59 , 0xFFFF},
+ {0x2F00 , 0x2FDF , 59 , 0xFFFF},
+ {0x2FE0 , 0x2FEF , 999, 0xFFFF},
+ {0x2FF0 , 0x2FFF , 59 , 0xFFFF},
+ {0x3000 , 0x303F , 48 , 0xFFFF},
+ {0x3040 , 0x309F , 49 , 932 },
+ {0x30A0 , 0x30FF , 50 , 932 },
+ {0x3100 , 0x3129 , 51 , 936 },
+ {0x312A , 0x312F , 51 , 0xFFFF},
+ {0x3130 , 0x318F , 52 , 949 },
+ {0x3190 , 0x319F , 59 , 0xFFFF},
+ {0x31A0 , 0x31BF , 51 , 0xFFFF},
+ {0x31C0 , 0x31EF , 61 , 0xFFFF},
+ {0x31F0 , 0x31FF , 50 , 0xFFFF},
+ {0x3200 , 0x321C , 54 , 949 },
+ {0x321D , 0x325F , 54 , 0xFFFF},
+ {0x3260 , 0x327F , 54 , 949 },
+ {0x3280 , 0x32FF , 54 , 0xFFFF},
+ {0x3300 , 0x3387 , 55 , 0xFFFF},
+ {0x3388 , 0x33D0 , 55 , 949 },
+ {0x33D1 , 0x33FF , 55 , 0xFFFF},
+ {0x3400 , 0x4DBF , 59 , 0xFFFF},
+ {0x4DC0 , 0x4DFF , 99 , 0xFFFF},
+ {0x4E00 , 0x9FA5 , 59 , 936 },
+ {0x9FA6 , 0x9FFF , 59 , 0xFFFF},
+ {0xA000 , 0xA48F , 83 , 0xFFFF},
+ {0xA490 , 0xA4CF , 83 , 0xFFFF},
+ {0xA4D0 , 0xA4FF , 999, 0xFFFF},
+ {0xA500 , 0xA63F , 12 , 0xFFFF},
+ {0xA640 , 0xA69F , 9 , 0xFFFF},
+ {0xA6A0 , 0xA6FF , 999, 0xFFFF},
+ {0xA700 , 0xA71F , 5 , 0xFFFF},
+ {0xA720 , 0xA7FF , 29 , 0xFFFF},
+ {0xA800 , 0xA82F , 100, 0xFFFF},
+ {0xA830 , 0xA8FF , 999, 0xFFFF},
+ {0xA840 , 0xA87F , 53 , 0xFFFF},
+ {0xA880 , 0xA8DF , 115, 0xFFFF},
+ {0xA8E0 , 0xA8FF , 999, 0xFFFF},
+ {0xA900 , 0xA92F , 116, 0xFFFF},
+ {0xA930 , 0xA95F , 117, 0xFFFF},
+ {0xA960 , 0xA9FF , 999, 0xFFFF},
+ {0xAA00 , 0xAA5F , 118, 0xFFFF},
+ {0xAA60 , 0xABFF , 999, 0xFFFF},
+ {0xAC00 , 0xD7AF , 56 , 949 },
+ {0xD7B0 , 0xD7FF , 999, 0xFFFF},
+ {0xD800 , 0xDB7F , 57 , 0xFFFF},
+ {0xDB80 , 0xDBFF , 57 , 0xFFFF},
+ {0xDC00 , 0xDFFF , 57 , 0xFFFF},
+ {0xE000 , 0xE814 , 60 , 0xFFFF},
+ {0xE815 , 0xE864 , 60 , 936 },
+ {0xE865 , 0xF8FF , 60 , 0xFFFF},
+ {0xF900 , 0xFA0B , 61 , 949 },
+ {0xFA0C , 0xFA0D , 61 , 936 },
+ {0xFA0E , 0xFA2D , 61 , 932 },
+ {0xFA2E , 0xFAFF , 61 , 0xFFFF},
+ {0xFB00 , 0xFB4F , 62 , 0xFFFF},
+ {0xFB50 , 0xFDFF , 63 , 1256 },
+ {0xFE00 , 0xFE0F , 91 , 0xFFFF},
+ {0xFE10 , 0xFE1F , 65 , 0xFFFF},
+ {0xFE20 , 0xFE2F , 64 , 0xFFFF},
+ {0xFE30 , 0xFE4F , 65 , 0xFFFF},
+ {0xFE50 , 0xFE6F , 66 , 0xFFFF},
+ {0xFE70 , 0xFEFF , 67 , 1256 },
+ {0xFF00 , 0xFF5F , 68 , 936 },
+ {0xFF60 , 0xFF9F , 68 , 932 },
+ {0xFFA0 , 0xFFEF , 68 , 0xFFFF},
+};
+FGAS_LPCFONTUSB FGAS_GetUnicodeBitField(FX_WCHAR wUnicode)
+{
+ FX_INT32 iEnd = sizeof(g_FXGdiFontUSBTable) / sizeof(FGAS_FONTUSB) - 1;
+ FXSYS_assert(iEnd >= 0);
+ FX_INT32 iStart = 0, iMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const FGAS_FONTUSB &usb = g_FXGdiFontUSBTable[iMid];
+ if (wUnicode < usb.wStartUnicode) {
+ iEnd = iMid - 1;
+ } else if (wUnicode > usb.wEndUnicode) {
+ iStart = iMid + 1;
+ } else {
+ return &usb;
+ }
+ } while (iStart <= iEnd);
+ return NULL;
+}
diff --git a/xfa/src/fgas/src/font/fx_fontutils.h b/xfa/src/fgas/src/font/fx_fontutils.h
new file mode 100644
index 0000000000..1e3088fde8
--- /dev/null
+++ b/xfa/src/fgas/src/font/fx_fontutils.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 _FGAS_FONTUTIL_H_
+#define _FGAS_FONTUTIL_H_
+typedef struct _FGAS_FONTUSB {
+ FX_WCHAR wStartUnicode;
+ FX_WCHAR wEndUnicode;
+ FX_WORD wBitField;
+ FX_WORD wCodePage;
+} FGAS_FONTUSB, * FGAS_LPFONTUSB;
+typedef FGAS_FONTUSB const * FGAS_LPCFONTUSB;
+FX_DWORD FGAS_GetFontHashCode(FX_WORD wCodePage, FX_DWORD dwFontStyles);
+FX_DWORD FGAS_GetFontFamilyHash(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage);
+FGAS_LPCFONTUSB FGAS_GetUnicodeBitField(FX_WCHAR wUnicode);
+#endif
diff --git a/xfa/src/fgas/src/font/fx_gdifont.cpp b/xfa/src/fgas/src/font/fx_gdifont.cpp
new file mode 100644
index 0000000000..e9ab665b5a
--- /dev/null
+++ b/xfa/src/fgas/src/font/fx_gdifont.cpp
@@ -0,0 +1,532 @@
+// 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 "../fgas_base.h"
+#include "fx_gdifont.h"
+#include "fx_stdfontmgr.h"
+#ifdef _FXPLUS
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || _FX_OS_ == _FX_WIN64_
+CFX_GdiFontCache::CFX_GdiFontCache()
+ : m_GlyphMap(128)
+{
+}
+CFX_GdiFontCache::~CFX_GdiFontCache()
+{
+ FX_POSITION pos = m_GlyphMap.GetStartPosition();
+ FX_INT32 iGlyph;
+ FX_LPGDIGOCACHE pGlyph;
+ while (pos != NULL) {
+ pGlyph = NULL;
+ m_GlyphMap.GetNextAssoc(pos, (void*&)iGlyph, (void*&)pGlyph);
+ if (pGlyph != NULL) {
+ FDE_Free(pGlyph->pOutline);
+ FDE_Free(pGlyph);
+ }
+ }
+ m_GlyphMap.RemoveAll();
+}
+void CFX_GdiFontCache::SetCachedGlyphOutline(FX_DWORD dwGlyph, const GLYPHMETRICS &gm, FX_LPBYTE pOutline)
+{
+ FXSYS_assert(pOutline != NULL);
+ FX_LPGDIGOCACHE pGlyph = (FX_LPGDIGOCACHE)FDE_Alloc(sizeof(FX_GDIGOCACHE));
+ pGlyph->gm = gm;
+ pGlyph->pOutline = pOutline;
+ m_GlyphMap.SetAt((void*)dwGlyph, (void*)pGlyph);
+}
+FX_LPCGDIGOCACHE CFX_GdiFontCache::GetCachedGlyphOutline(FX_DWORD dwGlyph) const
+{
+ FX_LPCGDIGOCACHE pGlyph = NULL;
+ if (!m_GlyphMap.Lookup((void*)dwGlyph, (void*&)pGlyph)) {
+ return FALSE;
+ }
+ return pGlyph;
+}
+IFX_Font* IFX_Font::LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage, IFX_FontMgr *pFontMgr)
+{
+ CFX_GdiFont *pFont = FX_NEW CFX_GdiFont(pFontMgr);
+ if (!pFont->LoadFont(pszFontFamily, dwFontStyles, wCodePage)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+}
+IFX_Font* IFX_Font::LoadFont(FX_LPCBYTE pBuffer, FX_INT32 iLength, IFX_FontMgr *pFontMgr)
+{
+ CFX_GdiFont *pFont = FX_NEW CFX_GdiFont(pFontMgr);
+ if (!pFont->LoadFont(pBuffer, iLength)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+}
+IFX_Font* IFX_Font::LoadFont(FX_LPCWSTR pszFileName, IFX_FontMgr *pFontMgr)
+{
+ CFX_GdiFont *pFont = FX_NEW CFX_GdiFont(pFontMgr);
+ if (!pFont->LoadFont(pszFileName)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+}
+IFX_Font* IFX_Font::LoadFont(IFX_Stream *pFontStream, IFX_FontMgr *pFontMgr, FX_BOOL bSaveStream )
+{
+ CFX_GdiFont *pFont = FX_NEW CFX_GdiFont(pFontMgr);
+ if (!pFont->LoadFont(pFontStream)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+}
+IFX_Font* IFX_Font::LoadFont(CFX_Font *pExtFont, IFX_FontMgr *pFontMgr)
+{
+ FXSYS_assert(FALSE);
+ return NULL;
+}
+#define FX_GDIFONT_FONTCACHESIZE 8
+CFX_GdiFont::CFX_GdiFont(IFX_FontMgr *pFontMgr)
+ : m_pFontMgr(pFontMgr)
+ , m_iRefCount(1)
+ , m_WidthCache(1024)
+ , m_hOldFont(NULL)
+ , m_hFont(NULL)
+ , m_hDC(NULL)
+ , m_wsFontFileName()
+ , m_FontFamilies()
+ , m_hRes(NULL)
+ , m_dwStyles(0)
+ , m_SubstFonts()
+ , m_FontMapper(16)
+ , m_FontCache(FX_GDIFONT_FONTCACHESIZE)
+{
+ m_hDC = ::CreateCompatibleDC(NULL);
+ FX_memset(&m_LogFont, 0, sizeof(m_LogFont));
+ FXSYS_assert(m_hDC != NULL);
+}
+CFX_GdiFont::~CFX_GdiFont()
+{
+ FX_INT32 iCount = m_SubstFonts.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ IFX_Font *pFont = (IFX_Font*)m_SubstFonts[i];
+ pFont->Release();
+ }
+ m_SubstFonts.RemoveAll();
+ m_FontMapper.RemoveAll();
+ if (m_hFont != NULL) {
+ ::SelectObject(m_hDC, m_hOldFont);
+ ::DeleteObject(m_hFont);
+ }
+ ::DeleteDC(m_hDC);
+ if (m_hRes != NULL) {
+ if (m_wsFontFileName.GetLength() > 0) {
+ ::RemoveFontResourceW((FX_LPCWSTR)m_wsFontFileName);
+ } else {
+ ::RemoveFontMemResourceEx(m_hRes);
+ }
+ }
+ m_WidthCache.RemoveAll();
+ ClearCache();
+}
+void CFX_GdiFont::ClearCache()
+{
+ FX_INT32 iCount = m_SubstFonts.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ IFX_Font *pFont = (IFX_Font*)m_SubstFonts[i];
+ ((CFX_GdiFont*)pFont)->ClearCache();
+ }
+ FX_POSITION pos = m_FontCache.GetStartPosition();
+ FX_DWORD dwMAT2;
+ CFX_GdiFontCache *pCache;
+ while (pos != NULL) {
+ pCache = NULL;
+ m_FontCache.GetNextAssoc(pos, (void*&)dwMAT2, (void*&)pCache);
+ if (pCache != NULL) {
+ delete pCache;
+ }
+ }
+ m_FontCache.RemoveAll();
+}
+void CFX_GdiFont::Release()
+{
+ if (-- m_iRefCount < 1) {
+ if (m_pFontMgr != NULL) {
+ m_pFontMgr->RemoveFont(this);
+ }
+ delete this;
+ }
+}
+IFX_Font* CFX_GdiFont::Retain()
+{
+ ++ m_iRefCount;
+ return this;
+}
+FX_BOOL CFX_GdiFont::LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage)
+{
+ FXSYS_assert(m_hFont == NULL);
+ LOGFONTW lf;
+ FX_memset(&lf, 0, sizeof(lf));
+ lf.lfHeight = -1000;
+ lf.lfWeight = (dwFontStyles & FX_FONTSTYLE_Bold) ? FW_BOLD : FW_NORMAL;
+ lf.lfItalic = (dwFontStyles & FX_FONTSTYLE_Italic) != 0;
+ lf.lfPitchAndFamily = (dwFontStyles & FX_FONTSTYLE_FixedPitch) ? FIXED_PITCH : VARIABLE_PITCH;
+ if (dwFontStyles & FX_FONTSTYLE_Serif) {
+ lf.lfPitchAndFamily |= FF_ROMAN;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Script) {
+ lf.lfPitchAndFamily |= FF_SCRIPT;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Symbolic) {
+ lf.lfCharSet = SYMBOL_CHARSET;
+ } else {
+ FX_WORD wCharSet = FX_GetCharsetFromCodePage(wCodePage);
+ lf.lfCharSet = wCharSet != 0xFFFF ? (FX_BYTE)wCharSet : DEFAULT_CHARSET;
+ }
+ if (pszFontFamily == NULL) {
+ lf.lfFaceName[0] = L'\0';
+ } else {
+ FXSYS_wcsncpy(lf.lfFaceName, pszFontFamily, 31);
+ }
+ return LoadFont(lf);
+}
+FX_BOOL CFX_GdiFont::LoadFont(FX_LPCBYTE pBuffer, FX_INT32 iLength)
+{
+ FXSYS_assert(m_hFont == NULL && pBuffer != NULL && iLength > 0);
+ Gdiplus::PrivateFontCollection pfc;
+ if (pfc.AddMemoryFont(pBuffer, iLength) != Gdiplus::Ok) {
+ return FALSE;
+ }
+ if (GetFontFamilies(pfc) < 1) {
+ return FALSE;
+ }
+ FX_DWORD dwCount = 0;
+ m_hRes = ::AddFontMemResourceEx((void*)pBuffer, iLength, 0, &dwCount);
+ if (m_hRes == NULL) {
+ return FALSE;
+ }
+ CFX_WideString wsFamily = m_FontFamilies[0];
+ m_hFont = ::CreateFontW(-1000, 0, 0, 0, FW_NORMAL, FALSE, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, (FX_LPCWSTR)wsFamily);
+ if (m_hFont == NULL) {
+ ::RemoveFontMemResourceEx(m_hRes);
+ m_hRes = NULL;
+ return FALSE;
+ }
+ RetrieveFontStyles();
+ m_hOldFont = ::SelectObject(m_hDC, m_hFont);
+ ::GetOutlineTextMetricsW(m_hDC, sizeof(m_OutlineTM), &m_OutlineTM);
+ return TRUE;
+}
+FX_BOOL CFX_GdiFont::LoadFont(FX_LPCWSTR pszFileName)
+{
+ FXSYS_assert(m_hFont == NULL && pszFileName != NULL);
+ Gdiplus::PrivateFontCollection pfc;
+ if (pfc.AddFontFile(pszFileName) != Gdiplus::Ok) {
+ return FALSE;
+ }
+ if (GetFontFamilies(pfc) < 1) {
+ return FALSE;
+ }
+ m_wsFontFileName = pszFileName;
+ m_hRes = (HANDLE)::AddFontResourceW(pszFileName);
+ if (m_hRes == NULL) {
+ return FALSE;
+ }
+ CFX_WideString wsFamily = m_FontFamilies[0];
+ m_hFont = ::CreateFontW(-1000, 0, 0, 0, FW_NORMAL, FALSE, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, (FX_LPCWSTR)wsFamily);
+ if (m_hFont == NULL) {
+ ::RemoveFontResourceW(pszFileName);
+ m_hRes = NULL;
+ return FALSE;
+ }
+ RetrieveFontStyles();
+ ::SelectObject(m_hDC, m_hFont);
+ ::GetOutlineTextMetricsW(m_hDC, sizeof(m_OutlineTM), &m_OutlineTM);
+ return TRUE;
+}
+FX_BOOL CFX_GdiFont::LoadFont(IFX_Stream *pFontStream)
+{
+ FXSYS_assert(m_hFont == NULL && pFontStream != NULL);
+ FX_INT32 iLength = pFontStream->GetLength();
+ if (iLength < 1) {
+ return FALSE;
+ }
+ FX_LPBYTE pBuf = (FX_LPBYTE)FDE_Alloc(iLength);
+ if (pBuf == NULL) {
+ return FALSE;
+ }
+ iLength = pFontStream->ReadData(pBuf, iLength);
+ FX_BOOL bRet = LoadFont(pBuf, iLength);
+ FDE_Free(pBuf);
+ return bRet;
+}
+FX_BOOL CFX_GdiFont::LoadFont(const LOGFONTW &lf)
+{
+ FXSYS_assert(m_hFont == NULL);
+ m_hFont = ::CreateFontIndirectW((LPLOGFONTW)&lf);
+ if (m_hFont == NULL) {
+ return FALSE;
+ }
+ RetrieveFontStyles();
+ ::SelectObject(m_hDC, m_hFont);
+ ::GetOutlineTextMetricsW(m_hDC, sizeof(m_OutlineTM), &m_OutlineTM);
+ return TRUE;
+}
+FX_INT32 CFX_GdiFont::GetFontFamilies(Gdiplus::FontCollection &fc)
+{
+ FX_INT32 iCount = fc.GetFamilyCount();
+ if (iCount < 1) {
+ return iCount;
+ }
+ Gdiplus::FontFamily *pFontFamilies = (Gdiplus::FontFamily*)FDE_Alloc(iCount * sizeof(Gdiplus::FontFamily));
+ if (pFontFamilies == NULL) {
+ return -1;
+ }
+ FX_INT32 iFind = 0;
+ fc.GetFamilies(iCount, pFontFamilies, &iFind);
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ CFX_WideString wsFamilyName;
+ FX_LPWSTR pName = wsFamilyName.GetBuffer(LF_FACESIZE);
+ pFontFamilies[i].GetFamilyName(pName);
+ wsFamilyName.ReleaseBuffer();
+ m_FontFamilies.Add(wsFamilyName);
+ }
+ FDE_Free(pFontFamilies);
+ return iCount;
+}
+void CFX_GdiFont::RetrieveFontStyles()
+{
+ FXSYS_assert(m_hFont != NULL);
+ FX_memset(&m_LogFont, 0, sizeof(m_LogFont));
+ ::GetObjectW(m_hFont, sizeof(m_LogFont), &m_LogFont);
+ m_dwStyles = FX_GetGdiFontStyles(m_LogFont);
+}
+void CFX_GdiFont::GetFamilyName(CFX_WideString &wsFamily) const
+{
+ FXSYS_assert(m_hFont != NULL);
+ wsFamily = m_LogFont.lfFaceName;
+}
+FX_BOOL CFX_GdiFont::GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bRecursive, FX_BOOL bCharCode)
+{
+ iWidth = (FX_INT32)(FX_SHORT)m_WidthCache.GetAt(wUnicode, 0);
+ if (iWidth == 0 || iWidth == -1) {
+ IFX_Font *pFont = NULL;
+ FX_INT32 iGlyph = GetGlyphIndex(wUnicode, TRUE, &pFont, bCharCode);
+ if (iGlyph != 0xFFFF && pFont != NULL) {
+ if (pFont == (IFX_Font*)this) {
+ if (!::GetCharWidthI(m_hDC, iGlyph, 1, NULL, &iWidth)) {
+ iWidth = -1;
+ }
+ } else if (((CFX_GdiFont*)pFont)->GetCharWidth(wUnicode, iWidth, FALSE, bCharCode)) {
+ return TRUE;
+ }
+ } else {
+ iWidth = -1;
+ }
+ Lock();
+ m_WidthCache.SetAtGrow(wUnicode, (FX_SHORT)iWidth);
+ Unlock();
+ }
+ return iWidth > 0;
+}
+FX_BOOL CFX_GdiFont::GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bCharCode)
+{
+ return GetCharWidth(wUnicode, iWidth, TRUE, bCharCode);
+}
+FX_INT32 CFX_GdiFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bRecursive, IFX_Font **ppFont, FX_BOOL bCharCode)
+{
+ FX_INT32 iGlyph = 0XFFFF;
+ if (::GetGlyphIndicesW(m_hDC, &wUnicode, 1, (LPWORD)&iGlyph, GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR && iGlyph != 0xFFFF) {
+ if (ppFont != NULL) {
+ *ppFont = (IFX_Font*)this;
+ }
+ return iGlyph;
+ }
+ FX_LPCFONTUSB pFontUSB = FX_GetUnicodeBitField(wUnicode);
+ if (pFontUSB == NULL) {
+ return 0xFFFF;
+ }
+ FX_WORD wBitField = pFontUSB->wBitField;
+ if (wBitField >= 128) {
+ return 0xFFFF;
+ }
+ IFX_Font *pFont = NULL;
+ m_FontMapper.Lookup((void*)wBitField, (void*&)pFont);
+ if (pFont != NULL && pFont != (IFX_Font*)this) {
+ iGlyph = ((CFX_GdiFont*)pFont)->GetGlyphIndex(wUnicode, FALSE, NULL, bCharCode);
+ if (iGlyph != 0xFFFF) {
+ FX_INT32 i = m_SubstFonts.Find(pFont);
+ if (i > -1) {
+ iGlyph |= ((i + 1) << 24);
+ if (ppFont != NULL) {
+ *ppFont = pFont;
+ }
+ return iGlyph;
+ }
+ }
+ }
+ if (m_pFontMgr != NULL && bRecursive) {
+ IFX_Font *pFont = m_pFontMgr->GetDefFontByUnicode(wUnicode, m_dwStyles, m_LogFont.lfFaceName);
+ if (pFont != NULL) {
+ if (pFont == (IFX_Font*)this) {
+ pFont->Release();
+ return 0xFFFF;
+ }
+ m_FontMapper.SetAt((void*)wBitField, (void*)pFont);
+ FX_INT32 i = m_SubstFonts.GetSize();
+ m_SubstFonts.Add(pFont);
+ iGlyph = ((CFX_GdiFont*)pFont)->GetGlyphIndex(wUnicode, FALSE, NULL, bCharCode);
+ if (iGlyph != 0xFFFF) {
+ iGlyph |= ((i + 1) << 24);
+ if (ppFont != NULL) {
+ *ppFont = pFont;
+ }
+ return iGlyph;
+ }
+ }
+ }
+ return 0xFFFF;
+}
+FX_INT32 CFX_GdiFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bCharCode)
+{
+ return GetGlyphIndex(wUnicode, TRUE, NULL, bCharCode);
+}
+FX_INT32 CFX_GdiFont::GetAscent() const
+{
+ return m_OutlineTM.otmAscent;
+}
+FX_INT32 CFX_GdiFont::GetDescent() const
+{
+ return m_OutlineTM.otmDescent;
+}
+FX_BOOL CFX_GdiFont::GetCharBBox(FX_WCHAR wUnicode, CFX_Rect &bbox, FX_BOOL bCharCode)
+{
+ FX_INT32 iGlyphIndex = GetGlyphIndex(wUnicode, bCharCode);
+ if (iGlyphIndex == 0xFFFF) {
+ return FALSE;
+ }
+ IFX_Font *pFont = GetSubstFont(iGlyphIndex);
+ if (pFont == NULL) {
+ return FALSE;
+ }
+ GLYPHMETRICS gm;
+ iGlyphIndex &= 0x00FFFFFF;
+ static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
+ if (::GetGlyphOutlineW(((CFX_GdiFont*)pFont)->m_hDC, iGlyphIndex, GGO_GLYPH_INDEX | GGO_METRICS, &gm, 0, NULL, &mat2) != GDI_ERROR) {
+ bbox.left = gm.gmptGlyphOrigin.x;
+ bbox.top = gm.gmptGlyphOrigin.y;
+ bbox.width = gm.gmBlackBoxX;
+ bbox.height = gm.gmBlackBoxY;
+ return TRUE;
+ }
+ return FALSE;
+}
+FX_BOOL CFX_GdiFont::GetBBox(CFX_Rect &bbox)
+{
+ bbox.left = m_OutlineTM.otmrcFontBox.left;
+ bbox.top = m_OutlineTM.otmrcFontBox.top;
+ bbox.width = m_OutlineTM.otmrcFontBox.right - m_OutlineTM.otmrcFontBox.left;
+ bbox.height = m_OutlineTM.otmrcFontBox.bottom - m_OutlineTM.otmrcFontBox.top;
+ return TRUE;
+}
+FX_INT32 CFX_GdiFont::GetItalicAngle() const
+{
+ return m_OutlineTM.otmItalicAngle / 10;
+}
+void CFX_GdiFont::Reset()
+{
+ Lock();
+ m_WidthCache.RemoveAll();
+ ClearCache();
+ Unlock();
+}
+IFX_Font* CFX_GdiFont::GetSubstFont(FX_INT32 iGlyphIndex) const
+{
+ FX_INT32 iHigher = (iGlyphIndex & 0x7F000000) >> 24;
+ if (iHigher == 0) {
+ return (IFX_Font*)this;
+ }
+ if (iHigher > m_SubstFonts.GetSize()) {
+ return (IFX_Font*)this;
+ }
+ return (IFX_Font*)m_SubstFonts[iHigher - 1];
+}
+FX_DWORD CFX_GdiFont::GetGlyphDIBits(FX_INT32 iGlyphIndex, FX_ARGB argb, const MAT2 *pMatrix, GLYPHMETRICS &gm, FX_LPVOID pBuffer, FX_DWORD bufSize)
+{
+ static const UINT uFormat = GGO_GLYPH_INDEX | GGO_GRAY8_BITMAP;
+ IFX_Font *pFont = GetSubstFont(iGlyphIndex);
+ if (pFont == NULL) {
+ return 0;
+ }
+ if (pFont != (IFX_Font*)this) {
+ return ((CFX_GdiFont*)pFont)->GetGlyphDIBits(iGlyphIndex & 0x00FFFFFF, argb, pMatrix, gm, pBuffer, bufSize);
+ }
+ FX_LPBYTE pGlyphOutline = NULL;
+ FXSYS_assert(pMatrix != NULL);
+ FX_DWORD dwMAT2 = GetMAT2HashCode((const FIXED*)pMatrix);
+ CFX_GdiFontCache *pCache = NULL;
+ if (m_FontCache.Lookup((void*)dwMAT2, (void*&)pCache) && pCache != NULL) {
+ FX_LPCGDIGOCACHE pGO = pCache->GetCachedGlyphOutline(iGlyphIndex);
+ if (pGO != NULL) {
+ gm = pGO->gm;
+ pGlyphOutline = pGO->pOutline;
+ }
+ }
+ if (pGlyphOutline == NULL) {
+ FX_DWORD dwGlyphSize = ::GetGlyphOutlineW(m_hDC, iGlyphIndex, uFormat, &gm, 0, NULL, pMatrix);
+ if (dwGlyphSize == 0 || dwGlyphSize == GDI_ERROR) {
+ return 0;
+ }
+ pGlyphOutline = (FX_LPBYTE)FX_Alloc(dwGlyphSize);
+ ::GetGlyphOutlineW(m_hDC, iGlyphIndex, uFormat, &gm, dwGlyphSize, pGlyphOutline, pMatrix);
+ if (pCache == NULL) {
+ pCache = FX_NEW CFX_GdiFontCache;
+ if (m_FontCache.GetCount() >= FX_GDIFONT_FONTCACHESIZE) {
+ ClearCache();
+ }
+ m_FontCache.SetAt((void*)dwMAT2, (void*)pCache);
+ }
+ pCache->SetCachedGlyphOutline(iGlyphIndex, gm, pGlyphOutline);
+ }
+ FX_DWORD dwDibSize = gm.gmBlackBoxX * 4 * gm.gmBlackBoxY;
+ if (pBuffer == NULL || bufSize < dwDibSize) {
+ return dwDibSize;
+ }
+ CreateGlyphBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY, pGlyphOutline, (FX_LPDWORD)pBuffer, argb);
+ return dwDibSize;
+}
+FX_DWORD CFX_GdiFont::GetHashCode() const
+{
+ return FX_GetFontHashCode(FX_GetCodePageFromCharset(m_LogFont.lfCharSet), FX_GetGdiFontStyles(m_LogFont));
+}
+FX_DWORD CFX_GdiFont::GetMAT2HashCode(const FIXED *pFixed)
+{
+ FXSYS_assert(pFixed != NULL);
+ FX_DWORD dwHash1 = 0, dwHash2 = 5381, dwRet;
+ for (int i = 0; i < 4; i ++) {
+ dwRet = *((const FX_DWORD*)pFixed);
+ dwHash1 = 1313 * dwHash1 + dwRet;
+ dwHash2 += (dwHash2 << 5) + dwRet;
+ pFixed ++;
+ }
+ return ((dwHash1 & 0x0000FFFF) << 16) | (dwHash2 & 0x0000FFFF);
+}
+void CFX_GdiFont::CreateGlyphBitmap(FX_INT32 iWidth, FX_INT32 iHeight, FX_LPBYTE pOutline, FX_LPDWORD pDIB, FX_ARGB argb)
+{
+ FX_INT32 padding = ((iWidth + 3) / 4) * 4 - iWidth;
+ FX_DWORD alpha;
+ FX_INT32 i, j;
+ for (j = iHeight - 1; j >= 0; --j) {
+ for (i = iWidth - 1; i >= 0; --i) {
+ if ((alpha = *pOutline++) == 0) {
+ *pDIB++ = 0;
+ } else {
+ alpha = (argb >> 24) * (alpha * 4 - 1) / 256;
+ *pDIB++ = (alpha << 24) | (argb & 0x00FFFFFF);
+ }
+ }
+ pOutline += padding;
+ }
+}
+#endif
+#endif
diff --git a/xfa/src/fgas/src/font/fx_gdifont.h b/xfa/src/fgas/src/font/fx_gdifont.h
new file mode 100644
index 0000000000..f6d88f38a0
--- /dev/null
+++ b/xfa/src/fgas/src/font/fx_gdifont.h
@@ -0,0 +1,89 @@
+// 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 _FX_GDIOBJECT_IMP
+#define _FX_GDIOBJECT_IMP
+#ifdef _FXPLUS
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || _FX_OS_ == _FX_WIN64_
+typedef struct _FX_GDIGOCACHE {
+ GLYPHMETRICS gm;
+ FX_LPBYTE pOutline;
+} FX_GDIGOCACHE, * FX_LPGDIGOCACHE;
+typedef FX_GDIGOCACHE const * FX_LPCGDIGOCACHE;
+class CFX_GdiFontCache : public CFX_Object
+{
+public:
+ CFX_GdiFontCache();
+ ~CFX_GdiFontCache();
+ void SetCachedGlyphOutline(FX_DWORD dwGlyph, const GLYPHMETRICS &gm, FX_LPBYTE pOutline);
+ FX_LPCGDIGOCACHE GetCachedGlyphOutline(FX_DWORD dwGlyph) const;
+protected:
+ CFX_MapPtrToPtr m_GlyphMap;
+};
+class CFX_GdiFont : public IFX_Font, public CFX_ThreadLock, public CFX_Object
+{
+public:
+ CFX_GdiFont(IFX_FontMgr *pFontMgr);
+ ~CFX_GdiFont();
+ virtual void Release();
+ virtual IFX_Font* Retain();
+ FX_BOOL LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage);
+ FX_BOOL LoadFont(FX_LPCBYTE pBuffer, FX_INT32 iLength);
+ FX_BOOL LoadFont(FX_LPCWSTR pszFileName);
+ FX_BOOL LoadFont(IFX_Stream *pFontStream);
+ FX_BOOL LoadFont(const LOGFONTW &lf);
+ virtual IFX_Font* Derive(FX_DWORD dwFontStyles, FX_WORD wCodePage = 0)
+ {
+ return NULL;
+ }
+ virtual void GetFamilyName(CFX_WideString &wsFamily) const;
+ virtual FX_DWORD GetFontStyles() const
+ {
+ return m_dwStyles;
+ }
+ virtual FX_BYTE GetCharSet() const
+ {
+ return m_LogFont.lfCharSet;
+ }
+ virtual FX_BOOL GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bCharCode = FALSE);
+ virtual FX_INT32 GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bCharCode = FALSE);
+ virtual FX_INT32 GetAscent() const;
+ virtual FX_INT32 GetDescent() const;
+ virtual FX_BOOL GetCharBBox(FX_WCHAR wUnicode, CFX_Rect &bbox, FX_BOOL bCharCode = FALSE);
+ virtual FX_BOOL GetBBox(CFX_Rect &bbox);
+ virtual FX_INT32 GetItalicAngle() const;
+ virtual void Reset();
+ FX_DWORD GetGlyphDIBits(FX_INT32 iGlyphIndex, FX_ARGB argb, const MAT2 *pMatrix, GLYPHMETRICS &gm, FX_LPVOID pBuffer, FX_DWORD bufSize);
+ FX_DWORD GetHashCode() const;
+protected:
+ IFX_FontMgr *m_pFontMgr;
+ FX_INT32 m_iRefCount;
+ CFX_WordDiscreteArray m_WidthCache;
+ OUTLINETEXTMETRICW m_OutlineTM;
+ HGDIOBJ m_hOldFont;
+ HFONT m_hFont;
+ HDC m_hDC;
+ LOGFONTW m_LogFont;
+ CFX_WideString m_wsFontFileName;
+ CFX_WideStringArray m_FontFamilies;
+ HANDLE m_hRes;
+ FX_DWORD m_dwStyles;
+ CFX_PtrArray m_SubstFonts;
+ CFX_MapPtrToPtr m_FontMapper;
+ CFX_MapPtrToPtr m_FontCache;
+ void ClearCache();
+ FX_INT32 GetFontFamilies(Gdiplus::FontCollection &fc);
+ void RetrieveFontStyles();
+ IFX_Font* GetSubstFont(FX_INT32 iGlyphIndex) const;
+ FX_BOOL GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bRecursive, FX_BOOL bCharCode = FALSE);
+ FX_INT32 GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bRecursive, IFX_Font **ppFont, FX_BOOL bCharCode = FALSE);
+ FX_DWORD GetMAT2HashCode(const FIXED *pFixed);
+ void CreateGlyphBitmap(FX_INT32 iWidth, FX_INT32 iHeight, FX_LPBYTE pOutline, FX_LPDWORD pDIB, FX_ARGB argb);
+ friend class CFX_GdiFontMgr;
+};
+#endif
+#endif
+#endif
diff --git a/xfa/src/fgas/src/font/fx_gefont.cpp b/xfa/src/fgas/src/font/fx_gefont.cpp
new file mode 100644
index 0000000000..f952bc730e
--- /dev/null
+++ b/xfa/src/fgas/src/font/fx_gefont.cpp
@@ -0,0 +1,595 @@
+// 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 "../fgas_base.h"
+#include "fx_gefont.h"
+#include "fx_fontutils.h"
+#ifndef _FXPLUS
+IFX_Font* IFX_Font::LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage, IFX_FontMgr *pFontMgr)
+{
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+ if (NULL != pFontMgr) {
+ return pFontMgr->GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);
+ }
+ return NULL;
+#else
+ CFX_GEFont *pFont = FX_NEW CFX_GEFont(pFontMgr);
+ if (!pFont->LoadFont(pszFontFamily, dwFontStyles, wCodePage)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+#endif
+}
+IFX_Font* IFX_Font::LoadFont(FX_LPCBYTE pBuffer, FX_INT32 iLength, IFX_FontMgr *pFontMgr)
+{
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+ if (NULL != pFontMgr) {
+ return pFontMgr->LoadFont(pBuffer, iLength, 0, NULL);
+ }
+ return NULL;
+#else
+ CFX_GEFont *pFont = FX_NEW CFX_GEFont(pFontMgr);
+ if (!pFont->LoadFont(pBuffer, iLength)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+#endif
+}
+IFX_Font* IFX_Font::LoadFont(FX_LPCWSTR pszFileName, IFX_FontMgr *pFontMgr)
+{
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+ if (NULL != pFontMgr) {
+ return pFontMgr->LoadFont(pszFileName, 0, NULL);
+ }
+ return NULL;
+#else
+ CFX_GEFont *pFont = FX_NEW CFX_GEFont(pFontMgr);
+ if (!pFont->LoadFont(pszFileName)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+#endif
+}
+IFX_Font* IFX_Font::LoadFont(IFX_Stream *pFontStream, IFX_FontMgr *pFontMgr, FX_BOOL bSaveStream)
+{
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+ if (NULL != pFontMgr) {
+ return pFontMgr->LoadFont(pFontStream, 0, NULL);
+ }
+ return NULL;
+#else
+ CFX_GEFont *pFont = FX_NEW CFX_GEFont(pFontMgr);
+ if (!pFont->LoadFont(pFontStream, bSaveStream)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+#endif
+}
+IFX_Font* IFX_Font::LoadFont(CFX_Font *pExtFont, IFX_FontMgr *pFontMgr, FX_BOOL bTakeOver)
+{
+ CFX_GEFont *pFont = FX_NEW CFX_GEFont(pFontMgr);
+ if (!pFont->LoadFont(pExtFont, bTakeOver)) {
+ pFont->Release();
+ return NULL;
+ }
+ return pFont;
+}
+CFX_GEFont::CFX_GEFont(IFX_FontMgr *pFontMgr)
+ : CFX_ThreadLock()
+ , m_pFont(NULL)
+ , m_pFontMgr(pFontMgr)
+ , m_iRefCount(1)
+ , m_bExtFont(FALSE)
+ , m_pStream(NULL)
+ , m_pFileRead(NULL)
+ , m_pFontEncoding(NULL)
+ , m_pCharWidthMap(NULL)
+ , m_pRectArray(NULL)
+ , m_pBBoxMap(NULL)
+ , m_wCharSet(0xFFFF)
+ , m_pProvider(NULL)
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+ , m_bUseLogFontStyle(FALSE)
+ , m_dwLogFontStyle(0)
+#endif
+ , m_SubstFonts()
+ , m_FontMapper(16)
+{
+}
+CFX_GEFont::CFX_GEFont(const CFX_GEFont &src, FX_DWORD dwFontStyles)
+ : CFX_ThreadLock()
+ , m_pFont(NULL)
+ , m_pFontMgr(src.m_pFontMgr)
+ , m_iRefCount(1)
+ , m_bExtFont(FALSE)
+ , m_pStream(NULL)
+ , m_pFileRead(NULL)
+ , m_pFontEncoding(NULL)
+ , m_pCharWidthMap(NULL)
+ , m_pRectArray(NULL)
+ , m_pBBoxMap(NULL)
+ , m_wCharSet(0xFFFF)
+ , m_pProvider(NULL)
+ , m_SubstFonts()
+ , m_FontMapper(16)
+{
+ m_pFont = FX_NEW CFX_Font;
+ FXSYS_assert(m_pFont != NULL);
+ FXSYS_assert(src.m_pFont != NULL);
+ m_pFont->LoadClone(src.m_pFont);
+ CFX_SubstFont *&pSubst = m_pFont->m_pSubstFont;
+ if (pSubst == NULL) {
+ pSubst = FX_NEW CFX_SubstFont;
+ }
+ if (pSubst) {
+ pSubst->m_Weight = (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
+ if (dwFontStyles & FX_FONTSTYLE_Italic) {
+ pSubst->m_SubstFlags |= FXFONT_SUBST_ITALIC;
+ }
+ }
+ InitFont();
+}
+CFX_GEFont::~CFX_GEFont()
+{
+ FX_INT32 iCount = m_SubstFonts.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ IFX_Font *pFont = (IFX_Font*)m_SubstFonts[i];
+ pFont->Release();
+ }
+ m_SubstFonts.RemoveAll();
+ m_FontMapper.RemoveAll();
+ if (m_pFileRead != NULL) {
+ m_pFileRead->Release();
+ }
+ if (m_pStream != NULL) {
+ m_pStream->Release();
+ }
+ if (m_pFontEncoding != NULL) {
+ delete m_pFontEncoding;
+ }
+ if (m_pCharWidthMap != NULL) {
+ FXTARGET_Delete m_pCharWidthMap;
+ }
+ if (m_pRectArray != NULL) {
+ FXTARGET_Delete m_pRectArray;
+ }
+ if (m_pBBoxMap != NULL) {
+ delete m_pBBoxMap;
+ }
+ if (m_pFont != NULL && !m_bExtFont) {
+ delete m_pFont;
+ }
+}
+void CFX_GEFont::Release()
+{
+ if (-- m_iRefCount < 1) {
+ if (m_pFontMgr != NULL) {
+ m_pFontMgr->RemoveFont(this);
+ }
+ delete this;
+ }
+}
+IFX_Font* CFX_GEFont::Retain()
+{
+ ++ m_iRefCount;
+ return this;
+}
+FX_BOOL CFX_GEFont::LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage)
+{
+ if (m_pFont != NULL) {
+ return FALSE;
+ }
+ Lock();
+ CFX_ByteString csFontFamily;
+ if (pszFontFamily != NULL) {
+ csFontFamily = CFX_ByteString::FromUnicode(pszFontFamily);
+ }
+ FX_DWORD dwFlags = 0;
+ if (dwFontStyles & FX_FONTSTYLE_FixedPitch) {
+ dwFlags |= FXFONT_FIXED_PITCH;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Serif) {
+ dwFlags |= FXFONT_SERIF;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Symbolic) {
+ dwFlags |= FXFONT_SYMBOLIC;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Script) {
+ dwFlags |= FXFONT_SCRIPT;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Italic) {
+ dwFlags |= FXFONT_ITALIC;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_Bold) {
+ dwFlags |= FXFONT_BOLD;
+ }
+ if (dwFontStyles & FX_FONTSTYLE_ExactMatch) {
+ dwFlags |= FXFONT_EXACTMATCH;
+ }
+ FX_INT32 iWeight = (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
+ FX_WORD wCharSet = FX_GetCharsetFromCodePage(wCodePage);
+ if (wCharSet == 0xFFFF) {
+ wCharSet = FXSYS_GetACP();
+ }
+ m_wCharSet = wCharSet;
+ m_pFont = FX_NEW CFX_Font;
+ if ((dwFlags & FXFONT_ITALIC) && (dwFlags & FXFONT_BOLD)) {
+ csFontFamily += ",BoldItalic";
+ } else if (dwFlags & FXFONT_BOLD) {
+ csFontFamily += ",Bold";
+ } else if (dwFlags & FXFONT_ITALIC) {
+ csFontFamily += ",Italic";
+ }
+ FX_BOOL bRet = m_pFont->LoadSubst(csFontFamily, TRUE, dwFlags, iWeight, 0, wCodePage);
+ bRet = m_pFont->m_Face != NULL;
+ if (bRet) {
+ InitFont();
+ }
+ Unlock();
+ return bRet;
+}
+FX_BOOL CFX_GEFont::LoadFont(FX_LPCBYTE pBuffer, FX_INT32 length)
+{
+ if (m_pFont != NULL) {
+ return FALSE;
+ }
+ Lock();
+ m_pFont = FX_NEW CFX_Font;
+ FX_BOOL bRet = m_pFont->LoadEmbedded(pBuffer, length);
+ if (bRet) {
+ InitFont();
+ }
+ m_wCharSet = 0xFFFF;
+ Unlock();
+ return bRet;
+}
+FX_BOOL CFX_GEFont::LoadFont(FX_LPCWSTR pszFileName)
+{
+ if (m_pFont != NULL) {
+ return FALSE;
+ }
+ if (m_pStream != NULL) {
+ return FALSE;
+ }
+ if (m_pFileRead != NULL) {
+ return FALSE;
+ }
+ Lock();
+ m_pStream = IFX_Stream::CreateStream(pszFileName, FX_STREAMACCESS_Binary | FX_STREAMACCESS_Read);
+ m_pFileRead = FX_CreateFileRead(m_pStream);
+ FX_BOOL bRet = FALSE;
+ if (m_pStream != NULL && m_pFileRead != NULL) {
+ m_pFont = FX_NEW CFX_Font;
+ bRet = m_pFont->LoadFile(m_pFileRead);
+ if (!bRet) {
+ m_pFileRead->Release();
+ m_pFileRead = NULL;
+ } else {
+ InitFont();
+ }
+ }
+ m_wCharSet = 0xFFFF;
+ Unlock();
+ return bRet;
+}
+FX_BOOL CFX_GEFont::LoadFont(IFX_Stream *pFontStream, FX_BOOL bSaveStream)
+{
+ if (m_pFont != NULL) {
+ return FALSE;
+ }
+ if (pFontStream == NULL || pFontStream->GetLength() < 1) {
+ return FALSE;
+ }
+ if (m_pFileRead != NULL) {
+ return FALSE;
+ }
+ Lock();
+ if (bSaveStream) {
+ m_pStream = pFontStream;
+ }
+ m_pFileRead = FX_CreateFileRead(pFontStream);
+ m_pFont = FX_NEW CFX_Font;
+ FX_BOOL bRet = m_pFont->LoadFile(m_pFileRead);
+ if (!bRet) {
+ m_pFileRead->Release();
+ m_pFileRead = NULL;
+ } else {
+ InitFont();
+ }
+ m_wCharSet = 0xFFFF;
+ Unlock();
+ return bRet;
+}
+FX_BOOL CFX_GEFont::LoadFont(CFX_Font *pExtFont, FX_BOOL bTakeOver)
+{
+ if (m_pFont != NULL) {
+ return FALSE;
+ }
+ if (pExtFont == NULL) {
+ return FALSE;
+ }
+ Lock();
+ if ((m_pFont = pExtFont) != NULL) {
+ m_bExtFont = !bTakeOver;
+ InitFont();
+ } else {
+ m_bExtFont = TRUE;
+ }
+ m_wCharSet = 0xFFFF;
+ Unlock();
+ return m_pFont != NULL;
+}
+void CFX_GEFont::InitFont()
+{
+ if (m_pFont == NULL) {
+ return;
+ }
+ if (m_pFontEncoding == NULL) {
+#ifdef FXFM_ENCODING_NONE
+ m_pFontEncoding = FX_CreateFontEncodingEx(m_pFont);
+#else
+ m_pFontEncoding = FXGE_CreateUnicodeEncoding(m_pFont);
+#endif
+ }
+ if (m_pCharWidthMap == NULL) {
+ m_pCharWidthMap = FXTARGET_New CFX_WordDiscreteArray(1024);
+ }
+ if (m_pRectArray == NULL) {
+ m_pRectArray = FXTARGET_New CFX_RectMassArray(16);
+ }
+ if (m_pBBoxMap == NULL) {
+ m_pBBoxMap = FX_NEW CFX_MapPtrToPtr(16);
+ }
+}
+IFX_Font* CFX_GEFont::Derive(FX_DWORD dwFontStyles, FX_WORD wCodePage )
+{
+ if (GetFontStyles() == dwFontStyles) {
+ return Retain();
+ }
+ return FX_NEW CFX_GEFont(*this, dwFontStyles);
+}
+FX_BYTE CFX_GEFont::GetCharSet() const
+{
+ FXSYS_assert(m_pFont != NULL);
+ if (m_wCharSet != 0xFFFF) {
+ return (FX_BYTE)m_wCharSet;
+ }
+ if (m_pFont->m_pSubstFont == NULL) {
+ return FX_CHARSET_Default;
+ }
+ return m_pFont->m_pSubstFont->m_Charset;
+}
+void CFX_GEFont::GetFamilyName(CFX_WideString &wsFamily) const
+{
+ FXSYS_assert(m_pFont != NULL);
+ if (m_pFont->m_pSubstFont == NULL || m_pFont->m_pSubstFont->m_Family.GetLength() == 0) {
+ wsFamily = CFX_WideString::FromLocal(m_pFont->GetFamilyName());
+ } else {
+ wsFamily = CFX_WideString::FromLocal(m_pFont->m_pSubstFont->m_Family);
+ }
+}
+void CFX_GEFont::GetPsName(CFX_WideString &wsName) const
+{
+ wsName = m_pFont->GetPsName();
+}
+FX_DWORD CFX_GEFont::GetFontStyles() const
+{
+ FXSYS_assert(m_pFont != NULL);
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+ if (m_bUseLogFontStyle) {
+ return m_dwLogFontStyle;
+ }
+#endif
+ FX_DWORD dwStyles = 0;
+ if (m_pFont->m_pSubstFont == NULL) {
+ if (m_pFont->IsBold()) {
+ dwStyles |= FX_FONTSTYLE_Bold;
+ }
+ if (m_pFont->IsItalic()) {
+ dwStyles |= FX_FONTSTYLE_Italic;
+ }
+ } else {
+ if (m_pFont->m_pSubstFont->m_Weight == FXFONT_FW_BOLD) {
+ dwStyles |= FX_FONTSTYLE_Bold;
+ }
+ if (m_pFont->m_pSubstFont->m_SubstFlags & FXFONT_SUBST_ITALIC) {
+ dwStyles |= FX_FONTSTYLE_Italic;
+ }
+ }
+ return dwStyles;
+}
+FX_BOOL CFX_GEFont::GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bCharCode)
+{
+ return GetCharWidth(wUnicode, iWidth, TRUE, bCharCode);
+}
+FX_BOOL CFX_GEFont::GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bRecursive, FX_BOOL bCharCode)
+{
+ FXSYS_assert (m_pCharWidthMap != NULL);
+ iWidth = m_pCharWidthMap->GetAt(wUnicode, 0);
+ if (iWidth < 1) {
+ if (!m_pProvider || !m_pProvider->GetCharWidth(this, wUnicode, iWidth, bCharCode)) {
+ IFX_Font *pFont = NULL;
+ FX_INT32 iGlyph = GetGlyphIndex(wUnicode, TRUE, &pFont, bCharCode);
+ if (iGlyph != 0xFFFF && pFont != NULL) {
+ if (pFont == (IFX_Font*)this) {
+ iWidth = m_pFont->GetGlyphWidth(iGlyph);
+ if (iWidth < 0) {
+ iWidth = -1;
+ }
+ } else if (((CFX_GEFont*)pFont)->GetCharWidth(wUnicode, iWidth, FALSE, bCharCode)) {
+ return TRUE;
+ }
+ } else {
+ iWidth = -1;
+ }
+ }
+ Lock();
+ m_pCharWidthMap->SetAtGrow(wUnicode, (FX_SHORT)iWidth);
+ Unlock();
+ } else if (iWidth == 65535) {
+ iWidth = -1;
+ }
+ return iWidth > 0;
+}
+FX_BOOL CFX_GEFont::GetCharBBox(FX_WCHAR wUnicode, CFX_Rect &bbox, FX_BOOL bCharCode)
+{
+ return GetCharBBox(wUnicode, bbox, TRUE, bCharCode);
+}
+FX_BOOL CFX_GEFont::GetCharBBox(FX_WCHAR wUnicode, CFX_Rect &bbox, FX_BOOL bRecursive, FX_BOOL bCharCode)
+{
+ FXSYS_assert(m_pRectArray != NULL);
+ FXSYS_assert(m_pBBoxMap != NULL);
+ FX_LPVOID pRect = NULL;
+ if (!m_pBBoxMap->Lookup((void*)(FX_UINTPTR)wUnicode, pRect)) {
+ IFX_Font *pFont = NULL;
+ FX_INT32 iGlyph = GetGlyphIndex(wUnicode, TRUE, &pFont, bCharCode);
+ if (iGlyph != 0xFFFF && pFont != NULL) {
+ if (pFont == (IFX_Font*)this) {
+ FX_RECT rtBBox;
+ if (m_pFont->GetGlyphBBox(iGlyph, rtBBox)) {
+ Lock();
+ CFX_Rect rt;
+ rt.Set(rtBBox.left, rtBBox.top, rtBBox.Width(), rtBBox.Height());
+ FX_INT32 index = m_pRectArray->Add(rt);
+ pRect = m_pRectArray->GetPtrAt(index);
+ m_pBBoxMap->SetAt((void*)(FX_UINTPTR)wUnicode, pRect);
+ Unlock();
+ }
+ } else if (((CFX_GEFont*)pFont)->GetCharBBox(wUnicode, bbox, FALSE, bCharCode)) {
+ return TRUE;
+ }
+ }
+ }
+ if (pRect == NULL) {
+ return FALSE;
+ }
+ bbox = *(FX_LPCRECT)pRect;
+ return TRUE;
+}
+FX_BOOL CFX_GEFont::GetBBox(CFX_Rect &bbox)
+{
+ FX_RECT rt(0, 0, 0, 0);
+ FX_BOOL bRet = m_pFont->GetBBox(rt);
+ if (bRet) {
+ bbox.left = rt.left;
+ bbox.width = rt.Width();
+ bbox.top = rt.bottom;
+ bbox.height = -rt.Height();
+ }
+ return bRet;
+}
+FX_INT32 CFX_GEFont::GetItalicAngle() const
+{
+ if (m_pFont->m_pSubstFont == NULL) {
+ return 0;
+ }
+ return m_pFont->m_pSubstFont->m_ItalicAngle;
+}
+FX_INT32 CFX_GEFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bCharCode)
+{
+ return GetGlyphIndex(wUnicode, TRUE, NULL, bCharCode);
+}
+FX_INT32 CFX_GEFont::GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bRecursive, IFX_Font **ppFont, FX_BOOL bCharCode)
+{
+ FXSYS_assert (m_pFontEncoding != NULL);
+ FX_INT32 iGlyphIndex = m_pFontEncoding->GlyphFromCharCode(wUnicode);
+ if (iGlyphIndex > 0) {
+ if (ppFont != NULL) {
+ *ppFont = (IFX_Font*)this;
+ }
+ return iGlyphIndex;
+ }
+ FGAS_LPCFONTUSB pFontUSB = FGAS_GetUnicodeBitField(wUnicode);
+ if (pFontUSB == NULL) {
+ return 0xFFFF;
+ }
+ FX_WORD wBitField = pFontUSB->wBitField;
+ if (wBitField >= 128) {
+ return 0xFFFF;
+ }
+ IFX_Font *pFont = NULL;
+ m_FontMapper.Lookup((void*)(FX_UINTPTR)wUnicode, (void*&)pFont);
+ if (pFont != NULL && pFont != (IFX_Font*)this) {
+ iGlyphIndex = ((CFX_GEFont*)pFont)->GetGlyphIndex(wUnicode, FALSE, NULL, bCharCode);
+ if (iGlyphIndex != 0xFFFF) {
+ FX_INT32 i = m_SubstFonts.Find(pFont);
+ if (i > -1) {
+ iGlyphIndex |= ((i + 1) << 24);
+ if (ppFont != NULL) {
+ *ppFont = pFont;
+ }
+ return iGlyphIndex;
+ }
+ }
+ }
+ if (m_pFontMgr != NULL && bRecursive) {
+ CFX_WideString wsFamily;
+ GetFamilyName(wsFamily);
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ IFX_Font *pFont = m_pFontMgr->GetDefFontByUnicode(wUnicode, GetFontStyles(), (FX_LPCWSTR)wsFamily);
+#else
+ IFX_Font *pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), (FX_LPCWSTR)wsFamily);
+ if (NULL == pFont) {
+ pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), NULL);
+ }
+#endif
+ if (pFont != NULL) {
+ if (pFont == (IFX_Font*)this) {
+ pFont->Release();
+ return 0xFFFF;
+ }
+ m_FontMapper.SetAt((void*)(FX_UINTPTR)wUnicode, (void*)pFont);
+ FX_INT32 i = m_SubstFonts.GetSize();
+ m_SubstFonts.Add(pFont);
+ iGlyphIndex = ((CFX_GEFont*)pFont)->GetGlyphIndex(wUnicode, FALSE, NULL, bCharCode);
+ if (iGlyphIndex != 0xFFFF) {
+ iGlyphIndex |= ((i + 1) << 24);
+ if (ppFont != NULL) {
+ *ppFont = pFont;
+ }
+ return iGlyphIndex;
+ }
+ }
+ }
+ return 0xFFFF;
+}
+FX_INT32 CFX_GEFont::GetAscent() const
+{
+ return m_pFont->GetAscent();
+}
+FX_INT32 CFX_GEFont::GetDescent() const
+{
+ return m_pFont->GetDescent();
+}
+void CFX_GEFont::Reset()
+{
+ Lock();
+ FX_INT32 iCount = m_SubstFonts.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ IFX_Font *pFont = (IFX_Font*)m_SubstFonts[i];
+ ((CFX_GEFont*)pFont)->Reset();
+ }
+ if (m_pCharWidthMap != NULL) {
+ m_pCharWidthMap->RemoveAll();
+ }
+ if (m_pBBoxMap != NULL) {
+ m_pBBoxMap->RemoveAll();
+ }
+ if (m_pRectArray != NULL) {
+ m_pRectArray->RemoveAll();
+ }
+ Unlock();
+}
+IFX_Font* CFX_GEFont::GetSubstFont(FX_INT32 iGlyphIndex) const
+{
+ iGlyphIndex = ((FX_DWORD)iGlyphIndex) >> 24;
+ return iGlyphIndex == 0 ? (IFX_Font*)this : (IFX_Font*)m_SubstFonts[iGlyphIndex - 1];
+}
+#endif
diff --git a/xfa/src/fgas/src/font/fx_gefont.h b/xfa/src/fgas/src/font/fx_gefont.h
new file mode 100644
index 0000000000..430ff09852
--- /dev/null
+++ b/xfa/src/fgas/src/font/fx_gefont.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 _FX_GRAPHOBJS_IMP
+#define _FX_GRAPHOBJS_IMP
+#ifndef _FXPLUS
+class CFX_GEFontMgr;
+#ifndef FXFONT_SUBST_ITALIC
+#define FXFONT_SUBST_ITALIC 0x02
+#endif
+class CFX_GEFont : public IFX_Font, public CFX_ThreadLock, public CFX_Object
+{
+public:
+ CFX_GEFont(const CFX_GEFont &src, FX_DWORD dwFontStyles);
+ CFX_GEFont(IFX_FontMgr *pFontMgr);
+ ~CFX_GEFont();
+ virtual void Release();
+ virtual IFX_Font* Retain();
+ FX_BOOL LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage);
+ FX_BOOL LoadFont(FX_LPCBYTE pBuffer, FX_INT32 length);
+ FX_BOOL LoadFont(FX_LPCWSTR pszFileName);
+ FX_BOOL LoadFont(IFX_Stream *pFontStream, FX_BOOL bSaveStream);
+ FX_BOOL LoadFont(CFX_Font *pExtFont, FX_BOOL bTakeOver = FALSE);
+ virtual IFX_Font* Derive(FX_DWORD dwFontStyles, FX_WORD wCodePage = 0);
+ virtual void GetFamilyName(CFX_WideString &wsFamily) const;
+ virtual void GetPsName(CFX_WideString &wsName) const;
+ virtual FX_DWORD GetFontStyles() const;
+ virtual FX_BYTE GetCharSet() const;
+ virtual FX_BOOL GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bCharCode = FALSE);
+ virtual FX_INT32 GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bCharCode = FALSE);
+ virtual FX_INT32 GetAscent() const;
+ virtual FX_INT32 GetDescent() const;
+ virtual FX_BOOL GetCharBBox(FX_WCHAR wUnicode, CFX_Rect &bbox, FX_BOOL bCharCode = FALSE);
+ virtual FX_BOOL GetBBox(CFX_Rect &bbox);
+ virtual FX_INT32 GetItalicAngle() const;
+ virtual void Reset();
+ virtual IFX_Font* GetSubstFont(FX_INT32 iGlyphIndex) const;
+ virtual void* GetDevFont()const
+ {
+ return (void*)m_pFont;
+ }
+ virtual void SetFontProvider(IFX_FontProvider* pProvider)
+ {
+ m_pProvider = pProvider;
+ }
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+ virtual void SetLogicalFontStyle(FX_DWORD dwLogFontStyle)
+ {
+ m_bUseLogFontStyle = TRUE;
+ m_dwLogFontStyle = dwLogFontStyle;
+ };
+#endif
+protected:
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+ FX_BOOL m_bUseLogFontStyle;
+ FX_DWORD m_dwLogFontStyle;
+#endif
+ CFX_Font *m_pFont;
+ IFX_FontMgr *m_pFontMgr;
+ FX_INT32 m_iRefCount;
+ FX_BOOL m_bExtFont;
+ IFX_Stream *m_pStream;
+ IFX_FileRead *m_pFileRead;
+ IFX_FontEncoding *m_pFontEncoding;
+ CFX_WordDiscreteArray *m_pCharWidthMap;
+ CFX_RectMassArray *m_pRectArray;
+ CFX_MapPtrToPtr *m_pBBoxMap;
+ IFX_FontProvider *m_pProvider;
+ FX_WORD m_wCharSet;
+ CFX_PtrArray m_SubstFonts;
+ CFX_MapPtrToPtr m_FontMapper;
+ void InitFont();
+ FX_BOOL GetCharBBox(FX_WCHAR wUnicode, CFX_Rect &bbox, FX_BOOL bRecursive, FX_BOOL bCharCode = FALSE);
+ FX_BOOL GetCharWidth(FX_WCHAR wUnicode, FX_INT32 &iWidth, FX_BOOL bRecursive, FX_BOOL bCharCode = FALSE);
+ FX_INT32 GetGlyphIndex(FX_WCHAR wUnicode, FX_BOOL bRecursive, IFX_Font **ppFont, FX_BOOL bCharCode = FALSE);
+};
+#endif
+#endif
diff --git a/xfa/src/fgas/src/font/fx_stdfontmgr.cpp b/xfa/src/fgas/src/font/fx_stdfontmgr.cpp
new file mode 100644
index 0000000000..ae59cab2e5
--- /dev/null
+++ b/xfa/src/fgas/src/font/fx_stdfontmgr.cpp
@@ -0,0 +1,1490 @@
+// 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 "../fgas_base.h"
+#include "fx_stdfontmgr.h"
+#include "fx_fontutils.h"
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+IFX_FontMgr* IFX_FontMgr::Create(FX_LPEnumAllFonts pEnumerator, FX_LPMatchFont pMatcher , FX_LPVOID pUserData )
+{
+ return FX_NEW CFX_StdFontMgrImp(pEnumerator, pMatcher, pUserData);
+}
+CFX_StdFontMgrImp::CFX_StdFontMgrImp(FX_LPEnumAllFonts pEnumerator, FX_LPMatchFont pMatcher, FX_LPVOID pUserData)
+ : m_pMatcher(pMatcher)
+ , m_pEnumerator(pEnumerator)
+ , m_FontFaces()
+ , m_Fonts()
+ , m_CPFonts(8)
+ , m_FamilyFonts(16)
+ , m_UnicodeFonts(16)
+ , m_BufferFonts(4)
+ , m_FileFonts(4)
+ , m_StreamFonts(4)
+ , m_DeriveFonts(4)
+ , m_pUserData(pUserData)
+{
+ if (m_pEnumerator != NULL) {
+ m_pEnumerator(m_FontFaces, m_pUserData, NULL, 0xFEFF);
+ }
+ if (m_pMatcher == NULL) {
+ m_pMatcher = FX_DefFontMatcher;
+ }
+ FXSYS_assert(m_pMatcher != NULL);
+}
+CFX_StdFontMgrImp::~CFX_StdFontMgrImp()
+{
+ m_FontFaces.RemoveAll();
+ m_CPFonts.RemoveAll();
+ m_FamilyFonts.RemoveAll();
+ m_UnicodeFonts.RemoveAll();
+ m_BufferFonts.RemoveAll();
+ m_FileFonts.RemoveAll();
+ m_StreamFonts.RemoveAll();
+ m_DeriveFonts.RemoveAll();
+ for (FX_INT32 i = m_Fonts.GetUpperBound(); i >= 0; i--) {
+ IFX_Font *pFont = (IFX_Font*)m_Fonts[i];
+ if (pFont != NULL) {
+ pFont->Release();
+ }
+ }
+ m_Fonts.RemoveAll();
+}
+IFX_Font* CFX_StdFontMgrImp::GetDefFontByCodePage(FX_WORD wCodePage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily)
+{
+ FX_DWORD dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles);
+ IFX_Font *pFont = NULL;
+ if (m_CPFonts.Lookup((void*)(FX_UINTPTR)dwHash, (void*&)pFont)) {
+ return pFont ? LoadFont(pFont, dwFontStyles, wCodePage) : NULL;
+ }
+ FX_LPCFONTDESCRIPTOR pFD;
+ if ((pFD = FindFont(pszFontFamily, dwFontStyles, TRUE, wCodePage)) == NULL)
+ if ((pFD = FindFont(NULL, dwFontStyles, TRUE, wCodePage)) == NULL)
+ if ((pFD = FindFont(NULL, dwFontStyles, FALSE, wCodePage)) == NULL) {
+ return NULL;
+ }
+ FXSYS_assert(pFD != NULL);
+ pFont = IFX_Font::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this);
+ if (pFont != NULL) {
+ m_Fonts.Add(pFont);
+ m_CPFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ dwHash = FGAS_GetFontFamilyHash(pFD->wsFontFace, dwFontStyles, wCodePage);
+ m_FamilyFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ return LoadFont(pFont, dwFontStyles, wCodePage);
+ }
+ return NULL;
+}
+IFX_Font* CFX_StdFontMgrImp::GetDefFontByCharset(FX_BYTE nCharset, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily)
+{
+ return GetDefFontByCodePage(FX_GetCodePageFromCharset(nCharset), dwFontStyles, pszFontFamily);
+}
+#define _FX_USEGASFONTMGR_
+IFX_Font* CFX_StdFontMgrImp::GetDefFontByUnicode(FX_WCHAR wUnicode, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily)
+{
+ FGAS_LPCFONTUSB pRet = FGAS_GetUnicodeBitField(wUnicode);
+ if (pRet->wBitField == 999) {
+ return NULL;
+ }
+ FX_DWORD dwHash = FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, pRet->wBitField);
+ IFX_Font *pFont = NULL;
+ if (m_UnicodeFonts.Lookup((void*)(FX_UINTPTR)dwHash, (void*&)pFont)) {
+ return pFont ? LoadFont(pFont, dwFontStyles, pRet->wCodePage) : NULL;
+ }
+#ifdef _FX_USEGASFONTMGR_
+ FX_LPCFONTDESCRIPTOR pFD = FindFont(pszFontFamily, dwFontStyles, FALSE, pRet->wCodePage, pRet->wBitField, wUnicode);
+ if (pFD == NULL && pszFontFamily) {
+ pFD = FindFont(NULL, dwFontStyles, FALSE, pRet->wCodePage, pRet->wBitField, wUnicode);
+ }
+ if (pFD == NULL) {
+ return NULL;
+ }
+ FXSYS_assert(pFD);
+ FX_WORD wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet);
+ FX_LPCWSTR pFontFace = pFD->wsFontFace;
+ pFont = IFX_Font::LoadFont(pFontFace, dwFontStyles, wCodePage, this);
+#else
+ CFX_FontMapper* pBuiltinMapper = CFX_GEModule::Get()->GetFontMgr()->m_pBuiltinMapper;
+ if (pBuiltinMapper == NULL) {
+ return NULL;
+ }
+ FX_INT32 iWeight = (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
+ int italic_angle = 0;
+ FXFT_Face ftFace = pBuiltinMapper->FindSubstFontByUnicode(wUnicode, dwFontStyles, iWeight, italic_angle);
+ if (ftFace == NULL) {
+ return NULL;
+ }
+ CFX_Font* pFXFont = FX_NEW CFX_Font;
+ if (pFXFont == NULL) {
+ return NULL;
+ }
+ pFXFont->m_Face = ftFace;
+ pFXFont->m_pFontData = FXFT_Get_Face_Stream_Base(ftFace);
+ pFXFont->m_dwSize = FXFT_Get_Face_Stream_Size(ftFace);
+ pFont = IFX_Font::LoadFont(pFXFont, this);
+ FX_WORD wCodePage = pRet->wCodePage;
+ CFX_WideString wsPsName = pFXFont->GetPsName();
+ FX_LPCWSTR pFontFace = wsPsName;
+#endif
+ if (pFont != NULL) {
+ m_Fonts.Add(pFont);
+ m_UnicodeFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles);
+ m_CPFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ dwHash = FGAS_GetFontFamilyHash(pFontFace, dwFontStyles, wCodePage);
+ m_FamilyFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ return LoadFont(pFont, dwFontStyles, wCodePage);
+ }
+ return NULL;
+}
+IFX_Font* CFX_StdFontMgrImp::GetDefFontByLanguage(FX_WORD wLanguage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily)
+{
+ return GetDefFontByCodePage(FX_GetDefCodePageByLanguage(wLanguage), dwFontStyles, pszFontFamily);
+}
+IFX_Font* CFX_StdFontMgrImp::LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage)
+{
+ FX_DWORD dwHash = FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, wCodePage);
+ IFX_Font *pFont = NULL;
+ if (m_FamilyFonts.Lookup((void*)(FX_UINTPTR)dwHash, (void*&)pFont)) {
+ return pFont ? LoadFont(pFont, dwFontStyles, wCodePage) : NULL;
+ }
+ FX_LPCFONTDESCRIPTOR pFD = NULL;
+ if ((pFD = FindFont(pszFontFamily, dwFontStyles, TRUE, wCodePage)) == NULL)
+ if ((pFD = FindFont(pszFontFamily, dwFontStyles, FALSE, wCodePage)) == NULL) {
+ return NULL;
+ }
+ FXSYS_assert(pFD != NULL);
+ if (wCodePage == 0xFFFF) {
+ wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet);
+ }
+ pFont = IFX_Font::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this);
+ if (pFont != NULL) {
+ m_Fonts.Add(pFont);
+ m_FamilyFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles);
+ m_CPFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ return LoadFont(pFont, dwFontStyles, wCodePage);
+ }
+ return NULL;
+}
+IFX_Font* CFX_StdFontMgrImp::LoadFont(FX_LPCBYTE pBuffer, FX_INT32 iLength)
+{
+ FXSYS_assert(pBuffer != NULL && iLength > 0);
+ IFX_Font *pFont = NULL;
+ if (m_BufferFonts.Lookup((void*)pBuffer, (void*&)pFont)) {
+ if (pFont != NULL) {
+ return pFont->Retain();
+ }
+ }
+ pFont = IFX_Font::LoadFont(pBuffer, iLength, this);
+ if (pFont != NULL) {
+ m_Fonts.Add(pFont);
+ m_BufferFonts.SetAt((void*)pBuffer, pFont);
+ return pFont->Retain();
+ }
+ return NULL;
+}
+IFX_Font* CFX_StdFontMgrImp::LoadFont(FX_LPCWSTR pszFileName)
+{
+ FXSYS_assert(pszFileName != NULL);
+ FX_DWORD dwHash = FX_HashCode_String_GetW(pszFileName, -1);
+ IFX_Font *pFont = NULL;
+ if (m_FileFonts.Lookup((void*)(FX_UINTPTR)dwHash, (void*&)pFont)) {
+ if (pFont != NULL) {
+ return pFont->Retain();
+ }
+ }
+ pFont = IFX_Font::LoadFont(pszFileName, NULL);
+ if (pFont != NULL) {
+ m_Fonts.Add(pFont);
+ m_FileFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ return pFont->Retain();
+ }
+ return NULL;
+}
+IFX_Font* CFX_StdFontMgrImp::LoadFont(IFX_Stream *pFontStream, FX_LPCWSTR pszFontAlias , FX_DWORD dwFontStyles , FX_WORD wCodePage , FX_BOOL bSaveStream )
+{
+ FXSYS_assert(pFontStream != NULL && pFontStream->GetLength() > 0);
+ IFX_Font *pFont = NULL;
+ if (m_StreamFonts.Lookup((void*)pFontStream, (void*&)pFont)) {
+ if (pFont != NULL) {
+ if (pszFontAlias != NULL) {
+ FX_DWORD dwHash = FGAS_GetFontFamilyHash(pszFontAlias, dwFontStyles, wCodePage);
+ m_FamilyFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ }
+ return LoadFont(pFont, dwFontStyles, wCodePage);
+ }
+ }
+ pFont = IFX_Font::LoadFont(pFontStream, this, bSaveStream);
+ if (pFont != NULL) {
+ m_Fonts.Add(pFont);
+ m_StreamFonts.SetAt((void*)pFontStream, (void*)pFont);
+ if (pszFontAlias != NULL) {
+ FX_DWORD dwHash = FGAS_GetFontFamilyHash(pszFontAlias, dwFontStyles, wCodePage);
+ m_FamilyFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ }
+ return LoadFont(pFont, dwFontStyles, wCodePage);
+ }
+ return NULL;
+}
+IFX_Font* CFX_StdFontMgrImp::LoadFont(IFX_Font *pSrcFont, FX_DWORD dwFontStyles, FX_WORD wCodePage)
+{
+ FXSYS_assert(pSrcFont != NULL);
+ if (pSrcFont->GetFontStyles() == dwFontStyles) {
+ return pSrcFont->Retain();
+ }
+ void* buffer[3] = {pSrcFont, (void*)(FX_UINTPTR)dwFontStyles, (void*)(FX_UINTPTR)wCodePage};
+ FX_DWORD dwHash = FX_HashCode_String_GetA((FX_LPCSTR)buffer, 3 * sizeof(void*));
+ IFX_Font *pFont = NULL;
+ if (m_DeriveFonts.GetCount() > 0) {
+ m_DeriveFonts.Lookup((void*)(FX_UINTPTR)dwHash, (void*&)pFont);
+ if (pFont != NULL) {
+ return pFont->Retain();
+ }
+ }
+ pFont = pSrcFont->Derive(dwFontStyles, wCodePage);
+ if (pFont != NULL) {
+ m_DeriveFonts.SetAt((void*)(FX_UINTPTR)dwHash, (void*)pFont);
+ FX_INT32 index = m_Fonts.Find(pFont);
+ if (index < 0) {
+ m_Fonts.Add(pFont);
+ pFont->Retain();
+ }
+ return pFont;
+ }
+ return NULL;
+}
+void CFX_StdFontMgrImp::ClearFontCache()
+{
+ FX_INT32 iCount = m_Fonts.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ IFX_Font *pFont = (IFX_Font*)m_Fonts[i];
+ if (pFont != NULL) {
+ pFont->Reset();
+ }
+ }
+}
+void CFX_StdFontMgrImp::RemoveFont(CFX_MapPtrToPtr &fontMap, IFX_Font *pFont)
+{
+ FX_POSITION pos = fontMap.GetStartPosition();
+ FX_LPVOID pKey;
+ FX_LPVOID pFind;
+ while (pos != NULL) {
+ pFind = NULL;
+ fontMap.GetNextAssoc(pos, pKey, pFind);
+ if (pFind != (void*)pFont) {
+ continue;
+ }
+ fontMap.RemoveKey(pKey);
+ break;
+ }
+}
+void CFX_StdFontMgrImp::RemoveFont(IFX_Font *pFont)
+{
+ RemoveFont(m_CPFonts, pFont);
+ RemoveFont(m_FamilyFonts, pFont);
+ RemoveFont(m_UnicodeFonts, pFont);
+ RemoveFont(m_BufferFonts, pFont);
+ RemoveFont(m_FileFonts, pFont);
+ RemoveFont(m_StreamFonts, pFont);
+ RemoveFont(m_DeriveFonts, pFont);
+ FX_INT32 iFind = m_Fonts.Find(pFont);
+ if (iFind > -1) {
+ m_Fonts.RemoveAt(iFind, 1);
+ }
+}
+FX_LPCFONTDESCRIPTOR CFX_StdFontMgrImp::FindFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_DWORD dwMatchFlags, FX_WORD wCodePage, FX_DWORD dwUSB , FX_WCHAR wUnicode )
+{
+ if (m_pMatcher == NULL) {
+ return NULL;
+ }
+ FX_FONTMATCHPARAMS params;
+ FX_memset(&params, 0, sizeof(params));
+ params.dwUSB = dwUSB;
+ params.wUnicode = wUnicode;
+ params.wCodePage = wCodePage;
+ params.pwsFamily = pszFontFamily;
+ params.dwFontStyles = dwFontStyles;
+ params.dwMatchFlags = dwMatchFlags;
+ FX_LPCFONTDESCRIPTOR pDesc = m_pMatcher(&params, m_FontFaces, m_pUserData);
+ if (pDesc) {
+ return pDesc;
+ }
+ if (pszFontFamily && m_pEnumerator) {
+ CFX_FontDescriptors namedFonts;
+ m_pEnumerator(namedFonts, m_pUserData, pszFontFamily, wUnicode);
+ params.pwsFamily = NULL;
+ pDesc = m_pMatcher(&params, namedFonts, m_pUserData);
+ if (pDesc == NULL) {
+ return NULL;
+ }
+ for (FX_INT32 i = m_FontFaces.GetSize() - 1; i >= 0; i--) {
+ FX_LPCFONTDESCRIPTOR pMatch = m_FontFaces.GetPtrAt(i);
+ if (*pMatch == *pDesc) {
+ return pMatch;
+ }
+ }
+ int index = m_FontFaces.Add(*pDesc);
+ return m_FontFaces.GetPtrAt(index);
+ }
+ return NULL;
+}
+FX_LPCFONTDESCRIPTOR FX_DefFontMatcher(FX_LPFONTMATCHPARAMS pParams, const CFX_FontDescriptors &fonts, FX_LPVOID pUserData)
+{
+ FX_LPCFONTDESCRIPTOR pBestFont = NULL;
+ FX_INT32 iBestSimilar = 0;
+ FX_BOOL bMatchStyle = (pParams->dwMatchFlags & FX_FONTMATCHPARA_MacthStyle) > 0;
+ FX_INT32 iCount = fonts.GetSize();
+ for (FX_INT32 i = 0; i < iCount; ++i) {
+ FX_LPCFONTDESCRIPTOR pFont = fonts.GetPtrAt(i);
+ if ((pFont->dwFontStyles & FX_FONTSTYLE_BoldItalic) == FX_FONTSTYLE_BoldItalic) {
+ continue;
+ }
+ if (pParams->pwsFamily) {
+ if (FXSYS_wcsicmp(pParams->pwsFamily, pFont->wsFontFace)) {
+ continue;
+ }
+ if (pFont->uCharSet == FX_CHARSET_Symbol) {
+ return pFont;
+ }
+ }
+ if (pFont->uCharSet == FX_CHARSET_Symbol) {
+ continue;
+ }
+ if (pParams->wCodePage != 0xFFFF) {
+ if (FX_GetCodePageFromCharset(pFont->uCharSet) != pParams->wCodePage) {
+ continue;
+ }
+ } else {
+ if (pParams->dwUSB < 128) {
+ FX_DWORD dwByte = pParams->dwUSB / 32;
+ FX_DWORD dwUSB = 1 << (pParams->dwUSB % 32);
+ if ((pFont->FontSignature.fsUsb[dwByte] & dwUSB) == 0) {
+ continue;
+ }
+ }
+ }
+ if (bMatchStyle) {
+ if ((pFont->dwFontStyles & 0x0F) == (pParams->dwFontStyles & 0x0F)) {
+ return pFont;
+ } else {
+ continue;
+ }
+ }
+ if (pParams->pwsFamily != NULL) {
+ if (FXSYS_wcsicmp(pParams->pwsFamily, pFont->wsFontFace) == 0) {
+ return pFont;
+ }
+ }
+ FX_INT32 iSimilarValue = FX_GetSimilarValue(pFont, pParams->dwFontStyles);
+ if (iBestSimilar < iSimilarValue) {
+ iBestSimilar = iSimilarValue;
+ pBestFont = pFont;
+ }
+ }
+ return iBestSimilar < 1 ? NULL : pBestFont;
+}
+FX_INT32 FX_GetSimilarValue(FX_LPCFONTDESCRIPTOR pFont, FX_DWORD dwFontStyles)
+{
+ FX_INT32 iValue = 0;
+ if ((dwFontStyles & FX_FONTSTYLE_Symbolic) == (pFont->dwFontStyles & FX_FONTSTYLE_Symbolic)) {
+ iValue += 64;
+ }
+ if ((dwFontStyles & FX_FONTSTYLE_FixedPitch) == (pFont->dwFontStyles & FX_FONTSTYLE_FixedPitch)) {
+ iValue += 32;
+ }
+ if ((dwFontStyles & FX_FONTSTYLE_Serif) == (pFont->dwFontStyles & FX_FONTSTYLE_Serif)) {
+ iValue += 16;
+ }
+ if ((dwFontStyles & FX_FONTSTYLE_Script) == (pFont->dwFontStyles & FX_FONTSTYLE_Script)) {
+ iValue += 8;
+ }
+ return iValue;
+}
+FX_LPMatchFont FX_GetDefFontMatchor()
+{
+ return FX_DefFontMatcher;
+}
+FX_DWORD FX_GetGdiFontStyles(const LOGFONTW &lf)
+{
+ FX_DWORD dwStyles = 0;
+ if ((lf.lfPitchAndFamily & 0x03) == FIXED_PITCH) {
+ dwStyles |= FX_FONTSTYLE_FixedPitch;
+ }
+ FX_BYTE nFamilies = lf.lfPitchAndFamily & 0xF0;
+ if (nFamilies == FF_ROMAN) {
+ dwStyles |= FX_FONTSTYLE_Serif;
+ }
+ if (nFamilies == FF_SCRIPT) {
+ dwStyles |= FX_FONTSTYLE_Script;
+ }
+ if (lf.lfCharSet == SYMBOL_CHARSET) {
+ dwStyles |= FX_FONTSTYLE_Symbolic;
+ }
+ return dwStyles;
+}
+static FX_INT32 CALLBACK FX_GdiFontEnumProc(ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, DWORD dwFontType, LPARAM lParam)
+{
+ if (dwFontType != TRUETYPE_FONTTYPE) {
+ return 1;
+ }
+ const LOGFONTW &lf = ((LPENUMLOGFONTEXW)lpelfe)->elfLogFont;
+ if (lf.lfFaceName[0] == L'@') {
+ return 1;
+ }
+ FX_LPFONTDESCRIPTOR pFont = FX_Alloc(FX_FONTDESCRIPTOR, 1);
+ if (NULL == pFont) {
+ return 0;
+ }
+ FXSYS_memset(pFont, 0, sizeof(FX_FONTDESCRIPTOR));
+ pFont->uCharSet = lf.lfCharSet;
+ pFont->dwFontStyles = FX_GetGdiFontStyles(lf);
+ FXSYS_wcsncpy(pFont->wsFontFace, (FX_LPCWSTR)lf.lfFaceName, 31);
+ pFont->wsFontFace[31] = 0;
+ FX_memcpy(&pFont->FontSignature, &lpntme->ntmFontSig, sizeof(lpntme->ntmFontSig));
+ ((CFX_FontDescriptors*)lParam)->Add(*pFont);
+ FX_Free(pFont);
+ return 1;
+}
+static void FX_EnumGdiFonts(CFX_FontDescriptors &fonts, FX_LPVOID pUserData, FX_LPCWSTR pwsFaceName, FX_WCHAR wUnicode)
+{
+ HDC hDC = ::GetDC(NULL);
+ LOGFONTW lfFind;
+ FX_memset(&lfFind, 0, sizeof(lfFind));
+ lfFind.lfCharSet = DEFAULT_CHARSET;
+ if (pwsFaceName) {
+ FXSYS_wcsncpy((FX_LPWSTR)lfFind.lfFaceName, pwsFaceName, 31);
+ lfFind.lfFaceName[31] = 0;
+ }
+ EnumFontFamiliesExW(hDC, (LPLOGFONTW)&lfFind, (FONTENUMPROCW)FX_GdiFontEnumProc, (LPARAM)&fonts, 0);
+ ::ReleaseDC(NULL, hDC);
+}
+FX_LPEnumAllFonts FX_GetDefFontEnumerator()
+{
+ return FX_EnumGdiFonts;
+}
+#else
+FX_LPCSTR g_FontFolders[] = {
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
+ (FX_LPCSTR)"/usr/share/fonts",
+ (FX_LPCSTR)"/usr/share/X11/fonts/Type1",
+ (FX_LPCSTR)"/usr/share/X11/fonts/TTF",
+ (FX_LPCSTR)"/usr/local/share/fonts",
+#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+ (FX_LPCSTR)"~/Library/Fonts",
+ (FX_LPCSTR)"/Library/Fonts",
+ (FX_LPCSTR)"/System/Library/Fonts",
+#elif _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_
+ (FX_LPCSTR)"/system/fonts",
+#endif
+};
+CFX_FontSourceEnum_File::CFX_FontSourceEnum_File()
+{
+ for (FX_INT32 i = 0; i < sizeof(g_FontFolders) / sizeof(FX_LPCSTR); i++) {
+ m_FolderPaths.Add(g_FontFolders[i]);
+ }
+}
+CFX_ByteString CFX_FontSourceEnum_File::GetNextFile()
+{
+Restart:
+ FX_LPVOID pCurHandle = m_FolderQueue.GetSize() == 0 ? NULL : m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->pFileHandle;
+ if (NULL == pCurHandle) {
+ if (m_FolderPaths.GetSize() < 1) {
+ return "";
+ }
+ pCurHandle = FX_OpenFolder(m_FolderPaths[m_FolderPaths.GetSize() - 1]);
+ FX_HandleParentPath hpp;
+ hpp.pFileHandle = pCurHandle;
+ hpp.bsParentPath = m_FolderPaths[m_FolderPaths.GetSize() - 1];
+ m_FolderQueue.Add(hpp);
+ }
+ CFX_ByteString bsName;
+ FX_BOOL bFolder;
+ CFX_ByteString bsFolderSpearator = CFX_ByteString::FromUnicode(CFX_WideString(FX_GetFolderSeparator()));
+ while (TRUE) {
+ if (!FX_GetNextFile(pCurHandle, bsName, bFolder)) {
+ FX_CloseFolder(pCurHandle);
+ m_FolderQueue.RemoveAt(m_FolderQueue.GetSize() - 1);
+ if (m_FolderQueue.GetSize() == 0) {
+ m_FolderPaths.RemoveAt(m_FolderPaths.GetSize() - 1);
+ if (m_FolderPaths.GetSize() == 0) {
+ return "";
+ } else {
+ goto Restart;
+ }
+ }
+ pCurHandle = m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->pFileHandle;
+ continue;
+ }
+ if (bsName == "." || bsName == "..") {
+ continue;
+ }
+ if (bFolder) {
+ FX_HandleParentPath hpp;
+ hpp.bsParentPath = m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->bsParentPath + bsFolderSpearator + bsName;
+ hpp.pFileHandle = FX_OpenFolder(hpp.bsParentPath);
+ if (hpp.pFileHandle == NULL) {
+ continue;
+ }
+ m_FolderQueue.Add(hpp);
+ pCurHandle = hpp.pFileHandle;
+ continue;
+ }
+ bsName = m_FolderQueue.GetDataPtr(m_FolderQueue.GetSize() - 1)->bsParentPath + bsFolderSpearator + bsName;
+ break;
+ }
+ return bsName;
+}
+FX_POSITION CFX_FontSourceEnum_File::GetStartPosition( FX_LPVOID pUserData )
+{
+ m_wsNext = GetNextFile().UTF8Decode();
+ if (0 == m_wsNext.GetLength()) {
+ return (FX_POSITION)0;
+ }
+ return (FX_POSITION) - 1;
+}
+IFX_FileAccess* CFX_FontSourceEnum_File::GetNext( FX_POSITION& pos, FX_LPVOID pUserData )
+{
+ IFX_FileAccess* pAccess = FX_CreateDefaultFileAccess(m_wsNext);
+ m_wsNext = GetNextFile().UTF8Decode();
+ pos = 0 != m_wsNext.GetLength() ? pAccess : NULL;
+ return (IFX_FileAccess*)pAccess;
+}
+IFX_FontSourceEnum* FX_CreateDefaultFontSourceEnum()
+{
+ return (IFX_FontSourceEnum*)FX_NEW CFX_FontSourceEnum_File;
+}
+IFX_FontMgr* IFX_FontMgr::Create(IFX_FontSourceEnum* pFontEnum, IFX_FontMgrDelegate* pDelegate, FX_LPVOID pUserData)
+{
+ if (NULL == pFontEnum) {
+ return NULL;
+ }
+ CFX_FontMgrImp* pFontMgr = FX_NEW CFX_FontMgrImp(pFontEnum, pDelegate, pUserData);
+ if (NULL == pFontMgr) {
+ return NULL;
+ }
+ if (pFontMgr->EnumFonts()) {
+ return pFontMgr;
+ }
+ delete pFontMgr;
+ return NULL;
+}
+CFX_FontMgrImp::CFX_FontMgrImp( IFX_FontSourceEnum* pFontEnum, IFX_FontMgrDelegate* pDelegate , FX_LPVOID pUserData )
+ : m_pFontSource(pFontEnum)
+ , m_pDelegate(pDelegate)
+ , m_pUserData(pUserData)
+{
+}
+FX_BOOL CFX_FontMgrImp::EnumFonts()
+{
+ FXFT_Library& library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary;
+ if (library == NULL) {
+ FXFT_Init_FreeType(&library);
+ }
+ if (library == NULL) {
+ return FALSE;
+ }
+ FXFT_Face pFace = NULL;
+ FX_POSITION pos = m_pFontSource->GetStartPosition();
+ IFX_FileAccess* pFontSource = NULL;
+ IFX_FileRead* pFontStream = NULL;
+ while (pos) {
+ pFontSource = m_pFontSource->GetNext(pos);
+ pFontStream = pFontSource->CreateFileStream(FX_FILEMODE_ReadOnly);
+ if (NULL == pFontStream) {
+ pFontSource->Release();
+ continue;
+ }
+ if (NULL == (pFace = LoadFace(pFontStream, 0))) {
+ pFontStream->Release();
+ pFontSource->Release();
+ continue;
+ }
+ FX_INT32 nFaceCount = pFace->num_faces;
+ ReportFace(pFace, m_InstalledFonts, pFontSource);
+ if (FXFT_Get_Face_External_Stream(pFace)) {
+ FXFT_Clear_Face_External_Stream(pFace);
+ }
+ FXFT_Done_Face(pFace);
+ for (FX_INT32 i = 1; i < nFaceCount; i++) {
+ if (NULL == (pFace = LoadFace(pFontStream, i))) {
+ continue;
+ }
+ ReportFace(pFace, m_InstalledFonts, pFontSource);
+ if (FXFT_Get_Face_External_Stream(pFace)) {
+ FXFT_Clear_Face_External_Stream(pFace);
+ }
+ FXFT_Done_Face(pFace);
+ }
+ pFontStream->Release();
+ pFontSource->Release();
+ }
+ return TRUE;
+}
+void CFX_FontMgrImp::Release()
+{
+ for (FX_INT32 i = 0; i < m_InstalledFonts.GetSize(); i++) {
+ delete m_InstalledFonts[i];
+ }
+ FX_POSITION pos = m_Hash2CandidateList.GetStartPosition();
+ while (pos) {
+ FX_DWORD dwHash;
+ CFX_FontDescriptorInfos* pDescs;
+ m_Hash2CandidateList.GetNextAssoc(pos, dwHash, pDescs);
+ if (NULL != pDescs) {
+ delete pDescs;
+ }
+ }
+ pos = m_Hash2Fonts.GetStartPosition();
+ while (pos) {
+ FX_DWORD dwHash;
+ CFX_ArrayTemplate<IFX_Font*>* pFonts;
+ m_Hash2Fonts.GetNextAssoc(pos, dwHash, pFonts);
+ if (NULL != pFonts) {
+ delete pFonts;
+ }
+ }
+ m_Hash2Fonts.RemoveAll();
+ pos = m_Hash2FileAccess.GetStartPosition();
+ while (pos) {
+ FX_DWORD dwHash;
+ IFX_FileAccess* pFileAccess;
+ m_Hash2FileAccess.GetNextAssoc(pos, dwHash, pFileAccess);
+ if (NULL != pFileAccess) {
+ pFileAccess->Release();
+ }
+ }
+ pos = m_FileAccess2IFXFont.GetStartPosition();
+ while (pos) {
+ FX_DWORD dwHash;
+ IFX_Font* pFont;
+ m_FileAccess2IFXFont.GetNextAssoc(pos, dwHash, pFont);
+ if (NULL != pFont) {
+ pFont->Release();
+ }
+ }
+ pos = m_IFXFont2FileRead.GetStartPosition();
+ while (pos) {
+ IFX_Font* pFont;
+ IFX_FileRead* pFileRead;
+ m_IFXFont2FileRead.GetNextAssoc(pos, pFont, pFileRead);
+ pFileRead->Release();
+ }
+ delete this;
+}
+IFX_Font* CFX_FontMgrImp::GetDefFontByCodePage( FX_WORD wCodePage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily )
+{
+ return NULL == m_pDelegate ? NULL : m_pDelegate->GetDefFontByCodePage(this, wCodePage, dwFontStyles, pszFontFamily);
+}
+IFX_Font* CFX_FontMgrImp::GetDefFontByCharset( FX_BYTE nCharset, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily )
+{
+ return NULL == m_pDelegate ? NULL : m_pDelegate->GetDefFontByCharset(this, nCharset, dwFontStyles, pszFontFamily);
+}
+IFX_Font* CFX_FontMgrImp::GetDefFontByUnicode( FX_WCHAR wUnicode, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily )
+{
+ return NULL == m_pDelegate ? NULL : m_pDelegate->GetDefFontByUnicode(this, wUnicode, dwFontStyles, pszFontFamily);
+}
+IFX_Font* CFX_FontMgrImp::GetDefFontByLanguage( FX_WORD wLanguage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily )
+{
+ return NULL == m_pDelegate ? NULL : m_pDelegate->GetDefFontByLanguage(this, wLanguage, dwFontStyles, pszFontFamily);
+}
+IFX_Font* CFX_FontMgrImp::GetFontByCodePage( FX_WORD wCodePage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily )
+{
+ CFX_ByteString bsHash;
+ bsHash.Format("%d, %d", wCodePage, dwFontStyles);
+ bsHash += CFX_WideString(pszFontFamily).UTF8Encode();
+ FX_DWORD dwHash = FX_HashCode_String_GetA(bsHash, bsHash.GetLength());
+ CFX_ArrayTemplate<IFX_Font*>* pFonts = NULL;
+ IFX_Font* pFont = NULL;
+ if (m_Hash2Fonts.Lookup(dwHash, pFonts)) {
+ if (NULL == pFonts) {
+ return NULL;
+ }
+ if (0 != pFonts->GetSize()) {
+ return pFonts->GetAt(0)->Retain();
+ }
+ }
+ if (NULL == pFonts) {
+ pFonts = FX_NEW CFX_ArrayTemplate<IFX_Font*>;
+ }
+ if (NULL == pFonts) {
+ return NULL;
+ }
+ m_Hash2Fonts.SetAt(dwHash, pFonts);
+ CFX_FontDescriptorInfos* sortedFonts = NULL;
+ if (!m_Hash2CandidateList.Lookup(dwHash, sortedFonts)) {
+ sortedFonts = FX_NEW CFX_FontDescriptorInfos;
+ MatchFonts(*sortedFonts, wCodePage, dwFontStyles, CFX_WideString(pszFontFamily), 0);
+ m_Hash2CandidateList.SetAt(dwHash, sortedFonts);
+ }
+ if (sortedFonts->GetSize() == 0) {
+ return NULL;
+ }
+ CFX_FontDescriptor* pDesc = sortedFonts->GetAt(0).pFont;
+ pFont = LoadFont(pDesc->m_pFileAccess, pDesc->m_nFaceIndex, NULL);
+ if (NULL != pFont) {
+ pFont->SetLogicalFontStyle(dwFontStyles);
+ }
+ pFonts->Add(pFont);
+ return pFont;
+}
+IFX_Font* CFX_FontMgrImp::GetFontByCharset( FX_BYTE nCharset, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily )
+{
+ return GetFontByCodePage(FX_GetCodePageFromCharset(nCharset), dwFontStyles, pszFontFamily);
+}
+IFX_Font* CFX_FontMgrImp::GetFontByUnicode( FX_WCHAR wUnicode, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily )
+{
+ IFX_Font* pFont = NULL;
+ if (m_FailedUnicodes2NULL.Lookup(wUnicode, pFont)) {
+ return NULL;
+ }
+ FGAS_LPCFONTUSB x = FGAS_GetUnicodeBitField(wUnicode);
+ FX_WORD wCodePage = NULL == x ? 0xFFFF : x->wCodePage;
+ FX_WORD wBitField = NULL == x ? 999 : x->wBitField;
+ CFX_ByteString bsHash;
+ if (wCodePage == 0xFFFF) {
+ bsHash.Format("%d, %d, %d", wCodePage, wBitField, dwFontStyles);
+ } else {
+ bsHash.Format("%d, %d", wCodePage, dwFontStyles);
+ }
+ bsHash += CFX_WideString(pszFontFamily).UTF8Encode();
+ FX_DWORD dwHash = FX_HashCode_String_GetA(bsHash, bsHash.GetLength());
+ CFX_ArrayTemplate<IFX_Font*>* pFonts = NULL;
+ if (m_Hash2Fonts.Lookup(dwHash, pFonts)) {
+ if (NULL == pFonts) {
+ return NULL;
+ }
+ if (0 != pFonts->GetSize()) {
+ for (FX_INT32 i = 0; i < pFonts->GetSize(); i++) {
+ if (VerifyUnicode(pFonts->GetAt(i), wUnicode)) {
+ return pFonts->GetAt(i)->Retain();
+ }
+ }
+ }
+ }
+ if (NULL == pFonts) {
+ pFonts = FX_NEW CFX_ArrayTemplate<IFX_Font*>;
+ }
+ if (NULL == pFonts) {
+ return NULL;
+ }
+ m_Hash2Fonts.SetAt(dwHash, pFonts);
+ CFX_FontDescriptorInfos* sortedFonts = NULL;
+ if (!m_Hash2CandidateList.Lookup(dwHash, sortedFonts)) {
+ sortedFonts = FX_NEW CFX_FontDescriptorInfos;
+ MatchFonts(*sortedFonts, wCodePage, dwFontStyles, CFX_WideString(pszFontFamily), wUnicode);
+ m_Hash2CandidateList.SetAt(dwHash, sortedFonts);
+ }
+ for (FX_INT32 i = 0; i < sortedFonts->GetSize(); i++) {
+ CFX_FontDescriptor* pDesc = sortedFonts->GetAt(i).pFont;
+ if (VerifyUnicode(pDesc, wUnicode)) {
+ pFont = LoadFont(pDesc->m_pFileAccess, pDesc->m_nFaceIndex, NULL);
+ if (NULL != pFont) {
+ pFont->SetLogicalFontStyle(dwFontStyles);
+ }
+ pFonts->Add(pFont);
+ return pFont;
+ }
+ }
+ if (NULL == pszFontFamily) {
+ m_FailedUnicodes2NULL.SetAt(wUnicode, NULL);
+ }
+ return NULL;
+}
+FX_BOOL CFX_FontMgrImp::VerifyUnicode( CFX_FontDescriptor* pDesc, FX_WCHAR wcUnicode )
+{
+ IFX_FileRead* pFileRead = pDesc->m_pFileAccess->CreateFileStream(FX_FILEMODE_ReadOnly);
+ if (NULL == pFileRead) {
+ return FALSE;
+ }
+ FXFT_Face pFace = LoadFace(pFileRead, pDesc->m_nFaceIndex);
+ if (NULL == pFace) {
+ goto BadRet;
+ }
+ if (0 != FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE)) {
+ goto BadRet;
+ }
+ if (0 == FXFT_Get_Char_Index(pFace, wcUnicode)) {
+ goto BadRet;
+ }
+ pFileRead->Release();
+ if (FXFT_Get_Face_External_Stream(pFace)) {
+ FXFT_Clear_Face_External_Stream(pFace);
+ }
+ FXFT_Done_Face(pFace);
+ return TRUE;
+BadRet:
+ if (NULL != pFileRead) {
+ pFileRead->Release();
+ }
+ if (NULL != pFace) {
+ if (FXFT_Get_Face_External_Stream(pFace)) {
+ FXFT_Clear_Face_External_Stream(pFace);
+ }
+ FXFT_Done_Face(pFace);
+ }
+ return FALSE;
+}
+FX_BOOL CFX_FontMgrImp::VerifyUnicode( IFX_Font* pFont, FX_WCHAR wcUnicode )
+{
+ if (NULL == pFont) {
+ return FALSE;
+ }
+ FXFT_Face pFace = ((CFX_Font*)pFont->GetDevFont())->m_Face;
+ FXFT_CharMap charmap = FXFT_Get_Face_Charmap(pFace);
+ if (0 != FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE)) {
+ return FALSE;
+ }
+ if (0 == FXFT_Get_Char_Index(pFace, wcUnicode)) {
+ FXFT_Set_Charmap(pFace, charmap);
+ return FALSE;
+ }
+ return TRUE;
+}
+IFX_Font* CFX_FontMgrImp::GetFontByLanguage( FX_WORD wLanguage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily )
+{
+ return GetFontByCodePage(FX_GetDefCodePageByLanguage(wLanguage), dwFontStyles, pszFontFamily);
+}
+IFX_Font* CFX_FontMgrImp::LoadFont( FX_LPCBYTE pBuffer, FX_INT32 iLength, FX_INT32 iFaceIndex, FX_INT32* pFaceCount )
+{
+ FX_LPVOID Hash[2] = {(FX_LPVOID)(FX_UINTPTR)pBuffer, (FX_LPVOID)(FX_UINTPTR)iLength};
+ FX_DWORD dwHash = FX_HashCode_String_GetA((FX_LPCSTR)Hash, 2 * sizeof (FX_LPVOID));
+ IFX_FileAccess* pFontAccess = NULL;
+ if (!m_Hash2FileAccess.Lookup(dwHash, pFontAccess)) {
+ }
+ if (NULL != pFontAccess) {
+ return LoadFont(pFontAccess, iFaceIndex, pFaceCount, TRUE);
+ } else {
+ return NULL;
+ }
+}
+IFX_Font* CFX_FontMgrImp::LoadFont( FX_LPCWSTR pszFileName, FX_INT32 iFaceIndex, FX_INT32* pFaceCount )
+{
+ CFX_ByteString bsHash;
+ bsHash += CFX_WideString(pszFileName).UTF8Encode();
+ FX_DWORD dwHash = FX_HashCode_String_GetA((FX_LPCSTR)bsHash, bsHash.GetLength());
+ IFX_FileAccess* pFontAccess = NULL;
+ if (!m_Hash2FileAccess.Lookup(dwHash, pFontAccess)) {
+ pFontAccess = FX_CreateDefaultFileAccess(pszFileName);
+ m_Hash2FileAccess.SetAt(dwHash, pFontAccess);
+ }
+ if (NULL != pFontAccess) {
+ return LoadFont(pFontAccess, iFaceIndex, pFaceCount, TRUE);
+ } else {
+ return NULL;
+ }
+}
+IFX_Font* CFX_FontMgrImp::LoadFont( IFX_Stream* pFontStream, FX_INT32 iFaceIndex, FX_INT32* pFaceCount, FX_BOOL bSaveStream )
+{
+ FX_LPVOID Hash[1] = {(FX_LPVOID)(FX_UINTPTR)pFontStream};
+ FX_DWORD dwHash = FX_HashCode_String_GetA((FX_LPCSTR)Hash, 1 * sizeof (FX_LPVOID));
+ IFX_FileAccess* pFontAccess = NULL;
+ if (!m_Hash2FileAccess.Lookup(dwHash, pFontAccess)) {
+ }
+ if (NULL != pFontAccess) {
+ return LoadFont(pFontAccess, iFaceIndex, pFaceCount, TRUE);
+ } else {
+ return NULL;
+ }
+}
+IFX_Font* CFX_FontMgrImp::LoadFont( IFX_FileAccess* pFontAccess, FX_INT32 iFaceIndex, FX_INT32* pFaceCount, FX_BOOL bWantCache )
+{
+ FX_DWORD dwHash = 0;
+ IFX_Font* pFont = NULL;
+ if (bWantCache) {
+ CFX_ByteString bsHash;
+ bsHash.Format("%d, %d", (FX_UINTPTR)pFontAccess, iFaceIndex);
+ dwHash = FX_HashCode_String_GetA(bsHash, bsHash.GetLength());
+ if (m_FileAccess2IFXFont.Lookup(dwHash, pFont)) {
+ if (NULL != pFont) {
+ if (NULL != pFaceCount) {
+ *pFaceCount = ((CFX_Font*)pFont->GetDevFont())->m_Face->num_faces;
+ }
+ return pFont->Retain();
+ }
+ }
+ }
+ CFX_Font* pInternalFont = FX_NEW CFX_Font;
+ if (NULL == pInternalFont) {
+ return NULL;
+ }
+ IFX_FileRead* pFontStream = pFontAccess->CreateFileStream(FX_FILEMODE_ReadOnly);
+ if (NULL == pFontStream) {
+ delete pInternalFont;
+ return NULL;
+ }
+ if (!pInternalFont->LoadFile(pFontStream, iFaceIndex)) {
+ delete pInternalFont;
+ pFontStream->Release();
+ return NULL;
+ }
+ pFont = IFX_Font::LoadFont(pInternalFont, this, TRUE);
+ if (NULL == pFont) {
+ delete pInternalFont;
+ pFontStream->Release();
+ return NULL;
+ }
+ if (bWantCache) {
+ m_FileAccess2IFXFont.SetAt(dwHash, pFont);
+ }
+ m_IFXFont2FileRead.SetAt(pFont, pFontStream);
+ if (NULL != pFaceCount) {
+ *pFaceCount = ((CFX_Font*)pFont->GetDevFont())->m_Face->num_faces;
+ }
+ return pFont;
+}
+extern "C"
+{
+ unsigned long _ftStreamRead(FXFT_Stream stream, unsigned long offset, unsigned char* buffer, unsigned long count)
+ {
+ if (count == 0) {
+ return 0;
+ }
+ IFX_FileRead* pFile = (IFX_FileRead*)stream->descriptor.pointer;
+ int res = pFile->ReadBlock(buffer, offset, count);
+ if (res) {
+ return count;
+ }
+ return 0;
+ }
+ void _ftStreamClose(FXFT_Stream stream)
+ {
+ }
+};
+FXFT_Face CFX_FontMgrImp::LoadFace( IFX_FileRead* pFontStream, FX_INT32 iFaceIndex )
+{
+ FXFT_Library& library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary;
+ FXFT_Open_Args ftArgs;
+ FXFT_Stream ftStream = FX_Alloc(FXFT_StreamRec, 1);
+ FXFT_Face pFace = NULL;
+ if (library == NULL) {
+ FXFT_Init_FreeType(&library);
+ }
+ if (library == NULL) {
+ goto BadRet;
+ }
+ FXSYS_memset(&ftArgs, 0, sizeof(FXFT_Open_Args));
+ if (NULL == ftStream) {
+ goto BadRet;
+ }
+ FXSYS_memset(ftStream, 0, sizeof(FXFT_StreamRec));
+ if (NULL == pFontStream) {
+ goto BadRet;
+ }
+ ftStream->base = NULL;
+ ftStream->descriptor.pointer = pFontStream;
+ ftStream->pos = 0;
+ ftStream->size = (unsigned long)pFontStream->GetSize();
+ ftStream->read = _ftStreamRead;
+ ftStream->close = _ftStreamClose;
+ ftArgs.flags |= FT_OPEN_STREAM;
+ ftArgs.stream = ftStream;
+ if (0 != FXFT_Open_Face(library, &ftArgs, iFaceIndex, &pFace)) {
+ goto BadRet;
+ }
+ FXFT_Set_Pixel_Sizes(pFace, 0, 64);
+ return pFace;
+BadRet:
+ if (NULL != ftStream) {
+ FX_Free(ftStream);
+ }
+ return NULL;
+}
+FX_INT32 CFX_FontMgrImp::MatchFonts( CFX_FontDescriptorInfos& MatchedFonts, FX_WORD wCodePage, FX_DWORD dwFontStyles, const CFX_WideString& FontName, FX_WCHAR wcUnicode )
+{
+ MatchedFonts.RemoveAll();
+ CFX_WideString wsNormalizedFontName = FontName;
+ NormalizeFontName(wsNormalizedFontName);
+ static const FX_INT32 nMax = 0xffff;
+ CFX_FontDescriptor* pFont = NULL;
+ FX_INT32 nCount = m_InstalledFonts.GetSize();
+ for (FX_INT32 i = 0; i < nCount; i++) {
+ pFont = m_InstalledFonts[i];
+ FX_INT32 nPenalty = CalcPenalty(pFont, wCodePage, dwFontStyles, wsNormalizedFontName, wcUnicode);
+ if (nPenalty >= 0xFFFF) {
+ continue;
+ }
+ FX_FontDescriptorInfo FontInfo;
+ FontInfo.pFont = pFont;
+ FontInfo.nPenalty = nPenalty;
+ MatchedFonts.Add(FontInfo);
+ if (MatchedFonts.GetSize() == nMax) {
+ break;
+ }
+ }
+ if (MatchedFonts.GetSize() == 0) {
+ return 0;
+ }
+ CFX_SSortTemplate<FX_FontDescriptorInfo> ssort;
+ ssort.ShellSort(MatchedFonts.GetData(), MatchedFonts.GetSize());
+ return MatchedFonts.GetSize();
+}
+struct FX_BitCodePage {
+ FX_WORD wBit;
+ FX_WORD wCodePage;
+};
+static const FX_BitCodePage g_Bit2CodePage[] = {
+ {0, 1252},
+ {1, 1250},
+ {2, 1251},
+ {3, 1253},
+ {4, 1254},
+ {5, 1255},
+ {6, 1256},
+ {7, 1257},
+ {8, 1258},
+ {9, 0},
+ {10, 0},
+ {11, 0},
+ {12, 0},
+ {13, 0},
+ {14, 0},
+ {15, 0},
+ {16, 874},
+ {17, 932},
+ {18, 936},
+ {19, 949},
+ {20, 950},
+ {21, 1361},
+ {22, 0},
+ {23, 0},
+ {24, 0},
+ {25, 0},
+ {26, 0},
+ {27, 0},
+ {28, 0},
+ {29, 0},
+ {30, 0},
+ {31, 0},
+ {32, 0},
+ {33, 0},
+ {34, 0},
+ {35, 0},
+ {36, 0},
+ {37, 0},
+ {38, 0},
+ {39, 0},
+ {40, 0},
+ {41, 0},
+ {42, 0},
+ {43, 0},
+ {44, 0},
+ {45, 0},
+ {46, 0},
+ {47, 0},
+ {48, 869},
+ {49, 866},
+ {50, 865},
+ {51, 864},
+ {52, 863},
+ {53, 862},
+ {54, 861},
+ {55, 860},
+ {56, 857},
+ {57, 855},
+ {58, 852},
+ {59, 775},
+ {60, 737},
+ {61, 708},
+ {62, 850},
+ {63, 437},
+};
+FX_WORD FX_GetCodePageBit(FX_WORD wCodePage)
+{
+ for (FX_INT32 i = 0; i < sizeof(g_Bit2CodePage) / sizeof (FX_BitCodePage); i++) {
+ if (g_Bit2CodePage[i].wCodePage == wCodePage) {
+ return g_Bit2CodePage[i].wBit;
+ }
+ }
+ return (FX_WORD) - 1;
+}
+FX_WORD FX_GetUnicodeBit(FX_WCHAR wcUnicode)
+{
+ FGAS_LPCFONTUSB x = FGAS_GetUnicodeBitField(wcUnicode);
+ if (NULL == x) {
+ return 999;
+ }
+ return x->wBitField;
+}
+FX_INT32 CFX_FontMgrImp::CalcPenalty( CFX_FontDescriptor* pInstalled, FX_WORD wCodePage, FX_DWORD dwFontStyles, const CFX_WideString& FontName, FX_WCHAR wcUnicode )
+{
+ FX_INT32 nPenalty = 30000;
+ if (0 != FontName.GetLength()) {
+ if (FontName != pInstalled->m_wsFaceName) {
+ FX_INT32 i;
+ for (i = 0; i < pInstalled->m_wsFamilyNames.GetSize(); i++) {
+ if (pInstalled->m_wsFamilyNames[i] == FontName) {
+ break;
+ }
+ }
+ if (i == pInstalled->m_wsFamilyNames.GetSize()) {
+ nPenalty += 0xFFFF;
+ } else {
+ nPenalty -= 28000;
+ }
+ } else {
+ nPenalty -= 30000;
+ }
+ if (30000 == nPenalty && 0 == IsPartName(pInstalled->m_wsFaceName, FontName)) {
+ FX_INT32 i;
+ for (i = 0; i < pInstalled->m_wsFamilyNames.GetSize(); i++) {
+ if (0 != IsPartName(pInstalled->m_wsFamilyNames[i], FontName)) {
+ break;
+ }
+ }
+ if (i == pInstalled->m_wsFamilyNames.GetSize()) {
+ nPenalty += 0xFFFF;
+ } else {
+ nPenalty -= 26000;
+ }
+ } else {
+ nPenalty -= 27000;
+ }
+ }
+ FX_DWORD dwStyleMask = pInstalled->m_dwFontStyles ^ dwFontStyles;
+ if (dwStyleMask & FX_FONTSTYLE_Bold) {
+ nPenalty += 4500;
+ }
+ if (dwStyleMask & FX_FONTSTYLE_FixedPitch) {
+ nPenalty += 10000;
+ }
+ if (dwStyleMask & FX_FONTSTYLE_Italic) {
+ nPenalty += 10000;
+ }
+ if (dwStyleMask & FX_FONTSTYLE_Serif) {
+ nPenalty += 500;
+ }
+ if (dwStyleMask & FX_FONTSTYLE_Symbolic) {
+ nPenalty += 0xFFFF;
+ }
+ if (nPenalty >= 0xFFFF) {
+ return 0xFFFF;
+ }
+ FX_WORD wBit = ((0 == wCodePage || 0xFFFF == wCodePage) ? (FX_WORD) - 1 : FX_GetCodePageBit(wCodePage));
+ if (wBit != (FX_WORD) - 1) {
+ FXSYS_assert(wBit < 64);
+ if (0 == (pInstalled->m_dwCsb[wBit / 32] & (1 << (wBit % 32)))) {
+ nPenalty += 0xFFFF;
+ } else {
+ nPenalty -= 60000;
+ }
+ }
+ wBit = ((0 == wcUnicode || 0xFFFE == wcUnicode) ? (FX_WORD)999 : FX_GetUnicodeBit(wcUnicode));
+ if (wBit != (FX_WORD)999) {
+ FXSYS_assert(wBit < 128);
+ if (0 == (pInstalled->m_dwUsb[wBit / 32] & (1 << (wBit % 32)))) {
+ nPenalty += 0xFFFF;
+ } else {
+ nPenalty -= 60000;
+ }
+ }
+ return nPenalty;
+}
+void CFX_FontMgrImp::ClearFontCache()
+{
+ FX_POSITION pos = m_Hash2CandidateList.GetStartPosition();
+ while (pos) {
+ FX_DWORD dwHash;
+ CFX_FontDescriptorInfos* pDescs;
+ m_Hash2CandidateList.GetNextAssoc(pos, dwHash, pDescs);
+ if (NULL != pDescs) {
+ delete pDescs;
+ }
+ }
+ pos = m_FileAccess2IFXFont.GetStartPosition();
+ while (pos) {
+ FX_DWORD dwHash;
+ IFX_Font* pFont;
+ m_FileAccess2IFXFont.GetNextAssoc(pos, dwHash, pFont);
+ if (NULL != pFont) {
+ pFont->Release();
+ }
+ }
+ pos = m_IFXFont2FileRead.GetStartPosition();
+ while (pos) {
+ IFX_Font* pFont;
+ IFX_FileRead* pFileRead;
+ m_IFXFont2FileRead.GetNextAssoc(pos, pFont, pFileRead);
+ pFileRead->Release();
+ }
+}
+void CFX_FontMgrImp::RemoveFont( IFX_Font* pEFont )
+{
+ if (NULL == pEFont) {
+ return ;
+ }
+ IFX_FileRead* pFileRead;
+ if (m_IFXFont2FileRead.Lookup(pEFont, pFileRead)) {
+ pFileRead->Release();
+ m_IFXFont2FileRead.RemoveKey(pEFont);
+ }
+ FX_POSITION pos;
+ pos = m_FileAccess2IFXFont.GetStartPosition();
+ while (pos) {
+ FX_DWORD dwHash;
+ IFX_Font* pCFont;
+ m_FileAccess2IFXFont.GetNextAssoc(pos, dwHash, pCFont);
+ if (pCFont == pEFont) {
+ m_FileAccess2IFXFont.RemoveKey(dwHash);
+ break;
+ }
+ }
+ pos = m_Hash2Fonts.GetStartPosition();
+ while (pos) {
+ FX_DWORD dwHash;
+ CFX_ArrayTemplate<IFX_Font*>* pFonts;
+ m_Hash2Fonts.GetNextAssoc(pos, dwHash, pFonts);
+ if (NULL != pFonts) {
+ for (FX_INT32 i = 0; i < pFonts->GetSize(); i++) {
+ if (pFonts->GetAt(i) == pEFont) {
+ pFonts->SetAt(i, NULL);
+ }
+ }
+ } else {
+ m_Hash2Fonts.RemoveKey(dwHash);
+ }
+ }
+}
+void CFX_FontMgrImp::ReportFace( FXFT_Face pFace, CFX_FontDescriptors& Fonts, IFX_FileAccess* pFontAccess)
+{
+ if (0 == (pFace->face_flags & FT_FACE_FLAG_SCALABLE)) {
+ return ;
+ }
+ CFX_FontDescriptor* pFont = FX_NEW CFX_FontDescriptor;
+ if (NULL == pFont) {
+ return;
+ }
+ pFont->m_dwFontStyles |= FXFT_Is_Face_Bold(pFace) ? FX_FONTSTYLE_Bold : 0;
+ pFont->m_dwFontStyles |= FXFT_Is_Face_Italic(pFace) ? FX_FONTSTYLE_Italic : 0;
+ pFont->m_dwFontStyles |= GetFlags(pFace);
+ CFX_WordArray Charsets;
+ GetCharsets(pFace, Charsets);
+ GetUSBCSB(pFace, pFont->m_dwUsb, pFont->m_dwCsb);
+ unsigned long nLength = 0;
+ FT_ULong dwTag;
+ FX_LPBYTE pTable = NULL;
+ FT_ENC_TAG(dwTag, 'n', 'a', 'm', 'e');
+ unsigned int error = FXFT_Load_Sfnt_Table(pFace, dwTag, 0, NULL, &nLength);
+ if (0 == error && 0 != nLength) {
+ pTable = FX_Alloc(FX_BYTE, nLength);
+ if (NULL != pTable) {
+ error = FXFT_Load_Sfnt_Table(pFace, dwTag, 0, pTable, NULL);
+ if (0 != error) {
+ FX_Free(pTable);
+ pTable = NULL;
+ }
+ }
+ }
+ GetNames(pTable, pFont->m_wsFamilyNames);
+ if (NULL != pTable) {
+ FX_Free(pTable);
+ }
+ pFont->m_wsFamilyNames.Add(CFX_ByteString(pFace->family_name).UTF8Decode());
+ pFont->m_wsFaceName = CFX_WideString::FromLocal(FXFT_Get_Postscript_Name(pFace));
+ pFont->m_nFaceIndex = pFace->face_index;
+ pFont->m_pFileAccess = pFontAccess->Retain();
+ NormalizeFontName(pFont->m_wsFaceName);
+ for (FX_INT32 i = 0; i < pFont->m_wsFamilyNames.GetSize(); i++) {
+ NormalizeFontName(pFont->m_wsFamilyNames[i]);
+ }
+ Fonts.Add(pFont);
+}
+FX_DWORD CFX_FontMgrImp::GetFlags(FXFT_Face pFace)
+{
+ FX_DWORD flag = 0;
+ if (FT_IS_FIXED_WIDTH(pFace)) {
+ flag |= FX_FONTSTYLE_FixedPitch;
+ }
+ TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
+ if (!pOS2) {
+ return flag;
+ }
+ if (pOS2->ulCodePageRange1 & (1 << 31)) {
+ flag |= FX_FONTSTYLE_Symbolic;
+ }
+ if (pOS2->panose[0] == 2) {
+ FX_BYTE uSerif = pOS2->panose[1];
+ if ((uSerif > 1 && uSerif < 10) || uSerif > 13) {
+ flag |= FX_FONTSTYLE_Serif;
+ }
+ }
+ return flag;
+}
+#define GetUInt8(p) ((FX_UINT8)((p)[0]))
+#define GetUInt16(p) ((FX_UINT16)((p)[0] << 8 | (p)[1]))
+#define GetUInt32(p) ((FX_UINT32)((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]))
+void CFX_FontMgrImp::GetNames(FX_LPCBYTE name_table, CFX_WideStringArray& Names)
+{
+ if (NULL == name_table) {
+ return;
+ }
+ FX_LPBYTE lpTable = (FX_LPBYTE)name_table;
+ CFX_WideString wsFamily;
+ FX_LPBYTE sp = lpTable + 2;
+ FX_LPBYTE lpNameRecord = lpTable + 6;
+ FX_UINT16 nNameCount = GetUInt16(sp);
+ FX_LPBYTE lpStr = lpTable + GetUInt16(sp + 2);
+ for (FX_UINT16 j = 0; j < nNameCount; j++) {
+ FX_UINT16 nNameID = GetUInt16(lpNameRecord + j * 12 + 6);
+ if (nNameID != 1) {
+ continue;
+ }
+ FX_UINT16 nPlatformID = GetUInt16(lpNameRecord + j * 12 + 0);
+ FX_UINT16 nNameLength = GetUInt16(lpNameRecord + j * 12 + 8);
+ FX_UINT16 nNameOffset = GetUInt16(lpNameRecord + j * 12 + 10);
+ wsFamily.Empty();
+ if (nPlatformID != 1) {
+ for (FX_UINT16 k = 0; k < nNameLength / 2; k++) {
+ FX_WCHAR wcTemp = GetUInt16(lpStr + nNameOffset + k * 2);
+ wsFamily += wcTemp;
+ }
+ Names.Add(wsFamily);
+ } else {
+ for (FX_UINT16 k = 0; k < nNameLength; k++) {
+ FX_WCHAR wcTemp = GetUInt8(lpStr + nNameOffset + k);
+ wsFamily += wcTemp;
+ }
+ Names.Add(wsFamily);
+ }
+ }
+}
+#undef GetUInt8
+#undef GetUInt16
+#undef GetUInt32
+struct FX_BIT2CHARSET {
+ FX_WORD wBit;
+ FX_WORD wCharset;
+};
+FX_BIT2CHARSET g_FX_Bit2Charset1[16] = {
+ {1 << 0 , FX_CHARSET_ANSI},
+ {1 << 1 , FX_CHARSET_MSWin_EasterEuropean},
+ {1 << 2 , FX_CHARSET_MSWin_Cyrillic},
+ {1 << 3 , FX_CHARSET_MSWin_Greek},
+ {1 << 4 , FX_CHARSET_MSWin_Turkish},
+ {1 << 5 , FX_CHARSET_MSWin_Hebrew},
+ {1 << 6 , FX_CHARSET_MSWin_Arabic},
+ {1 << 7 , FX_CHARSET_MSWin_Baltic},
+ {1 << 8 , FX_CHARSET_MSWin_Vietnamese},
+ {1 << 9 , FX_CHARSET_Default},
+ {1 << 10 , FX_CHARSET_Default},
+ {1 << 11 , FX_CHARSET_Default},
+ {1 << 12 , FX_CHARSET_Default},
+ {1 << 13 , FX_CHARSET_Default},
+ {1 << 14 , FX_CHARSET_Default},
+ {1 << 15 , FX_CHARSET_Default},
+};
+FX_BIT2CHARSET g_FX_Bit2Charset2[16] = {
+ {1 << 0 , FX_CHARSET_Thai},
+ {1 << 1 , FX_CHARSET_ShiftJIS},
+ {1 << 2 , FX_CHARSET_ChineseSimplified},
+ {1 << 3 , FX_CHARSET_Korean},
+ {1 << 4 , FX_CHARSET_ChineseTriditional},
+ {1 << 5 , FX_CHARSET_Johab},
+ {1 << 6 , FX_CHARSET_Default},
+ {1 << 7 , FX_CHARSET_Default},
+ {1 << 8 , FX_CHARSET_Default},
+ {1 << 9 , FX_CHARSET_Default},
+ {1 << 10 , FX_CHARSET_Default},
+ {1 << 11 , FX_CHARSET_Default},
+ {1 << 12 , FX_CHARSET_Default},
+ {1 << 13 , FX_CHARSET_Default},
+ {1 << 14 , FX_CHARSET_OEM},
+ {1 << 15 , FX_CHARSET_Symbol},
+};
+FX_BIT2CHARSET g_FX_Bit2Charset3[16] = {
+ {1 << 0 , FX_CHARSET_Default},
+ {1 << 1 , FX_CHARSET_Default},
+ {1 << 2 , FX_CHARSET_Default},
+ {1 << 3 , FX_CHARSET_Default},
+ {1 << 4 , FX_CHARSET_Default},
+ {1 << 5 , FX_CHARSET_Default},
+ {1 << 6 , FX_CHARSET_Default},
+ {1 << 7 , FX_CHARSET_Default},
+ {1 << 8 , FX_CHARSET_Default},
+ {1 << 9 , FX_CHARSET_Default},
+ {1 << 10 , FX_CHARSET_Default},
+ {1 << 11 , FX_CHARSET_Default},
+ {1 << 12 , FX_CHARSET_Default},
+ {1 << 13 , FX_CHARSET_Default},
+ {1 << 14 , FX_CHARSET_Default},
+ {1 << 15 , FX_CHARSET_Default},
+};
+FX_BIT2CHARSET g_FX_Bit2Charset4[16] = {
+ {1 << 0 , FX_CHARSET_Default },
+ {1 << 1 , FX_CHARSET_Default },
+ {1 << 2 , FX_CHARSET_Default },
+ {1 << 3 , FX_CHARSET_Default },
+ {1 << 4 , FX_CHARSET_Default },
+ {1 << 5 , FX_CHARSET_Default },
+ {1 << 6 , FX_CHARSET_Default },
+ {1 << 7 , FX_CHARSET_Default },
+ {1 << 8 , FX_CHARSET_Default },
+ {1 << 9 , FX_CHARSET_Default },
+ {1 << 10 , FX_CHARSET_Default },
+ {1 << 11 , FX_CHARSET_Default },
+ {1 << 12 , FX_CHARSET_Default },
+ {1 << 13 , FX_CHARSET_Default },
+ {1 << 14 , FX_CHARSET_Default },
+ {1 << 15 , FX_CHARSET_US },
+};
+#define CODEPAGERANGE_IMPLEMENT(n) \
+ for (FX_INT32 i = 0; i < 16; i++)\
+ {\
+ if ((a##n & g_FX_Bit2Charset##n[i].wBit) != 0)\
+ {\
+ Charsets.Add(g_FX_Bit2Charset##n[i].wCharset);\
+ }\
+ }
+void CFX_FontMgrImp::GetCharsets( FXFT_Face pFace, CFX_WordArray& Charsets )
+{
+ Charsets.RemoveAll();
+ TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
+ if (NULL != pOS2) {
+ FX_WORD a1, a2, a3, a4;
+ a1 = pOS2->ulCodePageRange1 & 0x0000ffff;
+ CODEPAGERANGE_IMPLEMENT(1);
+ a2 = (pOS2->ulCodePageRange1 >> 16) & 0x0000ffff;
+ CODEPAGERANGE_IMPLEMENT(2);
+ a3 = pOS2->ulCodePageRange2 & 0x0000ffff;
+ CODEPAGERANGE_IMPLEMENT(3);
+ a4 = (pOS2->ulCodePageRange2 >> 16) & 0x0000ffff;
+ CODEPAGERANGE_IMPLEMENT(4);
+ } else {
+ Charsets.Add(FX_CHARSET_Default);
+ }
+}
+#undef CODEPAGERANGE_IMPLEMENT
+void CFX_FontMgrImp::GetUSBCSB( FXFT_Face pFace, FX_DWORD* USB, FX_DWORD* CSB )
+{
+ TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
+ if (NULL != pOS2) {
+ USB[0] = pOS2->ulUnicodeRange1;
+ USB[1] = pOS2->ulUnicodeRange2;
+ USB[2] = pOS2->ulUnicodeRange3;
+ USB[3] = pOS2->ulUnicodeRange4;
+ CSB[0] = pOS2->ulCodePageRange1;
+ CSB[1] = pOS2->ulCodePageRange2;
+ } else {
+ USB[0] = 0;
+ USB[1] = 0;
+ USB[2] = 0;
+ USB[3] = 0;
+ CSB[0] = 0;
+ CSB[1] = 0;
+ }
+}
+void CFX_FontMgrImp::NormalizeFontName( CFX_WideString& FontName )
+{
+ FontName.MakeLower();
+ FontName.Remove(' ');
+ FontName.Remove('-');
+}
+FX_INT32 CFX_FontMgrImp::IsPartName( const CFX_WideString& Name1, const CFX_WideString& Name2 )
+{
+ if (Name1.Find((FX_LPCWSTR)Name2) != -1) {
+ return 1;
+ }
+ return 0;
+}
+#endif
diff --git a/xfa/src/fgas/src/font/fx_stdfontmgr.h b/xfa/src/fgas/src/font/fx_stdfontmgr.h
new file mode 100644
index 0000000000..adcc737ca5
--- /dev/null
+++ b/xfa/src/fgas/src/font/fx_stdfontmgr.h
@@ -0,0 +1,175 @@
+// 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 _FX_FONTMGR_IMP
+#define _FX_FONTMGR_IMP
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+FX_INT32 FX_GetSimilarValue(FX_LPCFONTDESCRIPTOR pFont, FX_DWORD dwFontStyles);
+FX_LPCFONTDESCRIPTOR FX_DefFontMatcher(FX_LPFONTMATCHPARAMS pParams, const CFX_FontDescriptors &fonts, FX_LPVOID pUserData);
+class CFX_StdFontMgrImp : public IFX_FontMgr, public CFX_Object
+{
+public:
+ CFX_StdFontMgrImp(FX_LPEnumAllFonts pEnumerator, FX_LPMatchFont pMatcher, FX_LPVOID pUserData);
+ ~CFX_StdFontMgrImp();
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual IFX_Font* GetDefFontByCodePage(FX_WORD wCodePage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* GetDefFontByCharset(FX_BYTE nCharset, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* GetDefFontByUnicode(FX_WCHAR wUnicode, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* GetDefFontByLanguage(FX_WORD wLanguage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* LoadFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_WORD wCodePage = 0xFFFF);
+ virtual IFX_Font* LoadFont(FX_LPCBYTE pBuffer, FX_INT32 iLength);
+ virtual IFX_Font* LoadFont(FX_LPCWSTR pszFileName);
+ virtual IFX_Font* LoadFont(IFX_Stream *pFontStream, FX_LPCWSTR pszFontAlias = NULL, FX_DWORD dwFontStyles = 0, FX_WORD wCodePage = 0, FX_BOOL bSaveStream = FALSE);
+ virtual IFX_Font* LoadFont(IFX_Font *pSrcFont, FX_DWORD dwFontStyles, FX_WORD wCodePage = 0xFFFF);
+ virtual void ClearFontCache();
+ virtual void RemoveFont(IFX_Font *pFont);
+protected:
+ FX_LPMatchFont m_pMatcher;
+ FX_LPEnumAllFonts m_pEnumerator;
+ CFX_FontDescriptors m_FontFaces;
+ CFX_PtrArray m_Fonts;
+ CFX_MapPtrToPtr m_CPFonts;
+ CFX_MapPtrToPtr m_FamilyFonts;
+ CFX_MapPtrToPtr m_UnicodeFonts;
+ CFX_MapPtrToPtr m_BufferFonts;
+ CFX_MapPtrToPtr m_FileFonts;
+ CFX_MapPtrToPtr m_StreamFonts;
+ CFX_MapPtrToPtr m_DeriveFonts;
+ FX_LPVOID m_pUserData;
+ void RemoveFont(CFX_MapPtrToPtr &fontMap, IFX_Font *pFont);
+ FX_LPCFONTDESCRIPTOR FindFont(FX_LPCWSTR pszFontFamily, FX_DWORD dwFontStyles, FX_DWORD dwMatchFlags, FX_WORD wCodePage, FX_DWORD dwUSB = 999, FX_WCHAR wUnicode = 0);
+ IFX_Font* GetFont(FX_LPCFONTDESCRIPTOR pFD, FX_DWORD dwFontStyles);
+};
+FX_DWORD FX_GetGdiFontStyles(const LOGFONTW &lf);
+#else
+class CFX_FontDescriptor : public CFX_Object
+{
+public:
+ CFX_FontDescriptor()
+ : m_pFileAccess(NULL)
+ , m_nFaceIndex(0)
+ , m_dwFontStyles(0)
+ {
+ m_dwUsb[0] = m_dwUsb[1] = m_dwUsb[2] = m_dwUsb[3] = 0;
+ m_dwCsb[0] = m_dwCsb[1] = 0;
+ }
+ ~CFX_FontDescriptor()
+ {
+ if (NULL != m_pFileAccess) {
+ m_pFileAccess->Release();
+ }
+ }
+ IFX_FileAccess* m_pFileAccess;
+ FX_INT32 m_nFaceIndex;
+ CFX_WideString m_wsFaceName;
+ CFX_WideStringArray m_wsFamilyNames;
+ FX_DWORD m_dwFontStyles;
+ FX_DWORD m_dwUsb[4];
+ FX_DWORD m_dwCsb[2];
+};
+typedef CFX_ArrayTemplate<CFX_FontDescriptor*> CFX_FontDescriptors;
+struct FX_FontDescriptorInfo {
+public:
+ CFX_FontDescriptor* pFont;
+ FX_INT32 nPenalty;
+ FX_BOOL operator > (const FX_FontDescriptorInfo& x)
+ {
+ return this->nPenalty > x.nPenalty;
+ };
+ FX_BOOL operator < (const FX_FontDescriptorInfo& x)
+ {
+ return this->nPenalty < x.nPenalty;
+ };
+ FX_BOOL operator == (const FX_FontDescriptorInfo& x)
+ {
+ return this->nPenalty == x.nPenalty;
+ };
+};
+typedef CFX_ArrayTemplate<FX_FontDescriptorInfo> CFX_FontDescriptorInfos;
+struct FX_HandleParentPath : public CFX_Object {
+ FX_HandleParentPath()
+ {
+ }
+ FX_HandleParentPath(const FX_HandleParentPath& x)
+ {
+ pFileHandle = x.pFileHandle;
+ bsParentPath = x.bsParentPath;
+ }
+ void* pFileHandle;
+ CFX_ByteString bsParentPath;
+};
+class CFX_FontSourceEnum_File : public IFX_FontSourceEnum, public CFX_Object
+{
+public:
+ CFX_FontSourceEnum_File();
+ virtual void Release()
+ {
+ delete this;
+ };
+ virtual FX_POSITION GetStartPosition(FX_LPVOID pUserData = NULL);
+ virtual IFX_FileAccess* GetNext(FX_POSITION& pos, FX_LPVOID pUserData = NULL);
+private:
+ CFX_ByteString GetNextFile();
+ CFX_WideString m_wsNext;
+ CFX_ObjectArray<FX_HandleParentPath> m_FolderQueue;
+ CFX_ByteStringArray m_FolderPaths;
+};
+typedef CFX_MapPtrTemplate<FX_DWORD, IFX_FileAccess*> CFX_HashFileMap;
+typedef CFX_MapPtrTemplate<FX_DWORD, IFX_Font*> CFX_HashFontMap;
+typedef CFX_MapPtrTemplate<FX_DWORD, CFX_FontDescriptorInfos*> CFX_HashFontDescsMap;
+typedef CFX_MapPtrTemplate<FX_DWORD, CFX_ArrayTemplate<IFX_Font*>* > CFX_HashFontsMap;
+typedef CFX_MapPtrTemplate<FX_WCHAR, IFX_Font*> CFX_UnicodeFontMap;
+typedef CFX_MapPtrTemplate<IFX_FileAccess*, CFX_ArrayTemplate<IFX_Font*>* > CFX_FileFontMap;
+typedef CFX_MapPtrTemplate<IFX_Font*, IFX_FileRead*> CFX_FonStreamtMap;
+class CFX_FontMgrImp : public IFX_FontMgr, public CFX_Object
+{
+public:
+ CFX_FontMgrImp(IFX_FontSourceEnum* pFontEnum, IFX_FontMgrDelegate* pDelegate = NULL, FX_LPVOID pUserData = NULL);
+ virtual void Release();
+ virtual IFX_Font* GetDefFontByCodePage(FX_WORD wCodePage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* GetDefFontByCharset(FX_BYTE nCharset, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* GetDefFontByUnicode(FX_WCHAR wUnicode, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* GetDefFontByLanguage(FX_WORD wLanguage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* GetFontByCodePage(FX_WORD wCodePage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* GetFontByCharset(FX_BYTE nCharset, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* GetFontByUnicode(FX_WCHAR wUnicode, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* GetFontByLanguage(FX_WORD wLanguage, FX_DWORD dwFontStyles, FX_LPCWSTR pszFontFamily = NULL);
+ virtual IFX_Font* LoadFont(FX_LPCBYTE pBuffer, FX_INT32 iLength, FX_INT32 iFaceIndex, FX_INT32* pFaceCount);
+ virtual IFX_Font* LoadFont(FX_LPCWSTR pszFileName, FX_INT32 iFaceIndex, FX_INT32* pFaceCount);
+ virtual IFX_Font* LoadFont(IFX_Stream* pFontStream, FX_INT32 iFaceIndex, FX_INT32* pFaceCount, FX_BOOL bSaveStream = FALSE);
+ virtual void ClearFontCache();
+ virtual void RemoveFont(IFX_Font* pFont);
+ FX_BOOL EnumFonts();
+protected:
+ void ReportFace(FXFT_Face pFace, CFX_FontDescriptors& Fonts, IFX_FileAccess* pFontAccess);
+ void GetNames(FX_LPCBYTE name_table, CFX_WideStringArray& Names);
+ void GetCharsets(FXFT_Face pFace, CFX_WordArray& Charsets);
+ void GetUSBCSB(FXFT_Face pFace, FX_DWORD* USB, FX_DWORD* CSB);
+ FX_DWORD GetFlags(FXFT_Face pFace);
+ CFX_FontDescriptors m_InstalledFonts;
+ FX_BOOL VerifyUnicode(CFX_FontDescriptor* pDesc, FX_WCHAR wcUnicode);
+ FX_BOOL VerifyUnicode(IFX_Font* pFont, FX_WCHAR wcUnicode);
+ void NormalizeFontName( CFX_WideString& FontName );
+ FX_INT32 IsPartName(const CFX_WideString& Name1, const CFX_WideString& Name2);
+ FX_INT32 MatchFonts(CFX_FontDescriptorInfos& MatchedFonts, FX_WORD wCodePage, FX_DWORD dwFontStyles, const CFX_WideString& FontName, FX_WCHAR wcUnicode = 0xFFFE);
+ FX_INT32 CalcPenalty(CFX_FontDescriptor* pInstalled, FX_WORD wCodePage, FX_DWORD dwFontStyles, const CFX_WideString& FontName, FX_WCHAR wcUnicode = 0xFFFE);
+ IFX_Font* LoadFont(IFX_FileAccess* pFontAccess, FX_INT32 iFaceIndex, FX_INT32* pFaceCount, FX_BOOL bWantCache = FALSE);
+ FXFT_Face LoadFace(IFX_FileRead* pFontStream, FX_INT32 iFaceIndex);
+ CFX_HashFontDescsMap m_Hash2CandidateList;
+ CFX_HashFontsMap m_Hash2Fonts;
+ CFX_HashFileMap m_Hash2FileAccess;
+ CFX_HashFontMap m_FileAccess2IFXFont;
+ CFX_FonStreamtMap m_IFXFont2FileRead;
+ CFX_UnicodeFontMap m_FailedUnicodes2NULL;
+ IFX_FontSourceEnum* m_pFontSource;
+ IFX_FontMgrDelegate* m_pDelegate;
+ FX_LPVOID m_pUserData;
+};
+#endif
+#endif
diff --git a/xfa/src/fgas/src/layout/fx_linebreak.cpp b/xfa/src/fgas/src/layout/fx_linebreak.cpp
new file mode 100644
index 0000000000..4662e1c122
--- /dev/null
+++ b/xfa/src/fgas/src/layout/fx_linebreak.cpp
@@ -0,0 +1,121 @@
+// 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 "../fgas_base.h"
+extern const FX_DWORD gs_FX_TextLayout_CodeProperties[65536];
+extern const FX_LINEBREAKTYPE gs_FX_LineBreak_PairTable[64][32] = {
+ {FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBCP, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBPB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBPB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBIB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBDB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBPB, FX_LBDB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBDB, FX_LBPB, FX_LBIB, FX_LBDB, FX_LBIB, FX_LBPB, FX_LBPB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBIB, FX_LBIB, FX_LBDB, FX_LBDB, FX_LBPB, FX_LBCB, FX_LBPB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBDB, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+ {FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN, FX_LBUN},
+};
+void FX_GetLineBreakPositions(FX_LPCWSTR pwsText, FX_LINEBREAKTYPE *pBrkType, FX_INT32 iLength)
+{
+ if (iLength < 2) {
+ return;
+ }
+ FX_DWORD dwCur, dwNext;
+ FX_WCHAR wch;
+ wch = *pwsText ++;
+ dwCur = gs_FX_TextLayout_CodeProperties[(FX_WORD)wch] & 0x003F;
+ iLength --;
+ for (FX_INT32 i = 0; i < iLength; i ++) {
+ wch = *pwsText ++;
+ dwNext = gs_FX_TextLayout_CodeProperties[(FX_WORD)wch] & 0x003F;
+ if (dwNext == FX_CBP_SP) {
+ pBrkType[i] = FX_LBT_PROHIBITED_BRK;
+ } else {
+ pBrkType[i] = *((const FX_LINEBREAKTYPE *)gs_FX_LineBreak_PairTable + (dwCur << 5) + dwNext);
+ }
+ dwCur = dwNext;
+ }
+ pBrkType[iLength] = FX_LBT_INDIRECT_BRK;
+}
+void FX_GetLineBreakPositions(FX_LPCWSTR pwsText, FX_INT32 iLength, CFX_Int32MassArray &bp)
+{
+ if (iLength < 2) {
+ return;
+ }
+ FX_LINEBREAKTYPE eType;
+ FX_DWORD dwCur, dwNext;
+ FX_WCHAR wch;
+ wch = *pwsText ++;
+ dwCur = gs_FX_TextLayout_CodeProperties[(FX_WORD)wch] & 0x003F;
+ iLength --;
+ for (FX_INT32 i = 0; i < iLength; i ++) {
+ wch = *pwsText ++;
+ dwNext = gs_FX_TextLayout_CodeProperties[(FX_WORD)wch] & 0x003F;
+ if (dwNext == FX_CBP_SP) {
+ eType = FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE *)gs_FX_LineBreak_PairTable + (dwCur << 5) + dwNext);
+ }
+ if (eType == FX_LBT_DIRECT_BRK) {
+ bp.Add(i);
+ }
+ dwCur = dwNext;
+ }
+}
diff --git a/xfa/src/fgas/src/layout/fx_rtfbreak.cpp b/xfa/src/fgas/src/layout/fx_rtfbreak.cpp
new file mode 100644
index 0000000000..24c64c453b
--- /dev/null
+++ b/xfa/src/fgas/src/layout/fx_rtfbreak.cpp
@@ -0,0 +1,1522 @@
+// 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 "../fgas_base.h"
+#include "fx_unicode.h"
+#include "fx_rtfbreak.h"
+extern const FX_DWORD gs_FX_TextLayout_CodeProperties[65536];
+extern const FX_WCHAR gs_FX_TextLayout_VerticalMirror[64];
+extern const FX_WCHAR gs_FX_TextLayout_BidiMirror[512];
+extern const FX_LINEBREAKTYPE gs_FX_LineBreak_PairTable[64][32];
+IFX_RTFBreak* IFX_RTFBreak::Create(FX_DWORD dwPolicies)
+{
+ return FX_NEW CFX_RTFBreak(dwPolicies);
+}
+CFX_RTFBreak::CFX_RTFBreak(FX_DWORD dwPolicies)
+ : m_dwPolicies(dwPolicies)
+ , m_pArabicChar(NULL)
+ , m_iLineStart(0)
+ , m_iLineEnd(2000000)
+ , m_dwLayoutStyles(0)
+ , m_bPagination(FALSE)
+ , m_bVertical(FALSE)
+ , m_bSingleLine(FALSE)
+ , m_bCharCode(FALSE)
+ , m_pFont(NULL)
+ , m_iFontHeight(240)
+ , m_iFontSize(240)
+ , m_iTabWidth(720000)
+ , m_PositionedTabs()
+ , m_bOrphanLine(FALSE)
+ , m_wDefChar(0xFEFF)
+ , m_iDefChar(0)
+ , m_wLineBreakChar(L'\n')
+ , m_iHorizontalScale(100)
+ , m_iVerticalScale(100)
+ , m_iLineRotation(0)
+ , m_iCharRotation(0)
+ , m_iRotation(0)
+ , m_iCharSpace(0)
+ , m_bWordSpace(FALSE)
+ , m_iWordSpace(0)
+ , m_bRTL(FALSE)
+ , m_iAlignment(FX_RTFLINEALIGNMENT_Left)
+ , m_pUserData(NULL)
+ , m_dwCharType(0)
+ , m_dwIdentity(0)
+ , m_RTFLine1()
+ , m_RTFLine2()
+ , m_pCurLine(NULL)
+ , m_iReady(0)
+ , m_iTolerance(0)
+{
+ m_pArabicChar = IFX_ArabicChar::Create();
+ m_pCurLine = &m_RTFLine1;
+}
+CFX_RTFBreak::~CFX_RTFBreak()
+{
+ Reset();
+ m_PositionedTabs.RemoveAll();
+ m_pArabicChar->Release();
+ if (m_pUserData != NULL) {
+ m_pUserData->Release();
+ }
+}
+void CFX_RTFBreak::SetLineWidth(FX_FLOAT fLineStart, FX_FLOAT fLineEnd)
+{
+ m_iLineStart = FXSYS_round(fLineStart * 20000.0f);
+ m_iLineEnd = FXSYS_round(fLineEnd * 20000.0f);
+ FXSYS_assert(m_iLineEnd >= m_iLineStart);
+ if (m_pCurLine->m_iStart < m_iLineStart) {
+ m_pCurLine->m_iStart = m_iLineStart;
+ }
+}
+void CFX_RTFBreak::SetLinePos(FX_FLOAT fLinePos)
+{
+ FX_INT32 iLinePos = FXSYS_round(fLinePos * 20000.0f);
+ if (iLinePos > m_iLineEnd) {
+ iLinePos = m_iLineEnd;
+ }
+ m_pCurLine->m_iStart = iLinePos;
+}
+void CFX_RTFBreak::SetLayoutStyles(FX_DWORD dwLayoutStyles)
+{
+ if (m_dwLayoutStyles == dwLayoutStyles) {
+ return;
+ }
+ SetBreakStatus();
+ m_dwLayoutStyles = dwLayoutStyles;
+ m_bPagination = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_Pagination) != 0;
+ m_bVertical = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_VerticalChars) != 0;
+ m_bSingleLine = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_SingleLine) != 0;
+ m_bCharCode = (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_MBCSCode) != 0;
+ m_iLineRotation = GetLineRotation(m_dwLayoutStyles);
+ m_iRotation = m_iLineRotation + m_iCharRotation;
+ m_iRotation %= 4;
+}
+void CFX_RTFBreak::SetFont(IFX_Font *pFont)
+{
+ if (pFont == NULL) {
+ return;
+ }
+ if (m_pFont == pFont) {
+ return;
+ }
+ SetBreakStatus();
+ m_pFont = pFont;
+ m_iDefChar = 0;
+ if (m_pFont != NULL) {
+ m_iFontHeight = m_iFontSize;
+ if (m_wDefChar != 0xFEFF) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ m_iDefChar *= m_iFontSize;
+ }
+ }
+}
+void CFX_RTFBreak::SetFontSize(FX_FLOAT fFontSize)
+{
+ FX_INT32 iFontSize = FXSYS_round(fFontSize * 20.0f);
+ if (m_iFontSize == iFontSize) {
+ return;
+ }
+ SetBreakStatus();
+ m_iFontSize = iFontSize;
+ m_iDefChar = 0;
+ if (m_pFont != NULL) {
+ m_iFontHeight = m_iFontSize;
+ if (m_wDefChar != 0xFEFF) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ m_iDefChar *= m_iFontSize;
+ }
+ }
+}
+void CFX_RTFBreak::SetTabWidth(FX_FLOAT fTabWidth)
+{
+ m_iTabWidth = FXSYS_round(fTabWidth * 20000.0f);
+}
+void CFX_RTFBreak::AddPositionedTab(FX_FLOAT fTabPos)
+{
+ FX_INT32 iLineEnd = m_iLineEnd;
+ FX_INT32 iTabPos = FXSYS_round(fTabPos * 20000.0f) + m_iLineStart;
+ if (iTabPos > iLineEnd) {
+ iTabPos = iLineEnd;
+ }
+ if (m_PositionedTabs.Find(iTabPos, 0) > -1) {
+ return;
+ }
+ FX_INT32 iCount = m_PositionedTabs.GetSize();
+ FX_INT32 iFind = 0;
+ for (; iFind < iCount; iFind ++) {
+ if (m_PositionedTabs[iFind] > iTabPos) {
+ break;
+ }
+ }
+ m_PositionedTabs.InsertAt(iFind, iTabPos);
+ if (m_dwPolicies & FX_RTFBREAKPOLICY_OrphanPositionedTab) {
+ m_bOrphanLine = GetLastPositionedTab() >= iLineEnd;
+ } else {
+ m_bOrphanLine = FALSE;
+ }
+}
+void CFX_RTFBreak::SetPositionedTabs(const CFX_FloatArray &tabs)
+{
+ m_PositionedTabs.RemoveAll();
+ FX_INT32 iCount = tabs.GetSize();
+ m_PositionedTabs.SetSize(iCount);
+ FX_INT32 iLineEnd = m_iLineEnd;
+ FX_INT32 iTabPos;
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ iTabPos = FXSYS_round(tabs[i] * 20000.0f) + m_iLineStart;
+ if (iTabPos > iLineEnd) {
+ iTabPos = iLineEnd;
+ }
+ m_PositionedTabs[i] = iTabPos;
+ }
+ if (m_dwPolicies & FX_RTFBREAKPOLICY_OrphanPositionedTab) {
+ m_bOrphanLine = GetLastPositionedTab() >= iLineEnd;
+ } else {
+ m_bOrphanLine = FALSE;
+ }
+}
+void CFX_RTFBreak::ClearPositionedTabs()
+{
+ m_PositionedTabs.RemoveAll();
+ m_bOrphanLine = FALSE;
+}
+void CFX_RTFBreak::SetDefaultChar(FX_WCHAR wch)
+{
+ m_wDefChar = wch;
+ m_iDefChar = 0;
+ if (m_wDefChar != 0xFEFF && m_pFont != NULL) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ if (m_iDefChar < 0) {
+ m_iDefChar = 0;
+ } else {
+ m_iDefChar *= m_iFontSize;
+ }
+ }
+}
+void CFX_RTFBreak::SetLineBreakChar(FX_WCHAR wch)
+{
+ if (wch != L'\r' && wch != L'\n') {
+ return;
+ }
+ m_wLineBreakChar = wch;
+}
+void CFX_RTFBreak::SetLineBreakTolerance(FX_FLOAT fTolerance)
+{
+ m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
+}
+void CFX_RTFBreak::SetHorizontalScale(FX_INT32 iScale)
+{
+ if (iScale < 0) {
+ iScale = 0;
+ }
+ if (m_iHorizontalScale == iScale) {
+ return;
+ }
+ SetBreakStatus();
+ m_iHorizontalScale = iScale;
+}
+void CFX_RTFBreak::SetVerticalScale(FX_INT32 iScale)
+{
+ if (iScale < 0) {
+ iScale = 0;
+ }
+ if (m_iVerticalScale == iScale) {
+ return;
+ }
+ SetBreakStatus();
+ m_iVerticalScale = iScale;
+}
+void CFX_RTFBreak::SetCharRotation(FX_INT32 iCharRotation)
+{
+ if (iCharRotation < 0) {
+ iCharRotation += (-iCharRotation / 4 + 1) * 4;
+ } else if (iCharRotation > 3) {
+ iCharRotation -= (iCharRotation / 4) * 4;
+ }
+ if (m_iCharRotation == iCharRotation) {
+ return;
+ }
+ SetBreakStatus();
+ m_iCharRotation = iCharRotation;
+ m_iRotation = m_iLineRotation + m_iCharRotation;
+ m_iRotation %= 4;
+}
+void CFX_RTFBreak::SetCharSpace(FX_FLOAT fCharSpace)
+{
+ m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
+}
+void CFX_RTFBreak::SetWordSpace(FX_BOOL bDefault, FX_FLOAT fWordSpace)
+{
+ m_bWordSpace = !bDefault;
+ m_iWordSpace = FXSYS_round(fWordSpace * 20000.0f);
+}
+void CFX_RTFBreak::SetReadingOrder(FX_BOOL bRTL)
+{
+ m_bRTL = bRTL;
+}
+void CFX_RTFBreak::SetAlignment(FX_INT32 iAlignment)
+{
+ FXSYS_assert(iAlignment >= FX_RTFLINEALIGNMENT_Left && iAlignment <= FX_RTFLINEALIGNMENT_Distributed);
+ m_iAlignment = iAlignment;
+}
+void CFX_RTFBreak::SetUserData(IFX_Unknown *pUserData)
+{
+ if (m_pUserData == pUserData) {
+ return;
+ }
+ SetBreakStatus();
+ if (m_pUserData != NULL) {
+ m_pUserData->Release();
+ }
+ m_pUserData = pUserData;
+ if (m_pUserData != NULL) {
+ m_pUserData->AddRef();
+ }
+}
+static const FX_INT32 gs_FX_RTFLineRotations[8] = {0, 3, 1, 0, 2, 1, 3, 2};
+FX_INT32 CFX_RTFBreak::GetLineRotation(FX_DWORD dwStyles) const
+{
+ return gs_FX_RTFLineRotations[(dwStyles & 0x0E) >> 1];
+}
+void CFX_RTFBreak::SetBreakStatus()
+{
+ m_dwIdentity ++;
+ FX_INT32 iCount = m_pCurLine->CountChars();
+ if (iCount < 1) {
+ return;
+ }
+ CFX_RTFChar &tc = m_pCurLine->GetChar(iCount - 1);
+ if (tc.m_dwStatus == 0) {
+ tc.m_dwStatus = FX_RTFBREAK_PieceBreak;
+ }
+}
+CFX_RTFChar* CFX_RTFBreak::GetLastChar(FX_INT32 index) const
+{
+ CFX_RTFCharArray &tca = m_pCurLine->m_LineChars;
+ FX_INT32 iCount = tca.GetSize();
+ if (index < 0 || index >= iCount) {
+ return NULL;
+ }
+ CFX_RTFChar *pTC;
+ FX_INT32 iStart = iCount - 1;
+ while (iStart > -1) {
+ pTC = tca.GetDataPtr(iStart --);
+ if (pTC->m_iCharWidth >= 0 || pTC->GetCharType() != FX_CHARTYPE_Combination) {
+ if (--index < 0) {
+ return pTC;
+ }
+ }
+ }
+ return NULL;
+}
+CFX_RTFLine* CFX_RTFBreak::GetRTFLine(FX_BOOL bReady) const
+{
+ if (bReady) {
+ if (m_iReady == 1) {
+ return (CFX_RTFLine*)&m_RTFLine1;
+ } else if (m_iReady == 2) {
+ return (CFX_RTFLine*)&m_RTFLine2;
+ } else {
+ return NULL;
+ }
+ }
+ FXSYS_assert(m_pCurLine != NULL);
+ return m_pCurLine;
+}
+CFX_RTFPieceArray* CFX_RTFBreak::GetRTFPieces(FX_BOOL bReady) const
+{
+ CFX_RTFLine *pRTFLine = GetRTFLine(bReady);
+ if (pRTFLine == NULL) {
+ return NULL;
+ }
+ return &pRTFLine->m_LinePieces;
+}
+inline FX_DWORD CFX_RTFBreak::GetUnifiedCharType(FX_DWORD dwType) const
+{
+ return dwType >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : dwType;
+}
+FX_INT32 CFX_RTFBreak::GetLastPositionedTab() const
+{
+ FX_INT32 iCount = m_PositionedTabs.GetSize();
+ if (iCount < 1) {
+ return m_iLineStart;
+ }
+ return m_PositionedTabs[iCount - 1];
+}
+FX_BOOL CFX_RTFBreak::GetPositionedTab(FX_INT32 &iTabPos) const
+{
+ FX_INT32 iCount = m_PositionedTabs.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ if (m_PositionedTabs[i] > iTabPos) {
+ iTabPos = m_PositionedTabs[i];
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+typedef FX_DWORD (CFX_RTFBreak::*FX_RTFBreak_LPFAppendChar)(CFX_RTFChar *pCurChar, FX_INT32 iRotation);
+static const FX_RTFBreak_LPFAppendChar g_FX_RTFBreak_lpfAppendChar[16] = {
+ &CFX_RTFBreak::AppendChar_Others,
+ &CFX_RTFBreak::AppendChar_Tab,
+ &CFX_RTFBreak::AppendChar_Others,
+ &CFX_RTFBreak::AppendChar_Control,
+ &CFX_RTFBreak::AppendChar_Combination,
+ &CFX_RTFBreak::AppendChar_Others,
+ &CFX_RTFBreak::AppendChar_Others,
+ &CFX_RTFBreak::AppendChar_Arabic,
+ &CFX_RTFBreak::AppendChar_Arabic,
+ &CFX_RTFBreak::AppendChar_Arabic,
+ &CFX_RTFBreak::AppendChar_Arabic,
+ &CFX_RTFBreak::AppendChar_Arabic,
+ &CFX_RTFBreak::AppendChar_Arabic,
+ &CFX_RTFBreak::AppendChar_Others,
+ &CFX_RTFBreak::AppendChar_Others,
+ &CFX_RTFBreak::AppendChar_Others,
+};
+FX_DWORD CFX_RTFBreak::AppendChar(FX_WCHAR wch)
+{
+ FXSYS_assert(m_pFont != NULL && m_pCurLine != NULL && m_pArabicChar != NULL);
+ if (m_bCharCode) {
+ return AppendChar_CharCode(wch);
+ }
+ FX_DWORD dwProps = gs_FX_TextLayout_CodeProperties[(FX_WORD)wch];
+ FX_DWORD dwType = (dwProps & FX_CHARTYPEBITSMASK);
+ CFX_RTFCharArray &tca = m_pCurLine->m_LineChars;
+ CFX_RTFChar *pCurChar = tca.AddSpace();
+ pCurChar->m_dwStatus = 0;
+ pCurChar->m_wCharCode = wch;
+ pCurChar->m_dwCharProps = dwProps;
+ pCurChar->m_dwCharStyles = 0;
+ pCurChar->m_dwLayoutStyles = 0;
+ pCurChar->m_iFontSize = m_iFontSize;
+ pCurChar->m_iFontHeight = m_iFontHeight;
+ pCurChar->m_iHorizontalScale = m_iHorizontalScale;
+ pCurChar->m_iVertialScale = m_iVerticalScale;
+ pCurChar->m_nRotation = m_iCharRotation;
+ pCurChar->m_iCharWidth = 0;
+ pCurChar->m_dwIdentity = m_dwIdentity;
+ if (m_pUserData != NULL) {
+ m_pUserData->AddRef();
+ }
+ pCurChar->m_pUserData = m_pUserData;
+ FX_DWORD dwRet1 = FX_RTFBREAK_None;
+ if (dwType != FX_CHARTYPE_Combination && GetUnifiedCharType(m_dwCharType) != GetUnifiedCharType(dwType)) {
+ if (!m_bSingleLine && !m_bOrphanLine && m_dwCharType > 0 && m_pCurLine->GetLineEnd() > m_iLineEnd + m_iTolerance) {
+ if (m_dwCharType != FX_CHARTYPE_Space || dwType != FX_CHARTYPE_Control) {
+ dwRet1 = EndBreak(FX_RTFBREAK_LineBreak);
+ FX_INT32 iCount = m_pCurLine->CountChars();
+ if (iCount > 0) {
+ pCurChar = m_pCurLine->m_LineChars.GetDataPtr(iCount - 1);
+ }
+ }
+ }
+ }
+ FX_INT32 iRotation = m_iRotation;
+ if (m_bVertical && (dwProps & 0x8000) != 0) {
+ iRotation = (iRotation + 1) % 4;
+ }
+ FX_DWORD dwRet2 = (this->*g_FX_RTFBreak_lpfAppendChar[dwType >> FX_CHARTYPEBITS])(pCurChar, iRotation);
+ m_dwCharType = dwType;
+ return FX_MAX(dwRet1, dwRet2);
+}
+FX_DWORD CFX_RTFBreak::AppendChar_CharCode(FX_WCHAR wch)
+{
+ FXSYS_assert(m_pFont != NULL && m_pCurLine != NULL);
+ FXSYS_assert(m_bCharCode);
+ m_pCurLine->m_iMBCSChars ++;
+ CFX_RTFCharArray &tca = m_pCurLine->m_LineChars;
+ CFX_RTFChar *pCurChar = tca.AddSpace();
+ pCurChar->m_dwStatus = 0;
+ pCurChar->m_wCharCode = wch;
+ pCurChar->m_dwCharProps = 0;
+ pCurChar->m_dwCharStyles = 0;
+ pCurChar->m_dwLayoutStyles = m_dwLayoutStyles;
+ pCurChar->m_iFontSize = m_iFontSize;
+ pCurChar->m_iFontHeight = m_iFontHeight;
+ pCurChar->m_iHorizontalScale = m_iHorizontalScale;
+ pCurChar->m_iVertialScale = m_iVerticalScale;
+ pCurChar->m_nRotation = m_iCharRotation;
+ pCurChar->m_iCharWidth = 0;
+ pCurChar->m_dwIdentity = m_dwIdentity;
+ if (m_pUserData != NULL) {
+ m_pUserData->AddRef();
+ }
+ pCurChar->m_pUserData = m_pUserData;
+ FX_INT32 iCharWidth = 0;
+ if (m_bVertical != FX_IsOdd(m_iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ if (!m_pFont->GetCharWidth(wch, iCharWidth, TRUE)) {
+ iCharWidth = m_iDefChar;
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorizontalScale / 100;
+ iCharWidth += m_iCharSpace;
+ pCurChar->m_iCharWidth = iCharWidth;
+ m_pCurLine->m_iWidth += iCharWidth;
+ m_dwCharType = 0;
+ if (!m_bSingleLine && m_pCurLine->GetLineEnd() > m_iLineEnd + m_iTolerance) {
+ return EndBreak(FX_RTFBREAK_LineBreak);
+ }
+ return FX_RTFBREAK_None;
+}
+FX_DWORD CFX_RTFBreak::AppendChar_Combination(CFX_RTFChar *pCurChar, FX_INT32 iRotation)
+{
+ FX_INT32 iCharWidth = 0;
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ if (!m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth, m_bCharCode)) {
+ iCharWidth = 0;
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorizontalScale / 100;
+ CFX_RTFChar *pLastChar = GetLastChar(0);
+ if (pLastChar != NULL && pLastChar->GetCharType() > FX_CHARTYPE_Combination) {
+ iCharWidth = -iCharWidth;
+ } else {
+ m_dwCharType = FX_CHARTYPE_Combination;
+ }
+ pCurChar->m_iCharWidth = iCharWidth;
+ if (iCharWidth > 0) {
+ m_pCurLine->m_iWidth += iCharWidth;
+ }
+ return FX_RTFBREAK_None;
+}
+FX_DWORD CFX_RTFBreak::AppendChar_Tab(CFX_RTFChar *pCurChar, FX_INT32 iRotation)
+{
+ if (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_ExpandTab) {
+ FX_BOOL bBreak = FALSE;
+ if ((m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0) {
+ bBreak = (m_pCurLine->GetLineEnd() > m_iLineEnd + m_iTolerance);
+ }
+ FX_INT32 &iLineWidth = m_pCurLine->m_iWidth;
+ FX_INT32 iCharWidth = iLineWidth;
+ if (GetPositionedTab(iCharWidth)) {
+ iCharWidth -= iLineWidth;
+ } else {
+ iCharWidth = m_iTabWidth * (iLineWidth / m_iTabWidth + 1) - iLineWidth;
+ }
+ pCurChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ if (!m_bSingleLine && !m_bOrphanLine && bBreak) {
+ return EndBreak(FX_RTFBREAK_LineBreak);
+ }
+ }
+ return FX_RTFBREAK_None;
+}
+FX_DWORD CFX_RTFBreak::AppendChar_Control(CFX_RTFChar *pCurChar, FX_INT32 iRotation)
+{
+ FX_DWORD dwRet2 = FX_RTFBREAK_None;
+ if (!m_bSingleLine) {
+ switch (pCurChar->m_wCharCode) {
+ case L'\v':
+ case 0x2028:
+ dwRet2 = FX_RTFBREAK_LineBreak;
+ break;
+ case L'\f':
+ dwRet2 = FX_RTFBREAK_PageBreak;
+ break;
+ case 0x2029:
+ dwRet2 = FX_RTFBREAK_ParagraphBreak;
+ break;
+ default:
+ if (pCurChar->m_wCharCode == m_wLineBreakChar) {
+ dwRet2 = FX_RTFBREAK_ParagraphBreak;
+ }
+ break;
+ }
+ if (dwRet2 != FX_RTFBREAK_None) {
+ dwRet2 = EndBreak(dwRet2);
+ }
+ }
+ return dwRet2;
+}
+FX_DWORD CFX_RTFBreak::AppendChar_Arabic(CFX_RTFChar *pCurChar, FX_INT32 iRotation)
+{
+ CFX_RTFChar *pLastChar = NULL;
+ FX_INT32 &iLineWidth = m_pCurLine->m_iWidth;
+ FX_INT32 iCharWidth = 0;
+ FX_WCHAR wForm;
+ FX_BOOL bAlef = FALSE;
+ if (m_dwCharType >= FX_CHARTYPE_ArabicAlef && m_dwCharType <= FX_CHARTYPE_ArabicDistortion) {
+ pLastChar = GetLastChar(1);
+ if (pLastChar != NULL) {
+ iLineWidth -= pLastChar->m_iCharWidth;
+ CFX_RTFChar *pPrevChar = GetLastChar(2);
+ wForm = m_pArabicChar->GetFormChar(pLastChar, pPrevChar, pCurChar);
+ bAlef = (wForm == 0xFEFF && pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef);
+ FX_INT32 iLastRotation = pLastChar->m_nRotation + m_iLineRotation;
+ if (m_bVertical && (pLastChar->m_dwCharProps & 0x8000) != 0) {
+ iLastRotation ++;
+ }
+ if (m_bVertical != FX_IsOdd(iLastRotation)) {
+ iCharWidth = 1000;
+ } else {
+ if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode))
+ if (!m_pFont->GetCharWidth(pLastChar->m_wCharCode, iCharWidth, m_bCharCode)) {
+ iCharWidth = m_iDefChar;
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorizontalScale / 100;
+ pLastChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ iCharWidth = 0;
+ }
+ }
+ wForm = m_pArabicChar->GetFormChar(pCurChar, (bAlef ? NULL : pLastChar), NULL);
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode))
+ if (!m_pFont->GetCharWidth(pCurChar->m_wCharCode, iCharWidth, m_bCharCode)) {
+ iCharWidth = m_iDefChar;
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorizontalScale / 100;
+ pCurChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ m_pCurLine->m_iArabicChars ++;
+ if (!m_bSingleLine && !m_bOrphanLine && m_pCurLine->GetLineEnd() > m_iLineEnd + m_iTolerance) {
+ return EndBreak(FX_RTFBREAK_LineBreak);
+ }
+ return FX_RTFBREAK_None;
+}
+FX_DWORD CFX_RTFBreak::AppendChar_Others(CFX_RTFChar *pCurChar, FX_INT32 iRotation)
+{
+ FX_DWORD dwType = (pCurChar->m_dwCharProps & FX_CHARTYPEBITSMASK);
+ FX_WCHAR wForm;
+ if (dwType == FX_CHARTYPE_Numeric) {
+ if (m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_ArabicNumber) {
+ wForm = pCurChar->m_wCharCode + 0x0630;
+ } else {
+ wForm = pCurChar->m_wCharCode;
+ }
+ } else if (m_bRTL || m_bVertical) {
+ wForm = FX_GetMirrorChar(pCurChar->m_wCharCode, pCurChar->m_dwCharProps, m_bRTL, m_bVertical);
+ } else {
+ wForm = pCurChar->m_wCharCode;
+ }
+ FX_INT32 iCharWidth = 0;
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ if (!m_pFont->GetCharWidth(wForm, iCharWidth, m_bCharCode)) {
+ iCharWidth = m_iDefChar;
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorizontalScale / 100;
+ iCharWidth += m_iCharSpace;
+ if (dwType == FX_CHARTYPE_Space && m_bWordSpace) {
+ iCharWidth += m_iWordSpace;
+ }
+ pCurChar->m_iCharWidth = iCharWidth;
+ m_pCurLine->m_iWidth += iCharWidth;
+ FX_BOOL bBreak = (dwType != FX_CHARTYPE_Space || (m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0);
+ if (!m_bSingleLine && !m_bOrphanLine && bBreak && m_pCurLine->GetLineEnd() > m_iLineEnd + m_iTolerance) {
+ return EndBreak(FX_RTFBREAK_LineBreak);
+ }
+ return FX_RTFBREAK_None;
+}
+FX_DWORD CFX_RTFBreak::EndBreak(FX_DWORD dwStatus)
+{
+ FXSYS_assert(dwStatus >= FX_RTFBREAK_PieceBreak && dwStatus <= FX_RTFBREAK_PageBreak);
+ m_dwIdentity ++;
+ CFX_RTFPieceArray *pCurPieces = &m_pCurLine->m_LinePieces;
+ FX_INT32 iCount = pCurPieces->GetSize();
+ if (iCount > 0) {
+ CFX_RTFPiece *pLastPiece = pCurPieces->GetPtrAt(-- iCount);
+ if (dwStatus > FX_RTFBREAK_PieceBreak) {
+ pLastPiece->m_dwStatus = dwStatus;
+ } else {
+ dwStatus = pLastPiece->m_dwStatus;
+ }
+ return dwStatus;
+ } else {
+ CFX_RTFLine *pLastLine = GetRTFLine(TRUE);
+ if (pLastLine != NULL) {
+ pCurPieces = &pLastLine->m_LinePieces;
+ iCount = pCurPieces->GetSize();
+ if (iCount -- > 0) {
+ CFX_RTFPiece *pLastPiece = pCurPieces->GetPtrAt(iCount);
+ if (dwStatus > FX_RTFBREAK_PieceBreak) {
+ pLastPiece->m_dwStatus = dwStatus;
+ } else {
+ dwStatus = pLastPiece->m_dwStatus;
+ }
+ return dwStatus;
+ }
+ return FX_RTFBREAK_None;
+ }
+ iCount = m_pCurLine->CountChars();
+ if (iCount < 1) {
+ return FX_RTFBREAK_None;
+ }
+ CFX_RTFChar &tc = m_pCurLine->GetChar(iCount - 1);
+ tc.m_dwStatus = dwStatus;
+ if (dwStatus <= FX_RTFBREAK_PieceBreak) {
+ return dwStatus;
+ }
+ }
+ m_iReady = (m_pCurLine == &m_RTFLine1) ? 1 : 2;
+ CFX_RTFLine *pNextLine = (m_pCurLine == &m_RTFLine1) ? &m_RTFLine2 : &m_RTFLine1;
+ FX_BOOL bAllChars = (m_iAlignment > FX_RTFLINEALIGNMENT_Right);
+ CFX_TPOArray tpos;
+ if (EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) {
+ goto EndBreak_Ret;
+ }
+ if (!m_bCharCode) {
+ EndBreak_BidiLine(tpos, dwStatus);
+ }
+ if (!m_bPagination && m_iAlignment > FX_RTFLINEALIGNMENT_Left) {
+ EndBreak_Alignment(tpos, bAllChars, dwStatus);
+ }
+EndBreak_Ret:
+ m_pCurLine = pNextLine;
+ m_pCurLine->m_iStart = m_iLineStart;
+ CFX_RTFChar *pTC = GetLastChar(0);
+ m_dwCharType = pTC == NULL ? 0 : pTC->GetCharType();
+ return dwStatus;
+}
+FX_BOOL CFX_RTFBreak::EndBreak_SplitLine(CFX_RTFLine *pNextLine, FX_BOOL bAllChars, FX_DWORD dwStatus)
+{
+ FX_BOOL bDone = FALSE;
+ if (!m_bSingleLine && !m_bOrphanLine && m_pCurLine->GetLineEnd() > m_iLineEnd + m_iTolerance) {
+ CFX_RTFChar &tc = m_pCurLine->GetChar(m_pCurLine->CountChars() - 1);
+ switch (tc.GetCharType()) {
+ case FX_CHARTYPE_Tab:
+ if ((m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0) {
+ SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
+ bDone = TRUE;
+ }
+ break;
+ case FX_CHARTYPE_Control:
+ break;
+ case FX_CHARTYPE_Space:
+ if ((m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0) {
+ SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
+ bDone = TRUE;
+ }
+ break;
+ default:
+ SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
+ bDone = TRUE;
+ break;
+ }
+ }
+ if (m_bPagination || m_pCurLine->m_iMBCSChars > 0) {
+ const CFX_RTFChar *pCurChars = m_pCurLine->m_LineChars.GetData();
+ const CFX_RTFChar *pTC;
+ CFX_RTFPieceArray *pCurPieces = &m_pCurLine->m_LinePieces;
+ CFX_RTFPiece tp;
+ tp.m_pChars = &m_pCurLine->m_LineChars;
+ FX_BOOL bNew = TRUE;
+ FX_DWORD dwIdentity = (FX_DWORD) - 1;
+ FX_INT32 iLast = m_pCurLine->CountChars() - 1, j = 0;
+ for (FX_INT32 i = 0; i <= iLast;) {
+ pTC = pCurChars + i;
+ if (bNew) {
+ tp.m_iStartChar = i;
+ tp.m_iStartPos += tp.m_iWidth;
+ tp.m_iWidth = 0;
+ tp.m_dwStatus = pTC->m_dwStatus;
+ tp.m_iFontSize = pTC->m_iFontSize;
+ tp.m_iFontHeight = pTC->m_iFontHeight;
+ tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
+ tp.m_iVerticalScale = pTC->m_iVertialScale;
+ tp.m_dwLayoutStyles = pTC->m_dwLayoutStyles;
+ dwIdentity = pTC->m_dwIdentity;
+ tp.m_dwIdentity = dwIdentity;
+ tp.m_pUserData = pTC->m_pUserData;
+ j = i;
+ bNew = FALSE;
+ }
+ if (i == iLast || pTC->m_dwStatus != FX_RTFBREAK_None || pTC->m_dwIdentity != dwIdentity) {
+ tp.m_iChars = i - j;
+ if (pTC->m_dwIdentity == dwIdentity) {
+ tp.m_dwStatus = pTC->m_dwStatus;
+ tp.m_iWidth += pTC->m_iCharWidth;
+ tp.m_iChars += 1;
+ i ++;
+ }
+ pCurPieces->Add(tp);
+ bNew = TRUE;
+ } else {
+ tp.m_iWidth += pTC->m_iCharWidth;
+ i ++;
+ }
+ }
+ return TRUE;
+ }
+ if (bAllChars && !bDone) {
+ FX_INT32 iEndPos = m_pCurLine->GetLineEnd();
+ GetBreakPos(m_pCurLine->m_LineChars, iEndPos, bAllChars, TRUE);
+ }
+ return FALSE;
+}
+void CFX_RTFBreak::EndBreak_BidiLine(CFX_TPOArray &tpos, FX_DWORD dwStatus)
+{
+ FX_TPO tpo;
+ CFX_RTFPiece tp;
+ CFX_RTFChar *pTC;
+ FX_INT32 i, j;
+ CFX_RTFCharArray &chars = m_pCurLine->m_LineChars;
+ FX_INT32 iCount = m_pCurLine->CountChars();
+ FX_BOOL bDone = (!m_bPagination && !m_bCharCode && (m_pCurLine->m_iArabicChars > 0 || m_bRTL));
+ if (bDone) {
+ FX_INT32 iBidiNum = 0;
+ for (i = 0; i < iCount; i ++) {
+ pTC = chars.GetDataPtr(i);
+ pTC->m_iBidiPos = i;
+ if (pTC->GetCharType() != FX_CHARTYPE_Control) {
+ iBidiNum = i;
+ }
+ if (i == 0) {
+ pTC->m_iBidiLevel = 1;
+ }
+ }
+ FX_BidiLine(chars, iBidiNum + 1, m_bRTL ? 1 : 0);
+ } else {
+ for (i = 0; i < iCount; i ++) {
+ pTC = chars.GetDataPtr(i);
+ pTC->m_iBidiLevel = 0;
+ pTC->m_iBidiPos = 0;
+ pTC->m_iBidiOrder = 0;
+ }
+ }
+ tp.m_dwStatus = FX_RTFBREAK_PieceBreak;
+ tp.m_iStartPos = m_pCurLine->m_iStart;
+ tp.m_pChars = &chars;
+ CFX_RTFPieceArray *pCurPieces = &m_pCurLine->m_LinePieces;
+ FX_INT32 iBidiLevel = -1, iCharWidth;
+ FX_DWORD dwIdentity = (FX_DWORD) - 1;
+ i = j = 0;
+ while (i < iCount) {
+ pTC = chars.GetDataPtr(i);
+ if (iBidiLevel < 0) {
+ iBidiLevel = pTC->m_iBidiLevel;
+ iCharWidth = pTC->m_iCharWidth;
+ if (iCharWidth < 1) {
+ tp.m_iWidth = 0;
+ } else {
+ tp.m_iWidth = iCharWidth;
+ }
+ tp.m_iBidiLevel = iBidiLevel;
+ tp.m_iBidiPos = pTC->m_iBidiOrder;
+ tp.m_iFontSize = pTC->m_iFontSize;
+ tp.m_iFontHeight = pTC->m_iFontHeight;
+ tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
+ tp.m_iVerticalScale = pTC->m_iVertialScale;
+ dwIdentity = pTC->m_dwIdentity;
+ tp.m_dwIdentity = dwIdentity;
+ tp.m_pUserData = pTC->m_pUserData;
+ tp.m_dwStatus = FX_RTFBREAK_PieceBreak;
+ i ++;
+ } else if (iBidiLevel != pTC->m_iBidiLevel || pTC->m_dwIdentity != dwIdentity) {
+ tp.m_iChars = i - tp.m_iStartChar;
+ pCurPieces->Add(tp);
+ tp.m_iStartPos += tp.m_iWidth;
+ tp.m_iStartChar = i;
+ tpo.index = j ++;
+ tpo.pos = tp.m_iBidiPos;
+ tpos.Add(tpo);
+ iBidiLevel = -1;
+ } else {
+ iCharWidth = pTC->m_iCharWidth;
+ if (iCharWidth > 0) {
+ tp.m_iWidth += iCharWidth;
+ }
+ i ++;
+ }
+ }
+ if (i > tp.m_iStartChar) {
+ tp.m_dwStatus = dwStatus;
+ tp.m_iChars = i - tp.m_iStartChar;
+ pCurPieces->Add(tp);
+ tpo.index = j;
+ tpo.pos = tp.m_iBidiPos;
+ tpos.Add(tpo);
+ }
+ if (!m_bCharCode) {
+ j = tpos.GetSize() - 1;
+ FX_TEXTLAYOUT_PieceSort(tpos, 0, j);
+ FX_INT32 iStartPos = m_pCurLine->m_iStart;
+ for (i = 0; i <= j; i ++) {
+ tpo = tpos.GetAt(i);
+ CFX_RTFPiece &ttp = pCurPieces->GetAt(tpo.index);
+ ttp.m_iStartPos = iStartPos;
+ iStartPos += ttp.m_iWidth;
+ }
+ }
+}
+void CFX_RTFBreak::EndBreak_Alignment(CFX_TPOArray &tpos, FX_BOOL bAllChars, FX_DWORD dwStatus)
+{
+ CFX_RTFPieceArray *pCurPieces = &m_pCurLine->m_LinePieces;
+ FX_INT32 iNetWidth = m_pCurLine->m_iWidth, iGapChars = 0, iCharWidth;
+ FX_INT32 iCount = pCurPieces->GetSize();
+ FX_BOOL bFind = FALSE;
+ FX_DWORD dwCharType;
+ FX_INT32 i, j;
+ FX_TPO tpo;
+ for (i = iCount - 1; i > -1; i --) {
+ tpo = tpos.GetAt(i);
+ CFX_RTFPiece &ttp = pCurPieces->GetAt(tpo.index);
+ if (!bFind) {
+ iNetWidth = ttp.GetEndPos();
+ }
+ FX_BOOL bArabic = FX_IsOdd(ttp.m_iBidiLevel);
+ j = bArabic ? 0 : ttp.m_iChars - 1;
+ while (j > -1 && j < ttp.m_iChars) {
+ const CFX_RTFChar &tc = ttp.GetChar(j);
+ if (tc.m_nBreakType == FX_LBT_DIRECT_BRK) {
+ iGapChars ++;
+ }
+ if (!bFind || !bAllChars) {
+ dwCharType = tc.GetCharType();
+ if (dwCharType == FX_CHARTYPE_Space || dwCharType == FX_CHARTYPE_Control) {
+ if (!bFind) {
+ iCharWidth = tc.m_iCharWidth;
+ if (bAllChars && iCharWidth > 0) {
+ iNetWidth -= iCharWidth;
+ }
+ }
+ } else {
+ bFind = TRUE;
+ if (!bAllChars) {
+ break;
+ }
+ }
+ }
+ j += bArabic ? 1 : -1;
+ }
+ if (!bAllChars && bFind) {
+ break;
+ }
+ }
+ FX_INT32 iOffset = m_iLineEnd - iNetWidth;
+ FX_INT32 iLowerAlignment = (m_iAlignment & FX_RTFLINEALIGNMENT_LowerMask);
+ FX_INT32 iHigherAlignment = (m_iAlignment & FX_RTFLINEALIGNMENT_HigherMask);
+ if (iGapChars > 0 && (iHigherAlignment == FX_RTFLINEALIGNMENT_Distributed || (iHigherAlignment == FX_RTFLINEALIGNMENT_Justified && dwStatus != FX_RTFBREAK_ParagraphBreak))) {
+ FX_INT32 iStart = -1;
+ for (i = 0; i < iCount; i ++) {
+ tpo = tpos.GetAt(i);
+ CFX_RTFPiece &ttp = pCurPieces->GetAt(tpo.index);
+ if (iStart < 0) {
+ iStart = ttp.m_iStartPos;
+ } else {
+ ttp.m_iStartPos = iStart;
+ }
+ FX_INT32 k;
+ for (j = 0; j < ttp.m_iChars; j ++) {
+ CFX_RTFChar &tc = ttp.GetChar(j);
+ if (tc.m_nBreakType != FX_LBT_DIRECT_BRK || tc.m_iCharWidth < 0) {
+ continue;
+ }
+ k = iOffset / iGapChars;
+ tc.m_iCharWidth += k;
+ ttp.m_iWidth += k;
+ iOffset -= k;
+ iGapChars --;
+ if (iGapChars < 1) {
+ break;
+ }
+ }
+ iStart += ttp.m_iWidth;
+ }
+ } else if (iLowerAlignment > FX_RTFLINEALIGNMENT_Left) {
+ if (iLowerAlignment == FX_RTFLINEALIGNMENT_Center) {
+ iOffset /= 2;
+ }
+ if (iOffset > 0) {
+ for (i = 0; i < iCount; i ++) {
+ CFX_RTFPiece &ttp = pCurPieces->GetAt(i);
+ ttp.m_iStartPos += iOffset;
+ }
+ }
+ }
+}
+FX_INT32 CFX_RTFBreak::GetBreakPos(CFX_RTFCharArray &tca, FX_INT32 &iEndPos, FX_BOOL bAllChars, FX_BOOL bOnlyBrk)
+{
+ FX_INT32 iLength = tca.GetSize() - 1;
+ if (iLength < 1) {
+ return iLength;
+ }
+ FX_INT32 iBreak = -1, iBreakPos = -1, iIndirect = -1, iIndirectPos = -1, iLast = -1, iLastPos = -1;
+ if (m_bSingleLine || m_bOrphanLine || iEndPos <= m_iLineEnd) {
+ if (!bAllChars || m_bCharCode) {
+ return iLength;
+ }
+ iBreak = iLength;
+ iBreakPos = iEndPos;
+ }
+ CFX_RTFChar *pCharArray = tca.GetData();
+ if (m_bCharCode) {
+ const CFX_RTFChar *pChar;
+ FX_INT32 iCharWidth;
+ while (iLength > 0) {
+ if (iEndPos <= m_iLineEnd) {
+ break;
+ }
+ pChar = pCharArray + iLength--;
+ iCharWidth = pChar->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iEndPos -= iCharWidth;
+ }
+ }
+ return iLength;
+ }
+ FX_BOOL bSpaceBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_SpaceBreak) != 0;
+ FX_BOOL bTabBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_TabBreak) != 0;
+ FX_BOOL bNumberBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_NumberBreak) != 0;
+ FX_BOOL bInfixBreak = (m_dwPolicies & FX_RTFBREAKPOLICY_InfixBreak) != 0;
+ FX_LINEBREAKTYPE eType;
+ FX_DWORD nCodeProp, nCur, nNext;
+ CFX_RTFChar *pCur = pCharArray + iLength--;
+ if (bAllChars) {
+ pCur->m_nBreakType = FX_LBT_UNKNOWN;
+ }
+ nCodeProp = pCur->m_dwCharProps;
+ nNext = nCodeProp & 0x003F;
+ FX_INT32 iCharWidth = pCur->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iEndPos -= iCharWidth;
+ }
+ while (iLength >= 0) {
+ pCur = pCharArray + iLength;
+ nCodeProp = pCur->m_dwCharProps;
+ nCur = nCodeProp & 0x003F;
+ FX_BOOL bNeedBreak = FALSE;
+ if (nCur == FX_CBP_SP) {
+ bNeedBreak = !bSpaceBreak;
+ if (nNext == FX_CBP_SP) {
+ eType = bSpaceBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE *)gs_FX_LineBreak_PairTable + (nCur << 5) + nNext);
+ }
+ } else if (nCur == FX_CBP_TB) {
+ bNeedBreak = !bTabBreak;
+ if (nNext == FX_CBP_TB) {
+ eType = bTabBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE *)gs_FX_LineBreak_PairTable + (nCur << 5) + nNext);
+ }
+ } else if (bNumberBreak && nCur == FX_CBP_NU && nNext == FX_CBP_NU) {
+ eType = FX_LBT_DIRECT_BRK;
+ } else if (bInfixBreak && nCur == FX_CBP_IS && nNext == FX_CBP_IS) {
+ eType = FX_LBT_DIRECT_BRK;
+ } else {
+ if (nNext == FX_CBP_SP) {
+ eType = FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE *)gs_FX_LineBreak_PairTable + (nCur << 5) + nNext);
+ }
+ }
+ if (bAllChars) {
+ pCur->m_nBreakType = eType;
+ }
+ if (!bOnlyBrk) {
+ iCharWidth = pCur->m_iCharWidth;
+ FX_BOOL bBreak = FALSE;
+ if (nCur == FX_CBP_TB && bTabBreak) {
+ bBreak = iCharWidth > 0 && iEndPos - iCharWidth <= m_iLineEnd;
+ } else {
+ bBreak = iEndPos <= m_iLineEnd;
+ }
+ if (m_bSingleLine || m_bOrphanLine || bBreak || bNeedBreak) {
+ if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) {
+ iBreak = iLength;
+ iBreakPos = iEndPos;
+ if (!bAllChars) {
+ return iLength;
+ }
+ } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) {
+ iIndirect = iLength;
+ iIndirectPos = iEndPos;
+ }
+ if (iLast < 0) {
+ iLast = iLength;
+ iLastPos = iEndPos;
+ }
+ }
+ if (iCharWidth > 0) {
+ iEndPos -= iCharWidth;
+ }
+ }
+ nNext = nCodeProp & 0x003F;
+ iLength --;
+ }
+ if (bOnlyBrk) {
+ return 0;
+ }
+ if (iBreak > -1) {
+ iEndPos = iBreakPos;
+ return iBreak;
+ }
+ if (iIndirect > -1) {
+ iEndPos = iIndirectPos;
+ return iIndirect;
+ }
+ if (iLast > -1) {
+ iEndPos = iLastPos;
+ return iLast;
+ }
+ return 0;
+}
+void CFX_RTFBreak::SplitTextLine(CFX_RTFLine *pCurLine, CFX_RTFLine *pNextLine, FX_BOOL bAllChars)
+{
+ FXSYS_assert(pCurLine != NULL && pNextLine != NULL);
+ FX_INT32 iCount = pCurLine->CountChars();
+ if (iCount < 2) {
+ return;
+ }
+ FX_INT32 iEndPos = pCurLine->GetLineEnd();
+ CFX_RTFCharArray &curChars = pCurLine->m_LineChars;
+ FX_INT32 iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, FALSE);
+ if (iCharPos < 0) {
+ iCharPos = 0;
+ }
+ iCharPos ++;
+ if (iCharPos >= iCount) {
+ pNextLine->RemoveAll(TRUE);
+ CFX_Char *pTC = curChars.GetDataPtr(iCharPos - 1);
+ pTC->m_nBreakType = FX_LBT_UNKNOWN;
+ return;
+ }
+ CFX_RTFCharArray &nextChars = pNextLine->m_LineChars;
+ int cur_size = curChars.GetSize();
+ nextChars.SetSize(cur_size - iCharPos);
+ FXSYS_memcpy(nextChars.GetData(), curChars.GetDataPtr(iCharPos), (cur_size - iCharPos) * sizeof(CFX_RTFChar));
+ iCount -= iCharPos;
+ cur_size = curChars.GetSize();
+ curChars.RemoveAt(cur_size - iCount, iCount);
+ pNextLine->m_iStart = pCurLine->m_iStart;
+ pNextLine->m_iWidth = pCurLine->GetLineEnd() - iEndPos;
+ pCurLine->m_iWidth = iEndPos;
+ CFX_RTFChar* tc = curChars.GetDataPtr(iCharPos - 1);
+ tc->m_nBreakType = FX_LBT_UNKNOWN;
+ iCount = nextChars.GetSize();
+ CFX_RTFChar *pNextChars = nextChars.GetData();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ CFX_RTFChar* tc = pNextChars + i;
+ if (tc->GetCharType() >= FX_CHARTYPE_ArabicAlef) {
+ pCurLine->m_iArabicChars --;
+ pNextLine->m_iArabicChars ++;
+ }
+ if (tc->m_dwLayoutStyles & FX_RTFLAYOUTSTYLE_MBCSCode) {
+ pCurLine->m_iMBCSChars --;
+ pNextLine->m_iMBCSChars ++;
+ }
+ tc->m_dwStatus = 0;
+ }
+}
+FX_INT32 CFX_RTFBreak::CountBreakPieces() const
+{
+ CFX_RTFPieceArray *pRTFPieces = GetRTFPieces(TRUE);
+ if (pRTFPieces == NULL) {
+ return 0;
+ }
+ return pRTFPieces->GetSize();
+}
+const CFX_RTFPiece* CFX_RTFBreak::GetBreakPiece(FX_INT32 index) const
+{
+ CFX_RTFPieceArray *pRTFPieces = GetRTFPieces(TRUE);
+ if (pRTFPieces == NULL) {
+ return NULL;
+ }
+ if (index < 0 || index >= pRTFPieces->GetSize()) {
+ return NULL;
+ }
+ return pRTFPieces->GetPtrAt(index);
+}
+void CFX_RTFBreak::GetLineRect(CFX_RectF &rect) const
+{
+ rect.top = 0;
+ CFX_RTFLine *pRTFLine = GetRTFLine(TRUE);
+ if (pRTFLine == NULL) {
+ rect.left = ((FX_FLOAT)m_iLineStart) / 20000.0f;
+ rect.width = rect.height = 0;
+ return;
+ }
+ rect.left = ((FX_FLOAT)pRTFLine->m_iStart) / 20000.0f;
+ rect.width = ((FX_FLOAT)pRTFLine->m_iWidth) / 20000.0f;
+ CFX_RTFPieceArray &rtfPieces = pRTFLine->m_LinePieces;
+ FX_INT32 iCount = rtfPieces.GetSize();
+ if (iCount < 1) {
+ rect.width = 0;
+ return;
+ }
+ CFX_RTFPiece *pBreakPiece;
+ FX_INT32 iLineHeight = 0, iMax;
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ pBreakPiece = rtfPieces.GetPtrAt(i);
+ FX_INT32 iFontHeight = FXSYS_round(pBreakPiece->m_iFontHeight * pBreakPiece->m_iVerticalScale / 100.0f);
+ iMax = FX_MAX(pBreakPiece->m_iFontSize, iFontHeight);
+ if (i == 0) {
+ iLineHeight = iMax;
+ } else if (iLineHeight < iMax) {
+ iLineHeight = iMax;
+ }
+ }
+ rect.height = ((FX_FLOAT)iLineHeight) / 20.0f;
+}
+void CFX_RTFBreak::ClearBreakPieces()
+{
+ CFX_RTFLine *pRTFLine = GetRTFLine(TRUE);
+ if (pRTFLine != NULL) {
+ pRTFLine->RemoveAll(TRUE);
+ }
+ m_iReady = 0;
+}
+void CFX_RTFBreak::Reset()
+{
+ m_dwCharType = 0;
+ m_RTFLine1.RemoveAll(TRUE);
+ m_RTFLine2.RemoveAll(TRUE);
+}
+FX_INT32 CFX_RTFBreak::GetDisplayPos(FX_LPCRTFTEXTOBJ pText, FXTEXT_CHARPOS *pCharPos, FX_BOOL bCharCode , CFX_WideString *pWSForms , FX_AdjustCharDisplayPos pAdjustPos ) const
+{
+ if (pText == NULL || pText->iLength < 1) {
+ return 0;
+ }
+ FXSYS_assert(pText->pStr != NULL && pText->pWidths != NULL && pText->pFont != NULL && pText->pRect != NULL);
+ FX_LPCWSTR pStr = pText->pStr;
+ FX_INT32 *pWidths = pText->pWidths;
+ FX_INT32 iLength = pText->iLength - 1;
+ IFX_Font *pFont = pText->pFont;
+ FX_DWORD dwStyles = pText->dwLayoutStyles;
+ CFX_RectF rtText(*pText->pRect);
+ FX_BOOL bRTLPiece = FX_IsOdd(pText->iBidiLevel);
+ FX_FLOAT fFontSize = pText->fFontSize;
+ FX_INT32 iFontSize = FXSYS_round(fFontSize * 20.0f);
+ FX_INT32 iAscent = pFont->GetAscent();
+ FX_INT32 iDescent = pFont->GetDescent();
+ FX_INT32 iMaxHeight = iAscent - iDescent;
+ FX_FLOAT fFontHeight = fFontSize;
+ FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight;
+ FX_FLOAT fDescent = fFontHeight * (FX_FLOAT)iDescent / (FX_FLOAT)iMaxHeight;
+ FX_BOOL bVerticalDoc = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalLayout) != 0;
+ FX_BOOL bVerticalChar = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalChars) != 0;
+ FX_BOOL bArabicNumber = (dwStyles & FX_RTFLAYOUTSTYLE_ArabicNumber) != 0;
+ FX_BOOL bMBCSCode = (dwStyles & FX_RTFLAYOUTSTYLE_MBCSCode) != 0;
+ FX_INT32 iRotation = GetLineRotation(dwStyles) + pText->iCharRotation;
+ FX_INT32 iCharRotation;
+ FX_WCHAR wch, wPrev = 0xFEFF, wNext, wForm;
+ FX_INT32 iWidth, iCharWidth, iCharHeight;
+ FX_FLOAT fX, fY, fCharWidth, fCharHeight;
+ FX_INT32 iHorScale = pText->iHorizontalScale;
+ FX_INT32 iVerScale = pText->iVerticalScale;
+ FX_BOOL bEmptyChar;
+ FX_DWORD dwProps, dwCharType;
+ fX = rtText.left;
+ fY = rtText.top;
+ if (bVerticalDoc) {
+ fX += (rtText.width - fFontSize) / 2.0f;
+ if (bRTLPiece) {
+ fY = rtText.bottom();
+ }
+ } else {
+ if (bRTLPiece) {
+ fX = rtText.right();
+ }
+ fY += fAscent;
+ }
+ FX_INT32 iCount = 0;
+ for (FX_INT32 i = 0; i <= iLength; i ++) {
+ wch = *pStr ++;
+ iWidth = *pWidths ++;
+ if (!bMBCSCode) {
+ dwProps = FX_GetUnicodeProperties(wch);
+ dwCharType = (dwProps & FX_CHARTYPEBITSMASK);
+ if (dwCharType == FX_CHARTYPE_ArabicAlef && iWidth == 0) {
+ wPrev = 0xFEFF;
+ continue;
+ }
+ } else {
+ dwProps = 0;
+ dwCharType = 0;
+ }
+ if (iWidth != 0) {
+ iCharWidth = iWidth;
+ if (iCharWidth < 0) {
+ iCharWidth = -iCharWidth;
+ }
+ if (!bMBCSCode) {
+ bEmptyChar = (dwCharType >= FX_CHARTYPE_Tab && dwCharType <= FX_CHARTYPE_Control);
+ } else {
+ bEmptyChar = FALSE;
+ }
+ if (!bEmptyChar) {
+ iCount ++;
+ }
+ if (pCharPos != NULL) {
+ iCharWidth /= iFontSize;
+ wForm = wch;
+ if (!bMBCSCode) {
+ if (dwCharType >= FX_CHARTYPE_ArabicAlef) {
+ if (i < iLength) {
+ wNext = *pStr;
+ if (*pWidths < 0) {
+ if (i + 1 < iLength) {
+ wNext = pStr[1];
+ }
+ }
+ } else {
+ wNext = 0xFEFF;
+ }
+ wForm = m_pArabicChar->GetFormChar(wch, wPrev, wNext);
+ } else if (bRTLPiece || bVerticalChar) {
+ wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, bVerticalChar);
+ } else if (dwCharType == FX_CHARTYPE_Numeric && bArabicNumber) {
+ wForm = wch + 0x0630;
+ }
+ dwProps = FX_GetUnicodeProperties(wForm);
+ }
+ iCharRotation = iRotation;
+ if (!bMBCSCode && bVerticalChar && (dwProps & 0x8000) != 0) {
+ iCharRotation ++;
+ iCharRotation %= 4;
+ }
+ if (!bEmptyChar) {
+ if (bCharCode) {
+ pCharPos->m_GlyphIndex = wch;
+ } else {
+ pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wForm, bMBCSCode);
+ if(pCharPos->m_GlyphIndex == 0xFFFF) {
+ pCharPos->m_GlyphIndex = pFont->GetGlyphIndex(wch, bMBCSCode);
+ }
+ }
+ pCharPos->m_ExtGID = pCharPos->m_GlyphIndex;
+ pCharPos->m_FontCharWidth = iCharWidth;
+ if (pWSForms) {
+ *pWSForms += wForm;
+ }
+ }
+ if (bVerticalDoc) {
+ iCharHeight = iCharWidth;
+ iCharWidth = 1000;
+ } else {
+ iCharHeight = 1000;
+ }
+ fCharWidth = fFontSize * iCharWidth / 1000.0f;
+ fCharHeight = fFontSize * iCharHeight / 1000.0f;
+ if (!bMBCSCode && bRTLPiece && dwCharType != FX_CHARTYPE_Combination) {
+ if (bVerticalDoc) {
+ fY -= fCharHeight;
+ } else {
+ fX -= fCharWidth;
+ }
+ }
+ if (!bEmptyChar) {
+ CFX_PointF ptOffset;
+ ptOffset.Reset();
+ FX_BOOL bAdjusted = FALSE;
+ if (pAdjustPos) {
+ bAdjusted = pAdjustPos(wForm, bMBCSCode, pFont, fFontSize, bVerticalChar, ptOffset);
+ }
+ if (!pAdjustPos && bVerticalChar && (dwProps & 0x00010000) != 0) {
+ CFX_Rect rtBBox;
+ rtBBox.Reset();
+ if (pFont->GetCharBBox(wForm, rtBBox, bMBCSCode)) {
+ ptOffset.x = fFontSize * (850 - rtBBox.right()) / 1000.0f;
+ ptOffset.y = fFontSize * (1000 - rtBBox.height) / 2000.0f;
+ }
+ }
+ pCharPos->m_OriginX = fX + ptOffset.x;
+ pCharPos->m_OriginY = fY - ptOffset.y;
+ }
+ if (!bRTLPiece && dwCharType != FX_CHARTYPE_Combination) {
+ if (bVerticalDoc) {
+ fY += fCharHeight;
+ } else {
+ fX += fCharWidth;
+ }
+ }
+ if (!bEmptyChar) {
+ pCharPos->m_bGlyphAdjust = TRUE;
+ if (bVerticalDoc) {
+ if (iCharRotation == 0) {
+ pCharPos->m_AdjustMatrix[0] = -1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = 1;
+ pCharPos->m_OriginY += fAscent * iVerScale / 100.0f;
+ } else if (iCharRotation == 1) {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = -1;
+ pCharPos->m_AdjustMatrix[2] = -1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX -= fDescent + fAscent * iVerScale / 100.0f - fAscent;
+ } else if (iCharRotation == 2) {
+ pCharPos->m_AdjustMatrix[0] = 1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = -1;
+ pCharPos->m_OriginX += fCharWidth;
+ pCharPos->m_OriginY += fAscent;
+ } else {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = 1;
+ pCharPos->m_AdjustMatrix[2] = 1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX += fAscent;
+ pCharPos->m_OriginY += fCharWidth;
+ }
+ } else {
+ if (iCharRotation == 0) {
+ pCharPos->m_AdjustMatrix[0] = -1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = 1;
+ pCharPos->m_OriginY += fAscent * iVerScale / 100.0f - fAscent;
+ } else if (iCharRotation == 1) {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = -1;
+ pCharPos->m_AdjustMatrix[2] = -1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX -= fDescent;
+ pCharPos->m_OriginY -= fAscent + fDescent;
+ } else if (iCharRotation == 2) {
+ pCharPos->m_AdjustMatrix[0] = 1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = -1;
+ pCharPos->m_OriginX += fCharWidth;
+ pCharPos->m_OriginY -= fAscent;
+ } else {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = 1;
+ pCharPos->m_AdjustMatrix[2] = 1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX += fAscent * iVerScale / 100.0f;
+ }
+ }
+ if (iHorScale != 100 || iVerScale != 100) {
+ pCharPos->m_AdjustMatrix[0] = pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f;
+ pCharPos->m_AdjustMatrix[1] = pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f;
+ pCharPos->m_AdjustMatrix[2] = pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f;
+ pCharPos->m_AdjustMatrix[3] = pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f;
+ }
+ pCharPos ++;
+ }
+ }
+ }
+ if (iWidth > 0) {
+ wPrev = wch;
+ }
+ }
+ return iCount;
+}
+FX_INT32 CFX_RTFBreak::GetCharRects(FX_LPCRTFTEXTOBJ pText, CFX_RectFArray &rtArray, FX_BOOL bCharBBox ) const
+{
+ if (pText == NULL || pText->iLength < 1) {
+ return 0;
+ }
+ FXSYS_assert(pText->pStr != NULL && pText->pWidths != NULL && pText->pFont != NULL && pText->pRect != NULL);
+ FX_LPCWSTR pStr = pText->pStr;
+ FX_INT32 *pWidths = pText->pWidths;
+ FX_INT32 iLength = pText->iLength;
+ CFX_RectF rect(*pText->pRect);
+ FX_BOOL bRTLPiece = FX_IsOdd(pText->iBidiLevel);
+ FX_FLOAT fFontSize = pText->fFontSize;
+ FX_INT32 iFontSize = FXSYS_round(fFontSize * 20.0f);
+ FX_FLOAT fScale = fFontSize / 1000.0f;
+ IFX_Font *pFont = pText->pFont;
+ if (pFont == NULL) {
+ bCharBBox = FALSE;
+ }
+ CFX_Rect bbox;
+ bbox.Set(0, 0, 0, 0);
+ if (bCharBBox) {
+ bCharBBox = pFont->GetBBox(bbox);
+ }
+ FX_FLOAT fLeft = FX_MAX(0, bbox.left * fScale);
+ FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale);
+ rtArray.RemoveAll();
+ rtArray.SetSize(iLength);
+ FX_DWORD dwStyles = pText->dwLayoutStyles;
+ FX_BOOL bVertical = (dwStyles & FX_RTFLAYOUTSTYLE_VerticalLayout) != 0;
+ FX_BOOL bMBCSCode = (dwStyles & FX_RTFLAYOUTSTYLE_MBCSCode) != 0;
+ FX_BOOL bSingleLine = (dwStyles & FX_RTFLAYOUTSTYLE_SingleLine) != 0;
+ FX_BOOL bCombText = (dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
+ FX_WCHAR wch, wLineBreakChar = pText->wLineBreakChar;
+ FX_INT32 iCharSize;
+ FX_FLOAT fCharSize, fStart;
+ if (bVertical) {
+ fStart = bRTLPiece ? rect.bottom() : rect.top;
+ } else {
+ fStart = bRTLPiece ? rect.right() : rect.left;
+ }
+ for (FX_INT32 i = 0; i < iLength; i ++) {
+ wch = *pStr ++;
+ iCharSize = *pWidths ++;
+ fCharSize = (FX_FLOAT)iCharSize / 20000.0f;
+ FX_BOOL bRet = (!bSingleLine && FX_IsCtrlCode(wch));
+ if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 || (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) {
+ bRet = FALSE;
+ }
+ if (bRet) {
+ iCharSize = iFontSize * 500;
+ fCharSize = fFontSize / 2.0f;
+ }
+ if (bVertical) {
+ rect.top = fStart;
+ if (bRTLPiece) {
+ rect.top -= fCharSize;
+ fStart -= fCharSize;
+ } else {
+ fStart += fCharSize;
+ }
+ rect.height = fCharSize;
+ } else {
+ rect.left = fStart;
+ if (bRTLPiece) {
+ rect.left -= fCharSize;
+ fStart -= fCharSize;
+ } else {
+ fStart += fCharSize;
+ }
+ rect.width = fCharSize;
+ }
+ if (bCharBBox && !bRet) {
+ FX_INT32 iCharWidth = 1000;
+ pFont->GetCharWidth(wch, iCharWidth);
+ FX_FLOAT fRTLeft = 0, fCharWidth = 0;
+ if (iCharWidth > 0) {
+ fCharWidth = iCharWidth * fScale;
+ fRTLeft = fLeft;
+ if (bCombText) {
+ fRTLeft = (rect.width - fCharWidth) / 2.0f;
+ }
+ }
+ CFX_RectF rtBBoxF;
+ if (bVertical) {
+ rtBBoxF.top = rect.left + fRTLeft;
+ rtBBoxF.left = rect.top + (rect.height - fHeight) / 2.0f;
+ rtBBoxF.height = fCharWidth;
+ rtBBoxF.width = fHeight;
+ rtBBoxF.left = FX_MAX(rtBBoxF.left, 0);
+ } else {
+ rtBBoxF.left = rect.left + fRTLeft;
+ rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f;
+ rtBBoxF.width = fCharWidth;
+ rtBBoxF.height = fHeight;
+ rtBBoxF.top = FX_MAX(rtBBoxF.top, 0);
+ }
+ rtArray.SetAt(i, rtBBoxF);
+ continue;
+ }
+ rtArray.SetAt(i, rect);
+ }
+ return iLength;
+}
diff --git a/xfa/src/fgas/src/layout/fx_rtfbreak.h b/xfa/src/fgas/src/layout/fx_rtfbreak.h
new file mode 100644
index 0000000000..bf5f1ee4b5
--- /dev/null
+++ b/xfa/src/fgas/src/layout/fx_rtfbreak.h
@@ -0,0 +1,180 @@
+// 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 _FX_RTFBREAK_IMP
+#define _FX_RTFBREAK_IMP
+class CFX_RTFLine;
+class CFX_RTFBreak;
+class CFX_RTFLine : public CFX_Object
+{
+public:
+ CFX_RTFLine() : m_LinePieces(16)
+ , m_iStart(0)
+ , m_iWidth(0)
+ , m_iArabicChars(0)
+ , m_iMBCSChars(0)
+ {
+ }
+ ~CFX_RTFLine()
+ {
+ RemoveAll();
+ }
+ FX_INT32 CountChars() const
+ {
+ return m_LineChars.GetSize();
+ }
+ CFX_RTFChar& GetChar(FX_INT32 index)
+ {
+ FXSYS_assert(index > -1 && index < m_LineChars.GetSize());
+ return *m_LineChars.GetDataPtr(index);
+ }
+ CFX_RTFChar* GetCharPtr(FX_INT32 index)
+ {
+ FXSYS_assert(index > -1 && index < m_LineChars.GetSize());
+ return m_LineChars.GetDataPtr(index);
+ }
+ FX_INT32 CountPieces() const
+ {
+ return m_LinePieces.GetSize();
+ }
+ CFX_RTFPiece& GetPiece(FX_INT32 index) const
+ {
+ FXSYS_assert(index > -1 && index < m_LinePieces.GetSize());
+ return m_LinePieces.GetAt(index);
+ }
+ CFX_RTFPiece* GetPiecePtr(FX_INT32 index) const
+ {
+ FXSYS_assert(index > -1 && index < m_LinePieces.GetSize());
+ return m_LinePieces.GetPtrAt(index);
+ }
+ FX_INT32 GetLineEnd() const
+ {
+ return m_iStart + m_iWidth;
+ }
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE)
+ {
+ CFX_RTFChar *pChar;
+ IFX_Unknown *pUnknown;
+ FX_INT32 iCount = m_LineChars.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ pChar = m_LineChars.GetDataPtr(i);
+ if ((pUnknown = pChar->m_pUserData) != NULL) {
+ pUnknown->Release();
+ }
+ }
+ m_LineChars.RemoveAll();
+ m_LinePieces.RemoveAll(bLeaveMemory);
+ m_iWidth = 0;
+ m_iArabicChars = 0;
+ m_iMBCSChars = 0;
+ }
+ CFX_RTFCharArray m_LineChars;
+ CFX_RTFPieceArray m_LinePieces;
+ FX_INT32 m_iStart;
+ FX_INT32 m_iWidth;
+ FX_INT32 m_iArabicChars;
+ FX_INT32 m_iMBCSChars;
+};
+class CFX_RTFBreak : public IFX_RTFBreak, public CFX_Object
+{
+public:
+ CFX_RTFBreak(FX_DWORD dwPolicies);
+ ~CFX_RTFBreak();
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual void SetLineWidth(FX_FLOAT fLineStart, FX_FLOAT fLineEnd);
+ virtual void SetLinePos(FX_FLOAT fLinePos);
+ virtual FX_DWORD GetLayoutStyles() const
+ {
+ return m_dwLayoutStyles;
+ }
+ virtual void SetLayoutStyles(FX_DWORD dwLayoutStyles);
+ virtual void SetFont(IFX_Font *pFont);
+ virtual void SetFontSize(FX_FLOAT fFontSize);
+ virtual void SetTabWidth(FX_FLOAT fTabWidth);
+ virtual void AddPositionedTab(FX_FLOAT fTabPos);
+ virtual void SetPositionedTabs(const CFX_FloatArray &tabs);
+ virtual void ClearPositionedTabs();
+ virtual void SetDefaultChar(FX_WCHAR wch);
+ virtual void SetLineBreakChar(FX_WCHAR wch);
+ virtual void SetLineBreakTolerance(FX_FLOAT fTolerance);
+ virtual void SetHorizontalScale(FX_INT32 iScale);
+ virtual void SetVerticalScale(FX_INT32 iScale);
+ virtual void SetCharRotation(FX_INT32 iCharRotation);
+ virtual void SetCharSpace(FX_FLOAT fCharSpace);
+ virtual void SetWordSpace(FX_BOOL bDefault, FX_FLOAT fWordSpace);
+ virtual void SetReadingOrder(FX_BOOL bRTL = FALSE);
+ virtual void SetAlignment(FX_INT32 iAlignment = FX_RTFLINEALIGNMENT_Left);
+ virtual void SetUserData(IFX_Unknown *pUserData);
+ virtual FX_DWORD AppendChar(FX_WCHAR wch);
+ virtual FX_DWORD EndBreak(FX_DWORD dwStatus = FX_RTFBREAK_PieceBreak);
+ virtual FX_INT32 CountBreakPieces() const;
+ virtual const CFX_RTFPiece* GetBreakPiece(FX_INT32 index) const;
+ virtual void GetLineRect(CFX_RectF &rect) const;
+ virtual void ClearBreakPieces();
+ virtual void Reset();
+ virtual FX_INT32 GetDisplayPos(FX_LPCRTFTEXTOBJ pText, FXTEXT_CHARPOS *pCharPos, FX_BOOL bCharCode = FALSE, CFX_WideString *pWSForms = NULL, FX_AdjustCharDisplayPos pAdjustPos = NULL) const;
+ virtual FX_INT32 GetCharRects(FX_LPCRTFTEXTOBJ pText, CFX_RectFArray &rtArray, FX_BOOL bCharBBox = FALSE) const;
+ FX_DWORD AppendChar_CharCode(FX_WCHAR wch);
+ FX_DWORD AppendChar_Combination(CFX_RTFChar *pCurChar, FX_INT32 iRotation);
+ FX_DWORD AppendChar_Tab(CFX_RTFChar *pCurChar, FX_INT32 iRotation);
+ FX_DWORD AppendChar_Control(CFX_RTFChar *pCurChar, FX_INT32 iRotation);
+ FX_DWORD AppendChar_Arabic(CFX_RTFChar *pCurChar, FX_INT32 iRotation);
+ FX_DWORD AppendChar_Others(CFX_RTFChar *pCurChar, FX_INT32 iRotation);
+protected:
+ FX_DWORD m_dwPolicies;
+ IFX_ArabicChar *m_pArabicChar;
+ FX_INT32 m_iLineStart;
+ FX_INT32 m_iLineEnd;
+ FX_DWORD m_dwLayoutStyles;
+ FX_BOOL m_bPagination;
+ FX_BOOL m_bVertical;
+ FX_BOOL m_bSingleLine;
+ FX_BOOL m_bCharCode;
+ IFX_Font *m_pFont;
+ FX_INT32 m_iFontHeight;
+ FX_INT32 m_iFontSize;
+ FX_INT32 m_iTabWidth;
+ CFX_Int32Array m_PositionedTabs;
+ FX_BOOL m_bOrphanLine;
+ FX_WCHAR m_wDefChar;
+ FX_INT32 m_iDefChar;
+ FX_WCHAR m_wLineBreakChar;
+ FX_INT32 m_iHorizontalScale;
+ FX_INT32 m_iVerticalScale;
+ FX_INT32 m_iLineRotation;
+ FX_INT32 m_iCharRotation;
+ FX_INT32 m_iRotation;
+ FX_INT32 m_iCharSpace;
+ FX_BOOL m_bWordSpace;
+ FX_INT32 m_iWordSpace;
+ FX_BOOL m_bRTL;
+ FX_INT32 m_iAlignment;
+ IFX_Unknown *m_pUserData;
+ FX_DWORD m_dwCharType;
+ FX_DWORD m_dwIdentity;
+ CFX_RTFLine m_RTFLine1;
+ CFX_RTFLine m_RTFLine2;
+ CFX_RTFLine *m_pCurLine;
+ FX_INT32 m_iReady;
+ FX_INT32 m_iTolerance;
+ FX_INT32 GetLineRotation(FX_DWORD dwStyles) const;
+ void SetBreakStatus();
+ CFX_RTFChar* GetLastChar(FX_INT32 index) const;
+ CFX_RTFLine* GetRTFLine(FX_BOOL bReady) const;
+ CFX_RTFPieceArray* GetRTFPieces(FX_BOOL bReady) const;
+ FX_DWORD GetUnifiedCharType(FX_DWORD dwType) const;
+ FX_INT32 GetLastPositionedTab() const;
+ FX_BOOL GetPositionedTab(FX_INT32 &iTabPos) const;
+ FX_INT32 GetBreakPos(CFX_RTFCharArray &tca, FX_INT32 &iEndPos, FX_BOOL bAllChars = FALSE, FX_BOOL bOnlyBrk = FALSE);
+ void SplitTextLine(CFX_RTFLine *pCurLine, CFX_RTFLine *pNextLine, FX_BOOL bAllChars = FALSE);
+ FX_BOOL EndBreak_SplitLine(CFX_RTFLine *pNextLine, FX_BOOL bAllChars, FX_DWORD dwStatus);
+ void EndBreak_BidiLine(CFX_TPOArray &tpos, FX_DWORD dwStatus);
+ void EndBreak_Alignment(CFX_TPOArray &tpos, FX_BOOL bAllChars, FX_DWORD dwStatus);
+};
+#endif
diff --git a/xfa/src/fgas/src/layout/fx_textbreak.cpp b/xfa/src/fgas/src/layout/fx_textbreak.cpp
new file mode 100644
index 0000000000..0bb7b69585
--- /dev/null
+++ b/xfa/src/fgas/src/layout/fx_textbreak.cpp
@@ -0,0 +1,1653 @@
+// 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 "../fgas_base.h"
+#include "fx_unicode.h"
+#include "fx_textbreak.h"
+extern const FX_DWORD gs_FX_TextLayout_CodeProperties[65536];
+extern const FX_WCHAR gs_FX_TextLayout_VerticalMirror[64];
+extern const FX_WCHAR gs_FX_TextLayout_BidiMirror[512];
+extern const FX_LINEBREAKTYPE gs_FX_LineBreak_PairTable[64][32];
+IFX_TxtBreak* IFX_TxtBreak::Create(FX_DWORD dwPolicies)
+{
+ return FX_NEW CFX_TxtBreak(dwPolicies);
+}
+CFX_TxtBreak::CFX_TxtBreak(FX_DWORD dwPolicies)
+ : m_dwPolicies(dwPolicies)
+ , m_pArabicChar(NULL)
+ , m_iLineWidth(2000000)
+ , m_dwLayoutStyles(0)
+ , m_bVertical(FALSE)
+ , m_bArabicContext(FALSE)
+ , m_bArabicShapes(FALSE)
+ , m_bRTL(FALSE)
+ , m_bSingleLine(FALSE)
+ , m_bCombText(FALSE)
+ , m_iArabicContext(1)
+ , m_iCurArabicContext(1)
+ , m_pFont(NULL)
+ , m_iFontSize(240)
+ , m_bEquidistant(TRUE)
+ , m_iTabWidth(720000)
+ , m_wDefChar(0xFEFF)
+ , m_wParagBreakChar(L'\n')
+ , m_iDefChar(0)
+ , m_iLineRotation(0)
+ , m_iCharRotation(0)
+ , m_iRotation(0)
+ , m_iAlignment(FX_TXTLINEALIGNMENT_Left)
+ , m_dwContextCharStyles(0)
+ , m_iCombWidth(360000)
+ , m_pUserData(NULL)
+ , m_dwCharType(0)
+ , m_bArabicNumber(FALSE)
+ , m_bArabicComma(FALSE)
+ , m_pCurLine(NULL)
+ , m_iReady(0)
+ , m_iTolerance(0)
+ , m_iHorScale(100)
+ , m_iVerScale(100)
+ , m_iCharSpace(0)
+{
+ m_bPagination = (m_dwPolicies & FX_TXTBREAKPOLICY_Pagination) != 0;
+ m_pArabicChar = IFX_ArabicChar::Create();
+ if (m_bPagination) {
+ m_pTxtLine1 = FX_NEW CFX_TxtLine(sizeof(CFX_Char));
+ m_pTxtLine2 = FX_NEW CFX_TxtLine(sizeof(CFX_Char));
+ } else {
+ m_pTxtLine1 = FX_NEW CFX_TxtLine(sizeof(CFX_TxtChar));
+ m_pTxtLine2 = FX_NEW CFX_TxtLine(sizeof(CFX_TxtChar));
+ }
+ m_pCurLine = m_pTxtLine1;
+ ResetArabicContext();
+}
+CFX_TxtBreak::~CFX_TxtBreak()
+{
+ Reset();
+ delete m_pTxtLine1;
+ delete m_pTxtLine2;
+ m_pArabicChar->Release();
+}
+void CFX_TxtBreak::SetLineWidth(FX_FLOAT fLineWidth)
+{
+ m_iLineWidth = FXSYS_round(fLineWidth * 20000.0f);
+ FXSYS_assert(m_iLineWidth >= 20000);
+}
+void CFX_TxtBreak::SetLinePos(FX_FLOAT fLinePos)
+{
+ FX_INT32 iLinePos = FXSYS_round(fLinePos * 20000.0f);
+ if (iLinePos < 0) {
+ iLinePos = 0;
+ }
+ if (iLinePos > m_iLineWidth) {
+ iLinePos = m_iLineWidth;
+ }
+ m_pCurLine->m_iStart = iLinePos;
+ m_pCurLine->m_iWidth += iLinePos;
+}
+void CFX_TxtBreak::SetLayoutStyles(FX_DWORD dwLayoutStyles)
+{
+ m_dwLayoutStyles = dwLayoutStyles;
+ m_bVertical = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0;
+ m_bArabicContext = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ArabicContext) != 0;
+ m_bArabicShapes = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ArabicShapes) != 0;
+ m_bRTL = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_RTLReadingOrder) != 0;
+ m_bSingleLine = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
+ m_bCombText = (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
+ ResetArabicContext();
+ m_iLineRotation = GetLineRotation(m_dwLayoutStyles);
+ m_iRotation = m_iLineRotation + m_iCharRotation;
+ m_iRotation %= 4;
+}
+void CFX_TxtBreak::SetFont(IFX_Font *pFont)
+{
+ if (pFont == NULL) {
+ return;
+ }
+ if (m_pFont == pFont) {
+ return;
+ }
+ SetBreakStatus();
+ m_pFont = pFont;
+ m_iDefChar = 0;
+ if (m_wDefChar != 0xFEFF && m_pFont != NULL) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ m_iDefChar *= m_iFontSize;
+ }
+}
+void CFX_TxtBreak::SetFontSize(FX_FLOAT fFontSize)
+{
+ FX_INT32 iFontSize = FXSYS_round(fFontSize * 20.0f);
+ if (m_iFontSize == iFontSize) {
+ return;
+ }
+ SetBreakStatus();
+ m_iFontSize = iFontSize;
+ m_iDefChar = 0;
+ if (m_wDefChar != 0xFEFF && m_pFont != NULL) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ m_iDefChar *= m_iFontSize;
+ }
+}
+void CFX_TxtBreak::SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant)
+{
+ m_iTabWidth = FXSYS_round(fTabWidth * 20000.0f);
+ if (m_iTabWidth < FX_TXTBREAK_MinimumTabWidth) {
+ m_iTabWidth = FX_TXTBREAK_MinimumTabWidth;
+ }
+ m_bEquidistant = bEquidistant;
+}
+void CFX_TxtBreak::SetDefaultChar(FX_WCHAR wch)
+{
+ m_wDefChar = wch;
+ m_iDefChar = 0;
+ if (m_wDefChar != 0xFEFF && m_pFont != NULL) {
+ m_pFont->GetCharWidth(m_wDefChar, m_iDefChar, FALSE);
+ if (m_iDefChar < 0) {
+ m_iDefChar = 0;
+ } else {
+ m_iDefChar *= m_iFontSize;
+ }
+ }
+}
+void CFX_TxtBreak::SetParagraphBreakChar(FX_WCHAR wch)
+{
+ if (wch != L'\r' && wch != L'\n') {
+ return;
+ }
+ m_wParagBreakChar = wch;
+}
+void CFX_TxtBreak::SetLineBreakTolerance(FX_FLOAT fTolerance)
+{
+ m_iTolerance = FXSYS_round(fTolerance * 20000.0f);
+}
+void CFX_TxtBreak::SetCharRotation(FX_INT32 iCharRotation)
+{
+ if (iCharRotation < 0) {
+ iCharRotation += (-iCharRotation / 4 + 1) * 4;
+ } else if (iCharRotation > 3) {
+ iCharRotation -= (iCharRotation / 4) * 4;
+ }
+ if (m_iCharRotation == iCharRotation) {
+ return;
+ }
+ SetBreakStatus();
+ m_iCharRotation = iCharRotation;
+ m_iRotation = m_iLineRotation + m_iCharRotation;
+ m_iRotation %= 4;
+}
+void CFX_TxtBreak::SetAlignment(FX_INT32 iAlignment)
+{
+ FXSYS_assert(iAlignment >= FX_TXTLINEALIGNMENT_Left && iAlignment <= FX_TXTLINEALIGNMENT_Distributed);
+ m_iAlignment = iAlignment;
+ ResetArabicContext();
+}
+void CFX_TxtBreak::ResetContextCharStyles()
+{
+ m_dwContextCharStyles = m_bArabicContext ? m_iCurAlignment : m_iAlignment;
+ if (m_bArabicNumber) {
+ m_dwContextCharStyles |= FX_TXTCHARSTYLE_ArabicNumber;
+ }
+ if (m_bArabicComma) {
+ m_dwContextCharStyles |= FX_TXTCHARSTYLE_ArabicComma;
+ }
+ if ((m_bArabicContext && m_bCurRTL) || (!m_bArabicContext && m_bRTL)) {
+ m_dwContextCharStyles |= FX_TXTCHARSTYLE_RTLReadingOrder;
+ }
+ m_dwContextCharStyles |= (m_iArabicContext << 8);
+}
+FX_DWORD CFX_TxtBreak::GetContextCharStyles() const
+{
+ return m_dwContextCharStyles;
+}
+void CFX_TxtBreak::SetContextCharStyles(FX_DWORD dwCharStyles)
+{
+ m_iCurAlignment = dwCharStyles & 0x0F;
+ m_bArabicNumber = (dwCharStyles & FX_TXTCHARSTYLE_ArabicNumber) != 0;
+ m_bArabicComma = (dwCharStyles & FX_TXTCHARSTYLE_ArabicComma) != 0;
+ m_bCurRTL = (dwCharStyles & FX_TXTCHARSTYLE_RTLReadingOrder) != 0;
+ m_iCurArabicContext = m_iArabicContext = ((dwCharStyles & 0x0300) >> 8);
+ ResetContextCharStyles();
+}
+void CFX_TxtBreak::SetCombWidth(FX_FLOAT fCombWidth)
+{
+ m_iCombWidth = FXSYS_round(fCombWidth * 20000.0f);
+}
+void CFX_TxtBreak::SetUserData(FX_LPVOID pUserData)
+{
+ if (m_pUserData == pUserData) {
+ return;
+ }
+ SetBreakStatus();
+ m_pUserData = pUserData;
+}
+void CFX_TxtBreak::SetBreakStatus()
+{
+ if (m_bPagination) {
+ return;
+ }
+ FX_INT32 iCount = m_pCurLine->CountChars();
+ if (iCount < 1) {
+ return;
+ }
+ CFX_TxtChar *pTC = (CFX_TxtChar*)m_pCurLine->GetCharPtr(iCount - 1);
+ if (pTC->m_dwStatus == 0) {
+ pTC->m_dwStatus = FX_TXTBREAK_PieceBreak;
+ }
+}
+void CFX_TxtBreak::SetHorizontalScale(FX_INT32 iScale)
+{
+ if (iScale < 0) {
+ iScale = 0;
+ }
+ if (iScale == m_iHorScale) {
+ return;
+ }
+ SetBreakStatus();
+ m_iHorScale = iScale;
+}
+void CFX_TxtBreak::SetVerticalScale(FX_INT32 iScale)
+{
+ if (iScale < 0) {
+ iScale = 0;
+ }
+ if (iScale == m_iHorScale) {
+ return;
+ }
+ SetBreakStatus();
+ m_iVerScale = iScale;
+}
+void CFX_TxtBreak::SetCharSpace(FX_FLOAT fCharSpace)
+{
+ m_iCharSpace = FXSYS_round(fCharSpace * 20000.0f);
+}
+static const FX_INT32 gs_FX_TxtLineRotations[8] = {0, 3, 1, 0, 2, 1, 3, 2};
+FX_INT32 CFX_TxtBreak::GetLineRotation(FX_DWORD dwStyles) const
+{
+ return gs_FX_TxtLineRotations[(dwStyles & 0x0E) >> 1];
+}
+CFX_TxtChar* CFX_TxtBreak::GetLastChar(FX_INT32 index, FX_BOOL bOmitChar) const
+{
+ CFX_TxtCharArray &ca = *m_pCurLine->m_pLineChars;
+ FX_INT32 iCount = ca.GetSize();
+ if (index < 0 || index >= iCount) {
+ return NULL;
+ }
+ CFX_TxtChar *pTC;
+ FX_INT32 iStart = iCount - 1;
+ while (iStart > -1) {
+ pTC = ca.GetDataPtr(iStart --);
+ if (bOmitChar && pTC->GetCharType() == FX_CHARTYPE_Combination) {
+ continue;
+ }
+ if (--index < 0) {
+ return pTC;
+ }
+ }
+ return NULL;
+}
+CFX_TxtLine* CFX_TxtBreak::GetTxtLine(FX_BOOL bReady) const
+{
+ if (!bReady) {
+ return m_pCurLine;
+ }
+ if (m_iReady == 1) {
+ return m_pTxtLine1;
+ } else if (m_iReady == 2) {
+ return m_pTxtLine2;
+ } else {
+ return NULL;
+ }
+}
+CFX_TxtPieceArray* CFX_TxtBreak::GetTxtPieces(FX_BOOL bReady) const
+{
+ CFX_TxtLine *pTxtLine = GetTxtLine(bReady);
+ if (pTxtLine == NULL) {
+ return NULL;
+ }
+ return pTxtLine->m_pLinePieces;
+}
+inline FX_DWORD CFX_TxtBreak::GetUnifiedCharType(FX_DWORD dwType) const
+{
+ return dwType >= FX_CHARTYPE_ArabicAlef ? FX_CHARTYPE_Arabic : dwType;
+}
+void CFX_TxtBreak::ResetArabicContext()
+{
+ if (m_bArabicContext) {
+ m_bCurRTL = m_iCurArabicContext > 1;
+ m_iCurAlignment = m_iCurArabicContext > 1 ? FX_TXTLINEALIGNMENT_Right : FX_TXTLINEALIGNMENT_Left;
+ m_iCurAlignment |= (m_iAlignment & FX_TXTLINEALIGNMENT_HigherMask);
+ m_bArabicNumber = m_iArabicContext >= 1 && m_bArabicShapes;
+ } else {
+ if (m_bPagination) {
+ m_bCurRTL = FALSE;
+ m_iCurAlignment = 0;
+ } else {
+ m_bCurRTL = m_bRTL;
+ m_iCurAlignment = m_iAlignment;
+ }
+ if (m_bRTL) {
+ m_bArabicNumber = m_iArabicContext >= 1;
+ } else {
+ m_bArabicNumber = m_iArabicContext > 1;
+ }
+ m_bArabicNumber = m_bArabicNumber && m_bArabicShapes;
+ }
+ m_bArabicComma = m_bArabicNumber;
+ ResetContextCharStyles();
+}
+void CFX_TxtBreak::AppendChar_PageLoad(CFX_Char *pCurChar, FX_DWORD dwProps)
+{
+ if (!m_bPagination) {
+ ((CFX_TxtChar*)pCurChar)->m_dwStatus = 0;
+ ((CFX_TxtChar*)pCurChar)->m_pUserData = m_pUserData;
+ }
+ if (m_bArabicContext || m_bArabicShapes) {
+ FX_INT32 iBidiCls = (dwProps & FX_BIDICLASSBITSMASK) >> FX_BIDICLASSBITS;
+ FX_INT32 iArabicContext = (iBidiCls == FX_BIDICLASS_R || iBidiCls == FX_BIDICLASS_AL) ? 2 : ((iBidiCls == FX_BIDICLASS_L || iBidiCls == FX_BIDICLASS_S) ? 0 : 1);
+ if (iArabicContext != m_iArabicContext && iArabicContext != 1) {
+ m_iArabicContext = iArabicContext;
+ if (m_iCurArabicContext == 1) {
+ m_iCurArabicContext = iArabicContext;
+ }
+ ResetArabicContext();
+ if (!m_bPagination) {
+ CFX_TxtChar *pLastChar = (CFX_TxtChar*)GetLastChar(1, FALSE);
+ if (pLastChar != NULL && pLastChar->m_dwStatus < 1) {
+ pLastChar->m_dwStatus = FX_TXTBREAK_PieceBreak;
+ }
+ }
+ }
+ }
+ pCurChar->m_dwCharStyles = m_dwContextCharStyles;
+}
+FX_DWORD CFX_TxtBreak::AppendChar_Combination(CFX_Char *pCurChar, FX_INT32 iRotation)
+{
+ FXSYS_assert(pCurChar != NULL);
+ FX_WCHAR wch = pCurChar->m_wCharCode;
+ FX_WCHAR wForm;
+ FX_INT32 iCharWidth = 0;
+ CFX_Char *pLastChar;
+ pCurChar->m_iCharWidth = -1;
+ if (m_bCombText) {
+ iCharWidth = m_iCombWidth;
+ } else {
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ wForm = wch;
+ if (!m_bPagination) {
+ pLastChar = GetLastChar(0, FALSE);
+ if (pLastChar != NULL && (((CFX_TxtChar*)pLastChar)->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicShadda) == 0) {
+ FX_BOOL bShadda = FALSE;
+ if (wch == 0x0651) {
+ FX_WCHAR wLast = pLastChar->m_wCharCode;
+ if (wLast >= 0x064C && wLast <= 0x0650) {
+ wForm = FX_GetArabicFromShaddaTable(wLast);
+ bShadda = TRUE;
+ }
+ } else if (wch >= 0x064C && wch <= 0x0650) {
+ if (pLastChar->m_wCharCode == 0x0651) {
+ wForm = FX_GetArabicFromShaddaTable(wch);
+ bShadda = TRUE;
+ }
+ }
+ if (bShadda) {
+ ((CFX_TxtChar*)pLastChar)->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
+ ((CFX_TxtChar*)pLastChar)->m_iCharWidth = 0;
+ ((CFX_TxtChar*)pCurChar)->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicShadda;
+ }
+ }
+ }
+ if (!m_pFont->GetCharWidth(wForm, iCharWidth, FALSE)) {
+ iCharWidth = 0;
+ }
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorScale / 100;
+ }
+ pCurChar->m_iCharWidth = -iCharWidth;
+ return FX_TXTBREAK_None;
+}
+FX_DWORD CFX_TxtBreak::AppendChar_Tab(CFX_Char *pCurChar, FX_INT32 iRotation)
+{
+ m_dwCharType = FX_CHARTYPE_Tab;
+ if ((m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_ExpandTab) == 0) {
+ return FX_TXTBREAK_None;
+ }
+ FX_INT32 &iLineWidth = m_pCurLine->m_iWidth;
+ FX_INT32 iCharWidth;
+ if (m_bCombText) {
+ iCharWidth = m_iCombWidth;
+ } else {
+ if (m_bEquidistant) {
+ iCharWidth = iLineWidth;
+ iCharWidth = m_iTabWidth * (iCharWidth / m_iTabWidth + 1) - iCharWidth;
+ if (iCharWidth < FX_TXTBREAK_MinimumTabWidth) {
+ iCharWidth += m_iTabWidth;
+ }
+ } else {
+ iCharWidth = m_iTabWidth;
+ }
+ }
+ pCurChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ if (!m_bSingleLine && iLineWidth >= m_iLineWidth + m_iTolerance) {
+ return EndBreak(FX_TXTBREAK_LineBreak);
+ }
+ return FX_TXTBREAK_None;
+}
+FX_DWORD CFX_TxtBreak::AppendChar_Control(CFX_Char *pCurChar, FX_INT32 iRotation)
+{
+ m_dwCharType = FX_CHARTYPE_Control;
+ FX_DWORD dwRet = FX_TXTBREAK_None;
+ if (!m_bSingleLine) {
+ FX_WCHAR wch = pCurChar->m_wCharCode;
+ switch (wch) {
+ case L'\v':
+ case 0x2028:
+ dwRet = FX_TXTBREAK_LineBreak;
+ break;
+ case L'\f':
+ dwRet = FX_TXTBREAK_PageBreak;
+ break;
+ case 0x2029:
+ dwRet = FX_TXTBREAK_ParagraphBreak;
+ break;
+ default:
+ if (wch == m_wParagBreakChar) {
+ dwRet = FX_TXTBREAK_ParagraphBreak;
+ }
+ break;
+ }
+ if (dwRet != FX_TXTBREAK_None) {
+ dwRet = EndBreak(dwRet);
+ }
+ }
+ return dwRet;
+}
+FX_DWORD CFX_TxtBreak::AppendChar_Arabic(CFX_Char *pCurChar, FX_INT32 iRotation)
+{
+ FX_DWORD dwType = (pCurChar->m_dwCharProps & FX_CHARTYPEBITSMASK);
+ FX_INT32 &iLineWidth = m_pCurLine->m_iWidth;
+ FX_WCHAR wForm;
+ FX_INT32 iCharWidth = 0;
+ CFX_Char *pLastChar = NULL;
+ FX_BOOL bAlef = FALSE;
+ if (!m_bCombText && m_dwCharType >= FX_CHARTYPE_ArabicAlef && m_dwCharType <= FX_CHARTYPE_ArabicDistortion) {
+ pLastChar = GetLastChar(1);
+ if (pLastChar != NULL) {
+ iCharWidth = pLastChar->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iLineWidth -= iCharWidth;
+ }
+ CFX_Char *pPrevChar = GetLastChar(2);
+ wForm = m_pArabicChar->GetFormChar(pLastChar, pPrevChar, pCurChar);
+ bAlef = (wForm == 0xFEFF && pLastChar->GetCharType() == FX_CHARTYPE_ArabicAlef);
+ FX_INT32 iLastRotation = pLastChar->m_nRotation + m_iLineRotation;
+ if (m_bVertical && (pLastChar->m_dwCharProps & 0x8000) != 0) {
+ iLastRotation ++;
+ }
+ if (m_bVertical != FX_IsOdd(iLastRotation)) {
+ iCharWidth = 1000;
+ } else {
+ m_pFont->GetCharWidth(wForm, iCharWidth, FALSE);
+ }
+ if (wForm == 0xFEFF) {
+ iCharWidth = m_iDefChar;
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorScale / 100;
+ pLastChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ iCharWidth = 0;
+ }
+ }
+ m_dwCharType = dwType;
+ wForm = m_pArabicChar->GetFormChar(pCurChar, bAlef ? NULL : pLastChar, NULL);
+ if (m_bCombText) {
+ iCharWidth = m_iCombWidth;
+ } else {
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else {
+ m_pFont->GetCharWidth(wForm, iCharWidth, FALSE);
+ }
+ if (wForm == 0xFEFF) {
+ iCharWidth = m_iDefChar;
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorScale / 100;
+ }
+ pCurChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ m_pCurLine->m_iArabicChars ++;
+ if (!m_bSingleLine && iLineWidth > m_iLineWidth + m_iTolerance) {
+ return EndBreak(FX_TXTBREAK_LineBreak);
+ }
+ return FX_TXTBREAK_None;
+}
+FX_DWORD CFX_TxtBreak::AppendChar_Others(CFX_Char *pCurChar, FX_INT32 iRotation)
+{
+ FX_DWORD dwProps = pCurChar->m_dwCharProps;
+ FX_DWORD dwType = (dwProps & FX_CHARTYPEBITSMASK);
+ FX_INT32 &iLineWidth = m_pCurLine->m_iWidth;
+ FX_INT32 iCharWidth = 0;
+ m_dwCharType = dwType;
+ FX_WCHAR wch = pCurChar->m_wCharCode;
+ FX_WCHAR wForm = wch;
+ if (dwType == FX_CHARTYPE_Numeric) {
+ if (m_bArabicNumber) {
+ wForm = wch + 0x0630;
+ pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicIndic;
+ }
+ } else if (wch == L',') {
+ if (m_bArabicShapes && m_iCurArabicContext > 0) {
+ wForm = 0x060C;
+ pCurChar->m_dwCharStyles |= FX_TXTCHARSTYLE_ArabicComma;
+ }
+ } else if (m_bCurRTL || m_bVertical) {
+ wForm = FX_GetMirrorChar(wch, dwProps, m_bCurRTL, m_bVertical);
+ }
+ if (m_bCombText) {
+ iCharWidth = m_iCombWidth;
+ } else {
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, FALSE)) {
+ iCharWidth = m_iDefChar;
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorScale / 100;
+ }
+ iCharWidth += m_iCharSpace;
+ pCurChar->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ FX_BOOL bBreak = (dwType != FX_CHARTYPE_Space || (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0);
+ if (!m_bSingleLine && bBreak && iLineWidth > m_iLineWidth + m_iTolerance) {
+ return EndBreak(FX_TXTBREAK_LineBreak);
+ }
+ return FX_TXTBREAK_None;
+}
+typedef FX_DWORD (CFX_TxtBreak::*FX_TxtBreak_LPFAppendChar)(CFX_Char *pCurChar, FX_INT32 iRotation);
+static const FX_TxtBreak_LPFAppendChar g_FX_TxtBreak_lpfAppendChar[16] = {
+ &CFX_TxtBreak::AppendChar_Others,
+ &CFX_TxtBreak::AppendChar_Tab,
+ &CFX_TxtBreak::AppendChar_Others,
+ &CFX_TxtBreak::AppendChar_Control,
+ &CFX_TxtBreak::AppendChar_Combination,
+ &CFX_TxtBreak::AppendChar_Others,
+ &CFX_TxtBreak::AppendChar_Others,
+ &CFX_TxtBreak::AppendChar_Arabic,
+ &CFX_TxtBreak::AppendChar_Arabic,
+ &CFX_TxtBreak::AppendChar_Arabic,
+ &CFX_TxtBreak::AppendChar_Arabic,
+ &CFX_TxtBreak::AppendChar_Arabic,
+ &CFX_TxtBreak::AppendChar_Arabic,
+ &CFX_TxtBreak::AppendChar_Others,
+ &CFX_TxtBreak::AppendChar_Others,
+ &CFX_TxtBreak::AppendChar_Others,
+};
+FX_DWORD CFX_TxtBreak::AppendChar(FX_WCHAR wch)
+{
+ FX_DWORD dwProps = gs_FX_TextLayout_CodeProperties[(FX_WORD)wch];
+ FX_DWORD dwType = (dwProps & FX_CHARTYPEBITSMASK);
+ CFX_TxtChar *pCurChar = m_pCurLine->m_pLineChars->AddSpace();
+ pCurChar->m_wCharCode = (FX_WORD)wch;
+ pCurChar->m_nRotation = m_iCharRotation;
+ pCurChar->m_dwCharProps = dwProps;
+ pCurChar->m_dwCharStyles = 0;
+ pCurChar->m_iCharWidth = 0;
+ pCurChar->m_iHorizontalScale = m_iHorScale;
+ pCurChar->m_iVertialScale = m_iVerScale;
+ pCurChar->m_dwStatus = 0;
+ pCurChar->m_iBidiClass = 0;
+ pCurChar->m_iBidiLevel = 0;
+ pCurChar->m_iBidiPos = 0;
+ pCurChar->m_iBidiOrder = 0;
+ pCurChar->m_pUserData = NULL;
+ AppendChar_PageLoad(pCurChar, dwProps);
+ FX_DWORD dwRet1 = FX_TXTBREAK_None;
+ if (dwType != FX_CHARTYPE_Combination && GetUnifiedCharType(m_dwCharType) != GetUnifiedCharType(dwType)) {
+ if (m_dwCharType > 0 && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance && !m_bSingleLine) {
+ if (m_dwCharType != FX_CHARTYPE_Space || dwType != FX_CHARTYPE_Control) {
+ dwRet1 = EndBreak(FX_TXTBREAK_LineBreak);
+ FX_INT32 iCount = m_pCurLine->CountChars();
+ if (iCount > 0) {
+ pCurChar = m_pCurLine->m_pLineChars->GetDataPtr(iCount - 1);
+ }
+ }
+ }
+ }
+ FX_INT32 iRotation = m_iRotation;
+ if (m_bVertical && (dwProps & 0x8000) != 0) {
+ iRotation = (iRotation + 1) % 4;
+ }
+ FX_DWORD dwRet2 = (this->*g_FX_TxtBreak_lpfAppendChar[dwType >> FX_CHARTYPEBITS])(pCurChar, iRotation);
+ return FX_MAX(dwRet1, dwRet2);
+}
+void CFX_TxtBreak::EndBreak_UpdateArabicShapes()
+{
+ FXSYS_assert(m_bArabicShapes);
+ FX_INT32 iCount = m_pCurLine->CountChars();
+ if (iCount < 2) {
+ return;
+ }
+ FX_INT32 &iLineWidth = m_pCurLine->m_iWidth;
+ CFX_Char *pCur, *pNext;
+ pCur = m_pCurLine->GetCharPtr(0);
+ FX_BOOL bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
+ pCur = m_pCurLine->GetCharPtr(1);
+ FX_WCHAR wch, wForm;
+ FX_BOOL bNextNum;
+ FX_INT32 i = 1, iCharWidth, iRotation;
+ do {
+ i ++;
+ if (i < iCount) {
+ pNext = m_pCurLine->GetCharPtr(i);
+ bNextNum = (pNext->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
+ } else {
+ pNext = NULL;
+ bNextNum = FALSE;
+ }
+ wch = pCur->m_wCharCode;
+ if (wch == L'.') {
+ if (bPrevNum && bNextNum) {
+ iRotation = m_iRotation;
+ if (m_bVertical && (pCur->m_dwCharProps & 0x8000) != 0) {
+ iRotation = ((iRotation + 1) & 0x03);
+ }
+ wForm = wch == L'.' ? 0x066B : 0x066C;
+ iLineWidth -= pCur->m_iCharWidth;
+ if (m_bCombText) {
+ iCharWidth = m_iCombWidth;
+ } else {
+ if (m_bVertical != FX_IsOdd(iRotation)) {
+ iCharWidth = 1000;
+ } else if (!m_pFont->GetCharWidth(wForm, iCharWidth, FALSE)) {
+ iCharWidth = m_iDefChar;
+ }
+ iCharWidth *= m_iFontSize;
+ iCharWidth = iCharWidth * m_iHorScale / 100;
+ }
+ pCur->m_iCharWidth = iCharWidth;
+ iLineWidth += iCharWidth;
+ }
+ }
+ bPrevNum = (pCur->m_dwCharStyles & FX_TXTCHARSTYLE_ArabicIndic) != 0;
+ pCur = pNext;
+ } while (i < iCount);
+}
+FX_BOOL CFX_TxtBreak::EndBreak_SplitLine(CFX_TxtLine *pNextLine, FX_BOOL bAllChars, FX_DWORD dwStatus)
+{
+ FX_INT32 iCount = m_pCurLine->CountChars();
+ FX_BOOL bDone = FALSE;
+ CFX_Char *pTC;
+ if (!m_bSingleLine && m_pCurLine->m_iWidth > m_iLineWidth + m_iTolerance) {
+ pTC = m_pCurLine->GetCharPtr(iCount - 1);
+ switch (pTC->GetCharType()) {
+ case FX_CHARTYPE_Tab:
+ case FX_CHARTYPE_Control:
+ break;
+ case FX_CHARTYPE_Space:
+ if ((m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0) {
+ SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
+ bDone = TRUE;
+ }
+ break;
+ default:
+ SplitTextLine(m_pCurLine, pNextLine, !m_bPagination && bAllChars);
+ bDone = TRUE;
+ break;
+ }
+ }
+ iCount = m_pCurLine->CountChars();
+ CFX_TxtPieceArray *pCurPieces = m_pCurLine->m_pLinePieces;
+ CFX_TxtPiece tp;
+ if (m_bPagination) {
+ tp.m_dwStatus = dwStatus;
+ tp.m_iStartPos = m_pCurLine->m_iStart;
+ tp.m_iWidth = m_pCurLine->m_iWidth;
+ tp.m_iStartChar = 0;
+ tp.m_iChars = iCount;
+ tp.m_pChars = m_pCurLine->m_pLineChars;
+ tp.m_pUserData = m_pUserData;
+ pTC = m_pCurLine->GetCharPtr(0);
+ tp.m_dwCharStyles = pTC->m_dwCharStyles;
+ tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
+ tp.m_iVerticalScale = pTC->m_iVertialScale;
+ pCurPieces->Add(tp);
+ m_pCurLine = pNextLine;
+ m_dwCharType = 0;
+ return TRUE;
+ }
+ if (bAllChars && !bDone) {
+ FX_INT32 iEndPos = m_pCurLine->m_iWidth;
+ GetBreakPos(*m_pCurLine->m_pLineChars, iEndPos, bAllChars, TRUE);
+ }
+ return FALSE;
+}
+void CFX_TxtBreak::EndBreak_BidiLine(CFX_TPOArray &tpos, FX_DWORD dwStatus)
+{
+ CFX_TxtPiece tp;
+ FX_TPO tpo;
+ CFX_TxtChar *pTC;
+ FX_INT32 i, j;
+ CFX_TxtCharArray &chars = *m_pCurLine->m_pLineChars;
+ FX_INT32 iCount = m_pCurLine->CountChars();
+ FX_BOOL bDone = (m_pCurLine->m_iArabicChars > 0 || m_bCurRTL);
+ if (!m_bPagination && bDone) {
+ FX_INT32 iBidiNum = 0;
+ for (i = 0; i < iCount; i ++) {
+ pTC = chars.GetDataPtr(i);
+ pTC->m_iBidiPos = i;
+ if (pTC->GetCharType() != FX_CHARTYPE_Control) {
+ iBidiNum = i;
+ }
+ if (i == 0) {
+ pTC->m_iBidiLevel = 1;
+ }
+ }
+ FX_BidiLine(chars, iBidiNum + 1, m_bCurRTL ? 1 : 0);
+ }
+ CFX_TxtPieceArray *pCurPieces = m_pCurLine->m_pLinePieces;
+ if (!m_bPagination && (bDone || (m_dwLayoutStyles & FX_TXTLAYOUTSTYLE_MutipleFormat) != 0)) {
+ tp.m_dwStatus = FX_TXTBREAK_PieceBreak;
+ tp.m_iStartPos = m_pCurLine->m_iStart;
+ tp.m_pChars = m_pCurLine->m_pLineChars;
+ FX_INT32 iBidiLevel = -1, iCharWidth;
+ i = 0, j = -1;
+ while (i < iCount) {
+ pTC = chars.GetDataPtr(i);
+ if (iBidiLevel < 0) {
+ iBidiLevel = pTC->m_iBidiLevel;
+ tp.m_iWidth = 0;
+ tp.m_iBidiLevel = iBidiLevel;
+ tp.m_iBidiPos = pTC->m_iBidiOrder;
+ tp.m_dwCharStyles = pTC->m_dwCharStyles;
+ tp.m_pUserData = pTC->m_pUserData;
+ tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
+ tp.m_iVerticalScale = pTC->m_iVertialScale;
+ tp.m_dwStatus = FX_TXTBREAK_PieceBreak;
+ }
+ if (iBidiLevel != pTC->m_iBidiLevel || pTC->m_dwStatus != 0) {
+ if (iBidiLevel == pTC->m_iBidiLevel) {
+ tp.m_dwStatus = pTC->m_dwStatus;
+ iCharWidth = pTC->m_iCharWidth;
+ if (iCharWidth > 0) {
+ tp.m_iWidth += iCharWidth;
+ }
+ i ++;
+ }
+ tp.m_iChars = i - tp.m_iStartChar;
+ pCurPieces->Add(tp);
+ tp.m_iStartPos += tp.m_iWidth;
+ tp.m_iStartChar = i;
+ tpo.index = ++ j;
+ tpo.pos = tp.m_iBidiPos;
+ tpos.Add(tpo);
+ iBidiLevel = -1;
+ } else {
+ iCharWidth = pTC->m_iCharWidth;
+ if (iCharWidth > 0) {
+ tp.m_iWidth += iCharWidth;
+ }
+ i ++;
+ }
+ }
+ if (i > tp.m_iStartChar) {
+ tp.m_dwStatus = dwStatus;
+ tp.m_iChars = i - tp.m_iStartChar;
+ pCurPieces->Add(tp);
+ tpo.index = ++ j;
+ tpo.pos = tp.m_iBidiPos;
+ tpos.Add(tpo);
+ }
+ if (j > -1) {
+ if (j > 0) {
+ FX_TEXTLAYOUT_PieceSort(tpos, 0, j);
+ FX_INT32 iStartPos = 0;
+ for (i = 0; i <= j; i ++) {
+ tpo = tpos.GetAt(i);
+ CFX_TxtPiece &ttp = pCurPieces->GetAt(tpo.index);
+ ttp.m_iStartPos = iStartPos;
+ iStartPos += ttp.m_iWidth;
+ }
+ }
+ CFX_TxtPiece &ttp = pCurPieces->GetAt(j);
+ ttp.m_dwStatus = dwStatus;
+ }
+ } else {
+ tp.m_dwStatus = dwStatus;
+ tp.m_iStartPos = m_pCurLine->m_iStart;
+ tp.m_iWidth = m_pCurLine->m_iWidth;
+ tp.m_iStartChar = 0;
+ tp.m_iChars = iCount;
+ tp.m_pChars = m_pCurLine->m_pLineChars;
+ tp.m_pUserData = m_pUserData;
+ pTC = chars.GetDataPtr(0);
+ tp.m_dwCharStyles = pTC->m_dwCharStyles;
+ tp.m_iHorizontalScale = pTC->m_iHorizontalScale;
+ tp.m_iVerticalScale = pTC->m_iVertialScale;
+ pCurPieces->Add(tp);
+ tpo.index = 0;
+ tpo.pos = 0;
+ tpos.Add(tpo);
+ }
+}
+void CFX_TxtBreak::EndBreak_Alignment(CFX_TPOArray &tpos, FX_BOOL bAllChars, FX_DWORD dwStatus)
+{
+ FX_INT32 iNetWidth = m_pCurLine->m_iWidth, iGapChars = 0, iCharWidth;
+ CFX_TxtPieceArray *pCurPieces = m_pCurLine->m_pLinePieces;
+ FX_INT32 i, j, iCount = pCurPieces->GetSize();
+ FX_BOOL bFind = FALSE;
+ FX_TPO tpo;
+ CFX_TxtChar *pTC;
+ FX_DWORD dwCharType;
+ for (i = iCount - 1; i > -1; i --) {
+ tpo = tpos.GetAt(i);
+ CFX_TxtPiece &ttp = pCurPieces->GetAt(tpo.index);
+ if (!bFind) {
+ iNetWidth = ttp.GetEndPos();
+ }
+ FX_BOOL bArabic = FX_IsOdd(ttp.m_iBidiLevel);
+ j = bArabic ? 0 : ttp.m_iChars - 1;
+ while (j > -1 && j < ttp.m_iChars) {
+ pTC = ttp.GetCharPtr(j);
+ if (pTC->m_nBreakType == FX_LBT_DIRECT_BRK) {
+ iGapChars ++;
+ }
+ if (!bFind || !bAllChars) {
+ dwCharType = pTC->GetCharType();
+ if (dwCharType == FX_CHARTYPE_Space || dwCharType == FX_CHARTYPE_Control) {
+ if (!bFind) {
+ iCharWidth = pTC->m_iCharWidth;
+ if (bAllChars && iCharWidth > 0) {
+ iNetWidth -= iCharWidth;
+ }
+ }
+ } else {
+ bFind = TRUE;
+ if (!bAllChars) {
+ break;
+ }
+ }
+ }
+ j += bArabic ? 1 : -1;
+ }
+ if (!bAllChars && bFind) {
+ break;
+ }
+ }
+ FX_INT32 iOffset = m_iLineWidth - iNetWidth;
+ FX_INT32 iLowerAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_LowerMask);
+ FX_INT32 iHigherAlignment = (m_iCurAlignment & FX_TXTLINEALIGNMENT_HigherMask);
+ if (iGapChars > 0 && (iHigherAlignment == FX_TXTLINEALIGNMENT_Distributed || (iHigherAlignment == FX_TXTLINEALIGNMENT_Justified && dwStatus != FX_TXTBREAK_ParagraphBreak))) {
+ FX_INT32 iStart = -1;
+ for (i = 0; i < iCount; i ++) {
+ tpo = tpos.GetAt(i);
+ CFX_TxtPiece &ttp = pCurPieces->GetAt(tpo.index);
+ if (iStart < -1) {
+ iStart = ttp.m_iStartPos;
+ } else {
+ ttp.m_iStartPos = iStart;
+ }
+ FX_INT32 k;
+ for (j = 0; j < ttp.m_iChars; j ++) {
+ pTC = ttp.GetCharPtr(j);
+ if (pTC->m_nBreakType != FX_LBT_DIRECT_BRK || pTC->m_iCharWidth < 0) {
+ continue;
+ }
+ k = iOffset / iGapChars;
+ pTC->m_iCharWidth += k;
+ ttp.m_iWidth += k;
+ iOffset -= k;
+ iGapChars --;
+ if (iGapChars < 1) {
+ break;
+ }
+ }
+ iStart += ttp.m_iWidth;
+ }
+ } else if (iLowerAlignment > FX_TXTLINEALIGNMENT_Left) {
+ if (iLowerAlignment == FX_TXTLINEALIGNMENT_Center) {
+ iOffset /= 2;
+ }
+ if (iOffset > 0) {
+ for (i = 0; i < iCount; i ++) {
+ CFX_TxtPiece &ttp = pCurPieces->GetAt(i);
+ ttp.m_iStartPos += iOffset;
+ }
+ }
+ }
+}
+FX_DWORD CFX_TxtBreak::EndBreak(FX_DWORD dwStatus)
+{
+ FXSYS_assert(dwStatus >= FX_TXTBREAK_PieceBreak && dwStatus <= FX_TXTBREAK_PageBreak);
+ CFX_TxtPieceArray *pCurPieces = m_pCurLine->m_pLinePieces;
+ FX_INT32 iCount = pCurPieces->GetSize();
+ if (iCount > 0) {
+ CFX_TxtPiece *pLastPiece = pCurPieces->GetPtrAt(-- iCount);
+ if (dwStatus > FX_TXTBREAK_PieceBreak) {
+ pLastPiece->m_dwStatus = dwStatus;
+ } else {
+ dwStatus = pLastPiece->m_dwStatus;
+ }
+ return dwStatus;
+ } else {
+ CFX_TxtLine *pLastLine = GetTxtLine(TRUE);
+ if (pLastLine != NULL) {
+ pCurPieces = pLastLine->m_pLinePieces;
+ iCount = pCurPieces->GetSize();
+ if (iCount -- > 0) {
+ CFX_TxtPiece *pLastPiece = pCurPieces->GetPtrAt(iCount);
+ if (dwStatus > FX_TXTBREAK_PieceBreak) {
+ pLastPiece->m_dwStatus = dwStatus;
+ } else {
+ dwStatus = pLastPiece->m_dwStatus;
+ }
+ return dwStatus;
+ }
+ return FX_TXTBREAK_None;
+ }
+ iCount = m_pCurLine->CountChars();
+ if (iCount < 1) {
+ return FX_TXTBREAK_None;
+ }
+ if (!m_bPagination) {
+ CFX_TxtChar *pTC = m_pCurLine->GetCharPtr(iCount - 1);
+ pTC->m_dwStatus = dwStatus;
+ }
+ if (dwStatus <= FX_TXTBREAK_PieceBreak) {
+ return dwStatus;
+ }
+ }
+ m_iReady = (m_pCurLine == m_pTxtLine1) ? 1 : 2;
+ CFX_TxtLine *pNextLine = (m_pCurLine == m_pTxtLine1) ? m_pTxtLine2 : m_pTxtLine1;
+ FX_BOOL bAllChars = (m_iCurAlignment > FX_TXTLINEALIGNMENT_Right);
+ CFX_TPOArray tpos;
+ CFX_Char *pTC;
+ if (m_bArabicShapes) {
+ EndBreak_UpdateArabicShapes();
+ }
+ if (EndBreak_SplitLine(pNextLine, bAllChars, dwStatus)) {
+ goto EndBreak_Ret;
+ }
+ EndBreak_BidiLine(tpos, dwStatus);
+ if (!m_bPagination && m_iCurAlignment > FX_TXTLINEALIGNMENT_Left) {
+ EndBreak_Alignment(tpos, bAllChars, dwStatus);
+ }
+EndBreak_Ret:
+ m_pCurLine = pNextLine;
+ pTC = GetLastChar(0, FALSE);
+ m_dwCharType = pTC == NULL ? 0 : pTC->GetCharType();
+ if (dwStatus == FX_TXTBREAK_ParagraphBreak) {
+ m_iArabicContext = m_iCurArabicContext = 1;
+ ResetArabicContext();
+ }
+ return dwStatus;
+}
+FX_INT32 CFX_TxtBreak::GetBreakPos(CFX_TxtCharArray &ca, FX_INT32 &iEndPos, FX_BOOL bAllChars, FX_BOOL bOnlyBrk)
+{
+ FX_INT32 iLength = ca.GetSize() - 1;
+ if (iLength < 1) {
+ return iLength;
+ }
+ FX_INT32 iBreak = -1, iBreakPos = -1, iIndirect = -1, iIndirectPos = -1, iLast = -1, iLastPos = -1;
+ if (m_bSingleLine || iEndPos <= m_iLineWidth) {
+ if (!bAllChars) {
+ return iLength;
+ }
+ iBreak = iLength;
+ iBreakPos = iEndPos;
+ }
+ FX_BOOL bSpaceBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_SpaceBreak) != 0;
+ FX_BOOL bNumberBreak = (m_dwPolicies & FX_TXTBREAKPOLICY_NumberBreak) != 0;
+ FX_LINEBREAKTYPE eType;
+ FX_DWORD nCodeProp, nCur, nNext;
+ CFX_Char *pCur = ca.GetDataPtr(iLength --);
+ if (bAllChars) {
+ pCur->m_nBreakType = FX_LBT_UNKNOWN;
+ }
+ nCodeProp = pCur->m_dwCharProps;
+ nNext = nCodeProp & 0x003F;
+ FX_INT32 iCharWidth = pCur->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iEndPos -= iCharWidth;
+ }
+ while (iLength >= 0) {
+ pCur = ca.GetDataPtr(iLength);
+ nCodeProp = pCur->m_dwCharProps;
+ nCur = nCodeProp & 0x003F;
+ if (nCur == FX_CBP_SP) {
+ if (nNext == FX_CBP_SP) {
+ eType = bSpaceBreak ? FX_LBT_DIRECT_BRK : FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE *)gs_FX_LineBreak_PairTable + (nCur << 5) + nNext);
+ }
+ } else if (bNumberBreak && nCur == FX_CBP_NU && nNext == FX_CBP_NU) {
+ eType = FX_LBT_DIRECT_BRK;
+ } else {
+ if (nNext == FX_CBP_SP) {
+ eType = FX_LBT_PROHIBITED_BRK;
+ } else {
+ eType = *((const FX_LINEBREAKTYPE *)gs_FX_LineBreak_PairTable + (nCur << 5) + nNext);
+ }
+ }
+ if (bAllChars) {
+ pCur->m_nBreakType = (FX_BYTE)eType;
+ }
+ if (!bOnlyBrk) {
+ if (m_bSingleLine || iEndPos <= m_iLineWidth || (nCur == FX_CBP_SP && !bSpaceBreak)) {
+ if (eType == FX_LBT_DIRECT_BRK && iBreak < 0) {
+ iBreak = iLength;
+ iBreakPos = iEndPos;
+ if (!bAllChars) {
+ return iLength;
+ }
+ } else if (eType == FX_LBT_INDIRECT_BRK && iIndirect < 0) {
+ iIndirect = iLength;
+ iIndirectPos = iEndPos;
+ }
+ if (iLast < 0) {
+ iLast = iLength;
+ iLastPos = iEndPos;
+ }
+ }
+ iCharWidth = pCur->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iEndPos -= iCharWidth;
+ }
+ }
+ nNext = nCodeProp & 0x003F;
+ iLength --;
+ }
+ if (bOnlyBrk) {
+ return 0;
+ }
+ if (iBreak > -1) {
+ iEndPos = iBreakPos;
+ return iBreak;
+ }
+ if (iIndirect > -1) {
+ iEndPos = iIndirectPos;
+ return iIndirect;
+ }
+ if (iLast > -1) {
+ iEndPos = iLastPos;
+ return iLast;
+ }
+ return 0;
+}
+void CFX_TxtBreak::SplitTextLine(CFX_TxtLine *pCurLine, CFX_TxtLine *pNextLine, FX_BOOL bAllChars)
+{
+ FXSYS_assert(pCurLine != NULL && pNextLine != NULL);
+ FX_INT32 iCount = pCurLine->CountChars();
+ if (iCount < 2) {
+ return;
+ }
+ FX_INT32 iEndPos = pCurLine->m_iWidth;
+ CFX_TxtCharArray &curChars = *pCurLine->m_pLineChars;
+ FX_INT32 iCharPos = GetBreakPos(curChars, iEndPos, bAllChars, FALSE);
+ if (iCharPos < 0) {
+ iCharPos = 0;
+ }
+ iCharPos ++;
+ if (iCharPos >= iCount) {
+ pNextLine->RemoveAll(TRUE);
+ CFX_Char *pTC = curChars.GetDataPtr(iCharPos - 1);
+ pTC->m_nBreakType = FX_LBT_UNKNOWN;
+ return;
+ }
+ CFX_TxtCharArray &nextChars = *pNextLine->m_pLineChars;
+ int cur_size = curChars.GetSize();
+ nextChars.SetSize(cur_size - iCharPos);
+ FXSYS_memcpy(nextChars.GetData(), curChars.GetDataPtr(iCharPos), (cur_size - iCharPos) * sizeof(CFX_TxtChar));
+ iCount -= iCharPos;
+ cur_size = curChars.GetSize();
+ curChars.RemoveAt(cur_size - iCount, iCount);
+ pCurLine->m_iWidth = iEndPos;
+ CFX_TxtChar *pTC = curChars.GetDataPtr(iCharPos - 1);
+ pTC->m_nBreakType = FX_LBT_UNKNOWN;
+ iCount = nextChars.GetSize();
+ FX_INT32 iCharWidth, iWidth = 0;
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ pTC = nextChars.GetDataPtr(i);
+ if (pTC->GetCharType() >= FX_CHARTYPE_ArabicAlef) {
+ pCurLine->m_iArabicChars --;
+ pNextLine->m_iArabicChars ++;
+ }
+ iCharWidth = pTC->m_iCharWidth;
+ if (iCharWidth > 0) {
+ iWidth += iCharWidth;
+ }
+ if (m_bPagination) {
+ continue;
+ }
+ pTC->m_dwStatus = 0;
+ }
+ pNextLine->m_iWidth = iWidth;
+}
+FX_INT32 CFX_TxtBreak::CountBreakChars() const
+{
+ CFX_TxtLine *pTxtLine = GetTxtLine(TRUE);
+ return pTxtLine == NULL ? 0 : pTxtLine->CountChars();
+}
+FX_INT32 CFX_TxtBreak::CountBreakPieces() const
+{
+ CFX_TxtPieceArray *pTxtPieces = GetTxtPieces(TRUE);
+ if (pTxtPieces == NULL) {
+ return 0;
+ }
+ return pTxtPieces->GetSize();
+}
+const CFX_TxtPiece* CFX_TxtBreak::GetBreakPiece(FX_INT32 index) const
+{
+ CFX_TxtPieceArray *pTxtPieces = GetTxtPieces(TRUE);
+ if (pTxtPieces == NULL) {
+ return NULL;
+ }
+ if (index < 0 || index >= pTxtPieces->GetSize()) {
+ return NULL;
+ }
+ return pTxtPieces->GetPtrAt(index);
+}
+void CFX_TxtBreak::ClearBreakPieces()
+{
+ CFX_TxtLine *pTxtLine = GetTxtLine(TRUE);
+ if (pTxtLine != NULL) {
+ pTxtLine->RemoveAll(TRUE);
+ }
+ m_iReady = 0;
+}
+void CFX_TxtBreak::Reset()
+{
+ m_dwCharType = 0;
+ m_iArabicContext = m_iCurArabicContext = 1;
+ ResetArabicContext();
+ m_pTxtLine1->RemoveAll(TRUE);
+ m_pTxtLine2->RemoveAll(TRUE);
+}
+typedef struct _FX_FORMCHAR {
+ FX_WORD wch;
+ FX_WORD wForm;
+ FX_INT32 iWidth;
+} FX_FORMCHAR, * FX_LPFORMCHAR;
+typedef FX_FORMCHAR const * FX_LPCFORMCHAR;
+FX_INT32 CFX_TxtBreak::GetDisplayPos(FX_LPCTXTRUN pTxtRun, FXTEXT_CHARPOS *pCharPos, FX_BOOL bCharCode , CFX_WideString *pWSForms , FX_AdjustCharDisplayPos pAdjustPos ) const
+{
+ if (pTxtRun == NULL || pTxtRun->iLength < 1) {
+ return 0;
+ }
+ IFX_TxtAccess *pAccess = pTxtRun->pAccess;
+ FX_LPVOID pIdentity = pTxtRun->pIdentity;
+ FX_LPCWSTR pStr = pTxtRun->pStr;
+ FX_INT32 *pWidths = pTxtRun->pWidths;
+ FX_INT32 iLength = pTxtRun->iLength - 1;
+ IFX_Font *pFont = pTxtRun->pFont;
+ FX_DWORD dwStyles = pTxtRun->dwStyles;
+ CFX_RectF rtText(*pTxtRun->pRect);
+ FX_BOOL bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
+ FX_BOOL bArabicNumber = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicNumber) != 0;
+ FX_BOOL bArabicComma = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_ArabicComma) != 0;
+ FX_FLOAT fFontSize = pTxtRun->fFontSize;
+ FX_INT32 iFontSize = FXSYS_round(fFontSize * 20.0f);
+ FX_INT32 iAscent = pFont->GetAscent();
+ FX_INT32 iDescent = pFont->GetDescent();
+ FX_INT32 iMaxHeight = iAscent - iDescent;
+ FX_FLOAT fFontHeight = fFontSize;
+ FX_FLOAT fAscent = fFontHeight * (FX_FLOAT)iAscent / (FX_FLOAT)iMaxHeight;
+ FX_FLOAT fDescent = fFontHeight * (FX_FLOAT)iDescent / (FX_FLOAT)iMaxHeight;
+ FX_BOOL bVerticalDoc = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0;
+ FX_BOOL bVerticalChar = (dwStyles & FX_TXTLAYOUTSTYLE_VerticalChars) != 0;
+ FX_INT32 iRotation = GetLineRotation(dwStyles) + pTxtRun->iCharRotation;
+ FX_INT32 iCharRotation;
+ FX_WCHAR wch, wPrev = 0xFEFF, wNext, wForm, wLast = 0xFEFF;
+ FX_INT32 iWidth, iCharWidth, iCharHeight;
+ FX_FLOAT fX, fY, fCharWidth, fCharHeight;
+ FX_INT32 iHorScale = pTxtRun->iHorizontalScale;
+ FX_INT32 iVerScale = pTxtRun->iVerticalScale;
+ FX_BOOL bSkipSpace = pTxtRun->bSkipSpace;
+ FX_BOOL bEmptyChar, bShadda = FALSE, bLam = FALSE;
+ FX_DWORD dwProps, dwCharType;
+ FX_FORMCHAR formChars[3];
+ FX_FLOAT fYBase;
+ fX = rtText.left;
+ if (bVerticalDoc) {
+ fX += (rtText.width - fFontSize) / 2.0f;
+ fYBase = bRTLPiece ? rtText.bottom() : rtText.top;
+ fY = fYBase;
+ } else {
+ if (bRTLPiece) {
+ fX = rtText.right();
+ }
+ fYBase = rtText.top + (rtText.height - fFontSize) / 2.0f;
+ fY = fYBase + fAscent;
+ }
+ FX_INT32 iCount = 0, iNext, iForms;
+ for (FX_INT32 i = 0; i <= iLength; i ++) {
+ if (pAccess != NULL) {
+ wch = pAccess->GetChar(pIdentity, i);
+ iWidth = pAccess->GetWidth(pIdentity, i);
+ } else {
+ wch = *pStr ++;
+ iWidth = *pWidths ++;
+ }
+ dwProps = FX_GetUnicodeProperties(wch);
+ dwCharType = (dwProps & FX_CHARTYPEBITSMASK);
+ if (dwCharType == FX_CHARTYPE_ArabicAlef && iWidth == 0) {
+ wPrev = 0xFEFF;
+ wLast = wch;
+ continue;
+ }
+ if (dwCharType >= FX_CHARTYPE_ArabicAlef) {
+ if (i < iLength) {
+ if (pAccess != NULL) {
+ iNext = i + 1;
+ while (iNext <= iLength) {
+ wNext = pAccess->GetChar(pIdentity, iNext);
+ dwProps = FX_GetUnicodeProperties(wNext);
+ if ((dwProps & FX_CHARTYPEBITSMASK) != FX_CHARTYPE_Combination) {
+ break;
+ }
+ iNext ++;
+ }
+ if (iNext > iLength) {
+ wNext = 0xFEFF;
+ }
+ } else {
+ FX_INT32 j = -1;
+ do {
+ j ++;
+ if (i + j >= iLength) {
+ break;
+ }
+ wNext = pStr[j];
+ dwProps = FX_GetUnicodeProperties(wNext);
+ } while ((dwProps & FX_CHARTYPEBITSMASK) == FX_CHARTYPE_Combination);
+ if (i + j >= iLength) {
+ wNext = 0xFEFF;
+ }
+ }
+ } else {
+ wNext = 0xFEFF;
+ }
+ wForm = m_pArabicChar->GetFormChar(wch, wPrev, wNext);
+ bLam = (wPrev == 0x0644 && wch == 0x0644 && wNext == 0x0647);
+ } else if (dwCharType == FX_CHARTYPE_Combination) {
+ wForm = wch;
+ if (wch >= 0x064C && wch <= 0x0651) {
+ if (bShadda) {
+ wForm = 0xFEFF;
+ bShadda = FALSE;
+ } else {
+ wNext = 0xFEFF;
+ if (pAccess != NULL) {
+ iNext = i + 1;
+ if (iNext <= iLength) {
+ wNext = pAccess->GetChar(pIdentity, iNext);
+ }
+ } else {
+ if (i < iLength) {
+ wNext = *pStr;
+ }
+ }
+ if (wch == 0x0651) {
+ if (wNext >= 0x064C && wNext <= 0x0650) {
+ wForm = FX_GetArabicFromShaddaTable(wNext);
+ bShadda = TRUE;
+ }
+ } else {
+ if (wNext == 0x0651) {
+ wForm = FX_GetArabicFromShaddaTable(wch);
+ bShadda = TRUE;
+ }
+ }
+ }
+ } else {
+ bShadda = FALSE;
+ }
+ } else if (dwCharType == FX_CHARTYPE_Numeric) {
+ wForm = wch;
+ if (bArabicNumber) {
+ wForm += 0x0630;
+ }
+ } else if (wch == L'.') {
+ wForm = wch;
+ if (bArabicNumber) {
+ wNext = 0xFEFF;
+ if (pAccess != NULL) {
+ iNext = i + 1;
+ if (iNext <= iLength) {
+ wNext = pAccess->GetChar(pIdentity, iNext);
+ }
+ } else {
+ if (i < iLength) {
+ wNext = *pStr;
+ }
+ }
+ if (wNext >= L'0' && wNext <= L'9') {
+ wForm = 0x066B;
+ }
+ }
+ } else if (wch == L',') {
+ wForm = wch;
+ if (bArabicComma) {
+ wForm = 0x060C;
+ }
+ } else if (bRTLPiece || bVerticalChar) {
+ wForm = FX_GetMirrorChar(wch, dwProps, bRTLPiece, bVerticalChar);
+ } else {
+ wForm = wch;
+ }
+ if (dwCharType != FX_CHARTYPE_Combination) {
+ bShadda = FALSE;
+ }
+ if (dwCharType < FX_CHARTYPE_ArabicAlef) {
+ bLam = FALSE;
+ }
+ dwProps = FX_GetUnicodeProperties(wForm);
+ iCharRotation = iRotation;
+ if (bVerticalChar && (dwProps & 0x8000) != 0) {
+ iCharRotation ++;
+ }
+ iCharRotation %= 4;
+ bEmptyChar = (dwCharType >= FX_CHARTYPE_Tab && dwCharType <= FX_CHARTYPE_Control);
+ if (wForm == 0xFEFF) {
+ bEmptyChar = TRUE;
+ }
+ iForms = bLam ? 3 : 1;
+ iCount += (bEmptyChar && bSkipSpace) ? 0 : iForms;
+ if (pCharPos == NULL) {
+ if (iWidth > 0) {
+ wPrev = wch;
+ }
+ wLast = wch;
+ continue;
+ }
+ iCharWidth = iWidth;
+ if (iCharWidth < 0) {
+ iCharWidth = -iCharWidth;
+ }
+ iCharWidth /= iFontSize;
+ formChars[0].wch = wch;
+ formChars[0].wForm = wForm;
+ formChars[0].iWidth = iCharWidth;
+ if (bLam) {
+ formChars[1].wForm = 0x0651;
+ iCharWidth = 0;
+ pFont->GetCharWidth(0x0651, iCharWidth, FALSE);
+ formChars[1].iWidth = iCharWidth;
+ formChars[2].wForm = 0x0670;
+ iCharWidth = 0;
+ pFont->GetCharWidth(0x0670, iCharWidth, FALSE);
+ formChars[2].iWidth = iCharWidth;
+ }
+ for (FX_INT32 j = 0; j < iForms; j ++) {
+ wForm = (FX_WCHAR)formChars[j].wForm;
+ iCharWidth = formChars[j].iWidth;
+ if (j > 0) {
+ dwCharType = FX_CHARTYPE_Combination;
+ wch = wForm;
+ wLast = (FX_WCHAR)formChars[j - 1].wForm;
+ }
+ if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
+ pCharPos->m_GlyphIndex = bCharCode ? wch : pFont->GetGlyphIndex(wForm, FALSE);
+ pCharPos->m_ExtGID = pCharPos->m_GlyphIndex;
+ pCharPos->m_FontCharWidth = iCharWidth;
+ if (pWSForms) {
+ *pWSForms += wForm;
+ }
+ }
+ if (bVerticalDoc) {
+ iCharHeight = iCharWidth;
+ iCharWidth = 1000;
+ } else {
+ iCharHeight = 1000;
+ }
+ fCharWidth = fFontSize * iCharWidth / 1000.0f;
+ fCharHeight = fFontSize * iCharHeight / 1000.0f;
+ if (bRTLPiece && dwCharType != FX_CHARTYPE_Combination) {
+ if (bVerticalDoc) {
+ fY -= fCharHeight;
+ } else {
+ fX -= fCharWidth;
+ }
+ }
+ if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
+ pCharPos->m_OriginX = fX;
+ pCharPos->m_OriginY = fY;
+ if ((dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0) {
+ FX_INT32 iFormWidth = iCharWidth;
+ pFont->GetCharWidth(wForm, iFormWidth, FALSE);
+ FX_FLOAT fOffset = fFontSize * (iCharWidth - iFormWidth) / 2000.0f;
+ if (bVerticalDoc) {
+ pCharPos->m_OriginY += fOffset;
+ } else {
+ pCharPos->m_OriginX += fOffset;
+ }
+ }
+ if (dwCharType == FX_CHARTYPE_Combination) {
+ CFX_Rect rtBBox;
+ rtBBox.Reset();
+ if (pFont->GetCharBBox(wForm, rtBBox, FALSE)) {
+ pCharPos->m_OriginY = fYBase + fFontSize - fFontSize * (FX_FLOAT)rtBBox.height / (FX_FLOAT)iMaxHeight;
+ }
+ if (wForm == wch && wLast != 0xFEFF) {
+ FX_DWORD dwLastProps = FX_GetUnicodeProperties(wLast);
+ if ((dwLastProps & FX_CHARTYPEBITSMASK) == FX_CHARTYPE_Combination) {
+ CFX_Rect rtBBox;
+ rtBBox.Reset();
+ if (pFont->GetCharBBox(wLast, rtBBox, FALSE)) {
+ pCharPos->m_OriginY -= fFontSize * rtBBox.height / iMaxHeight;
+ }
+ }
+ }
+ }
+ CFX_PointF ptOffset;
+ ptOffset.Reset();
+ FX_BOOL bAdjusted = FALSE;
+ if (pAdjustPos) {
+ bAdjusted = pAdjustPos(wForm, bCharCode, pFont, fFontSize, bVerticalChar, ptOffset);
+ }
+ if (!bAdjusted && bVerticalChar && (dwProps & 0x00010000) != 0) {
+ CFX_Rect rtBBox;
+ rtBBox.Reset();
+ if (pFont->GetCharBBox(wForm, rtBBox, FALSE)) {
+ ptOffset.x = fFontSize * (850 - rtBBox.right()) / iMaxHeight;
+ ptOffset.y = fFontSize * (iAscent - rtBBox.top - 150) / iMaxHeight;
+ }
+ }
+ pCharPos->m_OriginX += ptOffset.x;
+ pCharPos->m_OriginY -= ptOffset.y;
+ }
+ if (!bRTLPiece && dwCharType != FX_CHARTYPE_Combination) {
+ if (bVerticalDoc) {
+ fY += fCharHeight;
+ } else {
+ fX += fCharWidth;
+ }
+ }
+ if (!bEmptyChar || (bEmptyChar && !bSkipSpace)) {
+ pCharPos->m_bGlyphAdjust = TRUE;
+ if (bVerticalDoc) {
+ if (iCharRotation == 0) {
+ pCharPos->m_AdjustMatrix[0] = -1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = 1;
+ pCharPos->m_OriginY += fAscent;
+ } else if (iCharRotation == 1) {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = -1;
+ pCharPos->m_AdjustMatrix[2] = -1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX -= fDescent;
+ } else if (iCharRotation == 2) {
+ pCharPos->m_AdjustMatrix[0] = 1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = -1;
+ pCharPos->m_OriginX += fCharWidth;
+ pCharPos->m_OriginY += fAscent;
+ } else {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = 1;
+ pCharPos->m_AdjustMatrix[2] = 1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX += fAscent;
+ }
+ } else {
+ if (iCharRotation == 0) {
+ pCharPos->m_AdjustMatrix[0] = -1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = 1;
+ } else if (iCharRotation == 1) {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = -1;
+ pCharPos->m_AdjustMatrix[2] = -1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX -= fDescent;
+ pCharPos->m_OriginY -= fAscent + fDescent;
+ } else if (iCharRotation == 2) {
+ pCharPos->m_AdjustMatrix[0] = 1;
+ pCharPos->m_AdjustMatrix[1] = 0;
+ pCharPos->m_AdjustMatrix[2] = 0;
+ pCharPos->m_AdjustMatrix[3] = -1;
+ pCharPos->m_OriginX += fCharWidth;
+ pCharPos->m_OriginY -= fAscent;
+ } else {
+ pCharPos->m_AdjustMatrix[0] = 0;
+ pCharPos->m_AdjustMatrix[1] = 1;
+ pCharPos->m_AdjustMatrix[2] = 1;
+ pCharPos->m_AdjustMatrix[3] = 0;
+ pCharPos->m_OriginX += fAscent;
+ }
+ }
+ if (iHorScale != 100 || iVerScale != 100) {
+ pCharPos->m_AdjustMatrix[0] = pCharPos->m_AdjustMatrix[0] * iHorScale / 100.0f;
+ pCharPos->m_AdjustMatrix[1] = pCharPos->m_AdjustMatrix[1] * iHorScale / 100.0f;
+ pCharPos->m_AdjustMatrix[2] = pCharPos->m_AdjustMatrix[2] * iVerScale / 100.0f;
+ pCharPos->m_AdjustMatrix[3] = pCharPos->m_AdjustMatrix[3] * iVerScale / 100.0f;
+ }
+ pCharPos ++;
+ }
+ }
+ if (iWidth > 0) {
+ wPrev = (FX_WCHAR)formChars[0].wch;
+ }
+ wLast = wch;
+ }
+ return iCount;
+}
+FX_INT32 CFX_TxtBreak::GetCharRects(FX_LPCTXTRUN pTxtRun, CFX_RectFArray &rtArray, FX_BOOL bCharBBox ) const
+{
+ if (pTxtRun == NULL || pTxtRun->iLength < 1) {
+ return 0;
+ }
+ IFX_TxtAccess *pAccess = pTxtRun->pAccess;
+ FX_LPVOID pIdentity = pTxtRun->pIdentity;
+ FX_LPCWSTR pStr = pTxtRun->pStr;
+ FX_INT32 *pWidths = pTxtRun->pWidths;
+ FX_INT32 iLength = pTxtRun->iLength;
+ CFX_RectF rect(*pTxtRun->pRect);
+ FX_BOOL bRTLPiece = (pTxtRun->dwCharStyles & FX_TXTCHARSTYLE_OddBidiLevel) != 0;
+ FX_FLOAT fFontSize = pTxtRun->fFontSize;
+ FX_INT32 iFontSize = FXSYS_round(fFontSize * 20.0f);
+ FX_FLOAT fScale = fFontSize / 1000.0f;
+ IFX_Font *pFont = pTxtRun->pFont;
+ if (pFont == NULL) {
+ bCharBBox = FALSE;
+ }
+ CFX_Rect bbox;
+ bbox.Set(0, 0, 0, 0);
+ if (bCharBBox) {
+ bCharBBox = pFont->GetBBox(bbox);
+ }
+ FX_FLOAT fLeft = FX_MAX(0, bbox.left * fScale);
+ FX_FLOAT fHeight = FXSYS_fabs(bbox.height * fScale);
+ rtArray.RemoveAll();
+ rtArray.SetSize(iLength);
+ FX_BOOL bVertical = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_VerticalLayout) != 0;
+ FX_BOOL bSingleLine = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_SingleLine) != 0;
+ FX_BOOL bCombText = (pTxtRun->dwStyles & FX_TXTLAYOUTSTYLE_CombText) != 0;
+ FX_WCHAR wch, wLineBreakChar = pTxtRun->wLineBreakChar;
+ FX_INT32 iCharSize;
+ FX_FLOAT fCharSize, fStart;
+ if (bVertical) {
+ fStart = bRTLPiece ? rect.bottom() : rect.top;
+ } else {
+ fStart = bRTLPiece ? rect.right() : rect.left;
+ }
+ for (FX_INT32 i = 0; i < iLength; i ++) {
+ if (pAccess != NULL) {
+ wch = pAccess->GetChar(pIdentity, i);
+ iCharSize = pAccess->GetWidth(pIdentity, i);
+ } else {
+ wch = *pStr ++;
+ iCharSize = *pWidths ++;
+ }
+ fCharSize = (FX_FLOAT)iCharSize / 20000.0f;
+ FX_BOOL bRet = (!bSingleLine && FX_IsCtrlCode(wch));
+ if (!(wch == L'\v' || wch == L'\f' || wch == 0x2028 || wch == 0x2029 || (wLineBreakChar != 0xFEFF && wch == wLineBreakChar))) {
+ bRet = FALSE;
+ }
+ if (bRet) {
+ iCharSize = iFontSize * 500;
+ fCharSize = fFontSize / 2.0f;
+ }
+ if (bVertical) {
+ rect.top = fStart;
+ if (bRTLPiece) {
+ rect.top -= fCharSize;
+ fStart -= fCharSize;
+ } else {
+ fStart += fCharSize;
+ }
+ rect.height = fCharSize;
+ } else {
+ rect.left = fStart;
+ if (bRTLPiece) {
+ rect.left -= fCharSize;
+ fStart -= fCharSize;
+ } else {
+ fStart += fCharSize;
+ }
+ rect.width = fCharSize;
+ }
+ if (bCharBBox && !bRet) {
+ FX_INT32 iCharWidth = 1000;
+ pFont->GetCharWidth(wch, iCharWidth);
+ FX_FLOAT fRTLeft = 0, fCharWidth = 0;
+ if (iCharWidth > 0) {
+ fCharWidth = iCharWidth * fScale;
+ fRTLeft = fLeft;
+ if (bCombText) {
+ fRTLeft = (rect.width - fCharWidth) / 2.0f;
+ }
+ }
+ CFX_RectF rtBBoxF;
+ if (bVertical) {
+ rtBBoxF.top = rect.left + fRTLeft;
+ rtBBoxF.left = rect.top + (rect.height - fHeight) / 2.0f;
+ rtBBoxF.height = fCharWidth;
+ rtBBoxF.width = fHeight;
+ rtBBoxF.left = FX_MAX(rtBBoxF.left, 0);
+ } else {
+ rtBBoxF.left = rect.left + fRTLeft;
+ rtBBoxF.top = rect.top + (rect.height - fHeight) / 2.0f;
+ rtBBoxF.width = fCharWidth;
+ rtBBoxF.height = fHeight;
+ rtBBoxF.top = FX_MAX(rtBBoxF.top, 0);
+ }
+ rtArray.SetAt(i, rtBBoxF);
+ continue;
+ }
+ rtArray.SetAt(i, rect);
+ }
+ return iLength;
+}
diff --git a/xfa/src/fgas/src/layout/fx_textbreak.h b/xfa/src/fgas/src/layout/fx_textbreak.h
new file mode 100644
index 0000000000..c5bbc40946
--- /dev/null
+++ b/xfa/src/fgas/src/layout/fx_textbreak.h
@@ -0,0 +1,171 @@
+// 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 _FX_TEXTBREAK_IMP
+#define _FX_TEXTBREAK_IMP
+class CFX_TxtLine;
+class CFX_Txtbreak;
+class CFX_TxtLine : public CFX_Object
+{
+public:
+ CFX_TxtLine(FX_INT32 iBlockSize) : m_iStart(0)
+ , m_iWidth(0)
+ , m_iArabicChars(0)
+ {
+ m_pLineChars = FX_NEW CFX_TxtCharArray;
+ m_pLinePieces = FXTARGET_New CFX_TxtPieceArray(16);
+ }
+ ~CFX_TxtLine()
+ {
+ RemoveAll();
+ delete m_pLineChars;
+ FXTARGET_Delete m_pLinePieces;
+ }
+ FX_INT32 CountChars() const
+ {
+ return m_pLineChars->GetSize();
+ }
+ CFX_TxtChar* GetCharPtr(FX_INT32 index) const
+ {
+ FXSYS_assert(index > -1 && index < m_pLineChars->GetSize());
+ return m_pLineChars->GetDataPtr(index);
+ }
+ FX_INT32 CountPieces() const
+ {
+ return m_pLinePieces->GetSize();
+ }
+ CFX_TxtPiece* GetPiecePtr(FX_INT32 index) const
+ {
+ FXSYS_assert(index > -1 && index < m_pLinePieces->GetSize());
+ return m_pLinePieces->GetPtrAt(index);
+ }
+ void GetString(CFX_WideString &wsStr) const
+ {
+ FX_INT32 iCount = m_pLineChars->GetSize();
+ FX_LPWSTR pBuf = wsStr.GetBuffer(iCount);
+ CFX_Char *pChar;
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ pChar = m_pLineChars->GetDataPtr(i);
+ *pBuf ++ = (FX_WCHAR)pChar->m_wCharCode;
+ }
+ wsStr.ReleaseBuffer(iCount);
+ }
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE)
+ {
+ m_pLineChars->RemoveAll();
+ m_pLinePieces->RemoveAll(bLeaveMemory);
+ m_iWidth = 0;
+ m_iArabicChars = 0;
+ }
+ CFX_TxtCharArray *m_pLineChars;
+ CFX_TxtPieceArray *m_pLinePieces;
+ FX_INT32 m_iStart;
+ FX_INT32 m_iWidth;
+ FX_INT32 m_iArabicChars;
+};
+class CFX_TxtBreak : public IFX_TxtBreak, public CFX_Object
+{
+public:
+ CFX_TxtBreak(FX_DWORD dwPolicies);
+ ~CFX_TxtBreak();
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual void SetLineWidth(FX_FLOAT fLineWidth);
+ virtual void SetLinePos(FX_FLOAT fLinePos);
+ virtual FX_DWORD GetLayoutStyles() const
+ {
+ return m_dwLayoutStyles;
+ }
+ virtual void SetLayoutStyles(FX_DWORD dwLayoutStyles);
+ virtual void SetFont(IFX_Font *pFont);
+ virtual void SetFontSize(FX_FLOAT fFontSize);
+ virtual void SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant);
+ virtual void SetDefaultChar(FX_WCHAR wch);
+ virtual void SetParagraphBreakChar(FX_WCHAR wch);
+ virtual void SetLineBreakTolerance(FX_FLOAT fTolerance);
+ virtual void SetHorizontalScale(FX_INT32 iScale);
+ virtual void SetVerticalScale(FX_INT32 iScale);
+ virtual void SetCharRotation(FX_INT32 iCharRotation);
+ virtual void SetCharSpace(FX_FLOAT fCharSpace);
+ virtual void SetAlignment(FX_INT32 iAlignment);
+ virtual FX_DWORD GetContextCharStyles() const;
+ virtual void SetContextCharStyles(FX_DWORD dwCharStyles);
+ virtual void SetCombWidth(FX_FLOAT fCombWidth);
+ virtual void SetUserData(FX_LPVOID pUserData);
+ virtual FX_DWORD AppendChar(FX_WCHAR wch);
+ virtual FX_DWORD EndBreak(FX_DWORD dwStatus = FX_TXTBREAK_PieceBreak);
+ virtual FX_INT32 CountBreakChars() const;
+ virtual FX_INT32 CountBreakPieces() const;
+ virtual const CFX_TxtPiece* GetBreakPiece(FX_INT32 index) const;
+ virtual void ClearBreakPieces();
+ virtual void Reset();
+ virtual FX_INT32 GetDisplayPos(FX_LPCTXTRUN pTxtRun, FXTEXT_CHARPOS *pCharPos, FX_BOOL bCharCode = FALSE, CFX_WideString *pWSForms = NULL, FX_AdjustCharDisplayPos pAdjustPos = NULL) const;
+ virtual FX_INT32 GetCharRects(FX_LPCTXTRUN pTxtRun, CFX_RectFArray &rtArray, FX_BOOL bCharBBox = FALSE) const;
+ void AppendChar_PageLoad(CFX_Char *pCurChar, FX_DWORD dwProps);
+ FX_DWORD AppendChar_Combination(CFX_Char *pCurChar, FX_INT32 iRotation);
+ FX_DWORD AppendChar_Tab(CFX_Char *pCurChar, FX_INT32 iRotation);
+ FX_DWORD AppendChar_Control(CFX_Char *pCurChar, FX_INT32 iRotation);
+ FX_DWORD AppendChar_Arabic(CFX_Char *pCurChar, FX_INT32 iRotation);
+ FX_DWORD AppendChar_Others(CFX_Char *pCurChar, FX_INT32 iRotation);
+protected:
+ FX_DWORD m_dwPolicies;
+ FX_BOOL m_bPagination;
+ IFX_ArabicChar *m_pArabicChar;
+ FX_INT32 m_iLineWidth;
+ FX_DWORD m_dwLayoutStyles;
+ FX_BOOL m_bVertical;
+ FX_BOOL m_bArabicContext;
+ FX_BOOL m_bArabicShapes;
+ FX_BOOL m_bRTL;
+ FX_BOOL m_bSingleLine;
+ FX_BOOL m_bCombText;
+ FX_INT32 m_iArabicContext;
+ FX_INT32 m_iCurArabicContext;
+ IFX_Font *m_pFont;
+ FX_INT32 m_iFontSize;
+ FX_BOOL m_bEquidistant;
+ FX_INT32 m_iTabWidth;
+ FX_WCHAR m_wDefChar;
+ FX_WCHAR m_wParagBreakChar;
+ FX_INT32 m_iDefChar;
+ FX_INT32 m_iLineRotation;
+ FX_INT32 m_iCharRotation;
+ FX_INT32 m_iRotation;
+ FX_INT32 m_iAlignment;
+ FX_DWORD m_dwContextCharStyles;
+ FX_INT32 m_iCombWidth;
+ FX_LPVOID m_pUserData;
+ FX_DWORD m_dwCharType;
+ FX_BOOL m_bCurRTL;
+ FX_INT32 m_iCurAlignment;
+ FX_BOOL m_bArabicNumber;
+ FX_BOOL m_bArabicComma;
+ CFX_TxtLine *m_pTxtLine1;
+ CFX_TxtLine *m_pTxtLine2;
+ CFX_TxtLine *m_pCurLine;
+ FX_INT32 m_iReady;
+ FX_INT32 m_iTolerance;
+ FX_INT32 m_iHorScale;
+ FX_INT32 m_iVerScale;
+ FX_INT32 m_iCharSpace;
+ void SetBreakStatus();
+ FX_INT32 GetLineRotation(FX_DWORD dwStyles) const;
+ CFX_TxtChar* GetLastChar(FX_INT32 index, FX_BOOL bOmitChar = TRUE) const;
+ CFX_TxtLine* GetTxtLine(FX_BOOL bReady) const;
+ CFX_TxtPieceArray* GetTxtPieces(FX_BOOL bReady) const;
+ FX_DWORD GetUnifiedCharType(FX_DWORD dwType) const;
+ void ResetArabicContext();
+ void ResetContextCharStyles();
+ void EndBreak_UpdateArabicShapes();
+ FX_BOOL EndBreak_SplitLine(CFX_TxtLine *pNextLine, FX_BOOL bAllChars, FX_DWORD dwStatus);
+ void EndBreak_BidiLine(CFX_TPOArray &tpos, FX_DWORD dwStatus);
+ void EndBreak_Alignment(CFX_TPOArray &tpos, FX_BOOL bAllChars, FX_DWORD dwStatus);
+ FX_INT32 GetBreakPos(CFX_TxtCharArray &ca, FX_INT32 &iEndPos, FX_BOOL bAllChars = FALSE, FX_BOOL bOnlyBrk = FALSE);
+ void SplitTextLine(CFX_TxtLine *pCurLine, CFX_TxtLine *pNextLine, FX_BOOL bAllChars = FALSE);
+};
+#endif
diff --git a/xfa/src/fgas/src/layout/fx_unicode.cpp b/xfa/src/fgas/src/layout/fx_unicode.cpp
new file mode 100644
index 0000000000..def5d707f5
--- /dev/null
+++ b/xfa/src/fgas/src/layout/fx_unicode.cpp
@@ -0,0 +1,146 @@
+// 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 "../fgas_base.h"
+#include "fx_unicode.h"
+void FX_TEXTLAYOUT_PieceSort(CFX_TPOArray &tpos, FX_INT32 iStart, FX_INT32 iEnd)
+{
+ FXSYS_assert(iStart > -1 && iStart < tpos.GetSize());
+ FXSYS_assert(iEnd > -1 && iEnd < tpos.GetSize());
+ if (iStart >= iEnd) {
+ return;
+ }
+ FX_INT32 i = iStart, j = iEnd;
+ FX_TPO *pCur = tpos.GetPtrAt(iStart), *pSort;
+ FX_INT32 v = pCur->pos;
+ while (i < j) {
+ while (j > i) {
+ pSort = tpos.GetPtrAt(j);
+ if (pSort->pos < v) {
+ FX_TPO t = *pSort;
+ *pSort = *pCur;
+ *pCur = t;
+ pCur = pSort;
+ break;
+ }
+ j --;
+ }
+ while (i < j) {
+ pSort = tpos.GetPtrAt(i);
+ if (pSort->pos > v) {
+ FX_TPO t = *pSort;
+ *pSort = *pCur;
+ *pCur = t;
+ pCur = pSort;
+ break;
+ }
+ i ++;
+ }
+ }
+ i --, j ++;
+ if (iStart < i) {
+ FX_TEXTLAYOUT_PieceSort(tpos, iStart, i);
+ }
+ if (j < iEnd) {
+ FX_TEXTLAYOUT_PieceSort(tpos, j, iEnd);
+ }
+}
+static const FX_JAPCHARPROPERTYEX gs_FX_JapCharPropertysEx[] = {
+ {0x3001, 0x13},
+ {0x3002, 0x13},
+ {0x3041, 0x23},
+ {0x3043, 0x23},
+ {0x3045, 0x23},
+ {0x3047, 0x23},
+ {0x3049, 0x23},
+ {0x3063, 0x23},
+ {0x3083, 0x23},
+ {0x3085, 0x23},
+ {0x3087, 0x23},
+ {0x308E, 0x23},
+ {0x3095, 0x23},
+ {0x3096, 0x23},
+ {0x30A1, 0x23},
+ {0x30A3, 0x23},
+ {0x30A5, 0x23},
+ {0x30A7, 0x23},
+ {0x30A9, 0x23},
+ {0x30C3, 0x23},
+ {0x30E3, 0x23},
+ {0x30E5, 0x23},
+ {0x30E7, 0x23},
+ {0x30EE, 0x23},
+ {0x30F5, 0x23},
+ {0x30F6, 0x23},
+ {0x30FB, 0x22},
+ {0x31F0, 0x23},
+ {0x31F1, 0x23},
+ {0x31F2, 0x23},
+ {0x31F3, 0x23},
+ {0x31F4, 0x23},
+ {0x31F5, 0x23},
+ {0x31F6, 0x23},
+ {0x31F7, 0x23},
+ {0x31F8, 0x23},
+ {0x31F9, 0x23},
+ {0x31FA, 0x23},
+ {0x31FB, 0x23},
+ {0x31FC, 0x23},
+ {0x31FD, 0x23},
+ {0x31FE, 0x23},
+ {0x31FF, 0x23},
+};
+FX_LPCJAPCHARPROPERTYEX FX_GetJapCharPropertyEx(FX_WCHAR wch)
+{
+ FX_INT32 iStart = 0;
+ FX_INT32 iEnd = sizeof(gs_FX_JapCharPropertysEx) / sizeof(FX_JAPCHARPROPERTYEX);
+ while (iStart <= iEnd) {
+ FX_INT32 iMid = (iStart + iEnd) / 2;
+ FX_WCHAR wJapChar = gs_FX_JapCharPropertysEx[iMid].wChar;
+ if (wch == wJapChar) {
+ return gs_FX_JapCharPropertysEx + iMid;
+ } else if (wch < wJapChar) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ }
+ return NULL;
+}
+FX_BOOL FX_AdjustJapCharDisplayPos(FX_WCHAR wch, FX_BOOL bMBCSCode, IFX_Font *pFont, FX_FLOAT fFontSize, FX_BOOL bVertical, CFX_PointF &ptOffset)
+{
+ if (pFont == NULL || !bVertical) {
+ return FALSE;
+ }
+ if (wch < 0x3001 || wch > 0x31FF) {
+ return FALSE;
+ }
+ FX_LPCJAPCHARPROPERTYEX pJapChar = FX_GetJapCharPropertyEx(wch);
+ if (pJapChar == NULL) {
+ return FALSE;
+ }
+ CFX_Rect rtBBox;
+ rtBBox.Reset();
+ if (pFont->GetCharBBox(wch, rtBBox, bMBCSCode)) {
+ switch (pJapChar->uAlign & 0xF0) {
+ case FX_JAPCHARPROPERTYEX_Top:
+ ptOffset.y = fFontSize * (1000 - rtBBox.height) / 1200.0f;
+ break;
+ case FX_JAPCHARPROPERTYEX_Middle:
+ ptOffset.y = fFontSize * (1000 - rtBBox.height) / 6000.0f;
+ break;
+ }
+ switch (pJapChar->uAlign & 0x0F) {
+ case FX_JAPCHARPROPERTYEX_Center:
+ ptOffset.x = fFontSize * (600 - rtBBox.right()) / 1000.0f;
+ break;
+ case FX_JAPCHARPROPERTYEX_Right:
+ ptOffset.x = fFontSize * (950 - rtBBox.right()) / 1000.0f;
+ break;
+ }
+ }
+ return TRUE;
+}
diff --git a/xfa/src/fgas/src/layout/fx_unicode.h b/xfa/src/fgas/src/layout/fx_unicode.h
new file mode 100644
index 0000000000..5eadb5506f
--- /dev/null
+++ b/xfa/src/fgas/src/layout/fx_unicode.h
@@ -0,0 +1,15 @@
+// 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 _FGAS_UNICODE_IMP
+#define _FGAS_UNICODE_IMP
+typedef struct _FX_TPO {
+ FX_INT32 index;
+ FX_INT32 pos;
+} FX_TPO;
+typedef CFX_MassArrayTemplate<FX_TPO> CFX_TPOArray;
+void FX_TEXTLAYOUT_PieceSort(CFX_TPOArray &tpos, FX_INT32 iStart, FX_INT32 iEnd);
+#endif
diff --git a/xfa/src/fgas/src/localization/fx_datetime.cpp b/xfa/src/fgas/src/localization/fx_datetime.cpp
new file mode 100644
index 0000000000..03ecb5bf48
--- /dev/null
+++ b/xfa/src/fgas/src/localization/fx_datetime.cpp
@@ -0,0 +1,548 @@
+// 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 "../fgas_base.h"
+const FX_BYTE g_FXDaysPerMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+const FX_BYTE g_FXDaysPerLeapMonth[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+const FX_INT32 g_FXDaysBeforeMonth[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+const FX_INT32 g_FXDaysBeforeLeapMonth[12] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
+const FX_INT32 g_FXDaysPerYear = 365;
+const FX_INT32 g_FXDaysPerLeapYear = 366;
+const FX_INT32 g_FXDaysPer4Years = 1461;
+const FX_INT32 g_FXDaysPer100Years = 36524;
+const FX_INT32 g_FXDaysPer400Years = 146097;
+const FX_INT64 g_FXMillisecondsPerSecond = 1000;
+const FX_INT64 g_FXMillisecondsPerMinute = 60000;
+const FX_INT64 g_FXMillisecondsPerHour = 3600000;
+const FX_INT64 g_FXMillisecondsPerDay = 86400000;
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || _FX_OS_ == _FX_WIN64_
+const FX_INT64 g_FXMillisecondsPerYear = 0x0757B12C00;
+const FX_INT64 g_FXMillisecondsPerLeapYear = 0x075CD78800;
+const FX_INT64 g_FXMillisecondsPer4Years = 0x1D63EB0C00;
+const FX_INT64 g_FXMillisecondsPer100Years = 0x02DEBCCDD000;
+const FX_INT64 g_FXMillisecondsPer400Years = 0x0B7AF85D9C00;
+#endif
+FX_BOOL FX_IsLeapYear(FX_INT32 iYear)
+{
+ FXSYS_assert(iYear != 0);
+ return ((iYear % 4) == 0 && (iYear % 100) != 0) || (iYear % 400) == 0;
+}
+FX_INT32 FX_DaysInYear(FX_INT32 iYear)
+{
+ FXSYS_assert(iYear != 0);
+ return FX_IsLeapYear(iYear) ? g_FXDaysPerLeapYear : g_FXDaysPerYear;
+}
+FX_BYTE FX_DaysInMonth(FX_INT32 iYear, FX_BYTE iMonth)
+{
+ FXSYS_assert(iYear != 0);
+ FXSYS_assert(iMonth >= 1 && iMonth <= 12);
+ const FX_BYTE *p = FX_IsLeapYear(iYear) ? g_FXDaysPerLeapMonth : g_FXDaysPerMonth;
+ return p[iMonth - 1];
+}
+static FX_INT32 FX_DaysBeforeMonthInYear(FX_INT32 iYear, FX_BYTE iMonth)
+{
+ FXSYS_assert(iYear != 0);
+ FXSYS_assert(iMonth >= 1 && iMonth <= 12);
+ const FX_INT32 *p = FX_IsLeapYear(iYear) ? g_FXDaysBeforeLeapMonth : g_FXDaysBeforeMonth;
+ return p[iMonth - 1];
+}
+static FX_INT64 FX_DateToDays(FX_INT32 iYear, FX_BYTE iMonth, FX_BYTE iDay, FX_BOOL bIncludeThisDay = FALSE)
+{
+ FXSYS_assert(iYear != 0);
+ FXSYS_assert(iMonth >= 1 && iMonth <= 12);
+ FXSYS_assert(iDay >= 1 && iDay <= FX_DaysInMonth(iYear, iMonth));
+ FX_INT64 iDays = FX_DaysBeforeMonthInYear(iYear, iMonth);
+ iDays += iDay;
+ if (!bIncludeThisDay) {
+ iDays --;
+ }
+ if (iYear > 0) {
+ iYear --;
+ } else {
+ iDays -= FX_DaysInYear(iYear);
+ iYear ++;
+ }
+ return iDays + (FX_INT64)iYear * 365 + iYear / 4 - iYear / 100 + iYear / 400;
+}
+static void FX_DaysToDate(FX_INT64 iDays, FX_INT32 &iYear, FX_BYTE &iMonth, FX_BYTE &iDay)
+{
+ FX_BOOL bBC = iDays < 0;
+ if (bBC) {
+ iDays = -iDays;
+ }
+ iYear = 1;
+ iMonth = 1;
+ iDay = 1;
+ if (iDays >= g_FXDaysPer400Years) {
+ iYear += (FX_INT32)(iDays / g_FXDaysPer400Years * 400);
+ iDays %= g_FXDaysPer400Years;
+ }
+ if (iDays >= g_FXDaysPer100Years) {
+ if (iDays == g_FXDaysPer100Years * 4) {
+ iYear += 300;
+ iDays -= g_FXDaysPer100Years * 3;
+ } else {
+ iYear += (FX_INT32)(iDays / g_FXDaysPer100Years * 100);
+ iDays %= g_FXDaysPer100Years;
+ }
+ }
+ if (iDays >= g_FXDaysPer4Years) {
+ iYear += (FX_INT32)(iDays / g_FXDaysPer4Years * 4);
+ iDays %= g_FXDaysPer4Years;
+ }
+ while (TRUE) {
+ FX_INT32 iYearDays = FX_DaysInYear(iYear);
+ if (iDays < iYearDays) {
+ if (bBC) {
+ iYear = -iYear;
+ iDays = iYearDays - iDays;
+ }
+ break;
+ }
+ iYear ++;
+ iDays -= iYearDays;
+ }
+ while (TRUE) {
+ FX_INT32 iMonthDays = FX_DaysInMonth(iYear, iMonth);
+ if (iDays < iMonthDays) {
+ break;
+ }
+ iMonth ++;
+ iDays -= iMonthDays;
+ }
+ iDay += (FX_BYTE)iDays;
+}
+#if _FX_OS_ == _FX_LINUX_DESKTOP_ || _FX_OS_ == _FX_LINUX_EMBEDDED_ || _FX_OS_ == _FX_ANDROID_ || _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_
+#include <time.h>
+#include <sys/time.h>
+#endif
+typedef struct _FXUT_SYSTEMTIME {
+ FX_WORD wYear;
+ FX_WORD wMonth;
+ FX_WORD wDayOfWeek;
+ FX_WORD wDay;
+ FX_WORD wHour;
+ FX_WORD wMinute;
+ FX_WORD wSecond;
+ FX_WORD wMilliseconds;
+} FXUT_SYSTEMTIME;
+void CFX_Unitime::Now()
+{
+ FXUT_SYSTEMTIME utLocal;
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || _FX_OS_ == _FX_WIN64_
+ ::GetLocalTime((LPSYSTEMTIME)&utLocal);
+#elif _FX_OS_ != _FX_EMBEDDED_
+#if 1
+ timeval curTime;
+ gettimeofday(&curTime, NULL);
+#else
+ struct timespec curTime;
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &curTime);
+#endif
+ struct tm st;
+ localtime_r(&curTime.tv_sec, &st);
+ utLocal.wYear = st.tm_year + 1900;
+ utLocal.wMonth = st.tm_mon + 1;
+ utLocal.wDayOfWeek = st.tm_wday;
+ utLocal.wDay = st.tm_mday;
+ utLocal.wHour = st.tm_hour;
+ utLocal.wMinute = st.tm_min;
+ utLocal.wSecond = st.tm_sec;
+ utLocal.wMilliseconds = curTime.tv_usec / 1000;
+#endif
+ Set(utLocal.wYear, (FX_BYTE)utLocal.wMonth, (FX_BYTE)utLocal.wDay,
+ (FX_BYTE)utLocal.wHour, (FX_BYTE)utLocal.wMinute, (FX_BYTE)utLocal.wSecond, (FX_WORD)utLocal.wMilliseconds);
+}
+void CFX_Unitime::SetGMTime()
+{
+ FXUT_SYSTEMTIME utLocal;
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || _FX_OS_ == _FX_WIN64_
+ ::GetSystemTime((LPSYSTEMTIME)&utLocal);
+#elif _FX_OS_ != _FX_EMBEDDED_
+#if 1
+ timeval curTime;
+ gettimeofday(&curTime, NULL);
+#else
+ struct timespec curTime;
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &curTime);
+#endif
+ struct tm st;
+ gmtime_r(&curTime.tv_sec, &st);
+ utLocal.wYear = st.tm_year + 1900;
+ utLocal.wMonth = st.tm_mon + 1;
+ utLocal.wDayOfWeek = st.tm_wday;
+ utLocal.wDay = st.tm_mday;
+ utLocal.wHour = st.tm_hour;
+ utLocal.wMinute = st.tm_min;
+ utLocal.wSecond = st.tm_sec;
+ utLocal.wMilliseconds = curTime.tv_usec / 1000;
+#endif
+ Set(utLocal.wYear, (FX_BYTE)utLocal.wMonth, (FX_BYTE)utLocal.wDay,
+ (FX_BYTE)utLocal.wHour, (FX_BYTE)utLocal.wMinute, (FX_BYTE)utLocal.wSecond, (FX_WORD)utLocal.wMilliseconds);
+}
+void CFX_Unitime::Set(FX_INT32 year, FX_BYTE month, FX_BYTE day, FX_BYTE hour, FX_BYTE minute, FX_BYTE second, FX_WORD millisecond)
+{
+ FXSYS_assert(hour <= 23);
+ FXSYS_assert(minute <= 59);
+ FXSYS_assert(second <= 59);
+ FXSYS_assert(millisecond <= 999);
+ m_iUnitime = (FX_INT64)hour * g_FXMillisecondsPerHour + (FX_INT64)minute * g_FXMillisecondsPerMinute + (FX_INT64)second * g_FXMillisecondsPerSecond + millisecond;
+ if (year > 0) {
+ m_iUnitime = m_iUnitime + FX_DateToDays(year, month, day, FALSE) * g_FXMillisecondsPerDay;
+ }
+}
+void CFX_Unitime::Set(FX_UNITIME t)
+{
+ m_iUnitime = t;
+}
+FX_INT32 CFX_Unitime::GetYear() const
+{
+ FX_INT32 iYear;
+ FX_BYTE iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ return iYear;
+}
+FX_BYTE CFX_Unitime::GetMonth() const
+{
+ FX_INT32 iYear;
+ FX_BYTE iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ return iMonth;
+}
+FX_BYTE CFX_Unitime::GetDay() const
+{
+ FX_INT32 iYear;
+ FX_BYTE iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ return iDay;
+}
+FX_WEEKDAY CFX_Unitime::GetDayOfWeek() const
+{
+ FX_INT32 v = (FX_INT32)((m_iUnitime / g_FXMillisecondsPerDay + 1) % 7);
+ if (v < 0) {
+ v += 7;
+ }
+ return (FX_WEEKDAY)v;
+}
+FX_WORD CFX_Unitime::GetDayOfYear() const
+{
+ FX_INT32 iYear;
+ FX_BYTE iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ return FX_DaysBeforeMonthInYear(iYear, iMonth) + iDay;
+}
+FX_INT64 CFX_Unitime::GetDayOfAD() const
+{
+ FX_BOOL bBC = m_iUnitime < 0;
+ FX_INT64 iDays = m_iUnitime / g_FXMillisecondsPerDay;
+ iDays += bBC ? -1 : 0;
+ if (bBC && (m_iUnitime % g_FXMillisecondsPerDay) == 0) {
+ iDays ++;
+ }
+ return iDays;
+}
+FX_BYTE CFX_Unitime::GetHour() const
+{
+ FX_INT32 v = (FX_INT32)(m_iUnitime % g_FXMillisecondsPerDay);
+ if (v < 0) {
+ v += g_FXMillisecondsPerDay;
+ }
+ return (FX_BYTE)(v / g_FXMillisecondsPerHour);
+}
+FX_BYTE CFX_Unitime::GetMinute() const
+{
+ FX_INT32 v = (FX_INT32)(m_iUnitime % g_FXMillisecondsPerHour);
+ if (v < 0) {
+ v += g_FXMillisecondsPerHour;
+ }
+ return (FX_BYTE)(v / g_FXMillisecondsPerMinute);
+}
+FX_BYTE CFX_Unitime::GetSecond() const
+{
+ FX_INT32 v = (FX_INT32)(m_iUnitime % g_FXMillisecondsPerMinute);
+ if (v < 0) {
+ v += g_FXMillisecondsPerMinute;
+ }
+ return (FX_BYTE)(v / g_FXMillisecondsPerSecond);
+}
+FX_WORD CFX_Unitime::GetMillisecond() const
+{
+ FX_INT32 v = (FX_INT32)(m_iUnitime % g_FXMillisecondsPerSecond);
+ if (v < 0) {
+ v += g_FXMillisecondsPerSecond;
+ }
+ return (FX_WORD)v;
+}
+FX_BOOL CFX_Unitime::AddYears(FX_INT32 iYears)
+{
+ FX_UNITIME ut = m_iUnitime;
+ if (ut < 0) {
+ ut = -ut;
+ }
+ FX_UNITIME r = ut % g_FXMillisecondsPerDay;
+ FX_INT32 iYear;
+ FX_BYTE iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ iYear += iYears;
+ if (iYear == 0) {
+ iYear = iYears > 0 ? 1 : -1;
+ }
+ m_iUnitime = FX_DateToDays(iYear, iMonth, iDay, FALSE) * g_FXMillisecondsPerDay;
+ m_iUnitime += (iYear < 0) ? -r : r;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddMonths(FX_INT32 iMonths)
+{
+ FX_BOOL b = iMonths > 0;
+ FX_UNITIME ut = m_iUnitime;
+ if (ut < 0) {
+ ut = -ut;
+ }
+ FX_UNITIME r = ut % g_FXMillisecondsPerDay;
+ FX_INT32 iYear;
+ FX_BYTE iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ iMonths += iMonth;
+ while (iMonths < 1) {
+ iYear --, iMonths += 12;
+ }
+ while (iMonths > 12) {
+ iYear ++, iMonths -= 12;
+ }
+ if (iYear == 0) {
+ iYear = b ? 1 : -1;
+ }
+ m_iUnitime = FX_DateToDays(iYear, (FX_BYTE)iMonths, iDay, FALSE) * g_FXMillisecondsPerDay;
+ m_iUnitime += (iYear < 0) ? -r : r;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddDays(FX_INT32 iDays)
+{
+ m_iUnitime += (FX_INT64)iDays * g_FXMillisecondsPerDay;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddHours(FX_INT32 iHours)
+{
+ m_iUnitime += (FX_INT64)iHours * g_FXMillisecondsPerHour;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddMinutes(FX_INT32 iMinutes)
+{
+ m_iUnitime += (FX_INT64)iMinutes * g_FXMillisecondsPerMinute;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddSeconds(FX_INT32 iSeconds)
+{
+ m_iUnitime += ((FX_INT64)iSeconds) * g_FXMillisecondsPerSecond;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddMilliseconds(FX_INT32 iMilliseconds)
+{
+ m_iUnitime += iMilliseconds;
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::Set(FX_INT32 year, FX_BYTE month, FX_BYTE day, FX_BYTE hour, FX_BYTE minute, FX_BYTE second, FX_WORD millisecond)
+{
+ ASSERT(year != 0);
+ ASSERT(month >= 1 && month <= 12);
+ ASSERT(day >= 1 && day <= FX_DaysInMonth(year, month));
+ ASSERT(hour <= 23);
+ ASSERT(minute <= 59);
+ ASSERT(second <= 59);
+ ASSERT(millisecond <= 999);
+ m_DateTime.Date.sDate.year = year;
+ m_DateTime.Date.sDate.month = month;
+ m_DateTime.Date.sDate.day = day;
+ m_DateTime.Time.sTime.hour = hour;
+ m_DateTime.Time.sTime.minute = minute;
+ m_DateTime.Time.sTime.second = second;
+ m_DateTime.Time.sTime.millisecond = millisecond;
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::FromUnitime(FX_UNITIME t)
+{
+ CFX_Unitime ut(t);
+ FX_DaysToDate(ut.GetDayOfAD(), m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month, m_DateTime.Date.sDate.day);
+ m_DateTime.Date.sDate.day = ut.GetHour();
+ m_DateTime.Time.sTime.minute = ut.GetMinute();
+ m_DateTime.Time.sTime.second = ut.GetSecond();
+ m_DateTime.Time.sTime.millisecond = ut.GetMillisecond();
+ return TRUE;
+}
+FX_UNITIME CFX_DateTime::ToUnitime() const
+{
+ FX_UNITIME v = (FX_INT64)m_DateTime.Date.sDate.day * g_FXMillisecondsPerHour + (FX_INT64)m_DateTime.Time.sTime.minute * g_FXMillisecondsPerMinute + (FX_INT64)m_DateTime.Time.sTime.second * g_FXMillisecondsPerSecond + m_DateTime.Time.sTime.millisecond;
+ v += FX_DateToDays(m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month, m_DateTime.Date.sDate.day, FALSE) * g_FXMillisecondsPerDay;
+ return v;
+}
+FX_INT32 CFX_DateTime::GetYear() const
+{
+ return m_DateTime.Date.sDate.year;
+}
+FX_BYTE CFX_DateTime::GetMonth() const
+{
+ return m_DateTime.Date.sDate.month;
+}
+FX_BYTE CFX_DateTime::GetDay() const
+{
+ return m_DateTime.Date.sDate.day;
+}
+FX_WEEKDAY CFX_DateTime::GetDayOfWeek() const
+{
+ FX_INT32 v = (FX_INT32)(FX_DateToDays(m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month, m_DateTime.Date.sDate.day, TRUE) % 7);
+ if (v < 0) {
+ v += 7;
+ }
+ return (FX_WEEKDAY)v;
+}
+FX_WORD CFX_DateTime::GetDayOfYear() const
+{
+ return FX_DaysBeforeMonthInYear(m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month) + m_DateTime.Date.sDate.day;
+}
+FX_INT64 CFX_DateTime::GetDayOfAD() const
+{
+ return FX_DateToDays(m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month, m_DateTime.Date.sDate.day, TRUE);
+}
+FX_BYTE CFX_DateTime::GetHour() const
+{
+ return m_DateTime.Date.sDate.day;
+}
+FX_BYTE CFX_DateTime::GetMinute() const
+{
+ return m_DateTime.Time.sTime.minute;
+}
+FX_BYTE CFX_DateTime::GetSecond() const
+{
+ return m_DateTime.Time.sTime.second;
+}
+FX_WORD CFX_DateTime::GetMillisecond() const
+{
+ return m_DateTime.Time.sTime.millisecond;
+}
+FX_BOOL CFX_DateTime::AddYears(FX_INT32 iYears)
+{
+ if (iYears == 0) {
+ return FALSE;
+ }
+ FX_INT32 v = m_DateTime.Date.sDate.year + iYears;
+ if (v >= 0 && m_DateTime.Date.sDate.year < 0) {
+ v ++;
+ } else if (v <= 0 && m_DateTime.Date.sDate.year > 0) {
+ v --;
+ }
+ m_DateTime.Date.sDate.year = v;
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddMonths(FX_INT32 iMonths)
+{
+ if (iMonths == 0) {
+ return FALSE;
+ }
+ FX_BOOL b = iMonths > 0;
+ iMonths += m_DateTime.Date.sDate.month;
+ while (iMonths < 1) {
+ m_DateTime.Date.sDate.year --;
+ if (m_DateTime.Date.sDate.year == 0) {
+ m_DateTime.Date.sDate.year = -1;
+ }
+ iMonths += 12;
+ }
+ while (iMonths > 12) {
+ m_DateTime.Date.sDate.year ++;
+ if (m_DateTime.Date.sDate.year == 0) {
+ m_DateTime.Date.sDate.year = 1;
+ }
+ iMonths -= 12;
+ }
+ if (m_DateTime.Date.sDate.year == 0) {
+ m_DateTime.Date.sDate.year = b ? 1 : -1;
+ }
+ m_DateTime.Date.sDate.month = (FX_BYTE)iMonths;
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddDays(FX_INT32 iDays)
+{
+ if (iDays == 0) {
+ return FALSE;
+ }
+ FX_INT64 v1 = FX_DateToDays(m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month, m_DateTime.Date.sDate.day, TRUE);
+ FX_INT64 v2 = v1 + iDays;
+ if (v2 <= 0 && v1 > 0) {
+ v2 --;
+ } else if (v2 >= 0 && v1 < 0) {
+ v2 ++;
+ }
+ FX_DaysToDate(v2, m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month, m_DateTime.Date.sDate.day);
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddHours(FX_INT32 iHours)
+{
+ if (iHours == 0) {
+ return FALSE;
+ }
+ iHours += m_DateTime.Date.sDate.day;
+ FX_INT32 iDays = iHours / 24;
+ iHours %= 24;
+ if (iHours < 0) {
+ iDays --, iHours += 24;
+ }
+ m_DateTime.Date.sDate.day = (FX_BYTE)iHours;
+ if (iDays != 0) {
+ AddDays(iDays);
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddMinutes(FX_INT32 iMinutes)
+{
+ if (iMinutes == 0) {
+ return FALSE;
+ }
+ iMinutes += m_DateTime.Time.sTime.minute;
+ FX_INT32 iHours = iMinutes / 60;
+ iMinutes %= 60;
+ if (iMinutes < 0) {
+ iHours --, iMinutes += 60;
+ }
+ m_DateTime.Time.sTime.minute = (FX_BYTE)iMinutes;
+ if (iHours != 0) {
+ AddHours(iHours);
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddSeconds(FX_INT32 iSeconds)
+{
+ if (iSeconds == 0) {
+ return FALSE;
+ }
+ iSeconds += m_DateTime.Time.sTime.second;
+ FX_INT32 iMinutes = iSeconds / 60;
+ iSeconds %= 60;
+ if (iSeconds < 0) {
+ iMinutes --, iSeconds += 60;
+ }
+ m_DateTime.Time.sTime.second = (FX_BYTE)iSeconds;
+ if (iMinutes != 0) {
+ AddMinutes(iMinutes);
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddMilliseconds(FX_INT32 iMilliseconds)
+{
+ if (iMilliseconds == 0) {
+ return FALSE;
+ }
+ iMilliseconds += m_DateTime.Time.sTime.millisecond;
+ FX_INT32 iSeconds = (FX_INT32)(iMilliseconds / g_FXMillisecondsPerSecond);
+ iMilliseconds %= g_FXMillisecondsPerSecond;
+ if (iMilliseconds < 0) {
+ iSeconds --, iMilliseconds += g_FXMillisecondsPerSecond;
+ }
+ m_DateTime.Time.sTime.millisecond = (FX_WORD)iMilliseconds;
+ if (iSeconds != 0) {
+ AddSeconds(iSeconds);
+ }
+ return TRUE;
+}
diff --git a/xfa/src/fgas/src/localization/fx_locale.cpp b/xfa/src/fgas/src/localization/fx_locale.cpp
new file mode 100644
index 0000000000..a932a6c1a3
--- /dev/null
+++ b/xfa/src/fgas/src/localization/fx_locale.cpp
@@ -0,0 +1,4954 @@
+// 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 "../fgas_base.h"
+#include "fx_localeimp.h"
+#define FX_LOCALECATEGORY_DateHash 0xbde9abde
+#define FX_LOCALECATEGORY_TimeHash 0x2d71b00f
+#define FX_LOCALECATEGORY_DateTimeHash 0x158c72ed
+#define FX_LOCALECATEGORY_NumHash 0x0b4ff870
+#define FX_LOCALECATEGORY_TextHash 0x2d08af85
+#define FX_LOCALECATEGORY_ZeroHash 0x568cb500
+#define FX_LOCALECATEGORY_NullHash 0x052931bb
+typedef struct _FX_LOCALESUBCATEGORYINFO {
+ FX_UINT32 uHash;
+ FX_LPCWSTR pName;
+ FX_INT32 eSubCategory;
+} FX_LOCALESUBCATEGORYINFO, * FX_LPLOCALESUBCATEGORYINFO;
+typedef FX_LOCALESUBCATEGORYINFO const * FX_LPCLOCALESUBCATEGORYINFO;
+const static FX_LOCALESUBCATEGORYINFO g_FXLocaleDateTimeSubCatData[] = {
+ {0x14da2125, (FX_LPCWSTR)L"default", FX_LOCALEDATETIMESUBCATEGORY_Default},
+ {0x9041d4b0, (FX_LPCWSTR)L"short", FX_LOCALEDATETIMESUBCATEGORY_Short},
+ {0xa084a381, (FX_LPCWSTR)L"medium", FX_LOCALEDATETIMESUBCATEGORY_Medium},
+ {0xcdce56b3, (FX_LPCWSTR)L"full", FX_LOCALEDATETIMESUBCATEGORY_Full},
+ {0xf6b4afb0, (FX_LPCWSTR)L"long", FX_LOCALEDATETIMESUBCATEGORY_Long},
+};
+const static FX_INT32 g_iFXLocaleDateTimeSubCatCount = sizeof(g_FXLocaleDateTimeSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO);
+const static FX_LOCALESUBCATEGORYINFO g_FXLocaleNumSubCatData[] = {
+ {0x46f95531, (FX_LPCWSTR)L"percent", FX_LOCALENUMPATTERN_Percent},
+ {0x4c4e8acb, (FX_LPCWSTR)L"currency", FX_LOCALENUMPATTERN_Currency},
+ {0x54034c2f, (FX_LPCWSTR)L"decimal", FX_LOCALENUMPATTERN_Decimal},
+ {0x7568e6ae, (FX_LPCWSTR)L"integer", FX_LOCALENUMPATTERN_Integer},
+};
+const static FX_INT32 g_iFXLocaleNumSubCatCount = sizeof(g_FXLocaleNumSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO);
+typedef struct _FX_LOCALETIMEZONEINFO {
+ FX_DWORD uHash;
+ FX_INT16 iHour;
+ FX_INT16 iMinute;
+} FX_LOCALETIMEZONEINFO, * FX_LPLOCALETIMEZONEINFO;
+typedef FX_LOCALETIMEZONEINFO const * FX_LPCLOCALETIMEZONEINFO;
+const static FX_LOCALETIMEZONEINFO g_FXLocaleTimeZoneData[] = {
+ {FXBSTR_ID(0, 'C', 'D', 'T'), -5, 0}, {FXBSTR_ID(0, 'C', 'S', 'T'), -6, 0},
+ {FXBSTR_ID(0, 'E', 'D', 'T'), -4, 0}, {FXBSTR_ID(0, 'E', 'S', 'T'), -5, 0},
+ {FXBSTR_ID(0, 'M', 'D', 'T'), -6, 0}, {FXBSTR_ID(0, 'M', 'S', 'T'), -7, 0},
+ {FXBSTR_ID(0, 'P', 'D', 'T'), -7, 0}, {FXBSTR_ID(0, 'P', 'S', 'T'), -8, 0},
+};
+const static FX_INT32 g_iFXLocaleTimeZoneCount = sizeof(g_FXLocaleTimeZoneData) / sizeof(FX_LOCALETIMEZONEINFO);
+const static CFX_WideStringC gs_wsTextSymbols = FX_WSTRC(L"AXO09");
+const static CFX_WideStringC gs_wsTimeSymbols = FX_WSTRC(L"hHkKMSFAzZ");
+const static CFX_WideStringC gs_wsDateSymbols = FX_WSTRC(L"DJMEeGgYwW");
+const static CFX_WideStringC gs_wsConstChars = FX_WSTRC(L",-:/. ");
+static FX_STRSIZE FX_Local_Find(FX_WSTR wsSymbols, FX_WCHAR ch, FX_STRSIZE nStart = 0)
+{
+ FX_STRSIZE nLength = wsSymbols.GetLength();
+ if (nLength < 1 || nStart > nLength) {
+ return -1;
+ }
+ FX_LPCWSTR lpsz = (FX_LPCWSTR)FXSYS_wcschr(wsSymbols.GetPtr() + nStart, ch);
+ return (lpsz == NULL) ? -1 : (FX_STRSIZE)(lpsz - wsSymbols.GetPtr());
+}
+const static FX_LPCWSTR gs_LocalNumberSymbols[] = {
+ (FX_LPCWSTR)L"decimal", (FX_LPCWSTR)L"grouping", (FX_LPCWSTR)L"percent", (FX_LPCWSTR)L"minus", (FX_LPCWSTR)L"zero",
+ (FX_LPCWSTR)L"currencySymbol", (FX_LPCWSTR)L"currencyName",
+};
+IFX_Locale* IFX_Locale::Create(CXML_Element* pLocaleData)
+{
+ return FX_NEW CFX_Locale(pLocaleData);
+}
+CFX_Locale::CFX_Locale(CXML_Element* pLocaleData)
+{
+ m_pElement = pLocaleData;
+}
+CFX_Locale::~CFX_Locale()
+{
+}
+CFX_WideString CFX_Locale::GetName()
+{
+ return CFX_WideString();
+}
+static CFX_WideString FX_GetXMLContent(FX_BSTR bsSpace, CXML_Element* pxmlElement, FX_BSTR bsTag, FX_WSTR wsName)
+{
+ CXML_Element* pDatePattern = NULL;
+ FX_INT32 nCount = pxmlElement->CountElements(bsSpace, bsTag);
+ FX_INT32 i = 0;
+ for (; i < nCount; i++) {
+ pDatePattern = pxmlElement->GetElement(bsSpace, bsTag, i);
+ if (pDatePattern->GetAttrValue(FX_BSTRC("name")) == wsName) {
+ break;
+ }
+ }
+ if (i < nCount && pDatePattern) {
+ return pDatePattern->GetContent(0);
+ }
+ return L"";
+}
+void CFX_Locale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType, CFX_WideString& wsNumSymbol) const
+{
+ if (!m_pElement) {
+ return;
+ }
+ CFX_ByteString bsSpace;
+ CFX_WideString wsName = gs_LocalNumberSymbols[eType];
+ CXML_Element* pNumberSymbols = m_pElement->GetElement(bsSpace, FX_BSTRC("numberSymbols"));
+ if (!pNumberSymbols) {
+ return;
+ }
+ wsNumSymbol = FX_GetXMLContent(bsSpace, pNumberSymbols, FX_BSTRC("numberSymbol"), wsName);
+}
+void CFX_Locale::GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const
+{
+ if (!m_pElement) {
+ return;
+ }
+ CFX_ByteString bsSpace;
+ CXML_Element* pNumberSymbols = m_pElement->GetElement(bsSpace, FX_BSTRC("dateTimeSymbols"));
+ if (!pNumberSymbols) {
+ return;
+ }
+ wsDtSymbol = pNumberSymbols->GetContent(0);
+}
+static void FX_GetCalendarSymbol(CXML_Element* pXmlElement, const CFX_ByteString &symbol_type, FX_INT32 index, FX_BOOL bAbbr, CFX_WideString &wsName)
+{
+ CFX_ByteString bsSpace;
+ CFX_ByteString pstrSymbolNames = symbol_type + FX_BSTRC("Names");
+ CXML_Element* pChild = pXmlElement->GetElement(bsSpace, FX_BSTRC("calendarSymbols"));
+ if (!pChild) {
+ return;
+ }
+ CXML_Element* pSymbolNames = pChild->GetElement(bsSpace, pstrSymbolNames);
+ if (!pSymbolNames) {
+ return;
+ }
+ if (pSymbolNames->GetAttrInteger(FX_BSTRC("abbr")) != bAbbr) {
+ pSymbolNames = pChild->GetElement(bsSpace, pstrSymbolNames, 1);
+ }
+ if (pSymbolNames && pSymbolNames->GetAttrInteger(FX_BSTRC("abbr")) == bAbbr) {
+ CXML_Element* pSymbolName = pSymbolNames->GetElement(bsSpace, symbol_type, index);
+ if (pSymbolName) {
+ wsName = pSymbolName->GetContent(0);
+ }
+ }
+}
+void CFX_Locale::GetMonthName(FX_INT32 nMonth, CFX_WideString& wsMonthName, FX_BOOL bAbbr ) const
+{
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetCalendarSymbol(m_pElement, "month", nMonth, bAbbr, wsMonthName);
+}
+void CFX_Locale::GetDayName(FX_INT32 nWeek, CFX_WideString& wsDayName, FX_BOOL bAbbr ) const
+{
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetCalendarSymbol(m_pElement, "day", nWeek, bAbbr, wsDayName);
+}
+void CFX_Locale::GetMeridiemName(CFX_WideString& wsMeridiemName, FX_BOOL bAM ) const
+{
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetCalendarSymbol(m_pElement, "meridiem", bAM ? 0 : 1, FALSE, wsMeridiemName);
+}
+static FX_INT32 FX_ParseTimeZone(FX_LPCWSTR pStr, FX_INT32 iLen, FX_TIMEZONE& tz)
+{
+ tz.tzHour = 0;
+ tz.tzMinute = 0;
+ if (iLen < 0) {
+ return 0;
+ }
+ FX_INT32 iStart = 1;
+ FX_INT32 iEnd = iStart + 2;
+ while (iStart < iLen && iStart < iEnd) {
+ tz.tzHour = tz.tzHour * 10 + pStr[iStart++] - '0';
+ }
+ if (iStart < iLen && pStr[iStart] == ':') {
+ iStart++;
+ }
+ iEnd = iStart + 2;
+ while (iStart < iLen && iStart < iEnd) {
+ tz.tzMinute = tz.tzMinute * 10 + pStr[iStart++] - '0';
+ }
+ if (pStr[0] == '-') {
+ tz.tzHour = -tz.tzHour;
+ }
+ return iStart;
+}
+void CFX_Locale::GetTimeZone(FX_TIMEZONE& tz) const
+{
+ tz.tzHour = 0;
+ tz.tzMinute = 0;
+ if (!m_pElement) {
+ return;
+ }
+ CXML_Element* pxmlTimeZone = m_pElement->GetElement("", FX_BSTRC("timeZone"));
+ if (pxmlTimeZone) {
+ CFX_WideString wsTimeZone = pxmlTimeZone->GetContent(0);
+ FX_ParseTimeZone(wsTimeZone, wsTimeZone.GetLength(), tz);
+ }
+}
+void CFX_Locale::GetEraName(CFX_WideString& wsEraName, FX_BOOL bAD ) const
+{
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetCalendarSymbol(m_pElement, "era", bAD ? 0 : 1, FALSE, wsEraName);
+}
+static void FX_GetPattern(CXML_Element* pXmlElement, const CFX_ByteString& bsCategory, const CFX_WideString& wsSubCategory, CFX_WideString& wsPattern)
+{
+ CFX_ByteString bsSpace;
+ CXML_Element* pDatePatterns = pXmlElement->GetElement(bsSpace, bsCategory + "s");
+ if (!pDatePatterns) {
+ return;
+ }
+ wsPattern = FX_GetXMLContent(bsSpace, pDatePatterns, bsCategory, wsSubCategory);
+}
+static void FX_GetDateTimePattern(CXML_Element* pXmlElement, const CFX_ByteString& bsCategory, FX_LOCALEDATETIMESUBCATEGORY eType, CFX_WideString& wsPattern)
+{
+ CFX_WideString wsType = g_FXLocaleDateTimeSubCatData[eType].pName;
+ FX_GetPattern(pXmlElement, bsCategory, wsType, wsPattern);
+}
+void CFX_Locale::GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType, CFX_WideString& wsPattern) const
+{
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetDateTimePattern(m_pElement, "datePattern", eType, wsPattern);
+}
+void CFX_Locale::GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType, CFX_WideString& wsPattern) const
+{
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetDateTimePattern(m_pElement, "timePattern", eType, wsPattern);
+}
+void CFX_Locale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType, CFX_WideString& wsPattern) const
+{
+ CFX_WideString wsType = g_FXLocaleNumSubCatData[eType].pName;
+ FX_GetPattern(m_pElement, "numberPattern", wsType, wsPattern);
+}
+static FX_BOOL FX_IsDigit(FX_WCHAR c)
+{
+ return c >= '0' && c <= '9';
+}
+static FX_BOOL FX_IsAlpha(FX_WCHAR c)
+{
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+static FX_BOOL FX_IsSpace(FX_WCHAR c)
+{
+ return (c == 0x20) || (c == 0x0d) || (c == 0x0a) || (c == 0x09);
+}
+static const FX_FLOAT gs_fraction_scales[] = {0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f,
+ 0.0000001f, 0.00000001f, 0.000000001f, 0.0000000001f, 0.00000000001f
+ };
+static const FX_INT32 gs_fraction_count = sizeof(gs_fraction_scales) / sizeof(FX_FLOAT);
+class CFX_LCNumeric : public CFX_Object
+{
+public:
+ CFX_LCNumeric();
+ CFX_LCNumeric(FX_INT64 integral, FX_DWORD fractional = 0, FX_INT32 exponent = 0);
+ CFX_LCNumeric(FX_FLOAT dbRetValue);
+ CFX_LCNumeric(double dbvalue);
+ CFX_LCNumeric(CFX_WideString& wsNumeric);
+
+ FX_FLOAT GetFloat() const;
+ double GetDouble() const;
+ CFX_WideString ToString() const;
+ CFX_WideString ToString(FX_INT32 nTreading, FX_BOOL bTrimTailZeros) const;
+ FX_INT64 m_Integral;
+ FX_DWORD m_Fractional;
+#ifdef FX_NUM_DOUBLE
+ CFX_WideString m_wsValue;
+#endif
+ FX_INT32 m_Exponent;
+};
+static FX_BOOL FX_WStringToNumeric(const CFX_WideString& wsValue, CFX_LCNumeric& lcnum)
+{
+ FX_INT64 *pIntegral = &lcnum.m_Integral;
+ FX_DWORD *pFractional = &lcnum.m_Fractional;
+ FX_INT32 *pExponent = &lcnum.m_Exponent;
+ *pIntegral = 0;
+ *pFractional = 0;
+ *pExponent = 0;
+#ifdef FX_NUM_DOUBLE
+ lcnum.m_wsValue.Empty();
+#endif
+ if (wsValue.IsEmpty()) {
+ return FALSE;
+ }
+ const FX_INT32 nIntegralMaxLen = 17;
+ FX_INT32 cc = 0;
+ FX_BOOL bNegative = FALSE, bExpSign = FALSE;
+ FX_LPCWSTR str = (FX_LPCWSTR)wsValue;
+ FX_INT32 len = wsValue.GetLength();
+ while (cc < len && FX_IsSpace(str[cc])) {
+ cc++;
+ }
+ if (cc >= len) {
+ return FALSE;
+ }
+ if (str[cc] == '+') {
+ cc++;
+ } else if (str[cc] == '-') {
+ bNegative = TRUE;
+ cc++;
+ }
+ FX_INT32 nIntegralLen = 0;
+ while (cc < len) {
+ if (str[cc] == '.') {
+ break;
+ }
+ if (!FX_IsDigit(str[cc])) {
+ if ((str[cc] == 'E' || str[cc] == 'e')) {
+ break;
+ } else {
+ return FALSE;
+ }
+ }
+ if (nIntegralLen < nIntegralMaxLen) {
+ *pIntegral = *pIntegral * 10 + str[cc] - '0';
+ nIntegralLen++;
+ }
+ cc ++;
+ }
+ *pIntegral = bNegative ? -*pIntegral : *pIntegral;
+ if (cc < len && str[cc] == '.') {
+ int scale = 0;
+ double fraction = 0.0;
+ cc ++;
+ while (cc < len) {
+ if (scale >= gs_fraction_count) {
+ while (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ break;
+ }
+ cc++;
+ }
+ }
+ if (!FX_IsDigit(str[cc])) {
+ if ((str[cc] == 'E' || str[cc] == 'e')) {
+ break;
+ } else {
+ return FALSE;
+ }
+ }
+ fraction += gs_fraction_scales[scale] * (str[cc] - '0');
+ scale ++;
+ cc ++;
+ }
+ *pFractional = (FX_DWORD)(fraction * 4294967296.0);
+ }
+ if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) {
+ cc ++;
+ if (cc < len) {
+ if (str[cc] == '+') {
+ cc++;
+ } else if (str[cc] == '-') {
+ bExpSign = TRUE;
+ cc++;
+ }
+ }
+ while (cc < len) {
+ if (FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ *pExponent = *pExponent * 10 + str[cc] - '0';
+ cc ++;
+ }
+ *pExponent = bExpSign ? -*pExponent : *pExponent;
+ }
+#ifdef FX_NUM_DOUBLE
+ else {
+ lcnum.m_wsValue = wsValue;
+ }
+#endif
+ return TRUE;
+}
+CFX_LCNumeric::CFX_LCNumeric()
+{
+ m_Integral = 0;
+ m_Fractional = 0;
+ m_Exponent = 0;
+}
+CFX_LCNumeric::CFX_LCNumeric(FX_INT64 integral, FX_DWORD fractional , FX_INT32 exponent )
+{
+ m_Integral = integral;
+ m_Fractional = fractional;
+ m_Exponent = exponent;
+}
+CFX_LCNumeric::CFX_LCNumeric(FX_FLOAT dbRetValue)
+{
+ m_Integral = (FX_INT64)dbRetValue;
+ m_Fractional = (FX_DWORD)(((dbRetValue > 0) ? (dbRetValue - m_Integral) : (m_Integral - dbRetValue)) * 4294967296);
+ m_Exponent = 0;
+}
+CFX_LCNumeric::CFX_LCNumeric(double dbvalue)
+{
+ m_Integral = (FX_INT64)dbvalue;
+ m_Fractional = (FX_DWORD)(((dbvalue > 0) ? (dbvalue - m_Integral) : (m_Integral - dbvalue)) * 4294967296);
+ m_Exponent = 0;
+}
+CFX_LCNumeric::CFX_LCNumeric(CFX_WideString& wsNumeric)
+{
+ FX_WStringToNumeric(wsNumeric, *this);
+}
+FX_FLOAT CFX_LCNumeric::GetFloat() const
+{
+ FX_FLOAT dbRetValue = m_Fractional / 4294967296.0f;
+ dbRetValue = m_Integral + (m_Integral >= 0 ? dbRetValue : -dbRetValue);
+ if (m_Exponent != 0) {
+ dbRetValue *= FXSYS_pow(10, (FX_FLOAT)m_Exponent);
+ }
+ return dbRetValue;
+}
+double CFX_LCNumeric::GetDouble() const
+{
+ double value = m_Fractional / 4294967296.0;
+ value = m_Integral + (m_Integral >= 0 ? value : -value);
+ if (m_Exponent != 0) {
+ value *= FXSYS_pow(10, (FX_FLOAT)m_Exponent);
+ }
+ return value;
+}
+CFX_WideString CFX_LCNumeric::ToString() const
+{
+ return ToString(8, TRUE);
+}
+CFX_WideString CFX_LCNumeric::ToString(FX_INT32 nTreading, FX_BOOL bTrimTailZeros) const
+{
+#ifdef FX_NUM_DOUBLE
+ CFX_WideString wsResult;
+ if (!m_wsValue.IsEmpty()) {
+ const FX_INT32 nIntegralMaxLen = 17;
+ FX_INT32 cc = 0;
+ FX_BOOL bNegative = FALSE, bExpSign = FALSE;
+ FX_LPCWSTR str = (FX_LPCWSTR)m_wsValue;
+ FX_INT32 len = m_wsValue.GetLength();
+ while (cc < len && FX_IsSpace(str[cc])) {
+ cc++;
+ }
+ if (cc >= len) {
+ return wsResult;
+ }
+ if (str[cc] == '+') {
+ cc++;
+ } else if (str[cc] == '-') {
+ bNegative = TRUE;
+ cc++;
+ }
+ FX_INT32 nIntegralLen = 0;
+ while (cc < len) {
+ if (str[cc] == '.') {
+ break;
+ }
+ if (!FX_IsDigit(str[cc])) {
+ if ((str[cc] == 'E' || str[cc] == 'e')) {
+ break;
+ } else {
+ return wsResult;
+ }
+ }
+ if (nIntegralLen < nIntegralMaxLen) {
+ *pIntegral = *pIntegral * 10 + str[cc] - '0';
+ nIntegralLen++;
+ }
+ cc ++;
+ }
+ *pIntegral = bNegative ? -*pIntegral : *pIntegral;
+ if (cc < len && str[cc] == '.') {
+ int scale = 0;
+ double fraction = 0.0;
+ cc ++;
+ while (cc < len) {
+ if (scale >= gs_fraction_count) {
+ while (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ break;
+ }
+ cc++;
+ }
+ }
+ if (!FX_IsDigit(str[cc])) {
+ if ((str[cc] == 'E' || str[cc] == 'e')) {
+ break;
+ } else {
+ return FALSE;
+ }
+ }
+ fraction += gs_fraction_scales[scale] * (str[cc] - '0');
+ scale ++;
+ cc ++;
+ }
+ *pFractional = (FX_DWORD)(fraction * 4294967296.0);
+ }
+ }
+ double dbValeu = GetDouble();
+ FX_INT64 iInte = (FX_INT64)dbValeu;
+ wsResult.Format((FX_LPCWSTR)L"%l", (FX_INT64)iInte);
+ if (m_Fractional) {
+ CFX_WideString wsFormat;
+ wsFormat.Format((FX_LPCWSTR)L"%%.%dG", nTreading);
+ double dblMantissa = (dbValeu > 0) ? (dbValeu - iInte) : (iInte - dbValeu);
+ CFX_WideString wsFrac;
+ wsFrac.Format((FX_LPCWSTR)wsFormat, dblMantissa);
+ wsResult += CFX_WideStringC((FX_LPCWSTR)wsFrac + 1, wsFrac.GetLength() - 1);
+ if (bTrimTailZeros && nTreading > 0) {
+ wsResult.TrimRight(L"0");
+ wsResult.TrimRight(L".");
+ }
+ }
+#endif
+ CFX_WideString wsFormat;
+ wsFormat.Format((FX_LPCWSTR)L"%%.%df", nTreading);
+ CFX_WideString wsResult;
+ wsResult.Format(FX_LPCWSTR(wsFormat), GetDouble());
+ if (bTrimTailZeros && nTreading > 0) {
+ wsResult.TrimRight(L"0");
+ wsResult.TrimRight(L".");
+ }
+ return wsResult;
+}
+IFX_FormatString* IFX_FormatString::Create(IFX_LocaleMgr* pLocaleMgr, FX_BOOL bUseLCID)
+{
+ if (!pLocaleMgr) {
+ return NULL;
+ }
+ return FX_NEW CFX_FormatString(pLocaleMgr, bUseLCID);
+}
+CFX_FormatString::CFX_FormatString(IFX_LocaleMgr* pLocaleMgr, FX_BOOL bUseLCID)
+ : m_pLocaleMgr(pLocaleMgr)
+ , m_bUseLCID(bUseLCID)
+{
+}
+CFX_FormatString::~CFX_FormatString()
+{
+}
+void CFX_FormatString::SplitFormatString(const CFX_WideString& wsFormatString, CFX_WideStringArray& wsPatterns)
+{
+ FX_INT32 iStrLen = wsFormatString.GetLength();
+ FX_LPCWSTR pStr = (FX_LPCWSTR)wsFormatString;
+ FX_LPCWSTR pToken = pStr;
+ FX_LPCWSTR pEnd = pStr + iStrLen;
+ FX_BOOL iQuote = FALSE;
+ while (TRUE) {
+ if (pStr >= pEnd) {
+ CFX_WideString sub(pToken, pStr - pToken);
+ wsPatterns.Add(sub);
+ return;
+ } else if (*pStr == '\'') {
+ iQuote = !iQuote;
+ } else if (*pStr == L'|' && !iQuote) {
+ CFX_WideString sub(pToken, pStr - pToken);
+ wsPatterns.Add(sub);
+ pToken = pStr + 1;
+ }
+ pStr ++;
+ }
+}
+static CFX_WideString FX_GetLiteralText(FX_LPCWSTR pStrPattern, FX_INT32 &iPattern, FX_INT32 iLenPattern)
+{
+ CFX_WideString wsOutput;
+ if (pStrPattern[iPattern] != '\'') {
+ return wsOutput;
+ }
+ iPattern++;
+ FX_INT32 iQuote = 1;
+ while (iPattern < iLenPattern) {
+ if (pStrPattern[iPattern] == '\'') {
+ iQuote++;
+ if ((iPattern + 1 >= iLenPattern) || ((pStrPattern[iPattern + 1] != '\'') && (iQuote % 2 == 0))) {
+ break;
+ } else {
+ iQuote++;
+ }
+ iPattern++;
+ } else if (pStrPattern[iPattern] == '\\' && (iPattern + 1 < iLenPattern) && pStrPattern[iPattern + 1] == 'u') {
+ FX_INT32 iKeyValue = 0;
+ iPattern += 2;
+ FX_INT32 i = 0;
+ while (iPattern < iLenPattern && i++ < 4) {
+ FX_WCHAR ch = pStrPattern[iPattern++];
+ if ((ch >= '0' && ch <= '9')) {
+ iKeyValue = iKeyValue * 16 + ch - '0';
+ } else if ((ch >= 'a' && ch <= 'f')) {
+ iKeyValue = iKeyValue * 16 + ch - 'a' + 10;
+ } else if ((ch >= 'A' && ch <= 'F')) {
+ iKeyValue = iKeyValue * 16 + ch - 'A' + 10;
+ }
+ }
+ if (iKeyValue != 0) {
+ wsOutput += (FX_WCHAR)(iKeyValue & 0x0000FFFF);
+ }
+ continue;
+ }
+ wsOutput += pStrPattern[iPattern++];
+ }
+ return wsOutput;
+}
+static CFX_WideString FX_GetLiteralTextReverse(FX_LPCWSTR pStrPattern, FX_INT32 &iPattern)
+{
+ CFX_WideString wsOutput;
+ if (pStrPattern[iPattern] != '\'') {
+ return wsOutput;
+ }
+ iPattern--;
+ FX_INT32 iQuote = 1;
+ while (iPattern >= 0) {
+ if (pStrPattern[iPattern] == '\'') {
+ iQuote++;
+ if (iPattern - 1 >= 0 || ((pStrPattern[iPattern - 1] != '\'') && (iQuote % 2 == 0))) {
+ break;
+ } else {
+ iQuote++;
+ }
+ iPattern--;
+ } else if (pStrPattern[iPattern] == '\\' && pStrPattern[iPattern + 1] == 'u') {
+ iPattern--;
+ FX_INT32 iKeyValue = 0;
+ FX_INT32 iLen = wsOutput.GetLength();
+ FX_INT32 i = 1;
+ for (; i < iLen && i < 5; i++) {
+ FX_WCHAR ch = wsOutput[i];
+ if ((ch >= '0' && ch <= '9')) {
+ iKeyValue = iKeyValue * 16 + ch - '0';
+ } else if ((ch >= 'a' && ch <= 'f')) {
+ iKeyValue = iKeyValue * 16 + ch - 'a' + 10;
+ } else if ((ch >= 'A' && ch <= 'F')) {
+ iKeyValue = iKeyValue * 16 + ch - 'A' + 10;
+ }
+ }
+ if (iKeyValue != 0) {
+ wsOutput.Delete(0, i);
+ wsOutput = (FX_WCHAR)(iKeyValue & 0x0000FFFF) + wsOutput;
+ }
+ continue;
+ }
+ wsOutput = pStrPattern[iPattern--] + wsOutput;
+ }
+ return wsOutput;
+}
+FX_LOCALECATEGORY CFX_FormatString::GetCategory(const CFX_WideString& wsPattern)
+{
+ FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown;
+ FX_INT32 ccf = 0;
+ FX_INT32 iLenf = wsPattern.GetLength();
+ FX_LPCWSTR pStr = (FX_LPCWSTR)wsPattern;
+ FX_BOOL bBraceOpen = FALSE;
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ } else if (!bBraceOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
+ CFX_WideString wsCategory(pStr[ccf]);
+ ccf++;
+ while (TRUE) {
+ if (ccf == iLenf) {
+ return eCategory;
+ }
+ if ( pStr[ccf] == '.' || pStr[ccf] == '(') {
+ break;
+ }
+ if (pStr[ccf] == '{') {
+ bBraceOpen = TRUE;
+ break;
+ }
+ wsCategory += pStr[ccf];
+ ccf++;
+ }
+ FX_DWORD dwHash = FX_HashCode_String_GetW(wsCategory, wsCategory.GetLength());
+ if (dwHash == FX_LOCALECATEGORY_DateHash) {
+ if (eCategory == FX_LOCALECATEGORY_Time) {
+ return FX_LOCALECATEGORY_DateTime;
+ }
+ eCategory = FX_LOCALECATEGORY_Date;
+ } else if (dwHash == FX_LOCALECATEGORY_TimeHash) {
+ if (eCategory == FX_LOCALECATEGORY_Date) {
+ return FX_LOCALECATEGORY_DateTime;
+ }
+ eCategory = FX_LOCALECATEGORY_Time;
+ } else if (dwHash == FX_LOCALECATEGORY_DateTimeHash) {
+ return FX_LOCALECATEGORY_DateTime;
+ } else if (dwHash == FX_LOCALECATEGORY_TextHash) {
+ return FX_LOCALECATEGORY_Text;
+ } else if (dwHash == FX_LOCALECATEGORY_NumHash) {
+ return FX_LOCALECATEGORY_Num;
+ } else if (dwHash == FX_LOCALECATEGORY_ZeroHash) {
+ return FX_LOCALECATEGORY_Zero;
+ } else if (dwHash == FX_LOCALECATEGORY_NullHash) {
+ return FX_LOCALECATEGORY_Null;
+ }
+ } else if (pStr[ccf] == '}') {
+ bBraceOpen = FALSE;
+ }
+ ccf++;
+ }
+ return eCategory;
+}
+static FX_WORD FX_WStringToLCID(FX_LPCWSTR pstrLCID)
+{
+ if (!pstrLCID) {
+ return 0;
+ }
+ wchar_t* pEnd;
+ return (FX_WORD)wcstol((wchar_t*)pstrLCID, &pEnd, 16);
+}
+FX_WORD CFX_FormatString::GetLCID(const CFX_WideString& wsPattern)
+{
+ return FX_WStringToLCID(GetLocaleName(wsPattern));
+}
+CFX_WideString CFX_FormatString::GetLocaleName(const CFX_WideString& wsPattern)
+{
+ FX_INT32 ccf = 0;
+ FX_INT32 iLenf = wsPattern.GetLength();
+ FX_LPCWSTR pStr = (FX_LPCWSTR)wsPattern;
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ } else if (pStr[ccf] == '(') {
+ ccf++;
+ CFX_WideString wsLCID;
+ while (ccf < iLenf && pStr[ccf] != ')') {
+ wsLCID += pStr[ccf++];
+ }
+ return wsLCID;
+ }
+ ccf++;
+ }
+ return CFX_WideString();
+}
+IFX_Locale* CFX_FormatString::GetTextFormat(const CFX_WideString &wsPattern, FX_WSTR wsCategory, CFX_WideString& wsPurgePattern)
+{
+ IFX_Locale* pLocale = NULL;
+ FX_INT32 ccf = 0;
+ FX_INT32 iLenf = wsPattern.GetLength();
+ FX_LPCWSTR pStr = (FX_LPCWSTR)wsPattern;
+ FX_BOOL bBrackOpen = FALSE;
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ FX_INT32 iCurChar = ccf;
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ wsPurgePattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1);
+ } else if (!bBrackOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
+ CFX_WideString wsSearchCategory(pStr[ccf]);
+ ccf++;
+ while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' && pStr[ccf] != '(') {
+ wsSearchCategory += pStr[ccf];
+ ccf++;
+ }
+ if (wsSearchCategory != wsCategory) {
+ continue;
+ }
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '(') {
+ ccf++;
+ CFX_WideString wsLCID;
+ while (ccf < iLenf && pStr[ccf] != ')') {
+ wsLCID += pStr[ccf++];
+ }
+ pLocale = GetPatternLocale(wsLCID);
+ } else if (pStr[ccf] == '{') {
+ bBrackOpen = TRUE;
+ break;
+ }
+ ccf++;
+ }
+ } else if (pStr[ccf] != '}') {
+ wsPurgePattern += pStr[ccf];
+ }
+ ccf++;
+ }
+ if (!bBrackOpen) {
+ wsPurgePattern = wsPattern;
+ }
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ return pLocale;
+}
+#define FX_NUMSTYLE_Percent 0x01
+#define FX_NUMSTYLE_Exponent 0x02
+#define FX_NUMSTYLE_DotVorv 0x04
+IFX_Locale* CFX_FormatString::GetNumericFormat(const CFX_WideString& wsPattern, FX_INT32& iDotIndex, FX_DWORD& dwStyle, CFX_WideString& wsPurgePattern)
+{
+ dwStyle = 0;
+ IFX_Locale* pLocale = NULL;
+ FX_INT32 ccf = 0;
+ FX_INT32 iLenf = wsPattern.GetLength();
+ FX_LPCWSTR pStr = (FX_LPCWSTR)wsPattern;
+ FX_BOOL bFindDot = FALSE;
+ FX_BOOL bBrackOpen = FALSE;
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ FX_INT32 iCurChar = ccf;
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ wsPurgePattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1);
+ } else if (!bBrackOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
+ CFX_WideString wsCategory(pStr[ccf]);
+ ccf++;
+ while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' && pStr[ccf] != '(') {
+ wsCategory += pStr[ccf];
+ ccf++;
+ }
+ if (wsCategory != FX_WSTRC(L"num")) {
+ bBrackOpen = TRUE;
+ ccf = 0;
+ continue;
+ }
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '(') {
+ ccf++;
+ CFX_WideString wsLCID;
+ while (ccf < iLenf && pStr[ccf] != ')') {
+ wsLCID += pStr[ccf++];
+ }
+ pLocale = GetPatternLocale(wsLCID);
+ } else if (pStr[ccf] == '{') {
+ bBrackOpen = TRUE;
+ break;
+ } else if (pStr[ccf] == '.') {
+ CFX_WideString wsSubCategory;
+ ccf++;
+ while (ccf < iLenf && pStr[ccf] != '(' && pStr[ccf] != '{') {
+ wsSubCategory += pStr[ccf++];
+ }
+ FX_DWORD dwSubHash = FX_HashCode_String_GetW(wsSubCategory, wsSubCategory.GetLength());
+ FX_LOCALENUMSUBCATEGORY eSubCategory = FX_LOCALENUMPATTERN_Decimal;
+ for (FX_INT32 i = 0; i < g_iFXLocaleNumSubCatCount; i++) {
+ if (g_FXLocaleNumSubCatData[i].uHash == dwSubHash) {
+ eSubCategory = (FX_LOCALENUMSUBCATEGORY)g_FXLocaleNumSubCatData[i].eSubCategory;
+ break;
+ }
+ }
+ wsSubCategory.Empty();
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ FXSYS_assert(pLocale != NULL);
+ pLocale->GetNumPattern(eSubCategory, wsSubCategory);
+ iDotIndex = wsSubCategory.Find('.');
+ if (iDotIndex > 0) {
+ iDotIndex += wsPurgePattern.GetLength() ;
+ bFindDot = TRUE;
+ dwStyle |= FX_NUMSTYLE_DotVorv;
+ }
+ wsPurgePattern += wsSubCategory;
+ if (eSubCategory == FX_LOCALENUMPATTERN_Percent) {
+ dwStyle |= FX_NUMSTYLE_Percent;
+ }
+ continue;
+ }
+ ccf++;
+ }
+ } else if (pStr[ccf] == 'E') {
+ dwStyle |= FX_NUMSTYLE_Exponent;
+ wsPurgePattern += pStr[ccf];
+ } else if (pStr[ccf] == '%') {
+ dwStyle |= FX_NUMSTYLE_Percent;
+ wsPurgePattern += pStr[ccf];
+ } else if (pStr[ccf] != '}') {
+ wsPurgePattern += pStr[ccf];
+ }
+ if (!bFindDot) {
+ if (pStr[ccf] == '.' || pStr[ccf] == 'V' || pStr[ccf] == 'v') {
+ bFindDot = TRUE;
+ iDotIndex = wsPurgePattern.GetLength() - 1;
+ dwStyle |= FX_NUMSTYLE_DotVorv;
+ }
+ }
+ ccf++;
+ }
+ if (!bFindDot) {
+ iDotIndex = wsPurgePattern.GetLength();
+ }
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ return pLocale;
+}
+static FX_BOOL FX_GetNumericDotIndex(const CFX_WideString& wsNum, const CFX_WideString& wsDotSymbol, FX_INT32 &iDotIndex)
+{
+ FX_INT32 ccf = 0;
+ FX_INT32 iLenf = wsNum.GetLength();
+ FX_LPCWSTR pStr = (FX_LPCWSTR)wsNum;
+ FX_INT32 iLenDot = wsDotSymbol.GetLength();
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ } else if (ccf + iLenDot <= iLenf && !FXSYS_wcsncmp(pStr + ccf, (FX_LPCWSTR)wsDotSymbol, iLenDot)) {
+ iDotIndex = ccf;
+ return TRUE;
+ }
+ ccf++;
+ }
+ iDotIndex = wsNum.Find('.');
+ if (iDotIndex < 0) {
+ iDotIndex = iLenf;
+ return FALSE;
+ }
+ return TRUE;
+}
+FX_BOOL CFX_FormatString::ParseText(const CFX_WideString& wsSrcText, const CFX_WideString& wsPattern, CFX_WideString& wsValue)
+{
+ wsValue.Empty();
+ if (wsSrcText.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsTextFormat;
+ IFX_Locale* pLocale = GetTextFormat(wsPattern, FX_WSTRC(L"text"), wsTextFormat);
+ if (wsTextFormat.IsEmpty()) {
+ return FALSE;
+ }
+ FX_INT32 iText = 0, iPattern = 0;
+ FX_LPCWSTR pStrText = (FX_LPCWSTR)wsSrcText;
+ FX_INT32 iLenText = wsSrcText.GetLength();
+ FX_LPCWSTR pStrPattern = (FX_LPCWSTR)wsTextFormat;
+ FX_INT32 iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern && iText < iLenText) {
+ switch (pStrPattern[iPattern]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ FX_INT32 iLiteralLen = wsLiteral.GetLength();
+ if (iText + iLiteralLen > iLenText || FXSYS_wcsncmp(pStrText + iText, (FX_LPCWSTR)wsLiteral, iLiteralLen)) {
+ wsValue = wsSrcText;
+ return FALSE;
+ }
+ iText += iLiteralLen;
+ iPattern++;
+ break;
+ }
+ case 'A':
+ if (FX_IsAlpha(pStrText[iText])) {
+ wsValue += pStrText[iText];
+ iText++;
+ }
+ iPattern++;
+ break;
+ case 'X':
+ wsValue += pStrText[iText];
+ iText++;
+ iPattern++;
+ break;
+ case 'O':
+ case '0':
+ if (FX_IsDigit(pStrText[iText]) || FX_IsAlpha(pStrText[iText])) {
+ wsValue += pStrText[iText];
+ iText++;
+ }
+ iPattern++;
+ break;
+ case '9':
+ if (FX_IsDigit(pStrText[iText])) {
+ wsValue += pStrText[iText];
+ iText++;
+ }
+ iPattern++;
+ break;
+ default:
+ if (pStrPattern[iPattern] != pStrText[iText]) {
+ wsValue = wsSrcText;
+ return FALSE;
+ }
+ iPattern++;
+ iText++;
+ break;
+ }
+ }
+ return iPattern == iLenPattern && iText == iLenText;
+}
+FX_BOOL CFX_FormatString::ParseNum(const CFX_WideString& wsSrcNum, const CFX_WideString& wsPattern, FX_FLOAT &fValue)
+{
+ fValue = 0.0f;
+ if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ FX_INT32 dot_index_f = -1;
+ FX_DWORD dwFormatStyle = 0;
+ CFX_WideString wsNumFormat;
+ IFX_Locale* pLocale = GetNumericFormat(wsPattern, dot_index_f, dwFormatStyle, wsNumFormat);
+ if (!pLocale || wsNumFormat.IsEmpty()) {
+ return FALSE;
+ }
+ FX_INT32 iExponent = 0;
+ CFX_WideString wsDotSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
+ FX_INT32 iDotLen = wsDotSymbol.GetLength();
+ CFX_WideString wsGroupSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
+ FX_INT32 iGroupLen = wsGroupSymbol.GetLength();
+ CFX_WideString wsMinus;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinus);
+ FX_INT32 iMinusLen = wsMinus.GetLength();
+ int cc = 0, ccf = 0;
+ FX_LPCWSTR str = (FX_LPCWSTR)wsSrcNum;
+ int len = wsSrcNum.GetLength();
+ FX_LPCWSTR strf = (FX_LPCWSTR)wsNumFormat;
+ int lenf = wsNumFormat.GetLength();
+ double dbRetValue = 0;
+ double coeff = 1;
+ FX_BOOL bHavePercentSymbol = FALSE;
+ FX_BOOL bNeg = FALSE;
+ FX_BOOL bReverseParse = FALSE;
+ FX_INT32 dot_index = 0;
+ if (!FX_GetNumericDotIndex(wsSrcNum, wsDotSymbol, dot_index) && (dwFormatStyle & FX_NUMSTYLE_DotVorv)) {
+ bReverseParse = TRUE;
+ }
+ bReverseParse = FALSE;
+ if (bReverseParse) {
+ ccf = lenf - 1;
+ cc = len - 1;
+ while (ccf > dot_index_f && cc >= 0) {
+ switch (strf[ccf]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf);
+ FX_INT32 iLiteralLen = wsLiteral.GetLength();
+ cc -= iLiteralLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ }
+ case '9':
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1;
+ coeff *= 0.1;
+ cc--;
+ ccf--;
+ break;
+ case 'z':
+ if (cc >= 0) {
+ dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1;
+ coeff *= 0.1;
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'Z':
+ if (str[cc] != ' ') {
+ dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1;
+ coeff *= 0.1;
+ }
+ cc--;
+ ccf--;
+ break;
+ case 'S':
+ if (str[cc] == '+' || str[cc] == ' ') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 's':
+ if (str[cc] == '+') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 'E': {
+ if (cc >= dot_index) {
+ return FALSE;
+ }
+ FX_BOOL bExpSign = FALSE;
+ while (cc >= 0) {
+ if (str[cc] == 'E' || str[cc] == 'e') {
+ break;
+ }
+ if (FX_IsDigit(str[cc])) {
+ iExponent = iExponent + (str[cc] - '0') * 10;
+ cc--;
+ continue;
+ } else if (str[cc] == '+') {
+ cc--;
+ continue;
+ } else if (cc - iMinusLen + 1 > 0 && !FXSYS_wcsncmp(str + (cc - iMinusLen + 1), (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ bExpSign = TRUE;
+ cc -= iMinusLen;
+ } else {
+ return FALSE;
+ }
+ }
+ cc --;
+ iExponent = bExpSign ? -iExponent : iExponent;
+ ccf--;
+ }
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ FX_INT32 iSymbolLen = wsSymbol.GetLength();
+ cc -= iSymbolLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsSymbol, iSymbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ }
+ break;
+ case 'r':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
+ if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf --;
+ }
+ break;
+ case 'R':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'b':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
+ if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf --;
+ }
+ break;
+ case 'B':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case '.':
+ case 'V':
+ case 'v':
+ return FALSE;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ FX_INT32 iSysmbolLen = wsSymbol.GetLength();
+ cc -= iSysmbolLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsSymbol, iSysmbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ bHavePercentSymbol = TRUE;
+ }
+ break;
+ case '8':
+ while (ccf < lenf && strf[ccf] == '8') {
+ ccf++;
+ }
+ while (cc < len && FX_IsDigit(str[cc])) {
+ dbRetValue = (str[cc] - '0') * coeff + dbRetValue;
+ coeff *= 0.1;
+ cc++;
+ }
+ break;
+ case ',': {
+ if (cc >= 0) {
+ cc -= iGroupLen - 1;
+ if (cc >= 0 && FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsGroupSymbol, iGroupLen) == 0) {
+ cc--;
+ } else {
+ cc += iGroupLen - 1;
+ }
+ }
+ ccf--;
+ }
+ break;
+ case '(':
+ if (str[cc] == L'(') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ case ')':
+ if (str[cc] == L')') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ default:
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ }
+ }
+ dot_index = cc + 1;
+ }
+ ccf = dot_index_f - 1;
+ cc = dot_index - 1;
+ coeff = 1;
+ while (ccf >= 0 && cc >= 0) {
+ switch (strf[ccf]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf);
+ FX_INT32 iLiteralLen = wsLiteral.GetLength();
+ cc -= iLiteralLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ }
+ case '9':
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 10;
+ cc--;
+ ccf--;
+ break;
+ case 'z':
+ if (FX_IsDigit(str[cc])) {
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 10;
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'Z':
+ if (str[cc] != ' ') {
+ if (FX_IsDigit(str[cc])) {
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 10;
+ cc--;
+ }
+ } else {
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'S':
+ if (str[cc] == '+' || str[cc] == ' ') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 's':
+ if (str[cc] == '+') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 'E': {
+ if (cc >= dot_index) {
+ return FALSE;
+ }
+ FX_BOOL bExpSign = FALSE;
+ while (cc >= 0) {
+ if (str[cc] == 'E' || str[cc] == 'e') {
+ break;
+ }
+ if (FX_IsDigit(str[cc])) {
+ iExponent = iExponent + (str[cc] - '0') * 10;
+ cc--;
+ continue;
+ } else if (str[cc] == '+') {
+ cc--;
+ continue;
+ } else if (cc - iMinusLen + 1 > 0 && !FXSYS_wcsncmp(str + (cc - iMinusLen + 1), (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ bExpSign = TRUE;
+ cc -= iMinusLen;
+ } else {
+ return FALSE;
+ }
+ }
+ cc --;
+ iExponent = bExpSign ? -iExponent : iExponent;
+ ccf--;
+ }
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ FX_INT32 iSymbolLen = wsSymbol.GetLength();
+ cc -= iSymbolLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsSymbol, iSymbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ }
+ break;
+ case 'r':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
+ if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf --;
+ }
+ break;
+ case 'R':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'b':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
+ if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf --;
+ }
+ break;
+ case 'B':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case '.':
+ case 'V':
+ case 'v':
+ return FALSE;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ FX_INT32 iSysmbolLen = wsSymbol.GetLength();
+ cc -= iSysmbolLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsSymbol, iSysmbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ bHavePercentSymbol = TRUE;
+ }
+ break;
+ case '8':
+ return FALSE;
+ case ',': {
+ if (cc >= 0) {
+ cc -= iGroupLen - 1;
+ if (cc >= 0 && FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsGroupSymbol, iGroupLen) == 0) {
+ cc--;
+ } else {
+ cc += iGroupLen - 1;
+ }
+ }
+ ccf--;
+ }
+ break;
+ case '(':
+ if (str[cc] == L'(') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ case ')':
+ if (str[cc] == L')') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ default:
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ }
+ }
+ if (cc >= 0) {
+ return FALSE;
+ }
+ if (!bReverseParse) {
+ ccf = dot_index_f + 1;
+ cc = (dot_index == len) ? len : dot_index + 1;
+ coeff = 0.1;
+ while (cc < len && ccf < lenf) {
+ switch (strf[ccf]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
+ FX_INT32 iLiteralLen = wsLiteral.GetLength();
+ if (cc + iLiteralLen > len || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc += iLiteralLen;
+ ccf++;
+ break;
+ }
+ case '9':
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ {
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 0.1;
+ }
+ cc++;
+ ccf++;
+ break;
+ case 'z':
+ if (FX_IsDigit(str[cc])) {
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 0.1;
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'Z':
+ if (str[cc] != ' ') {
+ if (FX_IsDigit(str[cc])) {
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 0.1;
+ cc++;
+ }
+ } else {
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'S':
+ if (str[cc] == '+' || str[cc] == ' ') {
+ cc++;
+ } else {
+ if (cc + iMinusLen > len || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ bNeg = TRUE;
+ cc += iMinusLen;
+ }
+ ccf++;
+ break;
+ case 's':
+ if (str[cc] == '+') {
+ cc++;
+ } else {
+ if (cc + iMinusLen > len || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ bNeg = TRUE;
+ cc += iMinusLen;
+ }
+ ccf++;
+ break;
+ case 'E': {
+ if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) {
+ return FALSE;
+ }
+ FX_BOOL bExpSign = FALSE;
+ cc ++;
+ if (cc < len) {
+ if (str[cc] == '+') {
+ cc++;
+ } else if (str[cc] == '-') {
+ bExpSign = TRUE;
+ cc++;
+ }
+ }
+ while (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ break;
+ }
+ iExponent = iExponent * 10 + str[cc] - '0';
+ cc ++;
+ }
+ iExponent = bExpSign ? -iExponent : iExponent;
+ ccf++;
+ }
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ FX_INT32 iSymbolLen = wsSymbol.GetLength();
+ if (cc + iSymbolLen > len || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsSymbol, iSymbolLen)) {
+ return FALSE;
+ }
+ cc += iSymbolLen;
+ ccf++;
+ }
+ break;
+ case 'c':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
+ if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'C':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'd':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
+ if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'D':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case '.':
+ case 'V':
+ case 'v':
+ return FALSE;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ FX_INT32 iSysmbolLen = wsSymbol.GetLength();
+ if (cc + iSysmbolLen <= len && !FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsSymbol, iSysmbolLen)) {
+ cc += iSysmbolLen;
+ }
+ ccf++;
+ bHavePercentSymbol = TRUE;
+ }
+ break;
+ case '8': {
+ while (ccf < lenf && strf[ccf] == '8') {
+ ccf++;
+ }
+ while (cc < len && FX_IsDigit(str[cc])) {
+ dbRetValue = (str[cc] - '0') * coeff + dbRetValue;
+ coeff *= 0.1;
+ cc++;
+ }
+ }
+ break;
+ case ',': {
+ if (cc + iGroupLen <= len && FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsGroupSymbol, iGroupLen) == 0) {
+ cc += iGroupLen;
+ }
+ ccf++;
+ }
+ break;
+ case '(':
+ if (str[cc] == L'(') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ break;
+ case ')':
+ if (str[cc] == L')') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ break;
+ default:
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ }
+ }
+ if (cc != len) {
+ return FALSE;
+ }
+ }
+ if (iExponent) {
+ dbRetValue *= FXSYS_pow(10, (FX_FLOAT)iExponent);
+ }
+ if (bHavePercentSymbol) {
+ dbRetValue /= 100.0;
+ }
+ if (bNeg) {
+ dbRetValue = -dbRetValue;
+ }
+ fValue = (FX_FLOAT)dbRetValue;
+ return TRUE;
+}
+void FX_ParseNumString(const CFX_WideString& wsNum, CFX_WideString& wsResult)
+{
+ FX_INT32 iCount = wsNum.GetLength();
+ FX_LPCWSTR pStr = (FX_LPCWSTR)wsNum;
+ FX_LPWSTR pDst = wsResult.GetBuffer(iCount);
+ FX_INT32 nIndex = 0;
+ FX_BOOL bMinus = FALSE;
+ FX_INT32 i = 0;
+ for (i = 0; i < iCount; i++) {
+ FX_WCHAR wc = pStr[i];
+ if (wc == '.') {
+ break;
+ }
+ if ((wc == L'0' || wc == L' ' || wc == '+') && nIndex == 0) {
+ continue;
+ }
+ if (wc == '-') {
+ pDst[nIndex++] = wc;
+ bMinus = TRUE;
+ continue;
+ }
+ if (wc == L'0' && nIndex == 1 && bMinus) {
+ continue;
+ }
+ pDst[nIndex++] = wc;
+ }
+ if (bMinus && nIndex == 1) {
+ pDst[nIndex++] = '0';
+ }
+ if (nIndex == 0) {
+ wsResult.ReleaseBuffer(0);
+ pDst = wsResult.GetBuffer(iCount + 1);
+ pDst[nIndex++] = '0';
+ }
+ FX_INT32 j = 0;
+ for (j = iCount - 1; j > i; j--) {
+ FX_WCHAR wc = pStr[j];
+ if (wc != L'0' && wc != L' ') {
+ break;
+ }
+ }
+ if (j > i) {
+ pDst[nIndex++] = '.';
+ FXSYS_wcsncpy(pDst + nIndex, pStr + i + 1, j - i);
+ nIndex += j - i;
+ }
+ wsResult.ReleaseBuffer(nIndex);
+}
+FX_BOOL CFX_FormatString::ParseNum(const CFX_WideString& wsSrcNum, const CFX_WideString& wsPattern, CFX_WideString &wsValue)
+{
+ wsValue.Empty();
+ if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ FX_INT32 dot_index_f = -1;
+ FX_DWORD dwFormatStyle = 0;
+ CFX_WideString wsNumFormat;
+ IFX_Locale* pLocale = GetNumericFormat(wsPattern, dot_index_f, dwFormatStyle, wsNumFormat);
+ if (!pLocale || wsNumFormat.IsEmpty()) {
+ return FALSE;
+ }
+ FX_INT32 iExponent = 0;
+ CFX_WideString wsDotSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
+ FX_INT32 iDotLen = wsDotSymbol.GetLength();
+ CFX_WideString wsGroupSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
+ FX_INT32 iGroupLen = wsGroupSymbol.GetLength();
+ CFX_WideString wsMinus;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinus);
+ FX_INT32 iMinusLen = wsMinus.GetLength();
+ int cc = 0, ccf = 0;
+ FX_LPCWSTR str = (FX_LPCWSTR)wsSrcNum;
+ int len = wsSrcNum.GetLength();
+ FX_LPCWSTR strf = (FX_LPCWSTR)wsNumFormat;
+ int lenf = wsNumFormat.GetLength();
+ FX_BOOL bHavePercentSymbol = FALSE;
+ FX_BOOL bNeg = FALSE;
+ FX_BOOL bReverseParse = FALSE;
+ FX_INT32 dot_index = 0;
+ if (!FX_GetNumericDotIndex(wsSrcNum, wsDotSymbol, dot_index) && (dwFormatStyle & FX_NUMSTYLE_DotVorv)) {
+ bReverseParse = TRUE;
+ }
+ bReverseParse = FALSE;
+ ccf = dot_index_f - 1;
+ cc = dot_index - 1;
+ while (ccf >= 0 && cc >= 0) {
+ switch (strf[ccf]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf);
+ FX_INT32 iLiteralLen = wsLiteral.GetLength();
+ cc -= iLiteralLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ }
+ case '9':
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wsValue = CFX_WideStringC(str[cc]) + wsValue;
+ cc--;
+ ccf--;
+ break;
+ case 'z':
+ if (FX_IsDigit(str[cc])) {
+ wsValue = CFX_WideStringC(str[cc]) + wsValue;
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'Z':
+ if (str[cc] != ' ') {
+ if (FX_IsDigit(str[cc])) {
+ wsValue = CFX_WideStringC(str[cc]) + wsValue;
+ cc--;
+ }
+ } else {
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'S':
+ if (str[cc] == '+' || str[cc] == ' ') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 's':
+ if (str[cc] == '+') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 'E': {
+ if (cc >= dot_index) {
+ return FALSE;
+ }
+ FX_BOOL bExpSign = FALSE;
+ while (cc >= 0) {
+ if (str[cc] == 'E' || str[cc] == 'e') {
+ break;
+ }
+ if (FX_IsDigit(str[cc])) {
+ iExponent = iExponent + (str[cc] - '0') * 10;
+ cc--;
+ continue;
+ } else if (str[cc] == '+') {
+ cc--;
+ continue;
+ } else if (cc - iMinusLen + 1 > 0 && !FXSYS_wcsncmp(str + (cc - iMinusLen + 1), (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ bExpSign = TRUE;
+ cc -= iMinusLen;
+ } else {
+ return FALSE;
+ }
+ }
+ cc --;
+ iExponent = bExpSign ? -iExponent : iExponent;
+ ccf--;
+ }
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ FX_INT32 iSymbolLen = wsSymbol.GetLength();
+ cc -= iSymbolLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsSymbol, iSymbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ }
+ break;
+ case 'r':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
+ if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf --;
+ }
+ break;
+ case 'R':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'b':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
+ if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf --;
+ }
+ break;
+ case 'B':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case '.':
+ case 'V':
+ case 'v':
+ return FALSE;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ FX_INT32 iSysmbolLen = wsSymbol.GetLength();
+ cc -= iSysmbolLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsSymbol, iSysmbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ bHavePercentSymbol = TRUE;
+ }
+ break;
+ case '8':
+ return FALSE;
+ case ',': {
+ if (cc >= 0) {
+ cc -= iGroupLen - 1;
+ if (cc >= 0 && FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsGroupSymbol, iGroupLen) == 0) {
+ cc--;
+ } else {
+ cc += iGroupLen - 1;
+ }
+ }
+ ccf--;
+ }
+ break;
+ case '(':
+ if (str[cc] == L'(') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ case ')':
+ if (str[cc] == L')') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ default:
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ }
+ }
+ if (cc >= 0) {
+ if (str[cc] == '-') {
+ bNeg = TRUE;
+ cc --;
+ }
+ if (cc >= 0) {
+ return FALSE;
+ }
+ }
+ if (dot_index < len && (dwFormatStyle & FX_NUMSTYLE_DotVorv)) {
+ wsValue += '.';
+ }
+ if (!bReverseParse) {
+ ccf = dot_index_f + 1;
+ cc = (dot_index == len) ? len : dot_index + 1;
+ while (cc < len && ccf < lenf) {
+ switch (strf[ccf]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
+ FX_INT32 iLiteralLen = wsLiteral.GetLength();
+ if (cc + iLiteralLen > len || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc += iLiteralLen;
+ ccf++;
+ break;
+ }
+ case '9':
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ {
+ wsValue += str[cc];
+ }
+ cc++;
+ ccf++;
+ break;
+ case 'z':
+ if (FX_IsDigit(str[cc])) {
+ wsValue += str[cc];
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'Z':
+ if (str[cc] != ' ') {
+ if (FX_IsDigit(str[cc])) {
+ wsValue += str[cc];
+ cc++;
+ }
+ } else {
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'S':
+ if (str[cc] == '+' || str[cc] == ' ') {
+ cc++;
+ } else {
+ if (cc + iMinusLen > len || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ bNeg = TRUE;
+ cc += iMinusLen;
+ }
+ ccf++;
+ break;
+ case 's':
+ if (str[cc] == '+') {
+ cc++;
+ } else {
+ if (cc + iMinusLen > len || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ bNeg = TRUE;
+ cc += iMinusLen;
+ }
+ ccf++;
+ break;
+ case 'E': {
+ if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) {
+ return FALSE;
+ }
+ FX_BOOL bExpSign = FALSE;
+ cc ++;
+ if (cc < len) {
+ if (str[cc] == '+') {
+ cc++;
+ } else if (str[cc] == '-') {
+ bExpSign = TRUE;
+ cc++;
+ }
+ }
+ while (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ break;
+ }
+ iExponent = iExponent * 10 + str[cc] - '0';
+ cc ++;
+ }
+ iExponent = bExpSign ? -iExponent : iExponent;
+ ccf++;
+ }
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ FX_INT32 iSymbolLen = wsSymbol.GetLength();
+ if (cc + iSymbolLen > len || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsSymbol, iSymbolLen)) {
+ return FALSE;
+ }
+ cc += iSymbolLen;
+ ccf++;
+ }
+ break;
+ case 'c':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
+ if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'C':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'd':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
+ if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'D':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case '.':
+ case 'V':
+ case 'v':
+ return FALSE;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ FX_INT32 iSysmbolLen = wsSymbol.GetLength();
+ if (cc + iSysmbolLen <= len && !FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsSymbol, iSysmbolLen)) {
+ cc += iSysmbolLen;
+ }
+ ccf++;
+ bHavePercentSymbol = TRUE;
+ }
+ break;
+ case '8': {
+ while (ccf < lenf && strf[ccf] == '8') {
+ ccf++;
+ }
+ while (cc < len && FX_IsDigit(str[cc])) {
+ wsValue += str[cc];
+ cc++;
+ }
+ }
+ break;
+ case ',': {
+ if (cc + iGroupLen <= len && FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsGroupSymbol, iGroupLen) == 0) {
+ cc += iGroupLen;
+ }
+ ccf++;
+ }
+ break;
+ case '(':
+ if (str[cc] == L'(') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ break;
+ case ')':
+ if (str[cc] == L')') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ break;
+ default:
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ }
+ }
+ if (cc != len) {
+ return FALSE;
+ }
+ }
+ if (iExponent || bHavePercentSymbol) {
+ CFX_Decimal decimal = CFX_Decimal(wsValue);
+ if (iExponent) {
+ decimal = decimal * CFX_Decimal(FXSYS_pow(10, (FX_FLOAT)iExponent));
+ }
+ if (bHavePercentSymbol) {
+ decimal = decimal / CFX_Decimal(100);
+ }
+ wsValue = decimal;
+ }
+ if (bNeg) {
+ wsValue = CFX_WideStringC('-') + wsValue;
+ }
+ return TRUE;
+}
+FX_DATETIMETYPE CFX_FormatString::GetDateTimeFormat(const CFX_WideString& wsPattern, IFX_Locale*& pLocale, CFX_WideString &wsDatePattern, CFX_WideString &wsTimePattern)
+{
+ pLocale = NULL;
+ CFX_WideString wsTempPattern;
+ FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown;
+ FX_INT32 ccf = 0;
+ FX_INT32 iLenf = wsPattern.GetLength();
+ FX_LPCWSTR pStr = (FX_LPCWSTR)wsPattern;
+ FX_INT32 iFindCategory = 0;
+ FX_BOOL bBraceOpen = FALSE;
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ FX_INT32 iCurChar = ccf;
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ wsTempPattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1);
+ } else if (!bBraceOpen && iFindCategory != 3 && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
+ CFX_WideString wsCategory(pStr[ccf]);
+ ccf++;
+ while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' && pStr[ccf] != '(') {
+ if (pStr[ccf] == 'T') {
+ wsDatePattern = wsPattern.Left(ccf);
+ wsTimePattern = wsPattern.Right(wsPattern.GetLength() - ccf);
+ wsTimePattern.SetAt(0, ' ');
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ return FX_DATETIMETYPE_DateTime;
+ }
+ wsCategory += pStr[ccf];
+ ccf++;
+ }
+ if (!(iFindCategory & 1) && wsCategory == FX_WSTRC(L"date")) {
+ iFindCategory |= 1;
+ eCategory = FX_LOCALECATEGORY_Date;
+ if (iFindCategory & 2) {
+ iFindCategory = 4;
+ }
+ } else if (!(iFindCategory & 2) && wsCategory == FX_WSTRC(L"time")) {
+ iFindCategory |= 2;
+ eCategory = FX_LOCALECATEGORY_Time;
+ } else if (wsCategory == FX_WSTRC(L"datetime")) {
+ iFindCategory = 3;
+ eCategory = FX_LOCALECATEGORY_DateTime;
+ } else {
+ continue;
+ }
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '(') {
+ ccf++;
+ CFX_WideString wsLCID;
+ while (ccf < iLenf && pStr[ccf] != ')') {
+ wsLCID += pStr[ccf++];
+ }
+ pLocale = GetPatternLocale(wsLCID);
+ } else if (pStr[ccf] == '{') {
+ bBraceOpen = TRUE;
+ break;
+ } else if (pStr[ccf] == '.') {
+ CFX_WideString wsSubCategory;
+ ccf++;
+ while (ccf < iLenf && pStr[ccf] != '(' && pStr[ccf] != '{') {
+ wsSubCategory += pStr[ccf++];
+ }
+ FX_DWORD dwSubHash = FX_HashCode_String_GetW(wsSubCategory, wsSubCategory.GetLength());
+ FX_LOCALEDATETIMESUBCATEGORY eSubCategory = FX_LOCALEDATETIMESUBCATEGORY_Medium;
+ for (FX_INT32 i = 0; i < g_iFXLocaleDateTimeSubCatCount; i++) {
+ if (g_FXLocaleDateTimeSubCatData[i].uHash == dwSubHash) {
+ eSubCategory = (FX_LOCALEDATETIMESUBCATEGORY)g_FXLocaleDateTimeSubCatData[i].eSubCategory;
+ break;
+ }
+ }
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ FXSYS_assert(pLocale != NULL);
+ switch (eCategory) {
+ case FX_LOCALECATEGORY_Date:
+ pLocale->GetDatePattern(eSubCategory, wsDatePattern);
+ wsDatePattern = wsTempPattern + wsDatePattern;
+ break;
+ case FX_LOCALECATEGORY_Time:
+ pLocale->GetTimePattern(eSubCategory, wsTimePattern);
+ wsTimePattern = wsTempPattern + wsTimePattern;
+ break;
+ case FX_LOCALECATEGORY_DateTime:
+ pLocale->GetDatePattern(eSubCategory, wsDatePattern);
+ wsDatePattern = wsTempPattern + wsDatePattern;
+ pLocale->GetTimePattern(eSubCategory, wsTimePattern);
+ break;
+ default:
+ break;
+ }
+ wsTempPattern.Empty();
+ continue;
+ }
+ ccf++;
+ }
+ } else if (pStr[ccf] == '}') {
+ bBraceOpen = FALSE;
+ if (!wsTempPattern.IsEmpty()) {
+ if (eCategory == FX_LOCALECATEGORY_Time) {
+ wsTimePattern = wsTempPattern;
+ } else if (eCategory == FX_LOCALECATEGORY_Date) {
+ wsDatePattern = wsTempPattern;
+ }
+ wsTempPattern.Empty();
+ }
+ } else {
+ wsTempPattern += pStr[ccf];
+ }
+ ccf++;
+ }
+ if (!wsTempPattern.IsEmpty()) {
+ if (eCategory == FX_LOCALECATEGORY_Date) {
+ wsDatePattern += wsTempPattern;
+ } else {
+ wsTimePattern += wsTempPattern;
+ }
+ }
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ if (!iFindCategory) {
+ wsTimePattern.Empty();
+ wsDatePattern = wsPattern;
+ }
+ return (FX_DATETIMETYPE)iFindCategory;
+}
+static FX_BOOL FX_ParseLocaleDate(const CFX_WideString& wsDate, const CFX_WideString& wsDatePattern, IFX_Locale* pLocale, CFX_Unitime &datetime, FX_INT32 &cc)
+{
+ FX_INT32 year = 1900;
+ FX_INT32 month = 1;
+ FX_INT32 day = 1;
+ FX_INT32 ccf = 0;
+ FX_LPCWSTR str = (FX_LPCWSTR)wsDate;
+ FX_INT32 len = wsDate.GetLength();
+ FX_LPCWSTR strf = (FX_LPCWSTR)wsDatePattern;
+ FX_INT32 lenf = wsDatePattern.GetLength();
+ while (cc < len && ccf < lenf) {
+ if (strf[ccf] == '\'') {
+ CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
+ FX_INT32 iLiteralLen = wsLiteral.GetLength();
+ if (cc + iLiteralLen > len || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc += iLiteralLen;
+ ccf++;
+ continue;
+ } else if (FX_Local_Find(gs_wsDateSymbols, strf[ccf]) < 0) {
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ continue;
+ }
+ FX_DWORD dwSymbolNum = 1;
+ FX_DWORD dwSymbol = strf[ccf++];
+ while (ccf < lenf && strf[ccf] == dwSymbol) {
+ ccf++;
+ dwSymbolNum++;
+ }
+ dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
+ if (dwSymbol == FXBSTR_ID(0, 0, 'D', '1')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ day = str[cc++] - '0';
+ if (cc < len && FX_IsDigit(str[cc])) {
+ day = day * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'D', '2')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ day = str[cc++] - '0';
+ if (cc < len) {
+ day = day * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '1')) {
+ int i = 0;
+ while (cc < len && i < 3 && FX_IsDigit(str[cc])) {
+ cc++;
+ i++;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '3')) {
+ cc += 3;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ month = str[cc++] - '0';
+ if (cc < len && FX_IsDigit(str[cc])) {
+ month = month * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ month = str[cc++] - '0';
+ if (cc < len) {
+ month = month * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '3')) {
+ CFX_WideString wsMonthNameAbbr;
+ FX_WORD i = 0;
+ for (; i < 12; i++) {
+ pLocale->GetMonthName(i, wsMonthNameAbbr, TRUE);
+ if (wsMonthNameAbbr.IsEmpty()) {
+ continue;
+ }
+ if (!FXSYS_wcsncmp((FX_LPCWSTR)wsMonthNameAbbr, str + cc, wsMonthNameAbbr.GetLength())) {
+ break;
+ }
+ }
+ if (i < 12) {
+ cc += wsMonthNameAbbr.GetLength();
+ month = i + 1;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '4')) {
+ CFX_WideString wsMonthName;
+ FX_WORD i = 0;
+ for (; i < 12; i++) {
+ pLocale->GetMonthName(i, wsMonthName, FALSE);
+ if (wsMonthName.IsEmpty()) {
+ continue;
+ }
+ if (!FXSYS_wcsncmp((FX_LPCWSTR)wsMonthName, str + cc, wsMonthName.GetLength())) {
+ break;
+ }
+ }
+ if (i < 12) {
+ cc += wsMonthName.GetLength();
+ month = i + 1;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '1')) {
+ cc += 1;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '3')) {
+ CFX_WideString wsDayNameAbbr;
+ FX_WORD i = 0;
+ for (; i < 7; i++) {
+ pLocale->GetDayName(i, wsDayNameAbbr, TRUE);
+ if (wsDayNameAbbr.IsEmpty()) {
+ continue;
+ }
+ if (!FXSYS_wcsncmp((FX_LPCWSTR)wsDayNameAbbr, str + cc, wsDayNameAbbr.GetLength())) {
+ break;
+ }
+ }
+ if (i < 12) {
+ cc += wsDayNameAbbr.GetLength();
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '4')) {
+ CFX_WideString wsDayName;
+ FX_INT32 i = 0;
+ for (; i < 7; i++) {
+ pLocale->GetDayName(i, wsDayName, FALSE);
+ if (wsDayName == L"") {
+ continue;
+ }
+ if (!FXSYS_wcsncmp((FX_LPCWSTR)wsDayName, str + cc, wsDayName.GetLength())) {
+ break;
+ }
+ }
+ if (i < 12) {
+ cc += wsDayName.GetLength();
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'e', '1')) {
+ cc += 1;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'G', '1')) {
+ cc += 2;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '2')) {
+ if (cc + 2 > len) {
+ return FALSE;
+ }
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ year = str[cc++] - '0';
+ if (cc >= len || !FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ year = year * 10 + str[cc++] - '0';
+ if (year <= 29) {
+ year += 2000;
+ } else {
+ year += 1900;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '4')) {
+ int i = 0;
+ year = 0;
+ if (cc + 4 > len) {
+ return FALSE;
+ }
+ while (i < 4) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ year = year * 10 + str[cc] - '0';
+ cc++;
+ i++;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'w', '1')) {
+ cc += 1;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'W', '2')) {
+ cc += 2;
+ }
+ }
+ CFX_Unitime ut;
+ ut.Set(year, month, day);
+ datetime = datetime + ut;
+ return cc;
+}
+static void FX_ResolveZone(FX_BYTE& wHour, FX_BYTE& wMinute, FX_TIMEZONE tzDiff, IFX_Locale* pLocale)
+{
+ FX_INT32 iMinuteDiff = wHour * 60 + wMinute;
+ FX_TIMEZONE tzLocale;
+ pLocale->GetTimeZone(tzLocale);
+ iMinuteDiff += tzLocale.tzHour * 60 + (tzLocale.tzHour < 0 ? -tzLocale.tzMinute : tzLocale.tzMinute);
+ iMinuteDiff -= tzDiff.tzHour * 60 + (tzDiff.tzHour < 0 ? -tzDiff.tzMinute : tzDiff.tzMinute);
+ while (iMinuteDiff > 1440) {
+ iMinuteDiff -= 1440;
+ }
+ while (iMinuteDiff < 0) {
+ iMinuteDiff += 1440;
+ }
+ wHour = iMinuteDiff / 60;
+ wMinute = iMinuteDiff % 60;
+}
+static FX_BOOL FX_ParseLocaleTime(const CFX_WideString& wsTime, const CFX_WideString& wsTimePattern, IFX_Locale* pLocale, CFX_Unitime &datetime, FX_INT32 &cc)
+{
+ FX_BYTE hour = 0;
+ FX_BYTE minute = 0;
+ FX_BYTE second = 0;
+ FX_WORD millisecond = 0;
+ FX_INT32 ccf = 0;
+ FX_LPCWSTR str = (FX_LPCWSTR)wsTime;
+ int len = wsTime.GetLength();
+ FX_LPCWSTR strf = (FX_LPCWSTR)wsTimePattern;
+ int lenf = wsTimePattern.GetLength();
+ FX_BOOL bHasA = FALSE;
+ FX_BOOL bPM = FALSE;
+ while (cc < len && ccf < lenf) {
+ if (strf[ccf] == '\'') {
+ CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
+ FX_INT32 iLiteralLen = wsLiteral.GetLength();
+ if (cc + iLiteralLen > len || FXSYS_wcsncmp(str + cc, (FX_LPCWSTR)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc += iLiteralLen;
+ ccf++;
+ continue;
+ } else if (FX_Local_Find(gs_wsTimeSymbols, strf[ccf]) == -1) {
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ continue;
+ }
+ FX_DWORD dwSymbolNum = 1;
+ FX_DWORD dwSymbol = strf[ccf++];
+ while (ccf < lenf && strf[ccf] == dwSymbol) {
+ ccf++;
+ dwSymbolNum++;
+ }
+ dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
+ if (dwSymbol == FXBSTR_ID(0, 0, 'k', '1') || dwSymbol == FXBSTR_ID(0, 0, 'H', '1') || dwSymbol == FXBSTR_ID(0, 0, 'h', '1') || dwSymbol == FXBSTR_ID(0, 0, 'K', '1')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ hour = str[cc++] - '0';
+ if (cc < len && FX_IsDigit(str[cc])) {
+ hour = hour * 10 + str[cc++] - '0';
+ }
+ if (dwSymbol == FXBSTR_ID(0, 0, 'K', '1') && hour == 24) {
+ hour = 0;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '2') || dwSymbol == FXBSTR_ID(0, 0, 'H', '2') || dwSymbol == FXBSTR_ID(0, 0, 'h', '2') || dwSymbol == FXBSTR_ID(0, 0, 'K', '2')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ hour = str[cc++] - '0';
+ if (cc >= len) {
+ return FALSE;
+ }
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ hour = hour * 10 + str[cc++] - '0';
+ if (dwSymbol == FXBSTR_ID(0, 0, 'K', '2') && hour == 24) {
+ hour = 0;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ minute = str[cc++] - '0';
+ if (cc < len && FX_IsDigit(str[cc])) {
+ minute = minute * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ minute = str[cc++] - '0';
+ if (cc >= len) {
+ return FALSE;
+ }
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ minute = minute * 10 + str[cc++] - '0';
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '1')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ second = str[cc++] - '0';
+ if (cc < len && FX_IsDigit(str[cc])) {
+ second = second * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '2')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ second = str[cc++] - '0';
+ if (cc >= len) {
+ return FALSE;
+ }
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ second = second * 10 + str[cc++] - '0';
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'F', '3')) {
+ if (cc + 3 >= len) {
+ return FALSE;
+ }
+ int i = 0;
+ while (i < 3) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ millisecond = millisecond * 10 + str[cc++] - '0';
+ i++;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'A', '1')) {
+ CFX_WideString wsAM;
+ pLocale->GetMeridiemName(wsAM, TRUE);
+ CFX_WideString wsPM;
+ pLocale->GetMeridiemName(wsPM, FALSE);
+ if ((cc + wsAM.GetLength() <= len) && (CFX_WideStringC(str + cc, wsAM.GetLength()) == wsAM)) {
+ cc += wsAM.GetLength();
+ bHasA = TRUE;
+ } else if ((cc + wsPM.GetLength() <= len) && (CFX_WideStringC(str + cc, wsPM.GetLength()) == wsPM)) {
+ cc += wsPM.GetLength();
+ bHasA = TRUE;
+ bPM = TRUE;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Z', '1')) {
+ if (cc + 3 > len) {
+ continue;
+ }
+ FX_DWORD dwHash = str[cc++];
+ dwHash = (dwHash << 8) | str[cc++];
+ dwHash = (dwHash << 8) | str[cc++];
+ if (dwHash == FXBSTR_ID(0, 'G', 'M', 'T')) {
+ FX_TIMEZONE tzDiff;
+ tzDiff.tzHour = 0;
+ tzDiff.tzMinute = 0;
+ if (cc < len && (str[cc] == '-' || str[cc] == '+')) {
+ cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff);
+ }
+ FX_ResolveZone(hour, minute, tzDiff, pLocale);
+ } else {
+ FX_LPCLOCALETIMEZONEINFO pTimeZoneInfo = NULL;
+ FX_INT32 iStart = 0, iEnd = g_iFXLocaleTimeZoneCount - 1;
+ do {
+ FX_INT32 iMid = (iStart + iEnd) / 2;
+ FX_LPCLOCALETIMEZONEINFO pInfo = g_FXLocaleTimeZoneData + iMid;
+ if (dwHash == pInfo->uHash) {
+ pTimeZoneInfo = pInfo;
+ break;
+ } else if (dwHash < pInfo->uHash) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ if (pTimeZoneInfo) {
+ hour += pTimeZoneInfo->iHour;
+ minute += pTimeZoneInfo->iHour > 0 ? pTimeZoneInfo->iMinute : -pTimeZoneInfo->iMinute;
+ }
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'z', '1')) {
+ if (str[cc] != 'Z') {
+ FX_TIMEZONE tzDiff;
+ cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff);
+ FX_ResolveZone(hour, minute, tzDiff, pLocale);
+ } else {
+ cc++;
+ }
+ }
+ }
+ if (bHasA) {
+ if (bPM) {
+ hour += 12;
+ if (hour == 24) {
+ hour = 12;
+ }
+ } else {
+ if (hour == 12) {
+ hour = 0;
+ }
+ }
+ }
+ CFX_Unitime ut;
+ ut.Set(0, 0, 0, hour, minute, second, millisecond);
+ datetime = datetime + ut;
+ return cc;
+}
+FX_BOOL CFX_FormatString::ParseDateTime(const CFX_WideString& wsSrcDateTime, const CFX_WideString& wsPattern, FX_DATETIMETYPE eDateTimeType, CFX_Unitime& dtValue)
+{
+ dtValue.Set(0);
+ if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsDatePattern, wsTimePattern;
+ IFX_Locale* pLocale = NULL;
+ FX_DATETIMETYPE eCategory = GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
+ if (!pLocale) {
+ return FALSE;
+ }
+ if (eCategory == FX_DATETIMETYPE_Unknown) {
+ eCategory = eDateTimeType;
+ }
+ if (eCategory == FX_DATETIMETYPE_Unknown) {
+ return FALSE;
+ }
+ if (eCategory == FX_DATETIMETYPE_TimeDate) {
+ FX_INT32 iStart = 0;
+ if (!FX_ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue, iStart)) {
+ return FALSE;
+ }
+ if (!FX_ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue, iStart)) {
+ return FALSE;
+ }
+ } else {
+ FX_INT32 iStart = 0;
+ if ((eCategory & FX_DATETIMETYPE_Date) && !FX_ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue, iStart)) {
+ return FALSE;
+ }
+ if ((eCategory & FX_DATETIMETYPE_Time) && !FX_ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue, iStart)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL CFX_FormatString::ParseZero(const CFX_WideString& wsSrcText, const CFX_WideString& wsPattern)
+{
+ CFX_WideString wsTextFormat;
+ IFX_Locale* pLocale = GetTextFormat(wsPattern, FX_WSTRC(L"zero"), wsTextFormat);
+ FX_INT32 iText = 0, iPattern = 0;
+ FX_LPCWSTR pStrText = (FX_LPCWSTR)wsSrcText;
+ FX_INT32 iLenText = wsSrcText.GetLength();
+ FX_LPCWSTR pStrPattern = (FX_LPCWSTR)wsTextFormat;
+ FX_INT32 iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern && iText < iLenText) {
+ if (pStrPattern[iPattern] == '\'') {
+ CFX_WideString wsLiteral = FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ FX_INT32 iLiteralLen = wsLiteral.GetLength();
+ if (iText + iLiteralLen > iLenText || FXSYS_wcsncmp(pStrText + iText, (FX_LPCWSTR)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ iText += iLiteralLen;
+ iPattern++;
+ continue;
+ } else if (pStrPattern[iPattern] != pStrText[iText]) {
+ return FALSE;
+ } else {
+ iText++;
+ iPattern++;
+ }
+ }
+ return iPattern == iLenPattern && iText == iLenText;
+}
+FX_BOOL CFX_FormatString::ParseNull(const CFX_WideString& wsSrcText, const CFX_WideString& wsPattern)
+{
+ CFX_WideString wsTextFormat;
+ IFX_Locale* pLocale = GetTextFormat(wsPattern, FX_WSTRC(L"null"), wsTextFormat);
+ FX_INT32 iText = 0, iPattern = 0;
+ FX_LPCWSTR pStrText = (FX_LPCWSTR)wsSrcText;
+ FX_INT32 iLenText = wsSrcText.GetLength();
+ FX_LPCWSTR pStrPattern = (FX_LPCWSTR)wsTextFormat;
+ FX_INT32 iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern && iText < iLenText) {
+ if (pStrPattern[iPattern] == '\'') {
+ CFX_WideString wsLiteral = FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ FX_INT32 iLiteralLen = wsLiteral.GetLength();
+ if (iText + iLiteralLen > iLenText || FXSYS_wcsncmp(pStrText + iText, (FX_LPCWSTR)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ iText += iLiteralLen;
+ iPattern++;
+ continue;
+ } else if (pStrPattern[iPattern] != pStrText[iText]) {
+ return FALSE;
+ } else {
+ iText++;
+ iPattern++;
+ }
+ }
+ return iPattern == iLenPattern && iText == iLenText;
+}
+FX_BOOL CFX_FormatString::FormatText(const CFX_WideString& wsSrcText, const CFX_WideString& wsPattern, CFX_WideString& wsOutput)
+{
+ if (wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ FX_INT32 iLenText = wsSrcText.GetLength();
+ if (iLenText == 0) {
+ return FALSE;
+ }
+ CFX_WideString wsTextFormat;
+ IFX_Locale* pLocale = GetTextFormat(wsPattern, FX_WSTRC(L"text"), wsTextFormat);
+ FX_INT32 iText = 0, iPattern = 0;
+ FX_LPCWSTR pStrText = (FX_LPCWSTR)wsSrcText;
+ FX_LPCWSTR pStrPattern = (FX_LPCWSTR)wsTextFormat;
+ FX_INT32 iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern) {
+ switch (pStrPattern[iPattern]) {
+ case '\'': {
+ wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ iPattern++;
+ break;
+ }
+ case 'A':
+ if (iText >= iLenText || !FX_IsAlpha(pStrText[iText])) {
+ return FALSE;
+ }
+ wsOutput += pStrText[iText++];
+ iPattern++;
+ break;
+ case 'X':
+ if (iText >= iLenText) {
+ return FALSE;
+ }
+ wsOutput += pStrText[iText++];
+ iPattern++;
+ break;
+ case 'O':
+ case '0':
+ if (iText >= iLenText || (!FX_IsDigit(pStrText[iText]) && !FX_IsAlpha(pStrText[iText]))) {
+ return FALSE;
+ }
+ wsOutput += pStrText[iText++];
+ iPattern++;
+ break;
+ case '9':
+ if (iText >= iLenText || !FX_IsDigit(pStrText[iText])) {
+ return FALSE;
+ }
+ wsOutput += pStrText[iText++];
+ iPattern++;
+ break;
+ default:
+ wsOutput += pStrPattern[iPattern++];
+ break;
+ }
+ }
+ return iText == iLenText;
+}
+static FX_INT32 FX_GetNumTrailingLimit(const CFX_WideString& wsFormat, int iDotPos, FX_BOOL &bTrimTailZeros)
+{
+ if (iDotPos < 0) {
+ return 0;
+ }
+ FX_INT32 iCount = wsFormat.GetLength();
+ FX_INT32 iTreading = 0;
+ for (iDotPos ++; iDotPos < iCount; iDotPos ++) {
+ FX_WCHAR wc = wsFormat[iDotPos];
+ if (wc == L'z' || wc == L'9' || wc == 'Z') {
+ iTreading ++;
+ bTrimTailZeros = (wc == L'9' ? FALSE : TRUE);
+ }
+ }
+ return iTreading;
+}
+FX_BOOL CFX_FormatString::FormatStrNum(FX_WSTR wsInputNum, const CFX_WideString& wsPattern, CFX_WideString& wsOutput)
+{
+ if (wsInputNum.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ FX_INT32 dot_index_f = -1;
+ FX_DWORD dwNumStyle = 0;
+ CFX_WideString wsNumFormat;
+ IFX_Locale* pLocale = GetNumericFormat(wsPattern, dot_index_f, dwNumStyle, wsNumFormat);
+ if (!pLocale || wsNumFormat.IsEmpty()) {
+ return FALSE;
+ }
+ FX_INT32 cc = 0, ccf = 0;
+ FX_LPCWSTR strf = (FX_LPCWSTR)wsNumFormat;
+ int lenf = wsNumFormat.GetLength();
+ CFX_WideString wsSrcNum = wsInputNum;
+ wsSrcNum.TrimLeft('0');
+ if (wsSrcNum.IsEmpty() || wsSrcNum[0] == '.') {
+ wsSrcNum.Insert(0, '0');
+ }
+ CFX_Decimal decimal = CFX_Decimal(wsSrcNum);
+ if (dwNumStyle & FX_NUMSTYLE_Percent) {
+ decimal = decimal * CFX_Decimal(100);
+ wsSrcNum = decimal;
+ }
+ FX_INT32 exponent = 0;
+ if (dwNumStyle & FX_NUMSTYLE_Exponent) {
+ int fixed_count = 0;
+ while (ccf < dot_index_f) {
+ switch (strf[ccf]) {
+ case '\'':
+ FX_GetLiteralText(strf, ccf, dot_index_f);
+ break;
+ case '9':
+ case 'z':
+ case 'Z':
+ fixed_count++;
+ break;
+ }
+ ccf++;
+ }
+ int threshold = 1;
+ while (fixed_count > 1) {
+ threshold *= 10;
+ fixed_count--;
+ }
+ if (decimal != CFX_Decimal(0)) {
+ if (decimal < CFX_Decimal(threshold)) {
+ decimal = decimal * CFX_Decimal(10);
+ exponent = -1;
+ while (decimal < CFX_Decimal(threshold)) {
+ decimal = decimal * CFX_Decimal(10);
+ exponent -= 1;
+ }
+ } else if (decimal > CFX_Decimal(threshold)) {
+ threshold *= 10;
+ while (decimal > CFX_Decimal(threshold)) {
+ decimal = decimal / CFX_Decimal(10);
+ exponent += 1;
+ }
+ }
+ }
+ }
+ FX_BOOL bTrimTailZeros = FALSE;
+ FX_INT32 iTreading = FX_GetNumTrailingLimit(wsNumFormat, dot_index_f, bTrimTailZeros);
+ FX_INT32 scale = decimal.GetScale();
+ if (iTreading < scale) {
+ decimal.SetScale(iTreading);
+ wsSrcNum = decimal;
+ }
+ if (bTrimTailZeros && scale > 0 && iTreading > 0) {
+ wsSrcNum.TrimRight((FX_LPCWSTR)L"0");
+ wsSrcNum.TrimRight((FX_LPCWSTR)L".");
+ }
+ CFX_WideString wsGroupSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
+ FX_BOOL bNeg = FALSE;
+ if (wsSrcNum[0] == '-') {
+ bNeg = TRUE;
+ wsSrcNum.Delete(0, 1);
+ }
+ FX_BOOL bAddNeg = FALSE;
+ FX_LPCWSTR str = (FX_LPCWSTR)wsSrcNum;
+ int len = wsSrcNum.GetLength();
+ int dot_index = wsSrcNum.Find('.');
+ if (dot_index == -1) {
+ dot_index = len;
+ }
+ ccf = dot_index_f - 1;
+ cc = dot_index - 1;
+ while (ccf >= 0) {
+ switch (strf[ccf]) {
+ case '9':
+ if (cc >= 0) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ cc--;
+ } else {
+ wsOutput = CFX_WideStringC(L'0') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'z':
+ if (cc >= 0) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ if (str[0] != '0') {
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ }
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'Z':
+ if (cc >= 0) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ if (str[0] == '0') {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ } else {
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ }
+ cc--;
+ } else {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'S':
+ if (bNeg) {
+ CFX_WideString wsMinusSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
+ wsOutput = wsMinusSymbol + wsOutput;
+ bAddNeg = TRUE;
+ } else {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 's':
+ if (bNeg) {
+ CFX_WideString wsMinusSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
+ wsOutput = wsMinusSymbol + wsOutput;
+ bAddNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 'E': {
+ CFX_WideString wsExp;
+ wsExp.Format((FX_LPCWSTR)L"E%+d", exponent);
+ wsOutput = wsExp + wsOutput;
+ }
+ ccf--;
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ wsOutput = wsSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'r':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
+ if (bNeg) {
+ wsOutput = L"CR" + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'R':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
+ if (bNeg) {
+ wsOutput = L"CR" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'b':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
+ if (bNeg) {
+ wsOutput = L"db" + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'B':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
+ if (bNeg) {
+ wsOutput = L"DB" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ wsOutput = wsSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case ',':
+ if (cc >= 0) {
+ wsOutput = wsGroupSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case '(':
+ if (bNeg) {
+ wsOutput = L"(" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ bAddNeg = TRUE;
+ ccf--;
+ break;
+ case ')':
+ if (bNeg) {
+ wsOutput = L")" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf--;
+ break;
+ case '\'':
+ wsOutput = FX_GetLiteralTextReverse(strf, ccf) + wsOutput;
+ ccf--;
+ break;
+ default:
+ wsOutput = CFX_WideStringC(strf[ccf]) + wsOutput;
+ ccf--;
+ }
+ }
+ if (cc >= 0) {
+ int nPos = dot_index % 3;
+ wsOutput.Empty();
+ for (FX_INT32 i = 0; i < dot_index; i++) {
+ if (i % 3 == nPos && i != 0) {
+ wsOutput += wsGroupSymbol;
+ }
+ wsOutput += wsSrcNum[i];
+ }
+ if (dot_index < len) {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsSymbol);
+ wsOutput += wsSymbol;
+ wsOutput += wsSrcNum.Right(len - dot_index - 1);
+ }
+ if (bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput = wsMinusymbol + wsOutput;
+ }
+ return FALSE;
+ }
+ if (dot_index_f == wsNumFormat.GetLength()) {
+ if (!bAddNeg && bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput = wsMinusymbol + wsOutput;
+ }
+ return TRUE;
+ }
+ CFX_WideString wsDotSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
+ if (strf[dot_index_f] == 'V') {
+ wsOutput += wsDotSymbol;
+ } else if (strf[dot_index_f] == '.') {
+ if (dot_index < len) {
+ wsOutput += wsDotSymbol;
+ } else {
+ if (strf[dot_index_f + 1] == '9' || strf[dot_index_f + 1] == 'Z') {
+ wsOutput += wsDotSymbol;
+ }
+ }
+ }
+ ccf = dot_index_f + 1;
+ cc = dot_index + 1;
+ while (ccf < lenf) {
+ switch (strf[ccf]) {
+ case '\'':
+ wsOutput += FX_GetLiteralText(strf, ccf, lenf);
+ ccf++;
+ break;
+ case '9':
+ if (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wsOutput += str[cc];
+ cc++;
+ } else {
+ wsOutput += L'0';
+ }
+ ccf++;
+ break;
+ case 'z':
+ if (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wsOutput += str[cc];
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'Z':
+ if (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wsOutput += str[cc];
+ cc++;
+ } else {
+ wsOutput += L'0';
+ }
+ ccf++;
+ break;
+ case 'E': {
+ CFX_WideString wsExp;
+ wsExp.Format((FX_LPCWSTR)L"E%+d", exponent);
+ wsOutput += wsExp;
+ }
+ ccf++;
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ wsOutput += wsSymbol;
+ }
+ ccf++;
+ break;
+ case 'c':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
+ if (bNeg) {
+ wsOutput += L"CR";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'C':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
+ if (bNeg) {
+ wsOutput += L"CR";
+ } else {
+ wsOutput += L" ";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'd':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
+ if (bNeg) {
+ wsOutput += L"db";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'D':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
+ if (bNeg) {
+ wsOutput += L"DB";
+ } else {
+ wsOutput += L" ";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ wsOutput += wsSymbol;
+ }
+ ccf++;
+ break;
+ case '8': {
+ while (ccf < lenf && strf[ccf] == '8') {
+ ccf++;
+ }
+ while (cc < len && FX_IsDigit(str[cc])) {
+ wsOutput += str[cc];
+ cc++;
+ }
+ }
+ break;
+ case ',':
+ wsOutput += wsGroupSymbol;
+ ccf++;
+ break;
+ case '(':
+ if (bNeg) {
+ wsOutput += '(';
+ } else {
+ wsOutput += ' ';
+ }
+ bAddNeg = TRUE;
+ ccf++;
+ break;
+ case ')':
+ if (bNeg) {
+ wsOutput += ')';
+ } else {
+ wsOutput += ' ';
+ }
+ ccf++;
+ break;
+ default:
+ ccf++;
+ }
+ }
+ if (!bAddNeg && bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput = wsMinusymbol + wsOutput[0] + wsOutput.Mid(1, wsOutput.GetLength() - 1);
+ }
+ return TRUE;
+}
+FX_BOOL CFX_FormatString::FormatLCNumeric(CFX_LCNumeric& lcNum, const CFX_WideString& wsPattern, CFX_WideString& wsOutput)
+{
+ FX_INT32 dot_index_f = -1;
+ FX_DWORD dwNumStyle = 0;
+ CFX_WideString wsNumFormat;
+ IFX_Locale* pLocale = GetNumericFormat(wsPattern, dot_index_f, dwNumStyle, wsNumFormat);
+ if (!pLocale || wsNumFormat.IsEmpty()) {
+ return FALSE;
+ }
+ FX_INT32 cc = 0, ccf = 0;
+ FX_LPCWSTR strf = (FX_LPCWSTR)wsNumFormat;
+ int lenf = wsNumFormat.GetLength();
+ double dbOrgRaw = lcNum.GetDouble();
+ double dbRetValue = dbOrgRaw;
+ if (dwNumStyle & FX_NUMSTYLE_Percent) {
+ dbRetValue *= 100;
+ }
+ FX_INT32 exponent = 0;
+ if (dwNumStyle & FX_NUMSTYLE_Exponent) {
+ int fixed_count = 0;
+ while (ccf < dot_index_f) {
+ switch (strf[ccf]) {
+ case '\'':
+ FX_GetLiteralText(strf, ccf, dot_index_f);
+ break;
+ case '9':
+ case 'z':
+ case 'Z':
+ fixed_count++;
+ break;
+ }
+ ccf++;
+ }
+ int threshold = 1;
+ while (fixed_count > 1) {
+ threshold *= 10;
+ fixed_count--;
+ }
+ if (dbRetValue != 0) {
+ if (dbRetValue < threshold) {
+ dbRetValue *= 10;
+ exponent = -1;
+ while (dbRetValue < threshold) {
+ dbRetValue *= 10;
+ exponent -= 1;
+ }
+ } else if (dbRetValue > threshold) {
+ threshold *= 10;
+ while (dbRetValue > threshold) {
+ dbRetValue /= 10;
+ exponent += 1;
+ }
+ }
+ }
+ }
+ if (dwNumStyle & (FX_NUMSTYLE_Percent | FX_NUMSTYLE_Exponent)) {
+ lcNum = CFX_LCNumeric(dbRetValue);
+ }
+ FX_BOOL bTrimTailZeros = FALSE;
+ FX_INT32 iTreading = FX_GetNumTrailingLimit(wsNumFormat, dot_index_f, bTrimTailZeros);
+ CFX_WideString wsNumeric = lcNum.ToString(iTreading, bTrimTailZeros);
+ if (wsNumeric.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsGroupSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
+ FX_BOOL bNeg = FALSE;
+ if (wsNumeric[0] == '-') {
+ bNeg = TRUE;
+ wsNumeric.Delete(0, 1);
+ }
+ FX_BOOL bAddNeg = FALSE;
+ FX_LPCWSTR str = (FX_LPCWSTR)wsNumeric;
+ int len = wsNumeric.GetLength();
+ int dot_index = wsNumeric.Find('.');
+ if (dot_index == -1) {
+ dot_index = len;
+ }
+ ccf = dot_index_f - 1;
+ cc = dot_index - 1;
+ while (ccf >= 0) {
+ switch (strf[ccf]) {
+ case '9':
+ if (cc >= 0) {
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ cc--;
+ } else {
+ wsOutput = CFX_WideStringC(L'0') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'z':
+ if (cc >= 0) {
+ if (lcNum.m_Integral != 0) {
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ }
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'Z':
+ if (cc >= 0) {
+ if (lcNum.m_Integral == 0) {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ } else {
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ }
+ cc--;
+ } else {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'S':
+ if (bNeg) {
+ CFX_WideString wsMinusSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
+ wsOutput = wsMinusSymbol + wsOutput;
+ bAddNeg = TRUE;
+ } else {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 's':
+ if (bNeg) {
+ CFX_WideString wsMinusSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
+ wsOutput = wsMinusSymbol + wsOutput;
+ bAddNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 'E': {
+ CFX_WideString wsExp;
+ wsExp.Format((FX_LPCWSTR)L"E%+d", exponent);
+ wsOutput = wsExp + wsOutput;
+ }
+ ccf--;
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ wsOutput = wsSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'r':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
+ if (bNeg) {
+ wsOutput = L"CR" + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'R':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
+ if (bNeg) {
+ wsOutput = L"CR" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'b':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
+ if (bNeg) {
+ wsOutput = L"db" + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'B':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
+ if (bNeg) {
+ wsOutput = L"DB" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ wsOutput = wsSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case ',':
+ if (cc >= 0) {
+ wsOutput = wsGroupSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case '(':
+ if (bNeg) {
+ wsOutput = L"(" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ bAddNeg = TRUE;
+ ccf--;
+ break;
+ case ')':
+ if (bNeg) {
+ wsOutput = L")" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf--;
+ break;
+ case '\'':
+ wsOutput = FX_GetLiteralTextReverse(strf, ccf) + wsOutput;
+ ccf--;
+ break;
+ default:
+ wsOutput = CFX_WideStringC(strf[ccf]) + wsOutput;
+ ccf--;
+ }
+ }
+ if (cc >= 0) {
+ int nPos = dot_index % 3;
+ wsOutput.Empty();
+ for (FX_INT32 i = 0; i < dot_index; i++) {
+ if (i % 3 == nPos && i != 0) {
+ wsOutput += wsGroupSymbol;
+ }
+ wsOutput += wsNumeric[i];
+ }
+ if (dot_index < len) {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsSymbol);
+ wsOutput += wsSymbol;
+ wsOutput += wsNumeric.Right(len - dot_index - 1);
+ }
+ if (bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput = wsMinusymbol + wsOutput;
+ }
+ return FALSE;
+ }
+ if (dot_index_f == wsNumFormat.GetLength()) {
+ if (!bAddNeg && bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput = wsMinusymbol + wsOutput;
+ }
+ return TRUE;
+ }
+ CFX_WideString wsDotSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
+ if (strf[dot_index_f] == 'V') {
+ wsOutput += wsDotSymbol;
+ } else if (strf[dot_index_f] == '.') {
+ if (dot_index < len) {
+ wsOutput += wsDotSymbol;
+ } else {
+ if (strf[dot_index_f + 1] == '9' || strf[dot_index_f + 1] == 'Z') {
+ wsOutput += wsDotSymbol;
+ }
+ }
+ }
+ ccf = dot_index_f + 1;
+ cc = dot_index + 1;
+ while (ccf < lenf) {
+ switch (strf[ccf]) {
+ case '\'':
+ wsOutput += FX_GetLiteralText(strf, ccf, lenf);
+ ccf++;
+ break;
+ case '9':
+ if (cc < len) {
+ wsOutput += str[cc];
+ cc++;
+ } else {
+ wsOutput += L'0';
+ }
+ ccf++;
+ break;
+ case 'z':
+ if (cc < len) {
+ wsOutput += str[cc];
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'Z':
+ if (cc < len) {
+ wsOutput += str[cc];
+ cc++;
+ } else {
+ wsOutput += L'0';
+ }
+ ccf++;
+ break;
+ case 'E': {
+ CFX_WideString wsExp;
+ wsExp.Format((FX_LPCWSTR)L"E%+d", exponent);
+ wsOutput += wsExp;
+ }
+ ccf++;
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ wsOutput += wsSymbol;
+ }
+ ccf++;
+ break;
+ case 'c':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
+ if (bNeg) {
+ wsOutput += L"CR";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'C':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
+ if (bNeg) {
+ wsOutput += L"CR";
+ } else {
+ wsOutput += L" ";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'd':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
+ if (bNeg) {
+ wsOutput += L"db";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'D':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
+ if (bNeg) {
+ wsOutput += L"DB";
+ } else {
+ wsOutput += L" ";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ wsOutput += wsSymbol;
+ }
+ ccf++;
+ break;
+ case '8': {
+ while (ccf < lenf && strf[ccf] == '8') {
+ ccf++;
+ }
+ while (cc < len && FX_IsDigit(str[cc])) {
+ wsOutput += str[cc];
+ cc++;
+ }
+ }
+ break;
+ case ',':
+ wsOutput += wsGroupSymbol;
+ ccf++;
+ break;
+ case '(':
+ if (bNeg) {
+ wsOutput += '(';
+ } else {
+ wsOutput += ' ';
+ }
+ bAddNeg = TRUE;
+ ccf++;
+ break;
+ case ')':
+ if (bNeg) {
+ wsOutput += ')';
+ } else {
+ wsOutput += ' ';
+ }
+ ccf++;
+ break;
+ default:
+ ccf++;
+ }
+ }
+ if (!bAddNeg && bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput = wsOutput[0] + wsMinusymbol + wsOutput.Mid(1, wsOutput.GetLength() - 1);
+ }
+ return TRUE;
+}
+FX_BOOL CFX_FormatString::FormatNum(const CFX_WideString& wsSrcNum, const CFX_WideString& wsPattern, CFX_WideString& wsOutput)
+{
+ if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ return FormatStrNum(wsSrcNum, wsPattern, wsOutput);
+}
+FX_BOOL CFX_FormatString::FormatNum(FX_FLOAT fNum, const CFX_WideString& wsPattern, CFX_WideString& wsOutput)
+{
+ if (wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_LCNumeric lcNum(fNum);
+ return FormatLCNumeric(lcNum, wsPattern, wsOutput);
+}
+FX_BOOL FX_DateFromCanonical(const CFX_WideString& wsDate, CFX_Unitime& datetime)
+{
+ FX_INT32 year = 1900;
+ FX_INT32 month = 1;
+ FX_INT32 day = 1;
+ FX_WORD wYear = 0;
+ int cc_start = 0, cc = 0;
+ FX_LPCWSTR str = (FX_LPCWSTR)wsDate;
+ int len = wsDate.GetLength();
+ if(len > 10) {
+ return FALSE;
+ }
+ while (cc < len && cc < 4) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wYear = wYear * 10 + str[cc++] - '0';
+ }
+ year = wYear;
+ if (cc < 4 || wYear < 1900) {
+ return FALSE;
+ }
+ if(cc < len) {
+ if (str[cc] == '-') {
+ cc++;
+ }
+ cc_start = cc;
+ FX_BYTE tmpM = 0;
+ while (cc < len && cc < cc_start + 2) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ tmpM = tmpM * 10 + str[cc++] - '0';
+ }
+ month = tmpM;
+ if (cc == cc_start + 1 || tmpM > 12 || tmpM < 1) {
+ return FALSE;
+ }
+ if(cc < len) {
+ if (str[cc] == '-') {
+ cc++;
+ }
+ FX_BYTE tmpD = 0;
+ cc_start = cc;
+ while (cc < len && cc < cc_start + 2) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ tmpD = tmpD * 10 + str[cc++] - '0';
+ }
+ day = tmpD;
+ if (tmpD < 1) {
+ return FALSE;
+ }
+ if ((tmpM == 1 || tmpM == 3 || tmpM == 5 || tmpM == 7 || tmpM == 8 || tmpM == 10 || tmpM == 12) && tmpD > 31) {
+ return FALSE;
+ }
+ if((tmpM == 4 || tmpM == 6 || tmpM == 9 || tmpM == 11) && tmpD > 30) {
+ return FALSE;
+ }
+ FX_BOOL iLeapYear;
+ if((wYear % 4 == 0 && wYear % 100 != 0 ) || wYear % 400 == 0) {
+ iLeapYear = TRUE;
+ } else {
+ iLeapYear = FALSE;
+ }
+ if ((iLeapYear && tmpM == 2 && tmpD > 29) || (!iLeapYear && tmpM == 2 && tmpD > 28)) {
+ return FALSE;
+ }
+ }
+ }
+ CFX_Unitime ut;
+ ut.Set(year, month, day);
+ datetime = datetime + ut;
+ return TRUE;
+}
+FX_BOOL FX_TimeFromCanonical(FX_WSTR wsTime, CFX_Unitime& datetime, IFX_Locale* pLocale)
+{
+ if (wsTime.GetLength() == 0) {
+ return FALSE;
+ }
+ FX_BYTE hour = 0;
+ FX_BYTE minute = 0;
+ FX_BYTE second = 0;
+ FX_WORD millisecond = 0;
+ int cc_start = 0, cc = cc_start;
+ FX_LPCWSTR str = (FX_LPCWSTR)wsTime.GetPtr();
+ int len = wsTime.GetLength();
+ while (cc < len && cc < 2) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ hour = hour * 10 + str[cc++] - '0';
+ }
+ if (cc < 2 || hour >= 24) {
+ return FALSE;
+ }
+ if(cc < len) {
+ if (str[cc] == ':') {
+ cc++;
+ }
+ cc_start = cc;
+ while (cc < len && cc < cc_start + 2) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ minute = minute * 10 + str[cc++] - '0';
+ }
+ if (cc == cc_start + 1 || minute >= 60) {
+ return FALSE;
+ }
+ if(cc < len) {
+ if (str[cc] == ':') {
+ cc++;
+ }
+ cc_start = cc;
+ while (cc < len && cc < cc_start + 2) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ second = second * 10 + str[cc++] - '0';
+ }
+ if (cc == cc_start + 1 || second >= 60) {
+ return FALSE;
+ }
+ if(cc < len) {
+ if (str[cc] == '.') {
+ cc++;
+ cc_start = cc;
+ while (cc < len && cc < cc_start + 3) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ millisecond = millisecond * 10 + str[cc++] - '0';
+ }
+ if (cc < cc_start + 3 || millisecond >= 1000) {
+ return FALSE;
+ }
+ }
+ if(cc < len) {
+ FX_TIMEZONE tzDiff;
+ tzDiff.tzHour = 0;
+ tzDiff.tzMinute = 0;
+ if (str[cc] != 'Z') {
+ cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff);
+ }
+ FX_ResolveZone(hour, minute, tzDiff, pLocale);
+ }
+ }
+ }
+ }
+ CFX_Unitime ut;
+ ut.Set(0, 0, 0, hour, minute, second, millisecond);
+ datetime = datetime + ut;
+ return TRUE;
+}
+static FX_WORD FX_GetSolarMonthDays(FX_WORD year, FX_WORD month)
+{
+ if (month % 2) {
+ return 31;
+ } else if (month == 2) {
+ return FX_IsLeapYear(year) ? 29 : 28;
+ }
+ return 30;
+}
+static FX_WORD FX_GetWeekDay(FX_WORD year, FX_WORD month, FX_WORD day)
+{
+ FX_WORD g_month_day[] = { 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 };
+ FX_WORD nDays = (year - 1) % 7 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
+ nDays += g_month_day[month - 1] + day;
+ if (FX_IsLeapYear(year) && month > 2) {
+ nDays++;
+ }
+ return nDays % 7;
+}
+static FX_WORD FX_GetWeekOfMonth(FX_WORD year, FX_WORD month, FX_WORD day)
+{
+ FX_WORD week_day = FX_GetWeekDay(year, month, 1);
+ FX_WORD week_index = 0;
+ week_index += day / 7;
+ day = day % 7;
+ if (week_day + day > 7) {
+ week_index++;
+ }
+ return week_index;
+}
+static FX_WORD FX_GetWeekOfYear(FX_WORD year, FX_WORD month, FX_WORD day)
+{
+ FX_WORD nDays = 0;
+ for (FX_WORD i = 1; i < month; i++) {
+ nDays += FX_GetSolarMonthDays(year, i);
+ }
+ nDays += day;
+ FX_WORD week_day = FX_GetWeekDay(year, 1, 1);
+ FX_WORD week_index = 1;
+ week_index += nDays / 7;
+ nDays = nDays % 7;
+ if (week_day + nDays > 7) {
+ week_index++;
+ }
+ return week_index;
+}
+static FX_BOOL FX_DateFormat(const CFX_WideString& wsDatePattern, IFX_Locale *pLocale, const CFX_Unitime &datetime, CFX_WideString& wsResult)
+{
+ FX_BOOL bRet = TRUE;
+ FX_INT32 year = datetime.GetYear();
+ FX_BYTE month = datetime.GetMonth();
+ FX_BYTE day = datetime.GetDay();
+ FX_INT32 ccf = 0;
+ FX_LPCWSTR strf = (FX_LPCWSTR)wsDatePattern;
+ FX_INT32 lenf = wsDatePattern.GetLength();
+ while (ccf < lenf) {
+ if (strf[ccf] == '\'') {
+ wsResult += FX_GetLiteralText(strf, ccf, lenf);
+ ccf++;
+ continue;
+ } else if (FX_Local_Find(gs_wsDateSymbols, strf[ccf]) < 0) {
+ wsResult += strf[ccf++];
+ continue;
+ }
+ FX_DWORD dwSymbolNum = 1;
+ FX_DWORD dwSymbol = strf[ccf++];
+ while (ccf < lenf && strf[ccf] == dwSymbol) {
+ ccf++;
+ dwSymbolNum++;
+ }
+ dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
+ if (dwSymbol == FXBSTR_ID(0, 0, 'D', '1')) {
+ CFX_WideString wsDay;
+ wsDay.Format((FX_LPCWSTR)L"%d", day);
+ wsResult += wsDay;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'D', '2')) {
+ CFX_WideString wsDay;
+ wsDay.Format((FX_LPCWSTR)L"%02d", day);
+ wsResult += wsDay;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '1')) {
+ FX_WORD nDays = 0;
+ for (int i = 1; i < month; i++) {
+ nDays += FX_GetSolarMonthDays(year, i);
+ }
+ nDays += day;
+ CFX_WideString wsDays;
+ wsDays.Format((FX_LPCWSTR)L"%d", nDays);
+ wsResult += wsDays;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '3')) {
+ FX_WORD nDays = 0;
+ for (int i = 1; i < month; i++) {
+ nDays += FX_GetSolarMonthDays(year, i);
+ }
+ nDays += day;
+ CFX_WideString wsDays;
+ wsDays.Format((FX_LPCWSTR)L"%03d", nDays);
+ wsResult += wsDays;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
+ CFX_WideString wsMonth;
+ wsMonth.Format((FX_LPCWSTR)L"%d", month);
+ wsResult += wsMonth;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
+ CFX_WideString wsMonth;
+ wsMonth.Format((FX_LPCWSTR)L"%02d", month);
+ wsResult += wsMonth;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '3')) {
+ CFX_WideString wsTemp;
+ pLocale->GetMonthName(month - 1, wsTemp, TRUE);
+ wsResult += wsTemp;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '4')) {
+ CFX_WideString wsTemp;
+ pLocale->GetMonthName(month - 1, wsTemp, FALSE);
+ wsResult += wsTemp;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '1')) {
+ FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
+ CFX_WideString wsWeekDay;
+ wsWeekDay.Format((FX_LPCWSTR)L"%d", wWeekDay + 1);
+ wsResult += wsWeekDay;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '3')) {
+ FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
+ CFX_WideString wsTemp;
+ pLocale->GetDayName(wWeekDay, wsTemp, TRUE);
+ wsResult += wsTemp;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '4')) {
+ FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
+ if (pLocale) {
+ CFX_WideString wsTemp;
+ pLocale->GetDayName(wWeekDay, wsTemp, FALSE);
+ wsResult += wsTemp;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'e', '1')) {
+ FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
+ CFX_WideString wsWeekDay;
+ wsWeekDay.Format((FX_LPCWSTR)L"%d", wWeekDay ? wWeekDay : 7);
+ wsResult += wsWeekDay;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'G', '1')) {
+ CFX_WideString wsTemp;
+ pLocale->GetEraName(wsTemp, year < 0);
+ wsResult += wsTemp;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '2')) {
+ CFX_WideString wsYear;
+ wsYear.Format((FX_LPCWSTR)L"%02d", year % 100);
+ wsResult += wsYear;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '4')) {
+ CFX_WideString wsYear;
+ wsYear.Format((FX_LPCWSTR)L"%d", year);
+ wsResult += wsYear;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'w', '1')) {
+ FX_WORD week_index = FX_GetWeekOfMonth(year, month, day);
+ CFX_WideString wsWeekInMonth;
+ wsWeekInMonth.Format((FX_LPCWSTR)L"%d", week_index);
+ wsResult += wsWeekInMonth;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'W', '2')) {
+ FX_WORD week_index = FX_GetWeekOfYear(year, month, day);
+ CFX_WideString wsWeekInYear;
+ wsWeekInYear.Format((FX_LPCWSTR)L"%02d", week_index);
+ wsResult += wsWeekInYear;
+ }
+ }
+ return bRet;
+}
+static FX_BOOL FX_TimeFormat(const CFX_WideString& wsTimePattern, IFX_Locale *pLocale, const CFX_Unitime &datetime, CFX_WideString& wsResult)
+{
+ FX_BOOL bGMT = FALSE;
+ FX_BOOL bRet = TRUE;
+ FX_BYTE hour = datetime.GetHour();
+ FX_BYTE minute = datetime.GetMinute();
+ FX_BYTE second = datetime.GetSecond();
+ FX_WORD millisecond = datetime.GetMillisecond();
+ FX_INT32 ccf = 0;
+ FX_LPCWSTR strf = (FX_LPCWSTR)wsTimePattern;
+ FX_INT32 lenf = wsTimePattern.GetLength();
+ FX_WORD wHour = hour;
+ FX_BOOL bPM = FALSE;
+ if (wsTimePattern.Find('A') != -1) {
+ if (wHour >= 12) {
+ bPM = TRUE;
+ }
+ }
+ while (ccf < lenf) {
+ if (strf[ccf] == '\'') {
+ wsResult += FX_GetLiteralText(strf, ccf, lenf);
+ ccf++;
+ continue;
+ } else if (FX_Local_Find(gs_wsTimeSymbols, strf[ccf]) < 0) {
+ wsResult += strf[ccf++];
+ continue;
+ }
+ FX_DWORD dwSymbolNum = 1;
+ FX_DWORD dwSymbol = strf[ccf++];
+ while (ccf < lenf && strf[ccf] == dwSymbol) {
+ ccf++;
+ dwSymbolNum++;
+ }
+ dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
+ if (dwSymbol == FXBSTR_ID(0, 0, 'h', '1')) {
+ if (wHour > 12) {
+ wHour -= 12;
+ }
+ CFX_WideString wsHour;
+ wsHour.Format((FX_LPCWSTR)L"%d", wHour == 0 ? 12 : wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'h', '2')) {
+ if (wHour > 12) {
+ wHour -= 12;
+ }
+ CFX_WideString wsHour;
+ wsHour.Format((FX_LPCWSTR)L"%02d", wHour == 0 ? 12 : wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'K', '1')) {
+ CFX_WideString wsHour;
+ wsHour.Format((FX_LPCWSTR)L"%d", wHour == 0 ? 24 : wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'K', '2')) {
+ CFX_WideString wsHour;
+ wsHour.Format((FX_LPCWSTR)L"%02d", wHour == 0 ? 24 : wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '1')) {
+ if (wHour > 12) {
+ wHour -= 12;
+ }
+ CFX_WideString wsHour;
+ wsHour.Format((FX_LPCWSTR)L"%d", wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'H', '1')) {
+ CFX_WideString wsHour;
+ wsHour.Format((FX_LPCWSTR)L"%d", wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '2')) {
+ if (wHour > 12) {
+ wHour -= 12;
+ }
+ CFX_WideString wsHour;
+ wsHour.Format((FX_LPCWSTR)L"%02d", wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'H', '2')) {
+ CFX_WideString wsHour;
+ wsHour.Format((FX_LPCWSTR)L"%02d", wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
+ CFX_WideString wsMinute;
+ wsMinute.Format((FX_LPCWSTR)L"%d", minute);
+ wsResult += wsMinute;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
+ CFX_WideString wsMinute;
+ wsMinute.Format((FX_LPCWSTR)L"%02d", minute);
+ wsResult += wsMinute;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '1')) {
+ CFX_WideString wsSecond;
+ wsSecond.Format((FX_LPCWSTR)L"%d", second);
+ wsResult += wsSecond;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '2')) {
+ CFX_WideString wsSecond;
+ wsSecond.Format((FX_LPCWSTR)L"%02d", second);
+ wsResult += wsSecond;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'F', '3')) {
+ CFX_WideString wsMilliseconds;
+ wsMilliseconds.Format((FX_LPCWSTR)L"%03d", millisecond);
+ wsResult += wsMilliseconds;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'A', '1')) {
+ CFX_WideString wsMeridiem;
+ pLocale->GetMeridiemName(wsMeridiem, !bPM);
+ wsResult += wsMeridiem;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Z', '1')) {
+ wsResult += FX_WSTRC(L"GMT");
+ FX_TIMEZONE tz;
+ pLocale->GetTimeZone(tz);
+ if (!bGMT && (tz.tzHour != 0 || tz.tzMinute != 0)) {
+ if (tz.tzHour < 0) {
+ wsResult += FX_WSTRC(L"-");
+ } else {
+ wsResult += FX_WSTRC(L"+");
+ }
+ CFX_WideString wsTimezone;
+ wsTimezone.Format((FX_LPCWSTR)L"%02d:%02d", FXSYS_abs(tz.tzHour), tz.tzMinute);
+ wsResult += wsTimezone;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'z', '1')) {
+ FX_TIMEZONE tz;
+ pLocale->GetTimeZone(tz);
+ if (!bGMT && tz.tzHour != 0 && tz.tzMinute != 0) {
+ if (tz.tzHour < 0) {
+ wsResult += FX_WSTRC(L"-");
+ } else {
+ wsResult += FX_WSTRC(L"+");
+ }
+ CFX_WideString wsTimezone;
+ wsTimezone.Format((FX_LPCWSTR)L"%02d:%02d", FXSYS_abs(tz.tzHour), tz.tzMinute);
+ wsResult += wsTimezone;
+ }
+ }
+ }
+ return bRet;
+}
+static FX_BOOL FX_FormatDateTime(const CFX_Unitime& dt, const CFX_WideString& wsDatePattern, const CFX_WideString& wsTimePattern,
+ FX_BOOL bDateFirst, IFX_Locale* pLocale, CFX_WideString& wsOutput)
+{
+ FX_BOOL bRet = TRUE;
+ CFX_WideString wsDateOut, wsTimeOut;
+ if (!wsDatePattern.IsEmpty()) {
+ bRet &= FX_DateFormat(wsDatePattern, pLocale, dt, wsDateOut);
+ }
+ if (!wsTimePattern.IsEmpty()) {
+ bRet &= FX_TimeFormat(wsTimePattern, pLocale, dt, wsTimeOut);
+ }
+ wsOutput = bDateFirst ? wsDateOut + wsTimeOut : wsTimeOut + wsDateOut;
+ return bRet;
+}
+FX_BOOL CFX_FormatString::FormatDateTime(const CFX_WideString& wsSrcDateTime, const CFX_WideString& wsPattern, CFX_WideString& wsOutput)
+{
+ if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsDatePattern, wsTimePattern;
+ IFX_Locale* pLocale = NULL;
+ FX_DATETIMETYPE eCategory = GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
+ if (pLocale == NULL || eCategory == FX_DATETIMETYPE_Unknown) {
+ return FALSE;
+ }
+ CFX_Unitime dt(0);
+ FX_INT32 iT = wsSrcDateTime.Find(L"T");
+ if (iT < 0) {
+ if (eCategory == FX_DATETIMETYPE_Date) {
+ FX_DateFromCanonical(wsSrcDateTime, dt);
+ } else if (eCategory == FX_DATETIMETYPE_Time) {
+ FX_TimeFromCanonical(wsSrcDateTime, dt, pLocale);
+ }
+ } else {
+ FX_DateFromCanonical(wsSrcDateTime.Left(iT), dt);
+ FX_TimeFromCanonical(wsSrcDateTime.Right(wsSrcDateTime.GetLength() - iT - 1), dt, pLocale);
+ }
+ return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, eCategory != FX_DATETIMETYPE_TimeDate, pLocale, wsOutput);
+}
+FX_BOOL CFX_FormatString::FormatDateTime(const CFX_WideString& wsSrcDateTime, const CFX_WideString& wsPattern, CFX_WideString& wsOutput, FX_DATETIMETYPE eDateTimeType)
+{
+ if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsDatePattern, wsTimePattern;
+ IFX_Locale* pLocale = NULL;
+ FX_DATETIMETYPE eCategory = GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
+ if (!pLocale) {
+ return FALSE;
+ }
+ if (eCategory == FX_DATETIMETYPE_Unknown) {
+ if (eDateTimeType == FX_DATETIMETYPE_Time) {
+ wsTimePattern = wsDatePattern;
+ wsDatePattern.Empty();
+ }
+ eCategory = eDateTimeType;
+ }
+ if (eCategory == FX_DATETIMETYPE_Unknown) {
+ return FALSE;
+ }
+ CFX_Unitime dt(0);
+ FX_INT32 iT = wsSrcDateTime.Find(L"T");
+ if (iT < 0) {
+ if (eCategory == FX_DATETIMETYPE_Date && FX_DateFromCanonical(wsSrcDateTime, dt)) {
+ return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, TRUE, pLocale, wsOutput);
+ } else if (eCategory == FX_DATETIMETYPE_Time && FX_TimeFromCanonical(wsSrcDateTime, dt, pLocale)) {
+ return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, TRUE, pLocale, wsOutput);
+ }
+ } else {
+ CFX_WideStringC wsSrcDate((FX_LPCWSTR)wsSrcDateTime, iT);
+ CFX_WideStringC wsSrcTime((FX_LPCWSTR)wsSrcDateTime + iT + 1, wsSrcDateTime.GetLength() - iT - 1);
+ if(wsSrcDate.IsEmpty() || wsSrcTime.IsEmpty()) {
+ return FALSE;
+ }
+ if(FX_DateFromCanonical(wsSrcDate, dt) && FX_TimeFromCanonical(wsSrcTime, dt, pLocale)) {
+ return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, eCategory != FX_DATETIMETYPE_TimeDate, pLocale, wsOutput);
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CFX_FormatString::FormatDateTime(const CFX_Unitime& dt, const CFX_WideString& wsPattern, CFX_WideString& wsOutput)
+{
+ if (wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsDatePattern, wsTimePattern;
+ IFX_Locale* pLocale = NULL;
+ FX_DATETIMETYPE eCategory = GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
+ if (!pLocale) {
+ return FALSE;
+ }
+ return FX_FormatDateTime(dt, wsPattern, wsTimePattern, eCategory != FX_DATETIMETYPE_TimeDate, pLocale, wsOutput);
+}
+FX_BOOL CFX_FormatString::FormatZero(const CFX_WideString& wsPattern, CFX_WideString& wsOutput)
+{
+ if (wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsTextFormat;
+ IFX_Locale* pLocale = GetTextFormat(wsPattern, FX_WSTRC(L"zero"), wsTextFormat);
+ FX_INT32 iPattern = 0;
+ FX_LPCWSTR pStrPattern = (FX_LPCWSTR)wsTextFormat;
+ FX_INT32 iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern) {
+ if (pStrPattern[iPattern] == '\'') {
+ wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ iPattern++;
+ continue;
+ } else {
+ wsOutput += pStrPattern[iPattern++];
+ continue;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL CFX_FormatString::FormatNull(const CFX_WideString& wsPattern, CFX_WideString& wsOutput)
+{
+ if (wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsTextFormat;
+ IFX_Locale* pLocale = GetTextFormat(wsPattern, FX_WSTRC(L"null"), wsTextFormat);
+ FX_INT32 iPattern = 0;
+ FX_LPCWSTR pStrPattern = (FX_LPCWSTR)wsTextFormat;
+ FX_INT32 iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern) {
+ if (pStrPattern[iPattern] == '\'') {
+ wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ iPattern++;
+ continue;
+ } else {
+ wsOutput += pStrPattern[iPattern++];
+ continue;
+ }
+ }
+ return TRUE;
+}
+IFX_Locale* CFX_FormatString::GetPatternLocale(FX_WSTR wsLocale)
+{
+ if (m_bUseLCID) {
+ }
+ return m_pLocaleMgr->GetLocaleByName(wsLocale);
+}
+#define FXMATH_DECIMAL_SCALELIMIT 0x1c
+#define FXMATH_DECIMAL_NEGMASK (0x80000000L)
+#define FXMATH_DECIMAL_FORCEBOOL(x) (!(!(x)))
+#define FXMATH_DECIMAL_MAKEFLAGS(NEG, SCALE) (((SCALE) << 0x10) | ((NEG) ? FXMATH_DECIMAL_NEGMASK : 0))
+#define FXMATH_DECIMAL_FLAGS2NEG(FLAGS) FXMATH_DECIMAL_FORCEBOOL((FLAGS) & FXMATH_DECIMAL_NEGMASK)
+#define FXMATH_DECIMAL_FLAGS2SCALE(FLAGS) ((FX_UINT8)(((FLAGS) & ~FXMATH_DECIMAL_NEGMASK) >> 0x10))
+#define FXMATH_DECIMAL_RSHIFT32BIT(x) ((x)>>0x10>>0x10)
+#define FXMATH_DECIMAL_LSHIFT32BIT(x) ((x)<<0x10<<0x10)
+static inline FX_UINT8 fxmath_decimal_helper_div10(FX_UINT64& phi, FX_UINT64& pmid, FX_UINT64& plo)
+{
+ FX_UINT8 retVal;
+ pmid += FXMATH_DECIMAL_LSHIFT32BIT(phi % 0xA);
+ phi /= 0xA;
+ plo += FXMATH_DECIMAL_LSHIFT32BIT(pmid % 0xA);
+ pmid /= 0xA;
+ retVal = plo % 0xA;
+ plo /= 0xA;
+ return retVal;
+}
+static inline FX_UINT8 fxmath_decimal_helper_div10_any(FX_UINT64 nums[], FX_UINT8 numcount)
+{
+ FX_UINT8 retVal = 0;
+ for(int i = numcount - 1; i > 0; i --) {
+ nums[i - 1] += FXMATH_DECIMAL_LSHIFT32BIT(nums[i] % 0xA);
+ nums[i] /= 0xA;
+ }
+ if(numcount) {
+ retVal = nums[0] % 0xA;
+ nums[0] /= 0xA;
+ }
+ return retVal;
+}
+static inline void fxmath_decimal_helper_mul10(FX_UINT64& phi, FX_UINT64& pmid, FX_UINT64& plo)
+{
+ plo *= 0xA;
+ pmid = pmid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(plo);
+ plo = (FX_UINT32)plo;
+ phi = phi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(pmid);
+ pmid = (FX_UINT32)pmid;
+}
+static inline void fxmath_decimal_helper_mul10_any(FX_UINT64 nums[], FX_UINT8 numcount)
+{
+ nums[0] *= 0xA;
+ for(int i = 1; i < numcount; i++) {
+ nums[i] = nums[i] * 0xA + FXMATH_DECIMAL_RSHIFT32BIT (nums[i - 1]);
+ nums[i - 1] = (FX_UINT32)nums[i - 1];
+ }
+}
+static inline void fxmath_decimal_helper_normalize(FX_UINT64& phi, FX_UINT64& pmid, FX_UINT64& plo)
+{
+ phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid);
+ pmid = (FX_UINT32)pmid;
+ pmid += FXMATH_DECIMAL_RSHIFT32BIT(plo);
+ plo = (FX_UINT32)plo;
+ phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid);
+ pmid = (FX_UINT32)pmid;
+}
+static inline void fxmath_decimal_helper_normalize_any(FX_UINT64 nums[], FX_UINT8 len)
+{
+ {
+ for(int i = len - 2; i > 0; i --) {
+ nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]);
+ nums[i] = (FX_UINT32)nums[i];
+ }
+ }
+ {
+ for(int i = 0; i < len - 1; i ++) {
+ nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]);
+ nums[i] = (FX_UINT32)nums[i];
+ }
+ }
+}
+static inline FX_INT8 fxmath_decimal_helper_raw_compare(FX_UINT32 hi1, FX_UINT32 mid1, FX_UINT32 lo1, FX_UINT32 hi2, FX_UINT32 mid2, FX_UINT32 lo2)
+{
+ FX_INT8 retVal = 0;
+ if (!retVal) {
+ retVal += (hi1 > hi2 ? 1 : (hi1 < hi2 ? -1 : 0));
+ }
+ if (!retVal) {
+ retVal += (mid1 > mid2 ? 1 : (mid1 < mid2 ? -1 : 0));
+ }
+ if (!retVal) {
+ retVal += (lo1 > lo2 ? 1 : (lo1 < lo2 ? -1 : 0));
+ }
+ return retVal;
+}
+static inline FX_INT8 fxmath_decimal_helper_raw_compare_any(FX_UINT64 a[], FX_UINT8 al, FX_UINT64 b[], FX_UINT8 bl)
+{
+ FX_INT8 retVal = 0;
+ for(int i = FX_MAX(al - 1, bl - 1); i >= 0; i --) {
+ FX_UINT64 l = (i >= al ? 0 : a[i]), r = (i >= bl ? 0 : b[i]);
+ retVal += (l > r ? 1 : (l < r ? -1 : 0));
+ if(retVal) {
+ return retVal;
+ }
+ }
+ return retVal;
+}
+static inline void fxmath_decimal_helper_dec_any(FX_UINT64 a[], FX_UINT8 al)
+{
+ for(int i = 0; i < al; i ++) {
+ if(a[i]--) {
+ return;
+ }
+ }
+}
+static inline void fxmath_decimal_helper_inc_any(FX_UINT64 a[], FX_UINT8 al)
+{
+ for(int i = 0; i < al; i ++) {
+ a[i]++;
+ if((FX_UINT32)a[i] == a[i]) {
+ return;
+ }
+ a[i] = 0;
+ }
+}
+static inline void fxmath_decimal_helper_raw_mul(FX_UINT64 a[], FX_UINT8 al, FX_UINT64 b[], FX_UINT8 bl, FX_UINT64 c[], FX_UINT8 cl)
+{
+ assert(al + bl <= cl);
+ {
+ for(int i = 0; i < cl; i++) {
+ c[i] = 0;
+ }
+ }
+ {
+ for(int i = 0; i < al; i++) {
+ for(int j = 0; j < bl; j++) {
+ FX_UINT64 m = (FX_UINT64)a[i] * b[j];
+ c[i + j] += (FX_UINT32)m;
+ c[i + j + 1] += FXMATH_DECIMAL_RSHIFT32BIT(m);
+ }
+ }
+ }
+ {
+ for(int i = 0; i < cl - 1; i++) {
+ c[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(c[i]);
+ c[i] = (FX_UINT32)c[i];
+ }
+ }
+ {
+ for(int i = 0; i < cl; i++) {
+ c[i] = (FX_UINT32)c[i];
+ }
+ }
+}
+static inline void fxmath_decimal_helper_raw_div(FX_UINT64 a[], FX_UINT8 al, FX_UINT64 b[], FX_UINT8 bl, FX_UINT64 c[], FX_UINT8 cl)
+{
+ int i;
+ for(i = 0; i < cl; i++) {
+ c[i] = 0;
+ }
+ FX_UINT64 left[16] = {0}, right[16] = {0};
+ left[0] = 0;
+ for(i = 0; i < al; i++) {
+ right[i] = a[i];
+ }
+ FX_UINT64 tmp[16];
+ while(fxmath_decimal_helper_raw_compare_any(left, al, right, al) <= 0) {
+ FX_UINT64 cur[16];
+ for(i = 0; i < al; i++) {
+ cur[i] = left[i] + right[i];
+ }
+ for(i = al - 1; i >= 0; i--) {
+ if(i) {
+ cur[i - 1] += FXMATH_DECIMAL_LSHIFT32BIT(cur[i] % 2);
+ }
+ cur[i] /= 2;
+ }
+ fxmath_decimal_helper_raw_mul(cur, al, b, bl, tmp, 16);
+ switch(fxmath_decimal_helper_raw_compare_any(tmp, 16, a, al)) {
+ case -1:
+ for(i = 0; i < 16; i++) {
+ left[i] = cur[i];
+ }
+ left[0]++;
+ fxmath_decimal_helper_normalize_any(left, al);
+ break;
+ case 1:
+ for(i = 0; i < 16; i++) {
+ right[i] = cur[i];
+ }
+ fxmath_decimal_helper_dec_any(right, al);
+ break;
+ case 0:
+ for(i = 0; i < FX_MIN(al, cl); i++) {
+ c[i] = cur[i];
+ }
+ return;
+ }
+ }
+ for(i = 0; i < FX_MIN(al, cl); i++) {
+ c[i] = left[i];
+ }
+}
+static inline FX_BOOL fxmath_decimal_helper_outofrange(FX_UINT64 a[], FX_UINT8 al, FX_UINT8 goal)
+{
+ for(int i = goal; i < al; i++) {
+ if(a[i]) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+static inline void fxmath_decimal_helper_shrinkintorange(FX_UINT64 a[], FX_UINT8 al, FX_UINT8 goal, FX_UINT8& scale)
+{
+ FX_BOOL bRoundUp = FALSE;
+ while(scale != 0 && (scale > FXMATH_DECIMAL_SCALELIMIT || fxmath_decimal_helper_outofrange(a, al, goal))) {
+ bRoundUp = fxmath_decimal_helper_div10_any(a, al) >= 5;
+ scale --;
+ }
+ if(bRoundUp) {
+ fxmath_decimal_helper_normalize_any(a, goal);
+ fxmath_decimal_helper_inc_any(a, goal);
+ }
+}
+static inline void fxmath_decimal_helper_truncate(FX_UINT64& phi, FX_UINT64& pmid, FX_UINT64& plo, FX_UINT8& scale, FX_UINT8 minscale = 0)
+{
+ while(scale > minscale) {
+ FX_UINT64 thi = phi, tmid = pmid, tlo = plo;
+ if(fxmath_decimal_helper_div10(thi, tmid, tlo) != 0) {
+ break;
+ }
+ phi = thi, pmid = tmid, plo = tlo;
+ scale--;
+ }
+}
+CFX_Decimal::CFX_Decimal()
+{
+ m_uLo = m_uMid = m_uHi = m_uFlags = 0;
+}
+CFX_Decimal::CFX_Decimal(FX_UINT64 val)
+{
+ m_uLo = (FX_UINT32)val;
+ m_uMid = (FX_UINT32)FXMATH_DECIMAL_RSHIFT32BIT(val);
+ m_uHi = 0;
+ m_uFlags = 0;
+}
+CFX_Decimal::CFX_Decimal(FX_UINT32 val)
+{
+ m_uLo = (FX_UINT32)val;
+ m_uMid = m_uHi = 0;
+ m_uFlags = 0;
+}
+CFX_Decimal::CFX_Decimal(FX_UINT32 lo, FX_UINT32 mid, FX_UINT32 hi, FX_BOOL neg, FX_UINT8 scale)
+{
+ scale = (scale > FXMATH_DECIMAL_SCALELIMIT ? 0 : scale);
+ m_uLo = lo;
+ m_uMid = mid;
+ m_uHi = hi;
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(neg && IsNotZero(), scale);
+}
+CFX_Decimal::CFX_Decimal(FX_INT32 val)
+{
+ if(val >= 0) {
+ *this = CFX_Decimal((FX_UINT32)val);
+ } else {
+ *this = CFX_Decimal((FX_UINT32) - val);
+ SetNegate();
+ }
+}
+CFX_Decimal::CFX_Decimal(FX_INT64 val)
+{
+ if(val >= 0) {
+ *this = CFX_Decimal((FX_UINT64)val);
+ } else {
+ *this = CFX_Decimal((FX_UINT64) - val);
+ SetNegate();
+ }
+}
+CFX_Decimal::CFX_Decimal(FX_FLOAT val, FX_UINT8 scale )
+{
+ FX_FLOAT newval = fabs(val);
+ FX_UINT64 phi, pmid, plo;
+ plo = (FX_UINT64)newval;
+ pmid = (FX_UINT64)(newval / 1e32);
+ phi = (FX_UINT64)(newval / 1e64);
+ newval = FXSYS_fmod(newval, 1.0f);
+ for(FX_UINT8 iter = 0; iter < scale; iter++) {
+ fxmath_decimal_helper_mul10(phi, pmid, plo);
+ newval *= 10;
+ plo += (FX_UINT64)newval;
+ newval = FXSYS_fmod(newval, 1.0f);
+ }
+ plo += FXSYS_round(newval);
+ fxmath_decimal_helper_normalize(phi, pmid, plo);
+ m_uHi = (FX_UINT32)phi;
+ m_uMid = (FX_UINT32)pmid;
+ m_uLo = (FX_UINT32)plo;
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(val < 0 && IsNotZero(), scale);
+}
+CFX_Decimal::CFX_Decimal(FX_WSTR strObj)
+{
+ FX_LPCWSTR str = strObj.GetPtr();
+ FX_LPCWSTR strBound = str + strObj.GetLength();
+ FX_BOOL pointmet = 0;
+ FX_BOOL negmet = 0;
+ FX_UINT8 scale = 0;
+ m_uHi = m_uMid = m_uLo = 0;
+ while (str != strBound && *str == ' ') {
+ str++;
+ }
+ if (str != strBound && *str == '-') {
+ negmet = 1;
+ str++;
+ } else if (str != strBound && *str == '+') {
+ str++;
+ }
+ while (str != strBound && ((*str >= '0' && *str <= '9') || *str == '.') && scale < FXMATH_DECIMAL_SCALELIMIT) {
+ if (*str == '.') {
+ if(pointmet) {
+ goto cont;
+ }
+ pointmet = 1;
+ } else {
+ m_uHi = m_uHi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((FX_UINT64)m_uMid * 0xA);
+ m_uMid = m_uMid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((FX_UINT64)m_uLo * 0xA);
+ m_uLo = m_uLo * 0xA + (*str - '0');
+ if(pointmet) {
+ scale++;
+ }
+ }
+cont:
+ str++;
+ }
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(negmet && IsNotZero(), scale);
+}
+CFX_Decimal::CFX_Decimal(FX_BSTR strObj)
+{
+ CFX_WideString wstrObj;
+ wstrObj.ConvertFrom(strObj);
+ *this = CFX_Decimal(wstrObj);
+}
+CFX_Decimal::operator CFX_WideString() const
+{
+ CFX_WideString retString;
+ CFX_WideString tmpbuf;
+ FX_UINT64 phi = m_uHi, pmid = m_uMid, plo = m_uLo;
+ while(phi || pmid || plo) {
+ tmpbuf += fxmath_decimal_helper_div10(phi, pmid, plo) + '0';
+ }
+ FX_UINT8 outputlen = (FX_UINT8)tmpbuf.GetLength();
+ FX_UINT8 scale = (FX_UINT8)FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
+ while (scale >= outputlen) {
+ tmpbuf += '0';
+ outputlen++;
+ }
+ if (FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero()) {
+ retString += '-';
+ }
+ for (FX_UINT8 idx = 0; idx < outputlen; idx++) {
+ if (idx == (outputlen - scale) && scale != 0) {
+ retString += '.';
+ }
+ retString += tmpbuf[outputlen - 1 - idx];
+ }
+ return retString;
+}
+CFX_Decimal::operator double() const
+{
+ double pow = (double)(1 << 16) * (1 << 16);
+ double base = ((double)m_uHi) * pow * pow + ((double)m_uMid) * pow + ((double)m_uLo);
+ FX_INT8 scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
+ FX_BOOL bNeg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags);
+ return (bNeg ? -1 : 1) * base * ::pow(10.0, -scale);
+}
+void CFX_Decimal::SetScale(FX_UINT8 newscale)
+{
+ FX_UINT8 oldscale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
+ if (newscale > oldscale) {
+ FX_UINT64 phi = m_uHi, pmid = m_uMid, plo = m_uLo;
+ for (FX_UINT8 iter = 0; iter < newscale - oldscale; iter++) {
+ fxmath_decimal_helper_mul10(phi, pmid, plo);
+ }
+ m_uHi = (FX_UINT32)phi;
+ m_uMid = (FX_UINT32)pmid;
+ m_uLo = (FX_UINT32)plo;
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale);
+ } else if (newscale < oldscale) {
+ FX_UINT64 phi, pmid, plo;
+ phi = 0, pmid = 0, plo = 5;
+ {
+ for(FX_UINT8 iter = 0; iter < oldscale - newscale - 1; iter++) {
+ fxmath_decimal_helper_mul10(phi, pmid, plo);
+ }
+ }
+ phi += m_uHi;
+ pmid += m_uMid;
+ plo += m_uLo;
+ fxmath_decimal_helper_normalize(phi, pmid, plo);
+ {
+ for(FX_UINT8 iter = 0; iter < oldscale - newscale; iter++) {
+ fxmath_decimal_helper_div10(phi, pmid, plo);
+ }
+ }
+ m_uHi = (FX_UINT32)phi;
+ m_uMid = (FX_UINT32)pmid;
+ m_uLo = (FX_UINT32)plo;
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale);
+ }
+}
+FX_UINT8 CFX_Decimal::GetScale()
+{
+ FX_UINT8 oldscale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
+ return oldscale;
+}
+void CFX_Decimal::SetAbs()
+{
+ m_uFlags &= ~FXMATH_DECIMAL_NEGMASK;
+}
+void CFX_Decimal::SetNegate()
+{
+ if(IsNotZero()) {
+ m_uFlags ^= FXMATH_DECIMAL_NEGMASK;
+ }
+}
+void CFX_Decimal::FloorOrCeil(FX_BOOL bFloor)
+{
+ FX_UINT64 nums[3] = {m_uLo, m_uMid, m_uHi};
+ FX_BOOL bDataLoss = FALSE;
+ for(int i = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); i > 0; i --) {
+ bDataLoss = fxmath_decimal_helper_div10_any(nums, 3) || bDataLoss;
+ }
+ if(bDataLoss && (bFloor ? FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) : !FXMATH_DECIMAL_FLAGS2NEG(m_uFlags))) {
+ fxmath_decimal_helper_inc_any(nums, 3);
+ }
+ m_uHi = (FX_UINT32)nums[2];
+ m_uMid = (FX_UINT32)nums[1];
+ m_uLo = (FX_UINT32)nums[0];
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), 0);
+}
+void CFX_Decimal::SetFloor()
+{
+ FloorOrCeil(TRUE);
+}
+void CFX_Decimal::SetCeiling()
+{
+ FloorOrCeil(FALSE);
+}
+void CFX_Decimal::SetTruncate()
+{
+ FloorOrCeil(!FXMATH_DECIMAL_FLAGS2NEG(m_uFlags));
+}
+void CFX_Decimal::Swap(CFX_Decimal& val)
+{
+ FX_UINT32 tmp;
+ tmp = m_uHi;
+ m_uHi = val.m_uHi;
+ val.m_uHi = tmp;
+ tmp = m_uMid;
+ m_uMid = val.m_uMid;
+ val.m_uMid = tmp;
+ tmp = m_uLo;
+ m_uLo = val.m_uLo;
+ val.m_uLo = tmp;
+ tmp = m_uFlags;
+ m_uFlags = val.m_uFlags;
+ val.m_uFlags = tmp;
+}
+FX_INT8 CFX_Decimal::Compare (const CFX_Decimal& val) const
+{
+ CFX_Decimal lhs = *this, rhs = val;
+ FX_INT8 retVal = 0;
+ if (FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) != FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)) {
+ FX_UINT8 scale = FX_MIN(FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags), FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags));
+ lhs.SetScale(scale);
+ rhs.SetScale(scale);
+ }
+ retVal = - (FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) - FXMATH_DECIMAL_FLAGS2NEG(rhs.m_uFlags));
+ if (retVal) {
+ return retVal;
+ }
+ retVal = fxmath_decimal_helper_raw_compare(lhs.m_uHi, lhs.m_uMid, lhs.m_uLo, rhs.m_uHi, rhs.m_uMid, rhs.m_uLo);
+ return (FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) ? - retVal : retVal);
+}
+CFX_Decimal CFX_Decimal::AddOrMinus(const CFX_Decimal& val, FX_BOOL isAdding) const
+{
+ CFX_Decimal lhs = *this, rhs = val;
+ if (FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) != FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)) {
+ FX_UINT8 scale = FX_MAX(FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags), FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags));
+ lhs.SetScale(scale);
+ rhs.SetScale(scale);
+ }
+ if(!isAdding) {
+ rhs.SetNegate();
+ }
+ FX_BOOL doRawAdd = (FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) == FXMATH_DECIMAL_FLAGS2NEG(rhs.m_uFlags));
+ if (doRawAdd) {
+ FX_UINT64 phi = lhs.m_uHi, pmid = lhs.m_uMid, plo = lhs.m_uLo;
+ phi += rhs.m_uHi;
+ pmid += rhs.m_uMid;
+ plo += rhs.m_uLo;
+ fxmath_decimal_helper_normalize(phi, pmid, plo);
+ if(FXMATH_DECIMAL_RSHIFT32BIT(phi) && FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) != 0) {
+ fxmath_decimal_helper_div10(phi, pmid, plo);
+ lhs.m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags), FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) - 1);
+ }
+ lhs.m_uHi = (FX_UINT32)phi;
+ lhs.m_uMid = (FX_UINT32)pmid;
+ lhs.m_uLo = (FX_UINT32)plo;
+ return lhs;
+ } else {
+ if(fxmath_decimal_helper_raw_compare(lhs.m_uHi, lhs.m_uMid, lhs.m_uLo, rhs.m_uHi, rhs.m_uMid, rhs.m_uLo) < 0) {
+ lhs.Swap(rhs);
+ }
+ lhs.m_uHi -= rhs.m_uHi;
+ if(lhs.m_uMid < rhs.m_uMid) {
+ lhs.m_uHi--;
+ }
+ lhs.m_uMid -= rhs.m_uMid;
+ if(lhs.m_uLo < rhs.m_uLo) {
+ if(!lhs.m_uMid) {
+ lhs.m_uHi--;
+ }
+ lhs.m_uMid--;
+ }
+ lhs.m_uLo -= rhs.m_uLo;
+ return lhs;
+ }
+}
+CFX_Decimal CFX_Decimal::Multiply(const CFX_Decimal& val) const
+{
+ FX_UINT64 a[3] = {m_uLo, m_uMid, m_uHi}, b[3] = {val.m_uLo, val.m_uMid, val.m_uHi};
+ FX_UINT64 c[6];
+ fxmath_decimal_helper_raw_mul(a, 3, b, 3, c, 6);
+ FX_BOOL neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^ FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags);
+ FX_UINT8 scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) + FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags);
+ fxmath_decimal_helper_shrinkintorange(c, 6, 3, scale);
+ return CFX_Decimal((FX_UINT32)c[0], (FX_UINT32)c[1], (FX_UINT32)c[2], neg, scale);
+}
+CFX_Decimal CFX_Decimal::Divide(const CFX_Decimal& val) const
+{
+ if(!val.IsNotZero()) {
+ return CFX_Decimal();
+ }
+ FX_BOOL neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^ FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags);
+ FX_UINT64 a[7] = {m_uLo, m_uMid, m_uHi}, b[3] = {val.m_uLo, val.m_uMid, val.m_uHi}, c[7] = {0};
+ FX_UINT8 scale = 0;
+ if(FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) < FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags)) {
+ for(int i = FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags) - FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); i > 0; i--) {
+ fxmath_decimal_helper_mul10_any(a, 7);
+ }
+ } else {
+ scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) - FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags);
+ }
+ FX_UINT8 minscale = scale;
+ if(!IsNotZero()) {
+ return CFX_Decimal(0, 0, 0, 0, minscale);
+ }
+ while(!a[6]) {
+ fxmath_decimal_helper_mul10_any(a, 7);
+ scale++;
+ }
+ fxmath_decimal_helper_div10_any(a, 7);
+ scale--;
+ fxmath_decimal_helper_raw_div(a, 6, b, 3, c, 7);
+ fxmath_decimal_helper_shrinkintorange(c, 6, 3, scale);
+ fxmath_decimal_helper_truncate(c[2], c[1], c[0], scale, minscale);
+ return CFX_Decimal((FX_UINT32)c[0], (FX_UINT32)c[1], (FX_UINT32)c[2], neg, scale);
+}
+CFX_Decimal CFX_Decimal::Modulus(const CFX_Decimal& val) const
+{
+ CFX_Decimal lhs = *this, rhs_abs = val;
+ rhs_abs.SetAbs();
+ if(!rhs_abs.IsNotZero()) {
+ return *this;
+ }
+ while(TRUE) {
+ CFX_Decimal lhs_abs = lhs;
+ lhs_abs.SetAbs();
+ if(lhs_abs < rhs_abs) {
+ break;
+ }
+ CFX_Decimal quot = lhs / rhs_abs;
+ quot.SetTruncate();
+ lhs = lhs - quot * rhs_abs;
+ }
+ return lhs;
+}
+FX_BOOL CFX_Decimal::operator == (const CFX_Decimal& val) const
+{
+ return Compare(val) == 0;
+}
+FX_BOOL CFX_Decimal::operator <= (const CFX_Decimal& val) const
+{
+ return Compare(val) <= 0;
+}
+FX_BOOL CFX_Decimal::operator >= (const CFX_Decimal& val) const
+{
+ return Compare(val) >= 0;
+}
+FX_BOOL CFX_Decimal::operator != (const CFX_Decimal& val) const
+{
+ return Compare(val) != 0;
+}
+FX_BOOL CFX_Decimal::operator < (const CFX_Decimal& val) const
+{
+ return Compare(val) < 0;
+}
+FX_BOOL CFX_Decimal::operator > (const CFX_Decimal& val) const
+{
+ return Compare(val) > 0;
+}
+CFX_Decimal CFX_Decimal::operator + (const CFX_Decimal& val) const
+{
+ return AddOrMinus(val, TRUE);
+}
+CFX_Decimal CFX_Decimal::operator - (const CFX_Decimal& val) const
+{
+ return AddOrMinus(val, FALSE);
+}
+CFX_Decimal CFX_Decimal::operator * (const CFX_Decimal& val) const
+{
+ return Multiply(val);
+}
+CFX_Decimal CFX_Decimal::operator / (const CFX_Decimal& val) const
+{
+ return Divide(val);
+}
+CFX_Decimal CFX_Decimal::operator % (const CFX_Decimal& val) const
+{
+ return Modulus(val);
+}
diff --git a/xfa/src/fgas/src/localization/fx_localeimp.h b/xfa/src/fgas/src/localization/fx_localeimp.h
new file mode 100644
index 0000000000..7698388020
--- /dev/null
+++ b/xfa/src/fgas/src/localization/fx_localeimp.h
@@ -0,0 +1,74 @@
+// 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 _FX_LOCALE_IMP_H_
+#define _FX_LOCALE_IMP_H_
+class CFX_LCNumeric;
+class CFX_Locale : public IFX_Locale, public CFX_Object
+{
+public:
+ CFX_Locale(CXML_Element* pLocaleData);
+ virtual void Release()
+ {
+ delete this;
+ }
+
+ virtual CFX_WideString GetName();
+ virtual void GetNumbericSymbol(FX_LOCALENUMSYMBOL eType, CFX_WideString& wsNumSymbol) const;
+
+ virtual void GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const;
+ virtual void GetMonthName(FX_INT32 nMonth, CFX_WideString& wsMonthName, FX_BOOL bAbbr = TRUE) const;
+ virtual void GetDayName(FX_INT32 nWeek, CFX_WideString& wsDayName, FX_BOOL bAbbr = TRUE) const;
+ virtual void GetMeridiemName(CFX_WideString& wsMeridiemName, FX_BOOL bAM = TRUE) const;
+ virtual void GetTimeZone(FX_TIMEZONE& tz) const;
+ virtual void GetEraName(CFX_WideString& wsEraName, FX_BOOL bAD = TRUE) const;
+
+ virtual void GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType, CFX_WideString& wsPattern) const;
+ virtual void GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType, CFX_WideString& wsPattern) const;
+ virtual void GetNumPattern(FX_LOCALENUMSUBCATEGORY eType, CFX_WideString& wsPattern) const;
+protected:
+ virtual ~CFX_Locale();
+ CXML_Element* m_pElement;
+};
+class CFX_FormatString : public IFX_FormatString, public CFX_Object
+{
+public:
+ CFX_FormatString(IFX_LocaleMgr* pLocaleMgr, FX_BOOL bUseLCID);
+ virtual void Release()
+ {
+ delete this;
+ }
+
+ virtual void SplitFormatString(const CFX_WideString& wsFormatString, CFX_WideStringArray& wsPatterns);
+ virtual FX_LOCALECATEGORY GetCategory(const CFX_WideString& wsPattern);
+ virtual FX_WORD GetLCID(const CFX_WideString& wsPattern);
+ virtual CFX_WideString GetLocaleName(const CFX_WideString& wsPattern);
+ virtual FX_BOOL ParseText(const CFX_WideString& wsSrcText, const CFX_WideString& wsPattern, CFX_WideString& wsValue);
+ virtual FX_BOOL ParseNum(const CFX_WideString& wsSrcNum, const CFX_WideString& wsPattern, FX_FLOAT &fValue);
+ virtual FX_BOOL ParseNum(const CFX_WideString& wsSrcNum, const CFX_WideString& wsPattern, CFX_WideString &wsValue);
+ virtual FX_BOOL ParseDateTime(const CFX_WideString& wsSrcDateTime, const CFX_WideString& wsPattern, FX_DATETIMETYPE eDateTimeType, CFX_Unitime& dtValue);
+ virtual FX_BOOL ParseZero(const CFX_WideString& wsSrcText, const CFX_WideString& wsPattern);
+ virtual FX_BOOL ParseNull(const CFX_WideString& wsSrcText, const CFX_WideString& wsPattern);
+ virtual FX_BOOL FormatText(const CFX_WideString& wsSrcText, const CFX_WideString& wsPattern, CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatNum(const CFX_WideString& wsSrcNum, const CFX_WideString& wsPattern, CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatNum(FX_FLOAT fNum, const CFX_WideString& wsPattern, CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatDateTime(const CFX_WideString& wsSrcDateTime, const CFX_WideString& wsPattern, CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatDateTime(const CFX_WideString& wsSrcDateTime, const CFX_WideString& wsPattern, CFX_WideString& wsOutput, FX_DATETIMETYPE eDateTimeType);
+ virtual FX_BOOL FormatDateTime(const CFX_Unitime& dt, const CFX_WideString& wsPattern, CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatZero(const CFX_WideString& wsPattern, CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatNull(const CFX_WideString& wsPattern, CFX_WideString& wsOutput);
+protected:
+ virtual ~CFX_FormatString();
+ IFX_Locale* GetTextFormat(const CFX_WideString &wsPattern, FX_WSTR wsCategory, CFX_WideString& wsPurgePattern);
+ IFX_Locale* GetNumericFormat(const CFX_WideString& wsPattern, FX_INT32& iDotIndex, FX_DWORD& dwStyle, CFX_WideString& wsPurgePattern);
+ FX_BOOL FormatStrNum(FX_WSTR wsInputNum, const CFX_WideString& wsPattern, CFX_WideString& wsOutput);
+ FX_BOOL FormatLCNumeric(CFX_LCNumeric& lcNum, const CFX_WideString& wsPattern, CFX_WideString& wsOutput);
+ FX_DATETIMETYPE GetDateTimeFormat(const CFX_WideString& wsPattern, IFX_Locale*& pLocale, CFX_WideString &wsDatePattern, CFX_WideString &wsTimePattern);
+ IFX_Locale* GetPatternLocale(FX_WSTR wsLocale);
+ IFX_LocaleMgr* m_pLocaleMgr;
+ FX_BOOL m_bUseLCID;
+};
+#endif
diff --git a/xfa/src/fgas/src/localization/fx_localemgr.cpp b/xfa/src/fgas/src/localization/fx_localemgr.cpp
new file mode 100644
index 0000000000..3b93f101a3
--- /dev/null
+++ b/xfa/src/fgas/src/localization/fx_localemgr.cpp
@@ -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
+
+#include "../fgas_base.h"
+#include "fx_localemgr.h"
+IFX_LocaleMgr* FX_LocaleMgr_Create(FX_LPCWSTR pszLocalPath, FX_WORD wDefaultLCID)
+{
+ void* pPathHandle = FX_OpenFolder(pszLocalPath);
+ if (!pPathHandle) {
+ return NULL;
+ }
+ CFX_LocaleMgr* pLocaleMgr = FX_NEW CFX_LocaleMgr(wDefaultLCID);
+ CFX_WideString wsFileName;
+ FX_BOOL bFolder = FALSE;
+ while (FX_GetNextFile(pPathHandle, wsFileName, bFolder)) {
+ if (!bFolder) {
+ if (wsFileName.GetLength() < 4) {
+ continue;
+ }
+ CFX_WideString wsExt = wsFileName.Right(4);
+ wsExt.MakeLower();
+ if (wsExt != L".xml") {
+ continue;
+ }
+ CFX_WideString wsFullPath(pszLocalPath);
+ wsFullPath += L"\\" + wsFileName;
+ IFX_FileRead* pRead = FX_CreateFileRead(wsFullPath);
+ if (!pRead) {
+ continue;
+ }
+ CXML_Element* pXmlLocale = CXML_Element::Parse(pRead);
+ pRead->Release();
+ CFX_ByteString bssp = pXmlLocale->GetNamespace();
+ if (bssp == "http://www.foxitsoftware.com/localization") {
+ CFX_WideString wsLCID = pXmlLocale->GetAttrValue("", "lcid");
+ wchar_t* pEnd = NULL;
+ FX_DWORD dwLCID = wcstol(wsLCID, &pEnd, 16);
+ if (pLocaleMgr->m_lcid2xml.GetValueAt((FX_LPVOID)(FX_UINTPTR)dwLCID)) {
+ delete pXmlLocale;
+ } else {
+ pLocaleMgr->m_lcid2xml.SetAt((FX_LPVOID)(FX_UINTPTR)dwLCID, pXmlLocale);
+ }
+ } else {
+ delete pXmlLocale;
+ }
+ }
+ }
+ FX_CloseFolder(pPathHandle);
+ return pLocaleMgr;
+}
+CFX_LocaleMgr::CFX_LocaleMgr(FX_WORD wDefLCID)
+ : m_wDefLCID(wDefLCID)
+{
+}
+CFX_LocaleMgr::~CFX_LocaleMgr()
+{
+ FX_POSITION ps = m_lcid2locale.GetStartPosition();
+ while (ps) {
+ FX_LPVOID plcid;
+ IFX_Locale* pLocale = NULL;
+ m_lcid2locale.GetNextAssoc(ps, plcid, (void*&)pLocale);
+ pLocale->Release();
+ }
+ m_lcid2locale.RemoveAll();
+ ps = m_lcid2xml.GetStartPosition();
+ while (ps) {
+ FX_LPVOID plcid;
+ CXML_Element* pxml = NULL;
+ m_lcid2xml.GetNextAssoc(ps, plcid, (void*&)pxml);
+ delete pxml;
+ }
+ m_lcid2xml.RemoveAll();
+}
+FX_WORD CFX_LocaleMgr::GetDefLocaleID()
+{
+ return m_wDefLCID;
+}
+IFX_Locale* CFX_LocaleMgr::GetDefLocale()
+{
+ return GetLocale(m_wDefLCID);
+}
+IFX_Locale* CFX_LocaleMgr::GetLocale(FX_WORD lcid)
+{
+ IFX_Locale* pLocale = (IFX_Locale*)m_lcid2locale.GetValueAt((FX_LPVOID)(FX_UINTPTR)lcid);
+ if (!pLocale) {
+ CXML_Element* pxml = (CXML_Element*)m_lcid2xml.GetValueAt((FX_LPVOID)(FX_UINTPTR)lcid);
+ if (pxml) {
+ pLocale = IFX_Locale::Create(pxml);
+ m_lcid2locale.SetAt((FX_LPVOID)(FX_UINTPTR)lcid, pLocale);
+ }
+ }
+ return pLocale;
+}
+IFX_Locale* CFX_LocaleMgr::GetLocaleByName(FX_WSTR wsLocaleName)
+{
+ return NULL;
+}
diff --git a/xfa/src/fgas/src/localization/fx_localemgr.h b/xfa/src/fgas/src/localization/fx_localemgr.h
new file mode 100644
index 0000000000..b23940e8d5
--- /dev/null
+++ b/xfa/src/fgas/src/localization/fx_localemgr.h
@@ -0,0 +1,27 @@
+// 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 _FX_LOCALEMGR_IMP_H_
+#define _FX_LOCALEMGR_IMP_H_
+class CFX_LocaleMgr : public IFX_LocaleMgr, public CFX_Object
+{
+public:
+ CFX_LocaleMgr(FX_WORD wDefLCID);
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual FX_WORD GetDefLocaleID();
+ virtual IFX_Locale* GetDefLocale();
+ virtual IFX_Locale* GetLocale(FX_WORD lcid);
+ virtual IFX_Locale* GetLocaleByName(FX_WSTR wsLocaleName);
+ CFX_MapPtrToPtr m_lcid2xml;
+protected:
+ ~CFX_LocaleMgr();
+ CFX_MapPtrToPtr m_lcid2locale;
+ FX_WORD m_wDefLCID;
+};
+#endif
diff --git a/xfa/src/fgas/src/xml/fx_sax_imp.cpp b/xfa/src/fgas/src/xml/fx_sax_imp.cpp
new file mode 100644
index 0000000000..b41ee3fef4
--- /dev/null
+++ b/xfa/src/fgas/src/xml/fx_sax_imp.cpp
@@ -0,0 +1,720 @@
+// 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 "../fgas_base.h"
+#include "fx_sax_imp.h"
+IFX_SAXReader* FX_SAXReader_Create()
+{
+ return FX_NEW CFX_SAXReader;
+}
+CFX_SAXFile::CFX_SAXFile()
+ : m_pFile(NULL)
+ , m_dwStart(0)
+ , m_dwEnd(0)
+ , m_dwCur(0)
+ , m_pBuf(NULL)
+ , m_dwBufSize(0)
+ , m_dwBufIndex(0)
+{
+}
+FX_BOOL CFX_SAXFile::StartFile(IFX_FileRead *pFile, FX_DWORD dwStart, FX_DWORD dwLen)
+{
+ FXSYS_assert(m_pFile == NULL && pFile != NULL);
+ FX_DWORD dwSize = pFile->GetSize();
+ if (dwStart >= dwSize) {
+ return FALSE;
+ }
+ if (dwLen == -1 || dwStart + dwLen > dwSize) {
+ dwLen = dwSize - dwStart;
+ }
+ if (dwLen == 0) {
+ return FALSE;
+ }
+ m_dwBufSize = FX_MIN(dwLen, FX_SAXFILE_BUFSIZE);
+ m_pBuf = FX_Alloc(FX_BYTE, m_dwBufSize);
+ if (!m_pBuf) {
+ return FALSE;
+ }
+ if (!pFile->ReadBlock(m_pBuf, dwStart, m_dwBufSize)) {
+ return FALSE;
+ }
+ m_dwStart = dwStart;
+ m_dwEnd = dwStart + dwLen;
+ m_dwCur = dwStart;
+ m_pFile = pFile;
+ m_dwBufIndex = 0;
+ return TRUE;
+}
+FX_BOOL CFX_SAXFile::ReadNextBlock()
+{
+ FXSYS_assert(m_pFile != NULL);
+ FX_DWORD dwSize = m_dwEnd - m_dwCur;
+ if (dwSize == 0) {
+ return FALSE;
+ }
+ m_dwBufSize = FX_MIN(dwSize, FX_SAXFILE_BUFSIZE);
+ if (!m_pFile->ReadBlock(m_pBuf, m_dwCur, m_dwBufSize)) {
+ return FALSE;
+ }
+ m_dwBufIndex = 0;
+ return TRUE;
+}
+void CFX_SAXFile::Reset()
+{
+ if (m_pBuf) {
+ FX_Free(m_pBuf);
+ m_pBuf = NULL;
+ }
+ m_pFile = NULL;
+}
+#define FX_SAXCHARTYPE_Normal 0
+#define FX_SAXCHARTYPE_Space 1
+static FX_BYTE g_SAX_CharType[256] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+CFX_SAXReader::CFX_SAXReader()
+ : m_File()
+ , m_pHandler(NULL)
+ , m_iState(-1)
+ , m_pRoot(NULL)
+ , m_pCurItem(NULL)
+ , m_dwItemID(0)
+ , m_iDataSize(256)
+ , m_iNameSize(256)
+ , m_pCommentContext(NULL)
+ , m_dwParseMode(0)
+{
+ m_pszData = (FX_LPBYTE)FX_Alloc(FX_BYTE, m_iDataSize);
+ m_pszName = (FX_LPBYTE)FX_Alloc(FX_BYTE, m_iNameSize);
+}
+CFX_SAXReader::~CFX_SAXReader()
+{
+ Reset();
+ if (m_pszData) {
+ FX_Free(m_pszData);
+ m_pszData = NULL;
+ }
+ if (m_pszName) {
+ FX_Free(m_pszName);
+ m_pszName = NULL;
+ }
+}
+void CFX_SAXReader::Reset()
+{
+ m_File.Reset();
+ CFX_SAXItem *pItem = m_pRoot;
+ while (pItem) {
+ CFX_SAXItem *pNext = pItem->m_pNext;
+ delete pItem;
+ pItem = pNext;
+ }
+ m_pRoot = NULL;
+ m_pCurItem = NULL;
+ m_dwItemID = 0;
+ m_SkipStack.RemoveAll();
+ m_SkipChar = 0;
+ m_iDataLength = 0;
+ m_iEntityStart = -1;
+ m_iNameLength = 0;
+ m_iDataPos = 0;
+ if (m_pCommentContext) {
+ delete m_pCommentContext;
+ m_pCommentContext = NULL;
+ }
+}
+inline void CFX_SAXReader::Push()
+{
+ CFX_SAXItem *pNew = FX_NEW CFX_SAXItem;
+ pNew->m_dwID = ++m_dwItemID;
+ pNew->m_bSkip = m_pCurItem->m_bSkip;
+ pNew->m_pPrev = m_pCurItem;
+ m_pCurItem->m_pNext = pNew;
+ m_pCurItem = pNew;
+}
+inline void CFX_SAXReader::Pop()
+{
+ if (!m_pCurItem) {
+ return;
+ }
+ CFX_SAXItem *pPrev = m_pCurItem->m_pPrev;
+ pPrev->m_pNext = NULL;
+ delete m_pCurItem;
+ m_pCurItem = pPrev;
+}
+inline void CFX_SAXReader::AppendData(FX_BYTE ch)
+{
+ ReallocDataBuffer();
+ m_pszData[m_iDataPos++] = ch;
+}
+inline void CFX_SAXReader::AppendName(FX_BYTE ch)
+{
+ ReallocNameBuffer();
+ m_pszName[m_iDataPos++] = ch;
+}
+void CFX_SAXReader::ReallocDataBuffer()
+{
+ if (m_iDataPos < m_iDataSize) {
+ return;
+ }
+ if (m_iDataSize <= 1024 * 1024) {
+ m_iDataSize *= 2;
+ } else {
+ m_iDataSize += 1024 * 1024;
+ }
+ m_pszData = (FX_LPBYTE)FX_Realloc(FX_BYTE, m_pszData, m_iDataSize);
+}
+void CFX_SAXReader::ReallocNameBuffer()
+{
+ if (m_iDataPos < m_iNameSize) {
+ return;
+ }
+ if (m_iNameSize <= 1024 * 1024) {
+ m_iNameSize *= 2;
+ } else {
+ m_iNameSize += 1024 * 1024;
+ }
+ m_pszName = (FX_LPBYTE)FX_Realloc(FX_BYTE, m_pszName, m_iNameSize);
+}
+inline FX_BOOL CFX_SAXReader::SkipSpace(FX_BYTE ch)
+{
+ return (m_dwParseMode & FX_SAXPARSEMODE_NotSkipSpace) == 0 && ch < 0x21;
+}
+FX_INT32 CFX_SAXReader::StartParse(IFX_FileRead *pFile, FX_DWORD dwStart , FX_DWORD dwLen , FX_DWORD dwParseMode )
+{
+ m_iState = -1;
+ Reset();
+ if (!m_File.StartFile(pFile, dwStart, dwLen)) {
+ return -1;
+ }
+ m_iState = 0;
+ m_eMode = FX_SAXMODE_Text;
+ m_ePrevMode = FX_SAXMODE_Text;
+ m_bCharData = FALSE;
+ m_dwDataOffset = 0;
+ m_pRoot = m_pCurItem = FX_NEW CFX_SAXItem;
+ m_pCurItem->m_dwID = ++m_dwItemID;
+ m_dwParseMode = dwParseMode;
+ return 0;
+}
+typedef void (CFX_SAXReader::*FX_SAXReader_LPFParse)();
+static const FX_SAXReader_LPFParse g_FX_SAXReader_LPFParse[FX_SAXMODE_MAX] = {
+ &CFX_SAXReader::ParseText,
+ &CFX_SAXReader::ParseNodeStart,
+ &CFX_SAXReader::ParseDeclOrComment,
+ &CFX_SAXReader::ParseDeclNode,
+ &CFX_SAXReader::ParseComment,
+ &CFX_SAXReader::ParseCommentContent,
+ &CFX_SAXReader::ParseTagName,
+ &CFX_SAXReader::ParseTagAttributeName,
+ &CFX_SAXReader::ParseTagAttributeEqual,
+ &CFX_SAXReader::ParseTagAttributeValue,
+ &CFX_SAXReader::ParseMaybeClose,
+ &CFX_SAXReader::ParseTagClose,
+ &CFX_SAXReader::ParseTagEnd,
+ &CFX_SAXReader::ParseTargetData,
+};
+FX_INT32 CFX_SAXReader::ContinueParse(IFX_Pause *pPause )
+{
+ if (m_iState < 0 || m_iState > 99) {
+ return m_iState;
+ }
+ while(m_File.m_dwCur < m_File.m_dwEnd) {
+ FX_DWORD &index = m_File.m_dwBufIndex;
+ FX_DWORD size = m_File.m_dwBufSize;
+ FX_LPCBYTE pBuf = m_File.m_pBuf;
+ while (index < size) {
+ m_CurByte = pBuf[index];
+ (this->*g_FX_SAXReader_LPFParse[m_eMode])();
+ index ++;
+ }
+ m_File.m_dwCur += index;
+ m_iState = (m_File.m_dwCur - m_File.m_dwStart) * 100 / (m_File.m_dwEnd - m_File.m_dwStart);
+ if (m_File.m_dwCur >= m_File.m_dwEnd) {
+ break;
+ }
+ if (!m_File.ReadNextBlock()) {
+ m_iState = -2;
+ break;
+ }
+ m_dwDataOffset = 0;
+ if (pPause && pPause->NeedToPauseNow()) {
+ break;
+ }
+ }
+ return m_iState;
+}
+void CFX_SAXReader::ParseChar(FX_BYTE ch)
+{
+ ReallocDataBuffer();
+ m_pszData[m_iDataPos] = ch;
+ if (m_iEntityStart > -1 && ch == ';') {
+ FX_INT32 iSaveEntityStart = m_iEntityStart;
+ CFX_ByteString csEntity(m_pszData + m_iEntityStart + 1, m_iDataPos - m_iEntityStart - 1);
+ FX_INT32 iLen = csEntity.GetLength();
+ if (iLen > 0) {
+ if (csEntity[0] == '#') {
+ if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_sharp) == 0) {
+ ch = 0;
+ FX_BYTE w;
+ if (iLen > 1 && csEntity[1] == 'x') {
+ for (FX_INT32 i = 2; i < iLen; i ++) {
+ w = csEntity[i];
+ if (w >= '0' && w <= '9') {
+ ch = (ch << 4) + w - '0';
+ } else if (w >= 'A' && w <= 'F') {
+ ch = (ch << 4) + w - 55;
+ } else if (w >= 'a' && w <= 'f') {
+ ch = (ch << 4) + w - 87;
+ } else {
+ break;
+ }
+ }
+ } else {
+ for (FX_INT32 i = 1; i < iLen; i ++) {
+ w = csEntity[i];
+ if (w < '0' || w > '9') {
+ break;
+ }
+ ch = ch * 10 + w - '0';
+ }
+ }
+ if (ch != 0) {
+ m_pszData[m_iEntityStart ++] = ch;
+ }
+ }
+ } else {
+ if (csEntity.Compare("amp") == 0) {
+ if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_amp) == 0) {
+ m_pszData[m_iEntityStart ++] = '&';
+ }
+ } else if (csEntity.Compare("lt") == 0) {
+ if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_lt) == 0) {
+ m_pszData[m_iEntityStart ++] = '<';
+ }
+ } else if (csEntity.Compare("gt") == 0) {
+ if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_gt) == 0) {
+ m_pszData[m_iEntityStart ++] = '>';
+ }
+ } else if (csEntity.Compare("apos") == 0) {
+ if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_apos) == 0) {
+ m_pszData[m_iEntityStart ++] = '\'';
+ }
+ } else if (csEntity.Compare("quot") == 0) {
+ if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_quot) == 0) {
+ m_pszData[m_iEntityStart ++] = '\"';
+ }
+ }
+ }
+ }
+ if (iSaveEntityStart != m_iEntityStart) {
+ m_iDataPos = m_iEntityStart;
+ m_iEntityStart = -1;
+ } else {
+ m_iDataPos ++;
+ m_iEntityStart = -1;
+ }
+ } else {
+ if (m_iEntityStart < 0 && ch == '&') {
+ m_iEntityStart = m_iDataPos;
+ }
+ m_iDataPos ++;
+ }
+}
+void CFX_SAXReader::ParseText()
+{
+ if (m_CurByte == '<') {
+ if (m_iDataPos > 0) {
+ m_iDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ if (m_pHandler) {
+ NotifyData();
+ }
+ }
+ Push();
+ m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
+ m_eMode = FX_SAXMODE_NodeStart;
+ return;
+ }
+ if (m_iDataPos < 1 && SkipSpace(m_CurByte)) {
+ return;
+ }
+ ParseChar(m_CurByte);
+}
+void CFX_SAXReader::ParseNodeStart()
+{
+ if (m_CurByte == '?') {
+ m_pCurItem->m_eNode = FX_SAXNODE_Instruction;
+ m_eMode = FX_SAXMODE_TagName;
+ return;
+ }
+ if (m_CurByte == '!') {
+ m_eMode = FX_SAXMODE_DeclOrComment;
+ return;
+ }
+ if (m_CurByte == '/') {
+ m_eMode = FX_SAXMODE_TagEnd;
+ return;
+ }
+ if (m_CurByte == '>') {
+ Pop();
+ m_eMode = FX_SAXMODE_Text;
+ return;
+ }
+ if (m_CurByte > 0x20) {
+ m_dwDataOffset = m_File.m_dwBufIndex;
+ m_pCurItem->m_eNode = FX_SAXNODE_Tag;
+ m_eMode = FX_SAXMODE_TagName;
+ AppendData(m_CurByte);
+ }
+}
+void CFX_SAXReader::ParseDeclOrComment()
+{
+ if (m_CurByte == '-') {
+ m_eMode = FX_SAXMODE_Comment;
+ m_pCurItem->m_eNode = FX_SAXNODE_Comment;
+ if (m_pCommentContext == NULL) {
+ m_pCommentContext = FX_NEW CFX_SAXCommentContext;
+ }
+ m_pCommentContext->m_iHeaderCount = 1;
+ m_pCommentContext->m_iTailCount = 0;
+ } else {
+ m_eMode = FX_SAXMODE_DeclNode;
+ m_dwDataOffset = m_File.m_dwBufIndex;
+ m_SkipChar = '>';
+ m_SkipStack.Add('>');
+ SkipNode();
+ }
+}
+void CFX_SAXReader::ParseComment()
+{
+ m_pCommentContext->m_iHeaderCount = 2;
+ m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
+ m_eMode = FX_SAXMODE_CommentContent;
+}
+void CFX_SAXReader::ParseCommentContent()
+{
+ if (m_CurByte == '-') {
+ m_pCommentContext->m_iTailCount++;
+ } else if (m_CurByte == '>' && m_pCommentContext->m_iTailCount == 2) {
+ m_iDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ if (m_pHandler) {
+ NotifyTargetData();
+ }
+ Pop();
+ m_eMode = FX_SAXMODE_Text;
+ } else {
+ while (m_pCommentContext->m_iTailCount > 0) {
+ AppendData('-');
+ m_pCommentContext->m_iTailCount--;
+ }
+ AppendData(m_CurByte);
+ }
+}
+void CFX_SAXReader::ParseDeclNode()
+{
+ SkipNode();
+}
+void CFX_SAXReader::ParseTagName()
+{
+ if (m_CurByte < 0x21 || m_CurByte == '/' || m_CurByte == '>' || m_CurByte == '?') {
+ m_iDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ if (m_pHandler) {
+ NotifyEnter();
+ }
+ if (m_CurByte < 0x21) {
+ m_eMode = FX_SAXMODE_TagAttributeName;
+ } else if (m_CurByte == '/' || m_CurByte == '?') {
+ m_ePrevMode = m_eMode;
+ m_eMode = FX_SAXMODE_TagMaybeClose;
+ } else {
+ if (m_pHandler) {
+ NotifyBreak();
+ }
+ m_eMode = FX_SAXMODE_Text;
+ }
+ } else {
+ AppendData(m_CurByte);
+ }
+}
+void CFX_SAXReader::ParseTagAttributeName()
+{
+ if (m_CurByte < 0x21 || m_CurByte == '=') {
+ if (m_iDataPos < 1 && m_CurByte < 0x21) {
+ return;
+ }
+ m_iNameLength = m_iDataPos;
+ m_iDataPos = 0;
+ m_SkipChar = 0;
+ m_eMode = m_CurByte == '=' ? FX_SAXMODE_TagAttributeValue : FX_SAXMODE_TagAttributeEqual;
+ return;
+ }
+ if (m_CurByte == '/' || m_CurByte == '>' || m_CurByte == '?') {
+ if (m_CurByte == '/' || m_CurByte == '?') {
+ m_ePrevMode = m_eMode;
+ m_eMode = FX_SAXMODE_TagMaybeClose;
+ } else {
+ if (m_pHandler) {
+ NotifyBreak();
+ }
+ m_eMode = FX_SAXMODE_Text;
+ }
+ return;
+ }
+ if (m_iDataPos < 1) {
+ m_dwDataOffset = m_File.m_dwBufIndex;
+ }
+ AppendName(m_CurByte);
+}
+void CFX_SAXReader::ParseTagAttributeEqual()
+{
+ if (m_CurByte == '=') {
+ m_SkipChar = 0;
+ m_eMode = FX_SAXMODE_TagAttributeValue;
+ return;
+ } else if (m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
+ m_iDataPos = m_iNameLength;
+ AppendName(0x20);
+ m_eMode = FX_SAXMODE_TargetData;
+ ParseTargetData();
+ }
+}
+void CFX_SAXReader::ParseTagAttributeValue()
+{
+ if (m_SkipChar) {
+ if (m_SkipChar == m_CurByte) {
+ {
+ m_iDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ if (m_pHandler) {
+ NotifyAttribute();
+ }
+ }
+ m_SkipChar = 0;
+ m_eMode = FX_SAXMODE_TagAttributeName;
+ return;
+ }
+ ParseChar(m_CurByte);
+ return;
+ }
+ if (m_CurByte < 0x21) {
+ return;
+ }
+ if (m_iDataPos < 1) {
+ if (m_CurByte == '\'' || m_CurByte == '\"') {
+ m_SkipChar = m_CurByte;
+ }
+ }
+}
+void CFX_SAXReader::ParseMaybeClose()
+{
+ if (m_CurByte == '>') {
+ if (m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
+ m_iNameLength = m_iDataPos;
+ m_iDataPos = 0;
+ if (m_pHandler) {
+ NotifyTargetData();
+ }
+ }
+ ParseTagClose();
+ m_eMode = FX_SAXMODE_Text;
+ } else if (m_ePrevMode == FX_SAXMODE_TagName) {
+ AppendData('/');
+ m_eMode = FX_SAXMODE_TagName;
+ m_ePrevMode = FX_SAXMODE_Text;
+ ParseTagName();
+ } else if (m_ePrevMode == FX_SAXMODE_TagAttributeName) {
+ AppendName('/');
+ m_eMode = FX_SAXMODE_TagAttributeName;
+ m_ePrevMode = FX_SAXMODE_Text;
+ ParseTagAttributeName();
+ } else if (m_ePrevMode == FX_SAXMODE_TargetData) {
+ AppendName('?');
+ m_eMode = FX_SAXMODE_TargetData;
+ m_ePrevMode = FX_SAXMODE_Text;
+ ParseTargetData();
+ }
+}
+void CFX_SAXReader::ParseTagClose()
+{
+ m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
+ if (m_pHandler) {
+ NotifyClose();
+ }
+ Pop();
+}
+void CFX_SAXReader::ParseTagEnd()
+{
+ if (m_CurByte < 0x21) {
+ return;
+ }
+ if (m_CurByte == '>') {
+ Pop();
+ m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
+ m_iDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ if (m_pHandler) {
+ NotifyEnd();
+ }
+ Pop();
+ m_eMode = FX_SAXMODE_Text;
+ } else {
+ ParseChar(m_CurByte);
+ }
+}
+void CFX_SAXReader::ParseTargetData()
+{
+ if (m_CurByte == '?') {
+ m_ePrevMode = m_eMode;
+ m_eMode = FX_SAXMODE_TagMaybeClose;
+ } else {
+ AppendName(m_CurByte);
+ }
+}
+void CFX_SAXReader::SkipNode()
+{
+ FX_INT32 iLen = m_SkipStack.GetSize();
+ if (m_SkipChar == '\'' || m_SkipChar == '\"') {
+ if (m_CurByte != m_SkipChar) {
+ return;
+ }
+ iLen --;
+ FXSYS_assert(iLen > -1);
+ m_SkipStack.RemoveAt(iLen, 1);
+ m_SkipChar = iLen ? m_SkipStack[iLen - 1] : 0;
+ return;
+ }
+ switch (m_CurByte) {
+ case '<':
+ m_SkipChar = '>';
+ m_SkipStack.Add('>');
+ break;
+ case '[':
+ m_SkipChar = ']';
+ m_SkipStack.Add(']');
+ break;
+ case '(':
+ m_SkipChar = ')';
+ m_SkipStack.Add(')');
+ break;
+ case '\'':
+ m_SkipChar = '\'';
+ m_SkipStack.Add('\'');
+ break;
+ case '\"':
+ m_SkipChar = '\"';
+ m_SkipStack.Add('\"');
+ break;
+ default:
+ if (m_CurByte == m_SkipChar) {
+ iLen --;
+ m_SkipStack.RemoveAt(iLen, 1);
+ m_SkipChar = iLen ? m_SkipStack[iLen - 1] : 0;
+ if (iLen == 0 && m_CurByte == '>') {
+ m_iDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ if (m_iDataLength >= 9
+ && FXSYS_memcmp(m_pszData, "[CDATA[", 7 * sizeof(FX_BYTE)) == 0
+ && FXSYS_memcmp(m_pszData + m_iDataLength - 2, "]]", 2 * sizeof(FX_BYTE)) == 0) {
+ Pop();
+ m_iDataLength -= 9;
+ m_dwDataOffset += 7;
+ FXSYS_memmove(m_pszData , m_pszData + 7, m_iDataLength * sizeof(FX_BYTE));
+ m_bCharData = TRUE;
+ if (m_pHandler) {
+ NotifyData();
+ }
+ m_bCharData = FALSE;
+ } else {
+ Pop();
+ }
+ m_eMode = FX_SAXMODE_Text;
+ }
+ }
+ break;
+ }
+ if (iLen > 0) {
+ ParseChar(m_CurByte);
+ }
+}
+void CFX_SAXReader::NotifyData()
+{
+ FXSYS_assert(m_pHandler != NULL);
+ if (m_pCurItem->m_eNode == FX_SAXNODE_Tag)
+ m_pHandler->OnTagData(m_pCurItem->m_pNode, m_bCharData ? FX_SAXNODE_CharData : FX_SAXNODE_Text,
+ CFX_ByteStringC(m_pszData, m_iDataLength), m_File.m_dwCur + m_dwDataOffset);
+}
+void CFX_SAXReader::NotifyEnter()
+{
+ FXSYS_assert(m_pHandler != NULL);
+ if (m_pCurItem->m_eNode == FX_SAXNODE_Tag || m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
+ m_pCurItem->m_pNode = m_pHandler->OnTagEnter(CFX_ByteStringC(m_pszData, m_iDataLength), m_pCurItem->m_eNode, m_dwNodePos);
+ }
+}
+void CFX_SAXReader::NotifyAttribute()
+{
+ FXSYS_assert(m_pHandler != NULL);
+ if (m_pCurItem->m_eNode == FX_SAXNODE_Tag || m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
+ m_pHandler->OnTagAttribute(m_pCurItem->m_pNode, CFX_ByteStringC(m_pszName, m_iNameLength), CFX_ByteStringC(m_pszData, m_iDataLength));
+ }
+}
+void CFX_SAXReader::NotifyBreak()
+{
+ FXSYS_assert(m_pHandler != NULL);
+ if (m_pCurItem->m_eNode == FX_SAXNODE_Tag) {
+ m_pHandler->OnTagBreak(m_pCurItem->m_pNode);
+ }
+}
+void CFX_SAXReader::NotifyClose()
+{
+ FXSYS_assert(m_pHandler != NULL);
+ if (m_pCurItem->m_eNode == FX_SAXNODE_Tag || m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
+ m_pHandler->OnTagClose(m_pCurItem->m_pNode, m_dwNodePos);
+ }
+}
+void CFX_SAXReader::NotifyEnd()
+{
+ FXSYS_assert(m_pHandler != NULL);
+ if (m_pCurItem->m_eNode == FX_SAXNODE_Tag) {
+ m_pHandler->OnTagEnd(m_pCurItem->m_pNode, CFX_ByteStringC(m_pszData, m_iDataLength), m_dwNodePos);
+ }
+}
+void CFX_SAXReader::NotifyTargetData()
+{
+ FXSYS_assert(m_pHandler != NULL);
+ if (m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
+ m_pHandler->OnTargetData(m_pCurItem->m_pNode, m_pCurItem->m_eNode, CFX_ByteStringC(m_pszName, m_iNameLength), m_dwNodePos);
+ } else if (m_pCurItem->m_eNode == FX_SAXNODE_Comment) {
+ m_pHandler->OnTargetData(m_pCurItem->m_pNode, m_pCurItem->m_eNode, CFX_ByteStringC(m_pszData, m_iDataLength), m_dwNodePos);
+ }
+}
+void CFX_SAXReader::SkipCurrentNode()
+{
+ if (!m_pCurItem) {
+ return;
+ }
+ m_pCurItem->m_bSkip = TRUE;
+}
+void CFX_SAXReader::SetHandler(IFX_SAXReaderHandler *pHandler)
+{
+ m_pHandler = pHandler;
+}
diff --git a/xfa/src/fgas/src/xml/fx_sax_imp.h b/xfa/src/fgas/src/xml/fx_sax_imp.h
new file mode 100644
index 0000000000..f18173183f
--- /dev/null
+++ b/xfa/src/fgas/src/xml/fx_sax_imp.h
@@ -0,0 +1,140 @@
+// 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 _FX_SAX_IMP_
+#define _FX_SAX_IMP_
+#define FX_SAXFILE_BUFSIZE 32768
+class CFX_SAXFile : public CFX_Object
+{
+public:
+ CFX_SAXFile();
+ FX_BOOL StartFile(IFX_FileRead *pFile, FX_DWORD dwStart, FX_DWORD dwLen);
+ FX_BOOL ReadNextBlock();
+ void Reset();
+ IFX_FileRead* m_pFile;
+ FX_DWORD m_dwStart;
+ FX_DWORD m_dwEnd;
+ FX_DWORD m_dwCur;
+ FX_LPBYTE m_pBuf;
+ FX_DWORD m_dwBufSize;
+ FX_DWORD m_dwBufIndex;
+};
+enum FX_SAXMODE {
+ FX_SAXMODE_Text = 0,
+ FX_SAXMODE_NodeStart,
+ FX_SAXMODE_DeclOrComment,
+ FX_SAXMODE_DeclNode,
+ FX_SAXMODE_Comment,
+ FX_SAXMODE_CommentContent,
+ FX_SAXMODE_TagName,
+ FX_SAXMODE_TagAttributeName,
+ FX_SAXMODE_TagAttributeEqual,
+ FX_SAXMODE_TagAttributeValue,
+ FX_SAXMODE_TagMaybeClose,
+ FX_SAXMODE_TagClose,
+ FX_SAXMODE_TagEnd,
+ FX_SAXMODE_TargetData,
+ FX_SAXMODE_MAX,
+};
+class CFX_SAXItem : public CFX_Object
+{
+public:
+ CFX_SAXItem() : m_pNode(NULL)
+ , m_eNode(FX_SAXNODE_Unknown)
+ , m_dwID(0)
+ , m_bSkip(FALSE)
+ , m_pPrev(NULL)
+ , m_pNext(NULL)
+ {}
+ FX_LPVOID m_pNode;
+ FX_SAXNODE m_eNode;
+ FX_DWORD m_dwID;
+ FX_BOOL m_bSkip;
+ CFX_SAXItem* m_pPrev;
+ CFX_SAXItem* m_pNext;
+};
+class CFX_SAXCommentContext : public CFX_Object
+{
+public:
+ CFX_SAXCommentContext() : m_iHeaderCount(0)
+ , m_iTailCount(0)
+ {
+ }
+ FX_INT32 m_iHeaderCount;
+ FX_INT32 m_iTailCount;
+};
+class CFX_SAXReader : public IFX_SAXReader, public CFX_Object
+{
+public:
+ CFX_SAXReader();
+ ~CFX_SAXReader();
+ virtual void Release()
+ {
+ delete this;
+ }
+ virtual FX_INT32 StartParse(IFX_FileRead *pFile, FX_DWORD dwStart = 0, FX_DWORD dwLen = -1, FX_DWORD dwParseMode = 0);
+ virtual FX_INT32 ContinueParse(IFX_Pause *pPause = NULL);
+ virtual void SkipCurrentNode();
+ virtual void SetHandler(IFX_SAXReaderHandler *pHandler);
+ void AppendData(FX_BYTE ch);
+ void AppendName(FX_BYTE ch);
+ void ParseText();
+ void ParseNodeStart();
+ void ParseInstruction();
+ void ParseDeclOrComment();
+ void ParseDeclNode();
+ void ParseComment();
+ void ParseCommentContent();
+ void ParseTagName();
+ void ParseTagAttributeName();
+ void ParseTagAttributeEqual();
+ void ParseTagAttributeValue();
+ void ParseMaybeClose();
+ void ParseTagClose();
+ void ParseTagEnd();
+ void ParseTargetData();
+protected:
+ CFX_SAXFile m_File;
+ IFX_SAXReaderHandler* m_pHandler;
+ FX_INT32 m_iState;
+ CFX_SAXItem* m_pRoot;
+ CFX_SAXItem* m_pCurItem;
+ FX_DWORD m_dwItemID;
+ FX_SAXMODE m_eMode;
+ FX_SAXMODE m_ePrevMode;
+ FX_BOOL m_bCharData;
+ FX_BYTE m_CurByte;
+ FX_DWORD m_dwDataOffset;
+ CFX_ByteArray m_SkipStack;
+ FX_BYTE m_SkipChar;
+ FX_DWORD m_dwNodePos;
+ FX_LPBYTE m_pszData;
+ FX_INT32 m_iDataSize;
+ FX_INT32 m_iDataLength;
+ FX_INT32 m_iEntityStart;
+ FX_INT32 m_iDataPos;
+ FX_LPBYTE m_pszName;
+ FX_INT32 m_iNameSize;
+ FX_INT32 m_iNameLength;
+ FX_DWORD m_dwParseMode;
+ CFX_SAXCommentContext *m_pCommentContext;
+ void Reset();
+ void Push();
+ void Pop();
+ FX_BOOL SkipSpace(FX_BYTE ch);
+ void SkipNode();
+ void NotifyData();
+ void NotifyEnter();
+ void NotifyAttribute();
+ void NotifyBreak();
+ void NotifyClose();
+ void NotifyEnd();
+ void NotifyTargetData();
+ void ReallocDataBuffer();
+ void ReallocNameBuffer();
+ void ParseChar(FX_BYTE ch);
+};
+#endif